| 1055 | * this is applied to next.screen during scroll fast path. |
| 1056 | */ |
| 1057 | export function shiftRows( |
| 1058 | screen: Screen, |
| 1059 | top: number, |
| 1060 | bottom: number, |
| 1061 | n: number, |
| 1062 | ): void { |
| 1063 | if (n === 0 || top < 0 || bottom >= screen.height || top > bottom) return |
| 1064 | const w = screen.width |
| 1065 | const cells64 = screen.cells64 |
| 1066 | const noSel = screen.noSelect |
| 1067 | const sw = screen.softWrap |
| 1068 | const absN = Math.abs(n) |
| 1069 | if (absN > bottom - top) { |
| 1070 | cells64.fill(EMPTY_CELL_VALUE, top * w, (bottom + 1) * w) |
| 1071 | noSel.fill(0, top * w, (bottom + 1) * w) |
| 1072 | sw.fill(0, top, bottom + 1) |
| 1073 | return |
| 1074 | } |
| 1075 | if (n > 0) { |
| 1076 | // SU: row top+n..bottom → top..bottom-n; clear bottom-n+1..bottom |
| 1077 | cells64.copyWithin(top * w, (top + n) * w, (bottom + 1) * w) |
| 1078 | noSel.copyWithin(top * w, (top + n) * w, (bottom + 1) * w) |
| 1079 | sw.copyWithin(top, top + n, bottom + 1) |
| 1080 | cells64.fill(EMPTY_CELL_VALUE, (bottom - n + 1) * w, (bottom + 1) * w) |
| 1081 | noSel.fill(0, (bottom - n + 1) * w, (bottom + 1) * w) |
| 1082 | sw.fill(0, bottom - n + 1, bottom + 1) |
| 1083 | } else { |
| 1084 | // SD: row top..bottom+n → top-n..bottom; clear top..top-n-1 |
| 1085 | cells64.copyWithin((top - n) * w, top * w, (bottom + n + 1) * w) |
| 1086 | noSel.copyWithin((top - n) * w, top * w, (bottom + n + 1) * w) |
| 1087 | sw.copyWithin(top - n, top, bottom + n + 1) |
| 1088 | cells64.fill(EMPTY_CELL_VALUE, top * w, (top - n) * w) |
| 1089 | noSel.fill(0, top * w, (top - n) * w) |
| 1090 | sw.fill(0, top, top - n) |
| 1091 | } |
| 1092 | } |
| 1093 | |
| 1094 | // Matches OSC 8 ; ; URI BEL |
| 1095 | const OSC8_REGEX = new RegExp(`^${ESC}\\]8${SEP}${SEP}([^${BEL}]*)${BEL}$`) |