@xterm/xterm 5.4.0-beta.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/LICENSE +21 -0
- package/README.md +235 -0
- package/css/xterm.css +209 -0
- package/lib/xterm.js +2 -0
- package/lib/xterm.js.map +1 -0
- package/package.json +101 -0
- package/src/browser/AccessibilityManager.ts +278 -0
- package/src/browser/Clipboard.ts +93 -0
- package/src/browser/ColorContrastCache.ts +34 -0
- package/src/browser/Lifecycle.ts +33 -0
- package/src/browser/Linkifier2.ts +416 -0
- package/src/browser/LocalizableStrings.ts +12 -0
- package/src/browser/OscLinkProvider.ts +128 -0
- package/src/browser/RenderDebouncer.ts +83 -0
- package/src/browser/Terminal.ts +1317 -0
- package/src/browser/TimeBasedDebouncer.ts +86 -0
- package/src/browser/Types.d.ts +181 -0
- package/src/browser/Viewport.ts +401 -0
- package/src/browser/decorations/BufferDecorationRenderer.ts +134 -0
- package/src/browser/decorations/ColorZoneStore.ts +117 -0
- package/src/browser/decorations/OverviewRulerRenderer.ts +218 -0
- package/src/browser/input/CompositionHelper.ts +246 -0
- package/src/browser/input/Mouse.ts +54 -0
- package/src/browser/input/MoveToCell.ts +249 -0
- package/src/browser/public/Terminal.ts +260 -0
- package/src/browser/renderer/dom/DomRenderer.ts +509 -0
- package/src/browser/renderer/dom/DomRendererRowFactory.ts +526 -0
- package/src/browser/renderer/dom/WidthCache.ts +160 -0
- package/src/browser/renderer/shared/CellColorResolver.ts +137 -0
- package/src/browser/renderer/shared/CharAtlasCache.ts +96 -0
- package/src/browser/renderer/shared/CharAtlasUtils.ts +75 -0
- package/src/browser/renderer/shared/Constants.ts +14 -0
- package/src/browser/renderer/shared/CursorBlinkStateManager.ts +146 -0
- package/src/browser/renderer/shared/CustomGlyphs.ts +687 -0
- package/src/browser/renderer/shared/DevicePixelObserver.ts +41 -0
- package/src/browser/renderer/shared/README.md +1 -0
- package/src/browser/renderer/shared/RendererUtils.ts +58 -0
- package/src/browser/renderer/shared/SelectionRenderModel.ts +91 -0
- package/src/browser/renderer/shared/TextureAtlas.ts +1082 -0
- package/src/browser/renderer/shared/Types.d.ts +173 -0
- package/src/browser/selection/SelectionModel.ts +144 -0
- package/src/browser/selection/Types.d.ts +15 -0
- package/src/browser/services/CharSizeService.ts +102 -0
- package/src/browser/services/CharacterJoinerService.ts +339 -0
- package/src/browser/services/CoreBrowserService.ts +137 -0
- package/src/browser/services/MouseService.ts +46 -0
- package/src/browser/services/RenderService.ts +279 -0
- package/src/browser/services/SelectionService.ts +1031 -0
- package/src/browser/services/Services.ts +147 -0
- package/src/browser/services/ThemeService.ts +237 -0
- package/src/common/CircularList.ts +241 -0
- package/src/common/Clone.ts +23 -0
- package/src/common/Color.ts +357 -0
- package/src/common/CoreTerminal.ts +284 -0
- package/src/common/EventEmitter.ts +78 -0
- package/src/common/InputHandler.ts +3461 -0
- package/src/common/Lifecycle.ts +108 -0
- package/src/common/MultiKeyMap.ts +42 -0
- package/src/common/Platform.ts +44 -0
- package/src/common/SortedList.ts +118 -0
- package/src/common/TaskQueue.ts +166 -0
- package/src/common/TypedArrayUtils.ts +17 -0
- package/src/common/Types.d.ts +553 -0
- package/src/common/WindowsMode.ts +27 -0
- package/src/common/buffer/AttributeData.ts +196 -0
- package/src/common/buffer/Buffer.ts +654 -0
- package/src/common/buffer/BufferLine.ts +524 -0
- package/src/common/buffer/BufferRange.ts +13 -0
- package/src/common/buffer/BufferReflow.ts +223 -0
- package/src/common/buffer/BufferSet.ts +134 -0
- package/src/common/buffer/CellData.ts +94 -0
- package/src/common/buffer/Constants.ts +149 -0
- package/src/common/buffer/Marker.ts +43 -0
- package/src/common/buffer/Types.d.ts +52 -0
- package/src/common/data/Charsets.ts +256 -0
- package/src/common/data/EscapeSequences.ts +153 -0
- package/src/common/input/Keyboard.ts +398 -0
- package/src/common/input/TextDecoder.ts +346 -0
- package/src/common/input/UnicodeV6.ts +145 -0
- package/src/common/input/WriteBuffer.ts +246 -0
- package/src/common/input/XParseColor.ts +80 -0
- package/src/common/parser/Constants.ts +58 -0
- package/src/common/parser/DcsParser.ts +192 -0
- package/src/common/parser/EscapeSequenceParser.ts +792 -0
- package/src/common/parser/OscParser.ts +238 -0
- package/src/common/parser/Params.ts +229 -0
- package/src/common/parser/Types.d.ts +275 -0
- package/src/common/public/AddonManager.ts +53 -0
- package/src/common/public/BufferApiView.ts +35 -0
- package/src/common/public/BufferLineApiView.ts +29 -0
- package/src/common/public/BufferNamespaceApi.ts +36 -0
- package/src/common/public/ParserApi.ts +37 -0
- package/src/common/public/UnicodeApi.ts +27 -0
- package/src/common/services/BufferService.ts +151 -0
- package/src/common/services/CharsetService.ts +34 -0
- package/src/common/services/CoreMouseService.ts +318 -0
- package/src/common/services/CoreService.ts +87 -0
- package/src/common/services/DecorationService.ts +140 -0
- package/src/common/services/InstantiationService.ts +85 -0
- package/src/common/services/LogService.ts +124 -0
- package/src/common/services/OptionsService.ts +202 -0
- package/src/common/services/OscLinkService.ts +115 -0
- package/src/common/services/ServiceRegistry.ts +49 -0
- package/src/common/services/Services.ts +373 -0
- package/src/common/services/UnicodeService.ts +111 -0
- package/src/headless/Terminal.ts +136 -0
- package/src/headless/public/Terminal.ts +195 -0
- package/typings/xterm.d.ts +1857 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
|
3
|
+
* @license MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { IOscHandler, IHandlerCollection, OscFallbackHandlerType, IOscParser, ISubParserStackState } from 'common/parser/Types';
|
|
7
|
+
import { OscState, PAYLOAD_LIMIT } from 'common/parser/Constants';
|
|
8
|
+
import { utf32ToString } from 'common/input/TextDecoder';
|
|
9
|
+
import { IDisposable } from 'common/Types';
|
|
10
|
+
|
|
11
|
+
const EMPTY_HANDLERS: IOscHandler[] = [];
|
|
12
|
+
|
|
13
|
+
export class OscParser implements IOscParser {
|
|
14
|
+
private _state = OscState.START;
|
|
15
|
+
private _active = EMPTY_HANDLERS;
|
|
16
|
+
private _id = -1;
|
|
17
|
+
private _handlers: IHandlerCollection<IOscHandler> = Object.create(null);
|
|
18
|
+
private _handlerFb: OscFallbackHandlerType = () => { };
|
|
19
|
+
private _stack: ISubParserStackState = {
|
|
20
|
+
paused: false,
|
|
21
|
+
loopPosition: 0,
|
|
22
|
+
fallThrough: false
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
public registerHandler(ident: number, handler: IOscHandler): IDisposable {
|
|
26
|
+
if (this._handlers[ident] === undefined) {
|
|
27
|
+
this._handlers[ident] = [];
|
|
28
|
+
}
|
|
29
|
+
const handlerList = this._handlers[ident];
|
|
30
|
+
handlerList.push(handler);
|
|
31
|
+
return {
|
|
32
|
+
dispose: () => {
|
|
33
|
+
const handlerIndex = handlerList.indexOf(handler);
|
|
34
|
+
if (handlerIndex !== -1) {
|
|
35
|
+
handlerList.splice(handlerIndex, 1);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
public clearHandler(ident: number): void {
|
|
41
|
+
if (this._handlers[ident]) delete this._handlers[ident];
|
|
42
|
+
}
|
|
43
|
+
public setHandlerFallback(handler: OscFallbackHandlerType): void {
|
|
44
|
+
this._handlerFb = handler;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public dispose(): void {
|
|
48
|
+
this._handlers = Object.create(null);
|
|
49
|
+
this._handlerFb = () => { };
|
|
50
|
+
this._active = EMPTY_HANDLERS;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public reset(): void {
|
|
54
|
+
// force cleanup handlers if payload was already sent
|
|
55
|
+
if (this._state === OscState.PAYLOAD) {
|
|
56
|
+
for (let j = this._stack.paused ? this._stack.loopPosition - 1 : this._active.length - 1; j >= 0; --j) {
|
|
57
|
+
this._active[j].end(false);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
this._stack.paused = false;
|
|
61
|
+
this._active = EMPTY_HANDLERS;
|
|
62
|
+
this._id = -1;
|
|
63
|
+
this._state = OscState.START;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private _start(): void {
|
|
67
|
+
this._active = this._handlers[this._id] || EMPTY_HANDLERS;
|
|
68
|
+
if (!this._active.length) {
|
|
69
|
+
this._handlerFb(this._id, 'START');
|
|
70
|
+
} else {
|
|
71
|
+
for (let j = this._active.length - 1; j >= 0; j--) {
|
|
72
|
+
this._active[j].start();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private _put(data: Uint32Array, start: number, end: number): void {
|
|
78
|
+
if (!this._active.length) {
|
|
79
|
+
this._handlerFb(this._id, 'PUT', utf32ToString(data, start, end));
|
|
80
|
+
} else {
|
|
81
|
+
for (let j = this._active.length - 1; j >= 0; j--) {
|
|
82
|
+
this._active[j].put(data, start, end);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public start(): void {
|
|
88
|
+
// always reset leftover handlers
|
|
89
|
+
this.reset();
|
|
90
|
+
this._state = OscState.ID;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Put data to current OSC command.
|
|
95
|
+
* Expects the identifier of the OSC command in the form
|
|
96
|
+
* OSC id ; payload ST/BEL
|
|
97
|
+
* Payload chunks are not further processed and get
|
|
98
|
+
* directly passed to the handlers.
|
|
99
|
+
*/
|
|
100
|
+
public put(data: Uint32Array, start: number, end: number): void {
|
|
101
|
+
if (this._state === OscState.ABORT) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (this._state === OscState.ID) {
|
|
105
|
+
while (start < end) {
|
|
106
|
+
const code = data[start++];
|
|
107
|
+
if (code === 0x3b) {
|
|
108
|
+
this._state = OscState.PAYLOAD;
|
|
109
|
+
this._start();
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
if (code < 0x30 || 0x39 < code) {
|
|
113
|
+
this._state = OscState.ABORT;
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (this._id === -1) {
|
|
117
|
+
this._id = 0;
|
|
118
|
+
}
|
|
119
|
+
this._id = this._id * 10 + code - 48;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (this._state === OscState.PAYLOAD && end - start > 0) {
|
|
123
|
+
this._put(data, start, end);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Indicates end of an OSC command.
|
|
129
|
+
* Whether the OSC got aborted or finished normally
|
|
130
|
+
* is indicated by `success`.
|
|
131
|
+
*/
|
|
132
|
+
public end(success: boolean, promiseResult: boolean = true): void | Promise<boolean> {
|
|
133
|
+
if (this._state === OscState.START) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
// do nothing if command was faulty
|
|
137
|
+
if (this._state !== OscState.ABORT) {
|
|
138
|
+
// if we are still in ID state and get an early end
|
|
139
|
+
// means that the command has no payload thus we still have
|
|
140
|
+
// to announce START and send END right after
|
|
141
|
+
if (this._state === OscState.ID) {
|
|
142
|
+
this._start();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (!this._active.length) {
|
|
146
|
+
this._handlerFb(this._id, 'END', success);
|
|
147
|
+
} else {
|
|
148
|
+
let handlerResult: boolean | Promise<boolean> = false;
|
|
149
|
+
let j = this._active.length - 1;
|
|
150
|
+
let fallThrough = false;
|
|
151
|
+
if (this._stack.paused) {
|
|
152
|
+
j = this._stack.loopPosition - 1;
|
|
153
|
+
handlerResult = promiseResult;
|
|
154
|
+
fallThrough = this._stack.fallThrough;
|
|
155
|
+
this._stack.paused = false;
|
|
156
|
+
}
|
|
157
|
+
if (!fallThrough && handlerResult === false) {
|
|
158
|
+
for (; j >= 0; j--) {
|
|
159
|
+
handlerResult = this._active[j].end(success);
|
|
160
|
+
if (handlerResult === true) {
|
|
161
|
+
break;
|
|
162
|
+
} else if (handlerResult instanceof Promise) {
|
|
163
|
+
this._stack.paused = true;
|
|
164
|
+
this._stack.loopPosition = j;
|
|
165
|
+
this._stack.fallThrough = false;
|
|
166
|
+
return handlerResult;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
j--;
|
|
170
|
+
}
|
|
171
|
+
// cleanup left over handlers
|
|
172
|
+
// we always have to call .end for proper cleanup,
|
|
173
|
+
// here we use `success` to indicate whether a handler should execute
|
|
174
|
+
for (; j >= 0; j--) {
|
|
175
|
+
handlerResult = this._active[j].end(false);
|
|
176
|
+
if (handlerResult instanceof Promise) {
|
|
177
|
+
this._stack.paused = true;
|
|
178
|
+
this._stack.loopPosition = j;
|
|
179
|
+
this._stack.fallThrough = true;
|
|
180
|
+
return handlerResult;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
}
|
|
186
|
+
this._active = EMPTY_HANDLERS;
|
|
187
|
+
this._id = -1;
|
|
188
|
+
this._state = OscState.START;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Convenient class to allow attaching string based handler functions
|
|
194
|
+
* as OSC handlers.
|
|
195
|
+
*/
|
|
196
|
+
export class OscHandler implements IOscHandler {
|
|
197
|
+
private _data = '';
|
|
198
|
+
private _hitLimit: boolean = false;
|
|
199
|
+
|
|
200
|
+
constructor(private _handler: (data: string) => boolean | Promise<boolean>) { }
|
|
201
|
+
|
|
202
|
+
public start(): void {
|
|
203
|
+
this._data = '';
|
|
204
|
+
this._hitLimit = false;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
public put(data: Uint32Array, start: number, end: number): void {
|
|
208
|
+
if (this._hitLimit) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
this._data += utf32ToString(data, start, end);
|
|
212
|
+
if (this._data.length > PAYLOAD_LIMIT) {
|
|
213
|
+
this._data = '';
|
|
214
|
+
this._hitLimit = true;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
public end(success: boolean): boolean | Promise<boolean> {
|
|
219
|
+
let ret: boolean | Promise<boolean> = false;
|
|
220
|
+
if (this._hitLimit) {
|
|
221
|
+
ret = false;
|
|
222
|
+
} else if (success) {
|
|
223
|
+
ret = this._handler(this._data);
|
|
224
|
+
if (ret instanceof Promise) {
|
|
225
|
+
// need to hold data until `ret` got resolved
|
|
226
|
+
// dont care for errors, data will be freed anyway on next start
|
|
227
|
+
return ret.then(res => {
|
|
228
|
+
this._data = '';
|
|
229
|
+
this._hitLimit = false;
|
|
230
|
+
return res;
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
this._data = '';
|
|
235
|
+
this._hitLimit = false;
|
|
236
|
+
return ret;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
|
3
|
+
* @license MIT
|
|
4
|
+
*/
|
|
5
|
+
import { IParams, ParamsArray } from 'common/parser/Types';
|
|
6
|
+
|
|
7
|
+
// max value supported for a single param/subparam (clamped to positive int32 range)
|
|
8
|
+
const MAX_VALUE = 0x7FFFFFFF;
|
|
9
|
+
// max allowed subparams for a single sequence (hardcoded limitation)
|
|
10
|
+
const MAX_SUBPARAMS = 256;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Params storage class.
|
|
14
|
+
* This type is used by the parser to accumulate sequence parameters and sub parameters
|
|
15
|
+
* and transmit them to the input handler actions.
|
|
16
|
+
*
|
|
17
|
+
* NOTES:
|
|
18
|
+
* - params object for action handlers is borrowed, use `.toArray` or `.clone` to get a copy
|
|
19
|
+
* - never read beyond `params.length - 1` (likely to contain arbitrary data)
|
|
20
|
+
* - `.getSubParams` returns a borrowed typed array, use `.getSubParamsAll` for cloned sub params
|
|
21
|
+
* - hardcoded limitations:
|
|
22
|
+
* - max. value for a single (sub) param is 2^31 - 1 (greater values are clamped to that)
|
|
23
|
+
* - max. 256 sub params possible
|
|
24
|
+
* - negative values are not allowed beside -1 (placeholder for default value)
|
|
25
|
+
*
|
|
26
|
+
* About ZDM (Zero Default Mode):
|
|
27
|
+
* ZDM is not orchestrated by this class. If the parser is in ZDM,
|
|
28
|
+
* it should add 0 for empty params, otherwise -1. This does not apply
|
|
29
|
+
* to subparams, empty subparams should always be added with -1.
|
|
30
|
+
*/
|
|
31
|
+
export class Params implements IParams {
|
|
32
|
+
// params store and length
|
|
33
|
+
public params: Int32Array;
|
|
34
|
+
public length: number;
|
|
35
|
+
|
|
36
|
+
// sub params store and length
|
|
37
|
+
protected _subParams: Int32Array;
|
|
38
|
+
protected _subParamsLength: number;
|
|
39
|
+
|
|
40
|
+
// sub params offsets from param: param idx --> [start, end] offset
|
|
41
|
+
private _subParamsIdx: Uint16Array;
|
|
42
|
+
private _rejectDigits: boolean;
|
|
43
|
+
private _rejectSubDigits: boolean;
|
|
44
|
+
private _digitIsSub: boolean;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Create a `Params` type from JS array representation.
|
|
48
|
+
*/
|
|
49
|
+
public static fromArray(values: ParamsArray): Params {
|
|
50
|
+
const params = new Params();
|
|
51
|
+
if (!values.length) {
|
|
52
|
+
return params;
|
|
53
|
+
}
|
|
54
|
+
// skip leading sub params
|
|
55
|
+
for (let i = (Array.isArray(values[0])) ? 1 : 0; i < values.length; ++i) {
|
|
56
|
+
const value = values[i];
|
|
57
|
+
if (Array.isArray(value)) {
|
|
58
|
+
for (let k = 0; k < value.length; ++k) {
|
|
59
|
+
params.addSubParam(value[k]);
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
params.addParam(value);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return params;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @param maxLength max length of storable parameters
|
|
70
|
+
* @param maxSubParamsLength max length of storable sub parameters
|
|
71
|
+
*/
|
|
72
|
+
constructor(public maxLength: number = 32, public maxSubParamsLength: number = 32) {
|
|
73
|
+
if (maxSubParamsLength > MAX_SUBPARAMS) {
|
|
74
|
+
throw new Error('maxSubParamsLength must not be greater than 256');
|
|
75
|
+
}
|
|
76
|
+
this.params = new Int32Array(maxLength);
|
|
77
|
+
this.length = 0;
|
|
78
|
+
this._subParams = new Int32Array(maxSubParamsLength);
|
|
79
|
+
this._subParamsLength = 0;
|
|
80
|
+
this._subParamsIdx = new Uint16Array(maxLength);
|
|
81
|
+
this._rejectDigits = false;
|
|
82
|
+
this._rejectSubDigits = false;
|
|
83
|
+
this._digitIsSub = false;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Clone object.
|
|
88
|
+
*/
|
|
89
|
+
public clone(): Params {
|
|
90
|
+
const newParams = new Params(this.maxLength, this.maxSubParamsLength);
|
|
91
|
+
newParams.params.set(this.params);
|
|
92
|
+
newParams.length = this.length;
|
|
93
|
+
newParams._subParams.set(this._subParams);
|
|
94
|
+
newParams._subParamsLength = this._subParamsLength;
|
|
95
|
+
newParams._subParamsIdx.set(this._subParamsIdx);
|
|
96
|
+
newParams._rejectDigits = this._rejectDigits;
|
|
97
|
+
newParams._rejectSubDigits = this._rejectSubDigits;
|
|
98
|
+
newParams._digitIsSub = this._digitIsSub;
|
|
99
|
+
return newParams;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Get a JS array representation of the current parameters and sub parameters.
|
|
104
|
+
* The array is structured as follows:
|
|
105
|
+
* sequence: "1;2:3:4;5::6"
|
|
106
|
+
* array : [1, 2, [3, 4], 5, [-1, 6]]
|
|
107
|
+
*/
|
|
108
|
+
public toArray(): ParamsArray {
|
|
109
|
+
const res: ParamsArray = [];
|
|
110
|
+
for (let i = 0; i < this.length; ++i) {
|
|
111
|
+
res.push(this.params[i]);
|
|
112
|
+
const start = this._subParamsIdx[i] >> 8;
|
|
113
|
+
const end = this._subParamsIdx[i] & 0xFF;
|
|
114
|
+
if (end - start > 0) {
|
|
115
|
+
res.push(Array.prototype.slice.call(this._subParams, start, end));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return res;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Reset to initial empty state.
|
|
123
|
+
*/
|
|
124
|
+
public reset(): void {
|
|
125
|
+
this.length = 0;
|
|
126
|
+
this._subParamsLength = 0;
|
|
127
|
+
this._rejectDigits = false;
|
|
128
|
+
this._rejectSubDigits = false;
|
|
129
|
+
this._digitIsSub = false;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Add a parameter value.
|
|
134
|
+
* `Params` only stores up to `maxLength` parameters, any later
|
|
135
|
+
* parameter will be ignored.
|
|
136
|
+
* Note: VT devices only stored up to 16 values, xterm seems to
|
|
137
|
+
* store up to 30.
|
|
138
|
+
*/
|
|
139
|
+
public addParam(value: number): void {
|
|
140
|
+
this._digitIsSub = false;
|
|
141
|
+
if (this.length >= this.maxLength) {
|
|
142
|
+
this._rejectDigits = true;
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (value < -1) {
|
|
146
|
+
throw new Error('values lesser than -1 are not allowed');
|
|
147
|
+
}
|
|
148
|
+
this._subParamsIdx[this.length] = this._subParamsLength << 8 | this._subParamsLength;
|
|
149
|
+
this.params[this.length++] = value > MAX_VALUE ? MAX_VALUE : value;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Add a sub parameter value.
|
|
154
|
+
* The sub parameter is automatically associated with the last parameter value.
|
|
155
|
+
* Thus it is not possible to add a subparameter without any parameter added yet.
|
|
156
|
+
* `Params` only stores up to `subParamsLength` sub parameters, any later
|
|
157
|
+
* sub parameter will be ignored.
|
|
158
|
+
*/
|
|
159
|
+
public addSubParam(value: number): void {
|
|
160
|
+
this._digitIsSub = true;
|
|
161
|
+
if (!this.length) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (this._rejectDigits || this._subParamsLength >= this.maxSubParamsLength) {
|
|
165
|
+
this._rejectSubDigits = true;
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (value < -1) {
|
|
169
|
+
throw new Error('values lesser than -1 are not allowed');
|
|
170
|
+
}
|
|
171
|
+
this._subParams[this._subParamsLength++] = value > MAX_VALUE ? MAX_VALUE : value;
|
|
172
|
+
this._subParamsIdx[this.length - 1]++;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Whether parameter at index `idx` has sub parameters.
|
|
177
|
+
*/
|
|
178
|
+
public hasSubParams(idx: number): boolean {
|
|
179
|
+
return ((this._subParamsIdx[idx] & 0xFF) - (this._subParamsIdx[idx] >> 8) > 0);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Return sub parameters for parameter at index `idx`.
|
|
184
|
+
* Note: The values are borrowed, thus you need to copy
|
|
185
|
+
* the values if you need to hold them in nonlocal scope.
|
|
186
|
+
*/
|
|
187
|
+
public getSubParams(idx: number): Int32Array | null {
|
|
188
|
+
const start = this._subParamsIdx[idx] >> 8;
|
|
189
|
+
const end = this._subParamsIdx[idx] & 0xFF;
|
|
190
|
+
if (end - start > 0) {
|
|
191
|
+
return this._subParams.subarray(start, end);
|
|
192
|
+
}
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Return all sub parameters as {idx: subparams} mapping.
|
|
198
|
+
* Note: The values are not borrowed.
|
|
199
|
+
*/
|
|
200
|
+
public getSubParamsAll(): {[idx: number]: Int32Array} {
|
|
201
|
+
const result: {[idx: number]: Int32Array} = {};
|
|
202
|
+
for (let i = 0; i < this.length; ++i) {
|
|
203
|
+
const start = this._subParamsIdx[i] >> 8;
|
|
204
|
+
const end = this._subParamsIdx[i] & 0xFF;
|
|
205
|
+
if (end - start > 0) {
|
|
206
|
+
result[i] = this._subParams.slice(start, end);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return result;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Add a single digit value to current parameter.
|
|
214
|
+
* This is used by the parser to account digits on a char by char basis.
|
|
215
|
+
*/
|
|
216
|
+
public addDigit(value: number): void {
|
|
217
|
+
let length;
|
|
218
|
+
if (this._rejectDigits
|
|
219
|
+
|| !(length = this._digitIsSub ? this._subParamsLength : this.length)
|
|
220
|
+
|| (this._digitIsSub && this._rejectSubDigits)
|
|
221
|
+
) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const store = this._digitIsSub ? this._subParams : this.params;
|
|
226
|
+
const cur = store[length - 1];
|
|
227
|
+
store[length - 1] = ~cur ? Math.min(cur * 10 + value, MAX_VALUE) : value;
|
|
228
|
+
}
|
|
229
|
+
}
|