vterm.js 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/index.d.mts +8 -0
- package/dist/index.mjs +252 -224
- package/package.json +4 -1
package/README.md
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -204,6 +204,10 @@ interface Snapshot {
|
|
|
204
204
|
originMode: boolean;
|
|
205
205
|
autoWrap: boolean;
|
|
206
206
|
charsetG0: boolean;
|
|
207
|
+
/** True when DEC Special Graphics is designated as G1. Absent in older snapshots: ASCII. */
|
|
208
|
+
charsetG1?: boolean;
|
|
209
|
+
/** True when SO has invoked G1 into GL. Absent in older snapshots: SI/G0. */
|
|
210
|
+
activeG1?: boolean;
|
|
207
211
|
};
|
|
208
212
|
attrs: ScreenAttrsSnapshot;
|
|
209
213
|
modes: {
|
|
@@ -268,6 +272,10 @@ interface Snapshot {
|
|
|
268
272
|
};
|
|
269
273
|
unicode: {
|
|
270
274
|
charsetG0: boolean;
|
|
275
|
+
/** True when DEC Special Graphics is designated as G1. Absent in older snapshots: ASCII. */
|
|
276
|
+
charsetG1?: boolean;
|
|
277
|
+
/** True when SO has invoked G1 into GL. Absent in older snapshots: SI/G0. */
|
|
278
|
+
activeG1?: boolean;
|
|
271
279
|
lastChar: string;
|
|
272
280
|
pendingRegionalIndicator: string | null;
|
|
273
281
|
afterZWJ: boolean;
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/screen.ts
|
|
2
2
|
/** Default retained payload bound for one APC/DCS sequence (16 MiB of ASCII/base64). */
|
|
3
|
-
const DEFAULT_MAX_STRING_SEQUENCE_LENGTH =
|
|
3
|
+
const DEFAULT_MAX_STRING_SEQUENCE_LENGTH = 16777216;
|
|
4
4
|
/** Frozen sentinel for unwritten cells — never mutate, copy-on-write in writeChar(). */
|
|
5
5
|
const EMPTY_CELL = Object.freeze({
|
|
6
6
|
char: "",
|
|
@@ -58,7 +58,7 @@ const F_HIDDEN$1 = 64;
|
|
|
58
58
|
const F_BLINK$1 = 128;
|
|
59
59
|
const F_WIDE$1 = 256;
|
|
60
60
|
const UL_SHIFT$1 = 9;
|
|
61
|
-
const UL_MASK$1 =
|
|
61
|
+
const UL_MASK$1 = 3584;
|
|
62
62
|
const F_HAS_FG = 4096;
|
|
63
63
|
const F_HAS_BG = 8192;
|
|
64
64
|
const F_HAS_UL = 16384;
|
|
@@ -79,6 +79,17 @@ function underlineToBits(u) {
|
|
|
79
79
|
function bitsToUnderline(meta) {
|
|
80
80
|
return UL_STYLES[(meta & UL_MASK$1) >> UL_SHIFT$1] ?? "none";
|
|
81
81
|
}
|
|
82
|
+
/** Require an invariant-owned value and fail where the impossible state is first observed. */
|
|
83
|
+
function required(value, subject) {
|
|
84
|
+
if (value === null || value === void 0) throw new Error(`Missing ${subject}`);
|
|
85
|
+
return value;
|
|
86
|
+
}
|
|
87
|
+
/** Read a dense indexed value and fail at the violated invariant instead of propagating `undefined`. */
|
|
88
|
+
function itemAt(items, index, subject) {
|
|
89
|
+
const value = items[index];
|
|
90
|
+
if (value === void 0) throw new RangeError(`${subject}[${index}] is outside its ${items.length}-item range`);
|
|
91
|
+
return value;
|
|
92
|
+
}
|
|
82
93
|
/** Pack a color's 8-bit channels into a 24-bit `0xRRGGBB` word. */
|
|
83
94
|
function packRgb(c) {
|
|
84
95
|
return ((c.r & 255) << 16 | (c.g & 255) << 8 | c.b & 255) >>> 0;
|
|
@@ -110,7 +121,7 @@ function makePackedRow(width) {
|
|
|
110
121
|
let ulIdx = null;
|
|
111
122
|
let urlMap = null;
|
|
112
123
|
function setFg(col, c) {
|
|
113
|
-
if (fgRgb === null) {
|
|
124
|
+
if (fgRgb === null || fgIdx === null) {
|
|
114
125
|
fgRgb = new Uint32Array(width);
|
|
115
126
|
fgIdx = new Int16Array(width);
|
|
116
127
|
}
|
|
@@ -118,7 +129,7 @@ function makePackedRow(width) {
|
|
|
118
129
|
fgIdx[col] = c.index ?? -1;
|
|
119
130
|
}
|
|
120
131
|
function setBg(col, c) {
|
|
121
|
-
if (bgRgb === null) {
|
|
132
|
+
if (bgRgb === null || bgIdx === null) {
|
|
122
133
|
bgRgb = new Uint32Array(width);
|
|
123
134
|
bgIdx = new Int16Array(width);
|
|
124
135
|
}
|
|
@@ -126,7 +137,7 @@ function makePackedRow(width) {
|
|
|
126
137
|
bgIdx[col] = c.index ?? -1;
|
|
127
138
|
}
|
|
128
139
|
function setUl(col, c) {
|
|
129
|
-
if (ulRgb === null) {
|
|
140
|
+
if (ulRgb === null || ulIdx === null) {
|
|
130
141
|
ulRgb = new Uint32Array(width);
|
|
131
142
|
ulIdx = new Int16Array(width);
|
|
132
143
|
}
|
|
@@ -211,27 +222,27 @@ function makePackedRow(width) {
|
|
|
211
222
|
} else meta[col] = 0;
|
|
212
223
|
},
|
|
213
224
|
widen(col) {
|
|
214
|
-
meta[col] = (meta
|
|
225
|
+
meta[col] = (itemAt(meta, col, "packed row metadata") | F_WIDE$1) >>> 0;
|
|
215
226
|
if (col + 1 < width) row.setEmpty(col + 1);
|
|
216
227
|
},
|
|
217
228
|
appendChar(col, ch) {
|
|
218
|
-
chars[col] = chars
|
|
229
|
+
chars[col] = itemAt(chars, col, "packed row characters") + ch;
|
|
219
230
|
},
|
|
220
231
|
copyCellFrom(col, src, srcCol) {
|
|
221
232
|
row.setCellRaw(col, src.getCellRaw(srcCol));
|
|
222
233
|
},
|
|
223
234
|
getCellRaw(col) {
|
|
224
|
-
const m = meta
|
|
235
|
+
const m = itemAt(meta, col, "packed row metadata");
|
|
225
236
|
if (m === 0 && chars[col] === "") return emptyCell();
|
|
226
237
|
return {
|
|
227
|
-
char: chars
|
|
228
|
-
fg: m & F_HAS_FG ? unpackColor(fgRgb
|
|
229
|
-
bg: m & F_HAS_BG ? unpackColor(bgRgb
|
|
238
|
+
char: itemAt(chars, col, "packed row characters"),
|
|
239
|
+
fg: m & F_HAS_FG ? unpackColor(itemAt(required(fgRgb, "foreground color plane"), col, "foreground color plane"), itemAt(required(fgIdx, "foreground color index plane"), col, "foreground color index plane")) : null,
|
|
240
|
+
bg: m & F_HAS_BG ? unpackColor(itemAt(required(bgRgb, "background color plane"), col, "background color plane"), itemAt(required(bgIdx, "background color index plane"), col, "background color index plane")) : null,
|
|
230
241
|
bold: (m & F_BOLD$1) !== 0,
|
|
231
242
|
faint: (m & F_FAINT$1) !== 0,
|
|
232
243
|
italic: (m & F_ITALIC$1) !== 0,
|
|
233
244
|
underline: bitsToUnderline(m),
|
|
234
|
-
underlineColor: m & F_HAS_UL ? unpackColor(ulRgb
|
|
245
|
+
underlineColor: m & F_HAS_UL ? unpackColor(itemAt(required(ulRgb, "underline color plane"), col, "underline color plane"), itemAt(required(ulIdx, "underline color index plane"), col, "underline color index plane")) : null,
|
|
235
246
|
overline: (m & F_OVERLINE$1) !== 0,
|
|
236
247
|
strikethrough: (m & F_STRIKE$1) !== 0,
|
|
237
248
|
inverse: (m & F_INVERSE$1) !== 0,
|
|
@@ -239,7 +250,7 @@ function makePackedRow(width) {
|
|
|
239
250
|
blink: (m & F_BLINK$1) !== 0,
|
|
240
251
|
protected: (m & F_PROTECTED$1) !== 0,
|
|
241
252
|
wide: (m & F_WIDE$1) !== 0,
|
|
242
|
-
url: m & F_HAS_URL ? urlMap.get(col) ?? null : null
|
|
253
|
+
url: m & F_HAS_URL ? required(urlMap, "packed row URL map").get(col) ?? null : null
|
|
243
254
|
};
|
|
244
255
|
},
|
|
245
256
|
toCells() {
|
|
@@ -254,10 +265,10 @@ function makePackedRow(width) {
|
|
|
254
265
|
return meta[col] === 0 && chars[col] === "";
|
|
255
266
|
},
|
|
256
267
|
getChar(col) {
|
|
257
|
-
return chars
|
|
268
|
+
return itemAt(chars, col, "packed row characters");
|
|
258
269
|
},
|
|
259
270
|
isWide(col) {
|
|
260
|
-
return (meta
|
|
271
|
+
return (itemAt(meta, col, "packed row metadata") & F_WIDE$1) !== 0;
|
|
261
272
|
}
|
|
262
273
|
};
|
|
263
274
|
return row;
|
|
@@ -361,9 +372,9 @@ function buildPalette256() {
|
|
|
361
372
|
255
|
|
362
373
|
];
|
|
363
374
|
for (let r = 0; r < 6; r++) for (let g = 0; g < 6; g++) for (let b = 0; b < 6; b++) palette.push({
|
|
364
|
-
r: levels
|
|
365
|
-
g: levels
|
|
366
|
-
b: levels
|
|
375
|
+
r: itemAt(levels, r, "ANSI cube red levels"),
|
|
376
|
+
g: itemAt(levels, g, "ANSI cube green levels"),
|
|
377
|
+
b: itemAt(levels, b, "ANSI cube blue levels")
|
|
367
378
|
});
|
|
368
379
|
for (let i = 0; i < 24; i++) {
|
|
369
380
|
const v = 8 + i * 10;
|
|
@@ -389,14 +400,14 @@ function parseColorSpec(spec) {
|
|
|
389
400
|
return Math.round(v * 255 / max);
|
|
390
401
|
};
|
|
391
402
|
return {
|
|
392
|
-
r: scale(rgbMatch
|
|
393
|
-
g: scale(rgbMatch
|
|
394
|
-
b: scale(rgbMatch
|
|
403
|
+
r: scale(itemAt(rgbMatch, 1, "X11 red capture")),
|
|
404
|
+
g: scale(itemAt(rgbMatch, 2, "X11 green capture")),
|
|
405
|
+
b: scale(itemAt(rgbMatch, 3, "X11 blue capture"))
|
|
395
406
|
};
|
|
396
407
|
}
|
|
397
408
|
const hex6 = /^#([0-9a-fA-F]{6})$/.exec(s);
|
|
398
409
|
if (hex6) {
|
|
399
|
-
const v = hex6
|
|
410
|
+
const v = itemAt(hex6, 1, "six-digit hex capture");
|
|
400
411
|
return {
|
|
401
412
|
r: parseInt(v.substring(0, 2), 16),
|
|
402
413
|
g: parseInt(v.substring(2, 4), 16),
|
|
@@ -405,12 +416,12 @@ function parseColorSpec(spec) {
|
|
|
405
416
|
}
|
|
406
417
|
const hex3 = /^#([0-9a-fA-F]{3})$/.exec(s);
|
|
407
418
|
if (hex3) {
|
|
408
|
-
const v = hex3
|
|
419
|
+
const v = itemAt(hex3, 1, "three-digit hex capture");
|
|
409
420
|
const expand = (ch) => parseInt(ch + ch, 16);
|
|
410
421
|
return {
|
|
411
|
-
r: expand(v
|
|
412
|
-
g: expand(v
|
|
413
|
-
b: expand(v
|
|
422
|
+
r: expand(itemAt(v, 0, "short hex red channel")),
|
|
423
|
+
g: expand(itemAt(v, 1, "short hex green channel")),
|
|
424
|
+
b: expand(itemAt(v, 2, "short hex blue channel"))
|
|
414
425
|
};
|
|
415
426
|
}
|
|
416
427
|
return null;
|
|
@@ -484,7 +495,9 @@ function createScreen(options = {}) {
|
|
|
484
495
|
attrs: resetAttrs(),
|
|
485
496
|
originMode: false,
|
|
486
497
|
autoWrap: true,
|
|
487
|
-
charsetG0: false
|
|
498
|
+
charsetG0: false,
|
|
499
|
+
charsetG1: false,
|
|
500
|
+
activeG1: false
|
|
488
501
|
};
|
|
489
502
|
let savedCurX = 0;
|
|
490
503
|
let savedCurY = 0;
|
|
@@ -663,6 +676,8 @@ function createScreen(options = {}) {
|
|
|
663
676
|
assertBoolean("savedState.originMode", saved.originMode);
|
|
664
677
|
assertBoolean("savedState.autoWrap", saved.autoWrap);
|
|
665
678
|
assertBoolean("savedState.charsetG0", saved.charsetG0);
|
|
679
|
+
if (Object.hasOwn(saved, "charsetG1")) assertBoolean("savedState.charsetG1", saved.charsetG1);
|
|
680
|
+
if (Object.hasOwn(saved, "activeG1")) assertBoolean("savedState.activeG1", saved.activeG1);
|
|
666
681
|
assertRecord("attrs", value.attrs);
|
|
667
682
|
const modes = value.modes;
|
|
668
683
|
assertRecord("modes", modes);
|
|
@@ -745,6 +760,8 @@ function createScreen(options = {}) {
|
|
|
745
760
|
const unicode = value.unicode;
|
|
746
761
|
assertRecord("unicode", unicode);
|
|
747
762
|
assertBoolean("unicode.charsetG0", unicode.charsetG0);
|
|
763
|
+
if (Object.hasOwn(unicode, "charsetG1")) assertBoolean("unicode.charsetG1", unicode.charsetG1);
|
|
764
|
+
if (Object.hasOwn(unicode, "activeG1")) assertBoolean("unicode.activeG1", unicode.activeG1);
|
|
748
765
|
assertString("unicode.lastChar", unicode.lastChar);
|
|
749
766
|
if (unicode.pendingRegionalIndicator !== null) assertString("unicode.pendingRegionalIndicator", unicode.pendingRegionalIndicator);
|
|
750
767
|
assertBoolean("unicode.afterZWJ", unicode.afterZWJ);
|
|
@@ -774,6 +791,8 @@ function createScreen(options = {}) {
|
|
|
774
791
|
let advancedClipboard = "";
|
|
775
792
|
let viewportOffset = 0;
|
|
776
793
|
let charsetG0 = false;
|
|
794
|
+
let charsetG1 = false;
|
|
795
|
+
let activeG1 = false;
|
|
777
796
|
let clipboard = "";
|
|
778
797
|
let cwd = "";
|
|
779
798
|
let notifications = [];
|
|
@@ -939,13 +958,12 @@ function createScreen(options = {}) {
|
|
|
939
958
|
if (bytes.length === 0) return 0;
|
|
940
959
|
let continuationCount = 0;
|
|
941
960
|
let leadIndex = bytes.length - 1;
|
|
942
|
-
while (leadIndex >= 0 && (bytes
|
|
961
|
+
while (leadIndex >= 0 && (itemAt(bytes, leadIndex, "UTF-8 pending bytes") & 192) === 128 && continuationCount < 3) {
|
|
943
962
|
continuationCount++;
|
|
944
963
|
leadIndex--;
|
|
945
964
|
}
|
|
946
965
|
if (leadIndex < 0) return bytes.length;
|
|
947
|
-
const
|
|
948
|
-
const expectedLength = utf8SequenceLength(lead);
|
|
966
|
+
const expectedLength = utf8SequenceLength(itemAt(bytes, leadIndex, "UTF-8 lead byte"));
|
|
949
967
|
if (expectedLength === 0) return bytes.length;
|
|
950
968
|
return expectedLength > bytes.length - leadIndex ? leadIndex : bytes.length;
|
|
951
969
|
}
|
|
@@ -1051,11 +1069,11 @@ function createScreen(options = {}) {
|
|
|
1051
1069
|
const lm = leftMargin;
|
|
1052
1070
|
const rm = rightMargin;
|
|
1053
1071
|
for (let r = top; r < bottom; r++) {
|
|
1054
|
-
const srcRow = grid
|
|
1055
|
-
const dstRow = grid
|
|
1072
|
+
const srcRow = itemAt(grid, r + 1, "scroll source rows");
|
|
1073
|
+
const dstRow = itemAt(grid, r, "scroll destination rows");
|
|
1056
1074
|
for (let c = lm; c <= rm && c < cols; c++) dstRow.copyCellFrom(c, srcRow, c);
|
|
1057
1075
|
}
|
|
1058
|
-
const bottomRow = grid
|
|
1076
|
+
const bottomRow = itemAt(grid, bottom, "scroll bottom row");
|
|
1059
1077
|
for (let c = lm; c <= rm && c < cols; c++) bottomRow.setEmpty(c);
|
|
1060
1078
|
markScreenRowsDirty(top, bottom);
|
|
1061
1079
|
} else {
|
|
@@ -1098,16 +1116,16 @@ function createScreen(options = {}) {
|
|
|
1098
1116
|
const lm = leftMargin;
|
|
1099
1117
|
const rm = rightMargin;
|
|
1100
1118
|
for (let r = bottom; r > top; r--) {
|
|
1101
|
-
const srcRow = grid
|
|
1102
|
-
const dstRow = grid
|
|
1119
|
+
const srcRow = itemAt(grid, r - 1, "reverse-scroll source rows");
|
|
1120
|
+
const dstRow = itemAt(grid, r, "reverse-scroll destination rows");
|
|
1103
1121
|
for (let c = lm; c <= rm && c < cols; c++) dstRow.copyCellFrom(c, srcRow, c);
|
|
1104
1122
|
}
|
|
1105
|
-
const topRow = grid
|
|
1123
|
+
const topRow = itemAt(grid, top, "reverse-scroll top row");
|
|
1106
1124
|
for (let c = lm; c <= rm && c < cols; c++) topRow.setEmpty(c);
|
|
1107
1125
|
} else {
|
|
1108
1126
|
for (let i = bottom; i > top; i--) {
|
|
1109
|
-
grid[i] = grid
|
|
1110
|
-
softWrapped[i] = softWrapped
|
|
1127
|
+
grid[i] = itemAt(grid, i - 1, "reverse-scroll source rows");
|
|
1128
|
+
softWrapped[i] = itemAt(softWrapped, i - 1, "reverse-scroll source wrap flags");
|
|
1111
1129
|
}
|
|
1112
1130
|
grid[top] = makeRow(cols);
|
|
1113
1131
|
softWrapped[top] = false;
|
|
@@ -1132,7 +1150,7 @@ function createScreen(options = {}) {
|
|
|
1132
1150
|
if (prevRow < 0) return null;
|
|
1133
1151
|
prevCol = cols - 1;
|
|
1134
1152
|
}
|
|
1135
|
-
const row = grid
|
|
1153
|
+
const row = itemAt(grid, prevRow, "previous-cell rows");
|
|
1136
1154
|
if (prevCol > 0 && row.getChar(prevCol) === "" && row.isWide(prevCol - 1)) prevCol--;
|
|
1137
1155
|
if (row.isEmpty(prevCol)) return null;
|
|
1138
1156
|
return {
|
|
@@ -1146,7 +1164,7 @@ function createScreen(options = {}) {
|
|
|
1146
1164
|
row.widen(col);
|
|
1147
1165
|
}
|
|
1148
1166
|
function writeChar(ch) {
|
|
1149
|
-
if (charsetG0 && ch.length === 1) {
|
|
1167
|
+
if ((activeG1 ? charsetG1 : charsetG0) && ch.length === 1) {
|
|
1150
1168
|
const mapped = DEC_SPECIAL_GRAPHICS[ch];
|
|
1151
1169
|
if (mapped) ch = mapped;
|
|
1152
1170
|
}
|
|
@@ -1196,14 +1214,16 @@ function createScreen(options = {}) {
|
|
|
1196
1214
|
return;
|
|
1197
1215
|
}
|
|
1198
1216
|
}
|
|
1199
|
-
if (isRegionalIndicator(codePoint))
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1217
|
+
if (isRegionalIndicator(codePoint)) {
|
|
1218
|
+
if (pendingRegionalIndicator !== null) {
|
|
1219
|
+
const flag = pendingRegionalIndicator + ch;
|
|
1220
|
+
pendingRegionalIndicator = null;
|
|
1221
|
+
writeCharCore(flag, true);
|
|
1222
|
+
return;
|
|
1223
|
+
} else {
|
|
1224
|
+
pendingRegionalIndicator = ch;
|
|
1225
|
+
return;
|
|
1226
|
+
}
|
|
1207
1227
|
}
|
|
1208
1228
|
if (pendingRegionalIndicator !== null) {
|
|
1209
1229
|
const ri = pendingRegionalIndicator;
|
|
@@ -1218,18 +1238,20 @@ function createScreen(options = {}) {
|
|
|
1218
1238
|
const charWidth = wide ? 2 : 1;
|
|
1219
1239
|
const wrapBoundary = leftRightMarginMode ? rightMargin + 1 : rowCols(curY);
|
|
1220
1240
|
const wrapReturn = leftRightMarginMode ? leftMargin : 0;
|
|
1221
|
-
if (curX + charWidth > wrapBoundary)
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
curY
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1241
|
+
if (curX + charWidth > wrapBoundary) {
|
|
1242
|
+
if (autoWrap) {
|
|
1243
|
+
softWrapped[curY] = true;
|
|
1244
|
+
curX = wrapReturn;
|
|
1245
|
+
curY++;
|
|
1246
|
+
if (curY > scrollBottom) {
|
|
1247
|
+
curY = scrollBottom;
|
|
1248
|
+
scrollUp(scrollTop, scrollBottom);
|
|
1249
|
+
}
|
|
1250
|
+
} else curX = wrapBoundary - charWidth;
|
|
1251
|
+
}
|
|
1230
1252
|
if (insertMode) {
|
|
1231
1253
|
const insertEnd = leftRightMarginMode ? rightMargin + 1 : cols;
|
|
1232
|
-
mutateRowAsCells(grid
|
|
1254
|
+
mutateRowAsCells(itemAt(grid, curY, "cursor row"), (cells) => {
|
|
1233
1255
|
for (let i = 0; i < charWidth; i++) {
|
|
1234
1256
|
cells.splice(insertEnd - 1, 1);
|
|
1235
1257
|
cells.splice(curX, 0, emptyCell());
|
|
@@ -1272,7 +1294,6 @@ function createScreen(options = {}) {
|
|
|
1272
1294
|
case 6:
|
|
1273
1295
|
cursorShape = "bar";
|
|
1274
1296
|
cursorBlinking = false;
|
|
1275
|
-
break;
|
|
1276
1297
|
}
|
|
1277
1298
|
else if (finalByte === "@") handleShiftLeft(Math.max(parts[0] ?? 1, 1));
|
|
1278
1299
|
else if (finalByte === "A") handleShiftRight(Math.max(parts[0] ?? 1, 1));
|
|
@@ -1301,7 +1322,7 @@ function createScreen(options = {}) {
|
|
|
1301
1322
|
const { t, l, b, r } = normalizeRect(parts[1] ?? 1, parts[2] ?? 1, parts[3] ?? rows, parts[4] ?? cols);
|
|
1302
1323
|
const fillChar = String.fromCharCode(charCode);
|
|
1303
1324
|
for (let row = t; row <= b && row < rows; row++) {
|
|
1304
|
-
const gr = grid
|
|
1325
|
+
const gr = itemAt(grid, row, "rectangular erase rows");
|
|
1305
1326
|
for (let col = l; col <= r && col < cols; col++) {
|
|
1306
1327
|
const cell = emptyCell();
|
|
1307
1328
|
cell.char = fillChar;
|
|
@@ -1312,7 +1333,7 @@ function createScreen(options = {}) {
|
|
|
1312
1333
|
} else if (finalByte === "z" || finalByte === "{") {
|
|
1313
1334
|
const { t, l, b, r } = normalizeRect(parts[0] ?? 1, parts[1] ?? 1, parts[2] ?? rows, parts[3] ?? cols);
|
|
1314
1335
|
for (let row = t; row <= b && row < rows; row++) {
|
|
1315
|
-
const gr = grid
|
|
1336
|
+
const gr = itemAt(grid, row, "rectangular fill rows");
|
|
1316
1337
|
for (let col = l; col <= r && col < cols; col++) gr.setEmpty(col);
|
|
1317
1338
|
}
|
|
1318
1339
|
markScreenRowsDirty(t, Math.min(b, rows - 1));
|
|
@@ -1332,11 +1353,11 @@ function createScreen(options = {}) {
|
|
|
1332
1353
|
for (let row = 0; row < h; row++) {
|
|
1333
1354
|
const dr = dstTop + row;
|
|
1334
1355
|
if (dr < 0 || dr >= rows) continue;
|
|
1335
|
-
const dstRow = grid
|
|
1356
|
+
const dstRow = itemAt(grid, dr, "rectangular copy destination rows");
|
|
1336
1357
|
for (let col = 0; col < w; col++) {
|
|
1337
1358
|
const dc = dstLeft + col;
|
|
1338
1359
|
if (dc < 0 || dc >= cols) continue;
|
|
1339
|
-
dstRow.setCellRaw(dc, snapshot
|
|
1360
|
+
dstRow.setCellRaw(dc, itemAt(itemAt(snapshot, row, "rectangular copy rows"), col, "rectangular copy cells"));
|
|
1340
1361
|
}
|
|
1341
1362
|
}
|
|
1342
1363
|
markScreenRowsDirty(Math.max(0, dstTop), Math.min(dstTop + h - 1, rows - 1));
|
|
@@ -1345,7 +1366,7 @@ function createScreen(options = {}) {
|
|
|
1345
1366
|
const sgrParts = parts.slice(4);
|
|
1346
1367
|
const reverse = finalByte === "t";
|
|
1347
1368
|
for (let row = t; row <= b && row < rows; row++) {
|
|
1348
|
-
const gr = grid
|
|
1369
|
+
const gr = itemAt(grid, row, "rectangular attribute rows");
|
|
1349
1370
|
for (let col = l; col <= r && col < cols; col++) {
|
|
1350
1371
|
const cell = gr.getCellRaw(col);
|
|
1351
1372
|
applyRectAttrs(cell, sgrParts, reverse);
|
|
@@ -1459,9 +1480,7 @@ function createScreen(options = {}) {
|
|
|
1459
1480
|
case 20:
|
|
1460
1481
|
onResponse(`\x1b]L${title}\x1b\\`);
|
|
1461
1482
|
break;
|
|
1462
|
-
case 21:
|
|
1463
|
-
onResponse(`\x1b]l${title}\x1b\\`);
|
|
1464
|
-
break;
|
|
1483
|
+
case 21: onResponse(`\x1b]l${title}\x1b\\`);
|
|
1465
1484
|
}
|
|
1466
1485
|
break;
|
|
1467
1486
|
}
|
|
@@ -1580,8 +1599,6 @@ function createScreen(options = {}) {
|
|
|
1580
1599
|
curX = savedCurX;
|
|
1581
1600
|
curY = savedCurY;
|
|
1582
1601
|
clampCursor();
|
|
1583
|
-
break;
|
|
1584
|
-
default: break;
|
|
1585
1602
|
}
|
|
1586
1603
|
}
|
|
1587
1604
|
function handleCSIGt(params, _intermediates, finalByte) {
|
|
@@ -1688,9 +1705,7 @@ function createScreen(options = {}) {
|
|
|
1688
1705
|
case 1007:
|
|
1689
1706
|
value = altScrollMode ? 1 : 2;
|
|
1690
1707
|
break;
|
|
1691
|
-
case 1048:
|
|
1692
|
-
value = 2;
|
|
1693
|
-
break;
|
|
1708
|
+
case 1048: value = 2;
|
|
1694
1709
|
}
|
|
1695
1710
|
onResponse(`\x1b[?${mode};${value}$y`);
|
|
1696
1711
|
}
|
|
@@ -1819,16 +1834,14 @@ function createScreen(options = {}) {
|
|
|
1819
1834
|
case 1007:
|
|
1820
1835
|
altScrollMode = set;
|
|
1821
1836
|
break;
|
|
1822
|
-
case 1048:
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
}
|
|
1831
|
-
break;
|
|
1837
|
+
case 1048: if (set) {
|
|
1838
|
+
savedCurX = curX;
|
|
1839
|
+
savedCurY = curY;
|
|
1840
|
+
} else {
|
|
1841
|
+
curX = savedCurX;
|
|
1842
|
+
curY = savedCurY;
|
|
1843
|
+
clampCursor();
|
|
1844
|
+
}
|
|
1832
1845
|
}
|
|
1833
1846
|
}
|
|
1834
1847
|
function handleEraseDisplay(mode, selective = false) {
|
|
@@ -1846,7 +1859,6 @@ function createScreen(options = {}) {
|
|
|
1846
1859
|
for (let row = 0; row < rows; row++) eraseCells(row, 0, row, cols - 1, selective);
|
|
1847
1860
|
if (mode === 3) clearScrollback();
|
|
1848
1861
|
markAllDirty();
|
|
1849
|
-
break;
|
|
1850
1862
|
}
|
|
1851
1863
|
}
|
|
1852
1864
|
function handleEraseLine(mode, selective = false) {
|
|
@@ -1859,9 +1871,7 @@ function createScreen(options = {}) {
|
|
|
1859
1871
|
case 1:
|
|
1860
1872
|
eraseCells(curY, eraseLeft, curY, curX, selective);
|
|
1861
1873
|
break;
|
|
1862
|
-
case 2:
|
|
1863
|
-
eraseCells(curY, eraseLeft, curY, eraseRight, selective);
|
|
1864
|
-
break;
|
|
1874
|
+
case 2: eraseCells(curY, eraseLeft, curY, eraseRight, selective);
|
|
1865
1875
|
}
|
|
1866
1876
|
}
|
|
1867
1877
|
function eraseCells(row, startCol, _endRow, endCol, selective = false) {
|
|
@@ -2014,9 +2024,7 @@ function createScreen(options = {}) {
|
|
|
2014
2024
|
case 25:
|
|
2015
2025
|
cell.blink = false;
|
|
2016
2026
|
break;
|
|
2017
|
-
case 27:
|
|
2018
|
-
cell.inverse = false;
|
|
2019
|
-
break;
|
|
2027
|
+
case 27: cell.inverse = false;
|
|
2020
2028
|
}
|
|
2021
2029
|
}
|
|
2022
2030
|
function handleSGR(rawParams) {
|
|
@@ -2026,7 +2034,7 @@ function createScreen(options = {}) {
|
|
|
2026
2034
|
for (const seg of segments) if (seg.includes(":")) {
|
|
2027
2035
|
const subs = seg.split(":").map((s) => s === "" ? 0 : parseInt(s, 10));
|
|
2028
2036
|
subParams.set(params.length, subs);
|
|
2029
|
-
params.push(subs
|
|
2037
|
+
params.push(itemAt(subs, 0, "SGR sub-parameters"));
|
|
2030
2038
|
} else params.push(seg === "" ? 0 : parseInt(seg, 10));
|
|
2031
2039
|
if (params.length === 0 || params.length === 1 && params[0] === 0) {
|
|
2032
2040
|
attrs = resetSgrAttrs();
|
|
@@ -2034,7 +2042,7 @@ function createScreen(options = {}) {
|
|
|
2034
2042
|
}
|
|
2035
2043
|
let i = 0;
|
|
2036
2044
|
while (i < params.length) {
|
|
2037
|
-
const code = params
|
|
2045
|
+
const code = itemAt(params, i, "SGR parameters");
|
|
2038
2046
|
switch (code) {
|
|
2039
2047
|
case 0:
|
|
2040
2048
|
attrs = resetSgrAttrs();
|
|
@@ -2050,7 +2058,7 @@ function createScreen(options = {}) {
|
|
|
2050
2058
|
break;
|
|
2051
2059
|
case 4: {
|
|
2052
2060
|
const subs = subParams.get(i);
|
|
2053
|
-
if (subs && subs.length > 1) switch (subs
|
|
2061
|
+
if (subs && subs.length > 1) switch (itemAt(subs, 1, "underline style sub-parameters")) {
|
|
2054
2062
|
case 0:
|
|
2055
2063
|
attrs.underline = "none";
|
|
2056
2064
|
break;
|
|
@@ -2069,9 +2077,7 @@ function createScreen(options = {}) {
|
|
|
2069
2077
|
case 5:
|
|
2070
2078
|
attrs.underline = "dashed";
|
|
2071
2079
|
break;
|
|
2072
|
-
default:
|
|
2073
|
-
attrs.underline = "single";
|
|
2074
|
-
break;
|
|
2080
|
+
default: attrs.underline = "single";
|
|
2075
2081
|
}
|
|
2076
2082
|
else attrs.underline = "single";
|
|
2077
2083
|
break;
|
|
@@ -2125,7 +2131,7 @@ function createScreen(options = {}) {
|
|
|
2125
2131
|
case 36:
|
|
2126
2132
|
case 37:
|
|
2127
2133
|
attrs.fg = {
|
|
2128
|
-
...palette256
|
|
2134
|
+
...itemAt(palette256, code - 30, "basic foreground palette"),
|
|
2129
2135
|
index: code - 30
|
|
2130
2136
|
};
|
|
2131
2137
|
break;
|
|
@@ -2155,7 +2161,7 @@ function createScreen(options = {}) {
|
|
|
2155
2161
|
case 46:
|
|
2156
2162
|
case 47:
|
|
2157
2163
|
attrs.bg = {
|
|
2158
|
-
...palette256
|
|
2164
|
+
...itemAt(palette256, code - 40, "basic background palette"),
|
|
2159
2165
|
index: code - 40
|
|
2160
2166
|
};
|
|
2161
2167
|
break;
|
|
@@ -2208,7 +2214,7 @@ function createScreen(options = {}) {
|
|
|
2208
2214
|
case 96:
|
|
2209
2215
|
case 97:
|
|
2210
2216
|
attrs.fg = {
|
|
2211
|
-
...palette256
|
|
2217
|
+
...itemAt(palette256, code - 90 + 8, "bright foreground palette"),
|
|
2212
2218
|
index: code - 90 + 8
|
|
2213
2219
|
};
|
|
2214
2220
|
break;
|
|
@@ -2219,12 +2225,10 @@ function createScreen(options = {}) {
|
|
|
2219
2225
|
case 104:
|
|
2220
2226
|
case 105:
|
|
2221
2227
|
case 106:
|
|
2222
|
-
case 107:
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
};
|
|
2227
|
-
break;
|
|
2228
|
+
case 107: attrs.bg = {
|
|
2229
|
+
...itemAt(palette256, code - 100 + 8, "bright background palette"),
|
|
2230
|
+
index: code - 100 + 8
|
|
2231
|
+
};
|
|
2228
2232
|
}
|
|
2229
2233
|
i++;
|
|
2230
2234
|
}
|
|
@@ -2233,7 +2237,7 @@ function createScreen(options = {}) {
|
|
|
2233
2237
|
if (startIndex + 1 >= params.length) return null;
|
|
2234
2238
|
const type = params[startIndex + 1];
|
|
2235
2239
|
if (type === 5 && startIndex + 2 < params.length) {
|
|
2236
|
-
const idx = params
|
|
2240
|
+
const idx = itemAt(params, startIndex + 2, "indexed color parameters");
|
|
2237
2241
|
const entry = palette256[idx];
|
|
2238
2242
|
return {
|
|
2239
2243
|
color: entry ? {
|
|
@@ -2248,9 +2252,9 @@ function createScreen(options = {}) {
|
|
|
2248
2252
|
};
|
|
2249
2253
|
} else if (type === 2 && startIndex + 4 < params.length) return {
|
|
2250
2254
|
color: {
|
|
2251
|
-
r: params
|
|
2252
|
-
g: params
|
|
2253
|
-
b: params
|
|
2255
|
+
r: itemAt(params, startIndex + 2, "truecolor red parameter"),
|
|
2256
|
+
g: itemAt(params, startIndex + 3, "truecolor green parameter"),
|
|
2257
|
+
b: itemAt(params, startIndex + 4, "truecolor blue parameter")
|
|
2254
2258
|
},
|
|
2255
2259
|
nextIndex: startIndex + 5
|
|
2256
2260
|
};
|
|
@@ -2261,7 +2265,7 @@ function createScreen(options = {}) {
|
|
|
2261
2265
|
if (subs.length < 3) return null;
|
|
2262
2266
|
const type = subs[1];
|
|
2263
2267
|
if (type === 5 && subs.length >= 3) {
|
|
2264
|
-
const idx = subs
|
|
2268
|
+
const idx = itemAt(subs, 2, "indexed color sub-parameters");
|
|
2265
2269
|
const entry = palette256[idx];
|
|
2266
2270
|
return entry ? {
|
|
2267
2271
|
...entry,
|
|
@@ -2274,18 +2278,18 @@ function createScreen(options = {}) {
|
|
|
2274
2278
|
} else if (type === 2) {
|
|
2275
2279
|
if (subs.length >= 5) {
|
|
2276
2280
|
if (subs.length >= 6) return {
|
|
2277
|
-
r: subs
|
|
2278
|
-
g: subs
|
|
2279
|
-
b: subs
|
|
2281
|
+
r: itemAt(subs, 3, "colorspace red sub-parameter"),
|
|
2282
|
+
g: itemAt(subs, 4, "colorspace green sub-parameter"),
|
|
2283
|
+
b: itemAt(subs, 5, "colorspace blue sub-parameter")
|
|
2280
2284
|
};
|
|
2281
2285
|
return {
|
|
2282
|
-
r: subs
|
|
2283
|
-
g: subs
|
|
2284
|
-
b: subs
|
|
2286
|
+
r: itemAt(subs, 2, "truecolor red sub-parameter"),
|
|
2287
|
+
g: itemAt(subs, 3, "truecolor green sub-parameter"),
|
|
2288
|
+
b: itemAt(subs, 4, "truecolor blue sub-parameter")
|
|
2285
2289
|
};
|
|
2286
2290
|
} else if (subs.length >= 4) return {
|
|
2287
|
-
r: subs
|
|
2288
|
-
g: subs
|
|
2291
|
+
r: itemAt(subs, 2, "partial truecolor red sub-parameter"),
|
|
2292
|
+
g: itemAt(subs, 3, "partial truecolor green sub-parameter"),
|
|
2289
2293
|
b: 0
|
|
2290
2294
|
};
|
|
2291
2295
|
}
|
|
@@ -2317,14 +2321,11 @@ function createScreen(options = {}) {
|
|
|
2317
2321
|
startCol: curX
|
|
2318
2322
|
});
|
|
2319
2323
|
break;
|
|
2320
|
-
case "C":
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
});
|
|
2326
|
-
break;
|
|
2327
|
-
case "D": break;
|
|
2324
|
+
case "C": semanticZones.push({
|
|
2325
|
+
type: "output",
|
|
2326
|
+
startRow: curY,
|
|
2327
|
+
startCol: curX
|
|
2328
|
+
});
|
|
2328
2329
|
}
|
|
2329
2330
|
break;
|
|
2330
2331
|
case 1: break;
|
|
@@ -2342,8 +2343,8 @@ function createScreen(options = {}) {
|
|
|
2342
2343
|
case 4: {
|
|
2343
2344
|
const fields = value.split(";");
|
|
2344
2345
|
for (let fi = 0; fi + 1 < fields.length; fi += 2) {
|
|
2345
|
-
const idx = parseInt(fields
|
|
2346
|
-
const spec = fields
|
|
2346
|
+
const idx = parseInt(itemAt(fields, fi, "OSC 4 palette fields"), 10);
|
|
2347
|
+
const spec = itemAt(fields, fi + 1, "OSC 4 palette fields");
|
|
2347
2348
|
if (isNaN(idx) || idx < 0 || idx > 255) continue;
|
|
2348
2349
|
if (spec === "?") {
|
|
2349
2350
|
const c = palette256[idx];
|
|
@@ -2358,8 +2359,8 @@ function createScreen(options = {}) {
|
|
|
2358
2359
|
case 5: {
|
|
2359
2360
|
const fields = value.split(";");
|
|
2360
2361
|
for (let fi = 0; fi + 1 < fields.length; fi += 2) {
|
|
2361
|
-
const idx = parseInt(fields
|
|
2362
|
-
const spec = fields
|
|
2362
|
+
const idx = parseInt(itemAt(fields, fi, "OSC 5 special-color fields"), 10);
|
|
2363
|
+
const spec = itemAt(fields, fi + 1, "OSC 5 special-color fields");
|
|
2363
2364
|
if (isNaN(idx) || idx < 0 || idx > 4) continue;
|
|
2364
2365
|
if (spec === "?") {
|
|
2365
2366
|
const c = specialColors.get(idx);
|
|
@@ -2469,70 +2470,76 @@ function createScreen(options = {}) {
|
|
|
2469
2470
|
const isQuery = val === "?";
|
|
2470
2471
|
const paletteMatch = /^color(\d+)$/.exec(key);
|
|
2471
2472
|
if (paletteMatch) {
|
|
2472
|
-
const idx = parseInt(paletteMatch
|
|
2473
|
+
const idx = parseInt(itemAt(paletteMatch, 1, "OSC 104 palette capture"), 10);
|
|
2473
2474
|
if (idx < 0 || idx > 255) continue;
|
|
2474
2475
|
if (isQuery) {
|
|
2475
2476
|
const c = palette256[idx];
|
|
2476
2477
|
if (c) response.push(`${key}=${formatColorResponse(c)}`);
|
|
2477
2478
|
} else if (val === "") {
|
|
2478
2479
|
const fresh = buildPalette256();
|
|
2479
|
-
palette256[idx] = fresh
|
|
2480
|
+
palette256[idx] = itemAt(fresh, idx, "fresh ANSI palette");
|
|
2480
2481
|
} else {
|
|
2481
2482
|
const c = parseColorSpec(val);
|
|
2482
2483
|
if (c) palette256[idx] = c;
|
|
2483
2484
|
}
|
|
2484
|
-
} else if (key === "foreground")
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
if (
|
|
2485
|
+
} else if (key === "foreground") {
|
|
2486
|
+
if (isQuery) {
|
|
2487
|
+
const c = defaultFgColor ?? {
|
|
2488
|
+
r: 255,
|
|
2489
|
+
g: 255,
|
|
2490
|
+
b: 255
|
|
2491
|
+
};
|
|
2492
|
+
response.push(`${key}=${formatColorResponse(c)}`);
|
|
2493
|
+
} else if (val === "") defaultFgColor = null;
|
|
2494
|
+
else {
|
|
2495
|
+
const c = parseColorSpec(val);
|
|
2496
|
+
if (c) defaultFgColor = c;
|
|
2497
|
+
}
|
|
2498
|
+
} else if (key === "background") {
|
|
2499
|
+
if (isQuery) {
|
|
2500
|
+
const c = defaultBgColor ?? {
|
|
2501
|
+
r: 0,
|
|
2502
|
+
g: 0,
|
|
2503
|
+
b: 0
|
|
2504
|
+
};
|
|
2505
|
+
response.push(`${key}=${formatColorResponse(c)}`);
|
|
2506
|
+
} else if (val === "") defaultBgColor = null;
|
|
2507
|
+
else {
|
|
2508
|
+
const c = parseColorSpec(val);
|
|
2509
|
+
if (c) defaultBgColor = c;
|
|
2510
|
+
}
|
|
2511
|
+
} else if (key === "cursor") {
|
|
2512
|
+
if (isQuery) {
|
|
2513
|
+
const c = cursorColor ?? defaultFgColor ?? {
|
|
2514
|
+
r: 255,
|
|
2515
|
+
g: 255,
|
|
2516
|
+
b: 255
|
|
2517
|
+
};
|
|
2518
|
+
response.push(`${key}=${formatColorResponse(c)}`);
|
|
2519
|
+
} else if (val === "") cursorColor = null;
|
|
2520
|
+
else {
|
|
2521
|
+
const c = parseColorSpec(val);
|
|
2522
|
+
if (c) cursorColor = c;
|
|
2523
|
+
}
|
|
2524
|
+
} else if (key === "selection_background") {
|
|
2525
|
+
if (isQuery) {
|
|
2526
|
+
const c = highlightBgColor ?? defaultFgColor ?? {
|
|
2527
|
+
r: 255,
|
|
2528
|
+
g: 255,
|
|
2529
|
+
b: 255
|
|
2530
|
+
};
|
|
2531
|
+
response.push(`${key}=${formatColorResponse(c)}`);
|
|
2532
|
+
} else highlightBgColor = val === "" ? null : parseColorSpec(val);
|
|
2533
|
+
} else if (key === "selection_foreground") {
|
|
2534
|
+
if (isQuery) {
|
|
2535
|
+
const c = highlightFgColor ?? defaultBgColor ?? {
|
|
2536
|
+
r: 0,
|
|
2537
|
+
g: 0,
|
|
2538
|
+
b: 0
|
|
2539
|
+
};
|
|
2540
|
+
response.push(`${key}=${formatColorResponse(c)}`);
|
|
2541
|
+
} else highlightFgColor = val === "" ? null : parseColorSpec(val);
|
|
2519
2542
|
}
|
|
2520
|
-
else if (key === "selection_background") if (isQuery) {
|
|
2521
|
-
const c = highlightBgColor ?? defaultFgColor ?? {
|
|
2522
|
-
r: 255,
|
|
2523
|
-
g: 255,
|
|
2524
|
-
b: 255
|
|
2525
|
-
};
|
|
2526
|
-
response.push(`${key}=${formatColorResponse(c)}`);
|
|
2527
|
-
} else highlightBgColor = val === "" ? null : parseColorSpec(val);
|
|
2528
|
-
else if (key === "selection_foreground") if (isQuery) {
|
|
2529
|
-
const c = highlightFgColor ?? defaultBgColor ?? {
|
|
2530
|
-
r: 0,
|
|
2531
|
-
g: 0,
|
|
2532
|
-
b: 0
|
|
2533
|
-
};
|
|
2534
|
-
response.push(`${key}=${formatColorResponse(c)}`);
|
|
2535
|
-
} else highlightFgColor = val === "" ? null : parseColorSpec(val);
|
|
2536
2543
|
}
|
|
2537
2544
|
if (response.length > 0 && onResponse) onResponse(`\x1b]21;${response.join(";")}\x1b\\`);
|
|
2538
2545
|
break;
|
|
@@ -2543,7 +2550,7 @@ function createScreen(options = {}) {
|
|
|
2543
2550
|
const fresh = buildPalette256();
|
|
2544
2551
|
for (const tok of value.split(";")) {
|
|
2545
2552
|
const idx = parseInt(tok, 10);
|
|
2546
|
-
if (!isNaN(idx) && idx >= 0 && idx < 256) palette256[idx] = fresh
|
|
2553
|
+
if (!isNaN(idx) && idx >= 0 && idx < 256) palette256[idx] = itemAt(fresh, idx, "fresh ANSI palette");
|
|
2547
2554
|
}
|
|
2548
2555
|
}
|
|
2549
2556
|
break;
|
|
@@ -2614,14 +2621,11 @@ function createScreen(options = {}) {
|
|
|
2614
2621
|
startCol: curX
|
|
2615
2622
|
});
|
|
2616
2623
|
break;
|
|
2617
|
-
case "C":
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
});
|
|
2623
|
-
break;
|
|
2624
|
-
case "D": break;
|
|
2624
|
+
case "C": semanticZones.push({
|
|
2625
|
+
type: "output",
|
|
2626
|
+
startRow: curY,
|
|
2627
|
+
startCol: curX
|
|
2628
|
+
});
|
|
2625
2629
|
}
|
|
2626
2630
|
break;
|
|
2627
2631
|
case 66:
|
|
@@ -2694,10 +2698,8 @@ function createScreen(options = {}) {
|
|
|
2694
2698
|
advancedClipboard = "";
|
|
2695
2699
|
}
|
|
2696
2700
|
break;
|
|
2697
|
-
case 1337:
|
|
2698
|
-
|
|
2699
|
-
else if (value === "RequestCapabilities" && onResponse) onResponse("\x1B]1337;Capabilities=\x1B\\");
|
|
2700
|
-
break;
|
|
2701
|
+
case 1337: if (value === "ReportCellSize" && onResponse) onResponse("\x1B]1337;ReportCellSize=16;8\x1B\\");
|
|
2702
|
+
else if (value === "RequestCapabilities" && onResponse) onResponse("\x1B]1337;Capabilities=\x1B\\");
|
|
2701
2703
|
}
|
|
2702
2704
|
}
|
|
2703
2705
|
function handleDCS(data) {
|
|
@@ -2705,7 +2707,7 @@ function createScreen(options = {}) {
|
|
|
2705
2707
|
if (match) {
|
|
2706
2708
|
hasSixel = true;
|
|
2707
2709
|
sixelImages.push({
|
|
2708
|
-
data: match
|
|
2710
|
+
data: itemAt(match, 2, "sixel payload capture"),
|
|
2709
2711
|
row: dcsStartRow,
|
|
2710
2712
|
col: dcsStartCol
|
|
2711
2713
|
});
|
|
@@ -2759,6 +2761,8 @@ function createScreen(options = {}) {
|
|
|
2759
2761
|
rightMargin = cols - 1;
|
|
2760
2762
|
attrs = resetAttrs();
|
|
2761
2763
|
charsetG0 = false;
|
|
2764
|
+
charsetG1 = false;
|
|
2765
|
+
activeG1 = false;
|
|
2762
2766
|
curX = 0;
|
|
2763
2767
|
curY = 0;
|
|
2764
2768
|
}
|
|
@@ -2781,7 +2785,9 @@ function createScreen(options = {}) {
|
|
|
2781
2785
|
attrs: resetAttrs(),
|
|
2782
2786
|
originMode: false,
|
|
2783
2787
|
autoWrap: true,
|
|
2784
|
-
charsetG0: false
|
|
2788
|
+
charsetG0: false,
|
|
2789
|
+
charsetG1: false,
|
|
2790
|
+
activeG1: false
|
|
2785
2791
|
};
|
|
2786
2792
|
attrs = resetAttrs();
|
|
2787
2793
|
title = "";
|
|
@@ -2820,6 +2826,8 @@ function createScreen(options = {}) {
|
|
|
2820
2826
|
advancedClipboard = "";
|
|
2821
2827
|
viewportOffset = 0;
|
|
2822
2828
|
charsetG0 = false;
|
|
2829
|
+
charsetG1 = false;
|
|
2830
|
+
activeG1 = false;
|
|
2823
2831
|
clipboard = "";
|
|
2824
2832
|
cwd = "";
|
|
2825
2833
|
notifications = [];
|
|
@@ -3015,6 +3023,12 @@ function createScreen(options = {}) {
|
|
|
3015
3023
|
} else if (code === 13) {
|
|
3016
3024
|
curX = 0;
|
|
3017
3025
|
emitExecute(13);
|
|
3026
|
+
} else if (code === 14) {
|
|
3027
|
+
activeG1 = true;
|
|
3028
|
+
emitExecute(14);
|
|
3029
|
+
} else if (code === 15) {
|
|
3030
|
+
activeG1 = false;
|
|
3031
|
+
emitExecute(15);
|
|
3018
3032
|
} else if (code >= 32) {
|
|
3019
3033
|
let char = ch;
|
|
3020
3034
|
if (code >= 55296 && code <= 56319 && i + 1 < text.length) {
|
|
@@ -3067,7 +3081,9 @@ function createScreen(options = {}) {
|
|
|
3067
3081
|
},
|
|
3068
3082
|
originMode,
|
|
3069
3083
|
autoWrap,
|
|
3070
|
-
charsetG0
|
|
3084
|
+
charsetG0,
|
|
3085
|
+
charsetG1,
|
|
3086
|
+
activeG1
|
|
3071
3087
|
};
|
|
3072
3088
|
parserState = "ground";
|
|
3073
3089
|
emitEsc("7", "");
|
|
@@ -3083,6 +3099,8 @@ function createScreen(options = {}) {
|
|
|
3083
3099
|
originMode = savedState.originMode;
|
|
3084
3100
|
autoWrap = savedState.autoWrap;
|
|
3085
3101
|
charsetG0 = savedState.charsetG0;
|
|
3102
|
+
charsetG1 = savedState.charsetG1;
|
|
3103
|
+
activeG1 = savedState.activeG1;
|
|
3086
3104
|
clampCursor();
|
|
3087
3105
|
parserState = "ground";
|
|
3088
3106
|
emitEsc("8", "");
|
|
@@ -3104,9 +3122,11 @@ function createScreen(options = {}) {
|
|
|
3104
3122
|
parserState = "escape_hash";
|
|
3105
3123
|
} else if (ch === "(") {
|
|
3106
3124
|
escIntermediate = "(";
|
|
3125
|
+
escBuf = "(";
|
|
3107
3126
|
parserState = "escape_charset";
|
|
3108
3127
|
} else if (ch === ")") {
|
|
3109
3128
|
escIntermediate = ")";
|
|
3129
|
+
escBuf = ")";
|
|
3110
3130
|
parserState = "escape_charset";
|
|
3111
3131
|
} else if (ch === "=") {
|
|
3112
3132
|
applicationKeypad = true;
|
|
@@ -3126,17 +3146,19 @@ function createScreen(options = {}) {
|
|
|
3126
3146
|
} else parserState = "ground";
|
|
3127
3147
|
break;
|
|
3128
3148
|
case "escape_charset":
|
|
3129
|
-
|
|
3130
|
-
|
|
3149
|
+
const designator = escBuf === ")" ? ")" : "(";
|
|
3150
|
+
if (designator === ")") charsetG1 = ch === "0";
|
|
3151
|
+
else charsetG0 = ch === "0";
|
|
3152
|
+
escBuf = "";
|
|
3131
3153
|
parserState = "ground";
|
|
3132
|
-
emitEsc(ch,
|
|
3154
|
+
emitEsc(ch, designator);
|
|
3133
3155
|
break;
|
|
3134
3156
|
case "escape_hash":
|
|
3135
3157
|
if (ch === "8") {
|
|
3136
3158
|
const alignCell = emptyCell();
|
|
3137
3159
|
alignCell.char = "E";
|
|
3138
3160
|
for (let r = 0; r < rows; r++) {
|
|
3139
|
-
const row = grid
|
|
3161
|
+
const row = itemAt(grid, r, "selective erase rows");
|
|
3140
3162
|
for (let c = 0; c < cols; c++) row.setCellRaw(c, alignCell);
|
|
3141
3163
|
softWrapped[r] = false;
|
|
3142
3164
|
}
|
|
@@ -3223,7 +3245,6 @@ function createScreen(options = {}) {
|
|
|
3223
3245
|
apcOverflow = false;
|
|
3224
3246
|
}
|
|
3225
3247
|
parserState = "ground";
|
|
3226
|
-
break;
|
|
3227
3248
|
}
|
|
3228
3249
|
}
|
|
3229
3250
|
flushPrintRun();
|
|
@@ -3283,10 +3304,10 @@ function createScreen(options = {}) {
|
|
|
3283
3304
|
const outLine = [];
|
|
3284
3305
|
let tracked = null;
|
|
3285
3306
|
for (let li = 0; li < logicalLines.length; li++) {
|
|
3286
|
-
const line = logicalLines
|
|
3307
|
+
const line = itemAt(logicalLines, li, "reflow logical lines");
|
|
3287
3308
|
let lineLen = line.length;
|
|
3288
3309
|
while (lineLen > 0) {
|
|
3289
|
-
const cell = line
|
|
3310
|
+
const cell = itemAt(line, lineLen - 1, "reflow logical-line cells");
|
|
3290
3311
|
if (cell.char === "" && !cell.wide) lineLen--;
|
|
3291
3312
|
else break;
|
|
3292
3313
|
}
|
|
@@ -3305,7 +3326,7 @@ function createScreen(options = {}) {
|
|
|
3305
3326
|
const row = makeRow(newCols);
|
|
3306
3327
|
let col = 0;
|
|
3307
3328
|
while (col < newCols && pos < lineLen) {
|
|
3308
|
-
const cell = line
|
|
3329
|
+
const cell = itemAt(line, pos, "reflow logical-line cells");
|
|
3309
3330
|
if (cell.wide && col + 2 > newCols) break;
|
|
3310
3331
|
if (track?.line === li && pos === track.offset) tracked = {
|
|
3311
3332
|
row: outRows.length,
|
|
@@ -3351,14 +3372,11 @@ function createScreen(options = {}) {
|
|
|
3351
3372
|
*/
|
|
3352
3373
|
function trimTrailingEmptyRows(result) {
|
|
3353
3374
|
const floor = result.tracked == null ? 1 : Math.max(1, result.tracked.row + 1);
|
|
3354
|
-
while (result.rows.length > floor) {
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
result.lineIndex?.pop();
|
|
3360
|
-
} else break;
|
|
3361
|
-
}
|
|
3375
|
+
while (result.rows.length > floor) if (packedRowIsBlank(itemAt(result.rows, result.rows.length - 1, "reflow result rows")) && !result.wrapped[result.rows.length - 2]) {
|
|
3376
|
+
result.rows.pop();
|
|
3377
|
+
result.wrapped.pop();
|
|
3378
|
+
result.lineIndex?.pop();
|
|
3379
|
+
} else break;
|
|
3362
3380
|
}
|
|
3363
3381
|
function resize(newCols, newRows) {
|
|
3364
3382
|
if (newCols === cols && newRows === rows) return;
|
|
@@ -3388,7 +3406,7 @@ function createScreen(options = {}) {
|
|
|
3388
3406
|
if (restoredRows.length > 0) {
|
|
3389
3407
|
let completed = 0;
|
|
3390
3408
|
for (const wrapped of restoredWrapped) if (!wrapped) completed++;
|
|
3391
|
-
if (cursorTrack.line === 0 && restoredWrapped[restoredWrapped.length - 1] === true) for (let i = restoredWrapped.length - 1; i >= 0 && restoredWrapped[i]; i--) cursorTrack.offset += restoredRows
|
|
3409
|
+
if (cursorTrack.line === 0 && restoredWrapped[restoredWrapped.length - 1] === true) for (let i = restoredWrapped.length - 1; i >= 0 && restoredWrapped[i]; i--) cursorTrack.offset += itemAt(restoredRows, i, "restored rows").length;
|
|
3392
3410
|
cursorTrack.line += completed;
|
|
3393
3411
|
}
|
|
3394
3412
|
const mainSrc = restoredRows.length > 0 ? [...restoredRows, ...mainGrid] : mainGrid;
|
|
@@ -3410,8 +3428,8 @@ function createScreen(options = {}) {
|
|
|
3410
3428
|
if (overflow !== void 0) bankScrollbackRow(overflow, mainResult.wrapped[r] ?? false, mainLogicalAttrs[mainResult.lineIndex[r] ?? 0] ?? 0);
|
|
3411
3429
|
}
|
|
3412
3430
|
for (let r = 0; r < newRows && mainStartRow + r < mainResult.rows.length; r++) {
|
|
3413
|
-
newMain[r] = mainResult.rows
|
|
3414
|
-
newMainWrapped[r] = mainResult.wrapped
|
|
3431
|
+
newMain[r] = itemAt(mainResult.rows, mainStartRow + r, "resized main rows");
|
|
3432
|
+
newMainWrapped[r] = itemAt(mainResult.wrapped, mainStartRow + r, "resized main wrap flags");
|
|
3415
3433
|
newMainAttrs[r] = mainLogicalAttrs[mainResult.lineIndex[mainStartRow + r] ?? 0] ?? 0;
|
|
3416
3434
|
}
|
|
3417
3435
|
const newAlt = makeGrid(newCols, newRows);
|
|
@@ -3419,8 +3437,8 @@ function createScreen(options = {}) {
|
|
|
3419
3437
|
const newAltAttrs = new Array(newRows).fill(0);
|
|
3420
3438
|
const altStartRow = Math.max(0, altResult.rows.length - newRows);
|
|
3421
3439
|
for (let r = 0; r < newRows && altStartRow + r < altResult.rows.length; r++) {
|
|
3422
|
-
newAlt[r] = altResult.rows
|
|
3423
|
-
newAltWrapped[r] = altResult.wrapped
|
|
3440
|
+
newAlt[r] = itemAt(altResult.rows, altStartRow + r, "resized alternate rows");
|
|
3441
|
+
newAltWrapped[r] = itemAt(altResult.wrapped, altStartRow + r, "resized alternate wrap flags");
|
|
3424
3442
|
newAltAttrs[r] = altLogicalAttrs[altResult.lineIndex[altStartRow + r] ?? 0] ?? 0;
|
|
3425
3443
|
}
|
|
3426
3444
|
const activeResult = useAltScreen ? altResult : mainResult;
|
|
@@ -3492,7 +3510,9 @@ function createScreen(options = {}) {
|
|
|
3492
3510
|
attrs: cloneAttrsSnapshot(savedState.attrs),
|
|
3493
3511
|
originMode: savedState.originMode,
|
|
3494
3512
|
autoWrap: savedState.autoWrap,
|
|
3495
|
-
charsetG0: savedState.charsetG0
|
|
3513
|
+
charsetG0: savedState.charsetG0,
|
|
3514
|
+
charsetG1: savedState.charsetG1,
|
|
3515
|
+
activeG1: savedState.activeG1
|
|
3496
3516
|
},
|
|
3497
3517
|
attrs: cloneAttrsSnapshot(attrs),
|
|
3498
3518
|
modes: {
|
|
@@ -3556,6 +3576,8 @@ function createScreen(options = {}) {
|
|
|
3556
3576
|
},
|
|
3557
3577
|
unicode: {
|
|
3558
3578
|
charsetG0,
|
|
3579
|
+
charsetG1,
|
|
3580
|
+
activeG1,
|
|
3559
3581
|
lastChar,
|
|
3560
3582
|
pendingRegionalIndicator,
|
|
3561
3583
|
afterZWJ
|
|
@@ -3593,7 +3615,9 @@ function createScreen(options = {}) {
|
|
|
3593
3615
|
attrs: cloneAttrsSnapshot(snapshotValue.savedState.attrs),
|
|
3594
3616
|
originMode: snapshotValue.savedState.originMode,
|
|
3595
3617
|
autoWrap: snapshotValue.savedState.autoWrap,
|
|
3596
|
-
charsetG0: snapshotValue.savedState.charsetG0
|
|
3618
|
+
charsetG0: snapshotValue.savedState.charsetG0,
|
|
3619
|
+
charsetG1: snapshotValue.savedState.charsetG1 ?? false,
|
|
3620
|
+
activeG1: snapshotValue.savedState.activeG1 ?? false
|
|
3597
3621
|
};
|
|
3598
3622
|
attrs = cloneAttrsSnapshot(snapshotValue.attrs);
|
|
3599
3623
|
bracketedPaste = snapshotValue.modes.bracketedPaste;
|
|
@@ -3645,6 +3669,8 @@ function createScreen(options = {}) {
|
|
|
3645
3669
|
apcOverflow = snapshotValue.parser.apcOverflow ?? false;
|
|
3646
3670
|
utf8PendingBytes = [...snapshotValue.parser.utf8PendingBytes];
|
|
3647
3671
|
charsetG0 = snapshotValue.unicode.charsetG0;
|
|
3672
|
+
charsetG1 = snapshotValue.unicode.charsetG1 ?? false;
|
|
3673
|
+
activeG1 = snapshotValue.unicode.activeG1 ?? false;
|
|
3648
3674
|
lastChar = snapshotValue.unicode.lastChar;
|
|
3649
3675
|
pendingRegionalIndicator = snapshotValue.unicode.pendingRegionalIndicator;
|
|
3650
3676
|
afterZWJ = snapshotValue.unicode.afterZWJ;
|
|
@@ -3678,7 +3704,7 @@ function createScreen(options = {}) {
|
|
|
3678
3704
|
}
|
|
3679
3705
|
function getText() {
|
|
3680
3706
|
const lines = [];
|
|
3681
|
-
for (let r = 0; r < rows; r++) lines.push(rowToString(grid
|
|
3707
|
+
for (let r = 0; r < rows; r++) lines.push(rowToString(itemAt(grid, r, "screen text rows")));
|
|
3682
3708
|
return lines.join("\n");
|
|
3683
3709
|
}
|
|
3684
3710
|
function getScrollbackText() {
|
|
@@ -3697,7 +3723,7 @@ function createScreen(options = {}) {
|
|
|
3697
3723
|
}
|
|
3698
3724
|
function getRowAbsolute(row) {
|
|
3699
3725
|
if (row < 0 || row >= scrollback.length + rows) return makeRow(cols).toCells();
|
|
3700
|
-
return (row < scrollback.length ? scrollback
|
|
3726
|
+
return (row < scrollback.length ? itemAt(scrollback, row, "scrollback rows") : itemAt(grid, row - scrollback.length, "screen rows")).toCells().map(stripCellColorIndex);
|
|
3701
3727
|
}
|
|
3702
3728
|
function firstRetainedRow() {
|
|
3703
3729
|
return trimmedRowCount;
|
|
@@ -4267,7 +4293,7 @@ function serializeSnapshot(snapshot, options = {}) {
|
|
|
4267
4293
|
const wraps = snapshot.scrollbackSoftWrapped;
|
|
4268
4294
|
const last = snapshot.scrollback.length - 1;
|
|
4269
4295
|
for (let i = 0; i < snapshot.scrollback.length; i++) {
|
|
4270
|
-
const row = snapshot.scrollback
|
|
4296
|
+
const row = itemAt(snapshot.scrollback, i, "snapshot scrollback rows");
|
|
4271
4297
|
if (wraps?.[i] === true && i < last) out.push(serializeEncodeRow(row, hyperlinks, snapshot.cols), "\x1B[0m");
|
|
4272
4298
|
else out.push(serializeEncodeRow(row, hyperlinks), "\x1B[0m\r\n");
|
|
4273
4299
|
}
|
|
@@ -4306,6 +4332,8 @@ function serializeSnapshot(snapshot, options = {}) {
|
|
|
4306
4332
|
out.push(m.autoWrap ? "\x1B[?7h" : "\x1B[?7l");
|
|
4307
4333
|
if (snapshot.cursor.shape !== "block" || !snapshot.cursor.blinking) out.push(`\x1b[${String(serializeCursorStyleCode(snapshot.cursor.shape, snapshot.cursor.blinking))} q`);
|
|
4308
4334
|
if (snapshot.unicode.charsetG0) out.push("\x1B(0");
|
|
4335
|
+
if (snapshot.unicode.charsetG1) out.push("\x1B)0");
|
|
4336
|
+
if (snapshot.unicode.activeG1) out.push("");
|
|
4309
4337
|
if (m.insert && !excluded.has("insert")) out.push("\x1B[4h");
|
|
4310
4338
|
if (!serializeTabStopsAreDefault(snapshot.tabStops, snapshot.cols)) {
|
|
4311
4339
|
out.push("\x1B[3g");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vterm.js",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "Modern terminal emulator — full VT/ECMA-48/xterm standards coverage. Pure TypeScript, zero dependencies.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ansi",
|
|
@@ -46,5 +46,8 @@
|
|
|
46
46
|
},
|
|
47
47
|
"engines": {
|
|
48
48
|
"node": ">=23.6.0"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsdown"
|
|
49
52
|
}
|
|
50
53
|
}
|