@xterm/xterm 6.1.0-beta.211 → 6.1.0-beta.212

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xterm/xterm",
3
3
  "description": "Full xterm terminal, in your browser",
4
- "version": "6.1.0-beta.211",
4
+ "version": "6.1.0-beta.212",
5
5
  "main": "lib/xterm.js",
6
6
  "module": "lib/xterm.mjs",
7
7
  "style": "css/xterm.css",
@@ -66,7 +66,7 @@
66
66
  "benchmark-baseline": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json --baseline out-test/benchmark/*benchmark.js",
67
67
  "benchmark-eval": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json --eval out-test/benchmark/*benchmark.js",
68
68
  "clean": "rm -rf lib out addons/*/lib addons/*/out",
69
- "vtfeatures": "node bin/extract_vtfeatures.js src/**/*.ts src/*.ts",
69
+ "vtfeatures": "node bin/extract_vtfeatures.js src/*/*.ts src/*/*/*.ts src/*.ts addons/**/src/*.ts",
70
70
  "prepackage": "npm run build",
71
71
  "package": "webpack",
72
72
  "postpackage": "npm run esbuild-package",
@@ -119,5 +119,5 @@
119
119
  "ws": "^8.2.3",
120
120
  "xterm-benchmark": "^0.3.1"
121
121
  },
122
- "commit": "605a7c6e3020b23155ad0544c3e56e88dd295c20"
122
+ "commit": "874e767b4022a85d9bd7f8d9780f0812efe49fb6"
123
123
  }
@@ -243,8 +243,8 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
243
243
  }
244
244
 
245
245
  /** Add handler for APC escape sequence. See xterm.d.ts for details. */
246
- public registerApcHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable {
247
- return this._inputHandler.registerApcHandler(ident, callback);
246
+ public registerApcHandler(id: IFunctionIdentifier, callback: (data: string) => boolean | Promise<boolean>): IDisposable {
247
+ return this._inputHandler.registerApcHandler(id, callback);
248
248
  }
249
249
 
250
250
  protected _setup(): void {
@@ -30,28 +30,9 @@ import { XTERM_VERSION } from 'common/Version';
30
30
  */
31
31
  const GLEVEL: { [key: string]: number } = { '(': 0, ')': 1, '*': 2, '+': 3, '-': 1, '.': 2 };
32
32
 
33
- /**
34
- * VT commands done by the parser - FIXME: move this to the parser?
35
- */
36
- // @vt: #Y ESC CSI "Control Sequence Introducer" "ESC [" "Start of a CSI sequence."
37
- // @vt: #Y ESC OSC "Operating System Command" "ESC ]" "Start of an OSC sequence."
38
- // @vt: #Y ESC DCS "Device Control String" "ESC P" "Start of a DCS sequence."
39
- // @vt: #Y ESC ST "String Terminator" "ESC \" "Terminator used for string type sequences."
40
- // @vt: #Y ESC PM "Privacy Message" "ESC ^" "Start of a privacy message."
41
- // @vt: #Y ESC APC "Application Program Command" "ESC _" "Start of an APC sequence."
42
- // @vt: #Y C1 CSI "Control Sequence Introducer" "\x9B" "Start of a CSI sequence."
43
- // @vt: #Y C1 OSC "Operating System Command" "\x9D" "Start of an OSC sequence."
44
- // @vt: #Y C1 DCS "Device Control String" "\x90" "Start of a DCS sequence."
45
- // @vt: #Y C1 ST "String Terminator" "\x9C" "Terminator used for string type sequences."
46
- // @vt: #Y C1 PM "Privacy Message" "\x9E" "Start of a privacy message."
47
- // @vt: #Y C1 APC "Application Program Command" "\x9F" "Start of an APC sequence."
48
- // @vt: #Y C0 NUL "Null" "\0, \x00" "NUL is ignored."
49
- // @vt: #Y C0 ESC "Escape" "\e, \x1B" "Start of a sequence. Cancels any other sequence."
50
-
51
33
  /**
52
34
  * Document xterm VT features here that are currently unsupported
53
35
  */
54
- // @vt: #E[Supported via @xterm/addon-image.] DCS SIXEL "SIXEL Graphics" "DCS Ps ; Ps ; Ps ; q Pt ST" "Draw SIXEL image."
55
36
  // @vt: #N DCS DECUDK "User Defined Keys" "DCS Ps ; Ps \| Pt ST" "Definitions for user-defined keys."
56
37
  // @vt: #N DCS XTGETTCAP "Request Terminfo String" "DCS + q Pt ST" "Request Terminfo String."
57
38
  // @vt: #N DCS XTSETTCAP "Set Terminfo Data" "DCS + p Pt ST" "Set Terminfo Data."
@@ -211,6 +192,9 @@ export class InputHandler extends Disposable implements IInputHandler {
211
192
  }
212
193
  this._logService.debug('Unknown DCS code: ', { identifier: this._parser.identToString(ident), action, payload });
213
194
  });
195
+ this._parser.setApcHandlerFallback((ident, action, payload) => {
196
+ this._logService.debug('Unknown APC code: ', { identifier: this._parser.identToString(ident), action, payload });
197
+ });
214
198
 
215
199
  /**
216
200
  * print handler
@@ -729,8 +713,8 @@ export class InputHandler extends Disposable implements IInputHandler {
729
713
  /**
730
714
  * Forward registerApcHandler from parser.
731
715
  */
732
- public registerApcHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable {
733
- return this._parser.registerApcHandler(ident, new ApcHandler(callback));
716
+ public registerApcHandler(id: IFunctionIdentifier, callback: (data: string) => boolean | Promise<boolean>): IDisposable {
717
+ return this._parser.registerApcHandler(id, new ApcHandler(callback));
734
718
  }
735
719
 
736
720
  /**
@@ -22,7 +22,7 @@ export interface ICoreTerminal {
22
22
  registerDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean | Promise<boolean>): IDisposable;
23
23
  registerEscHandler(id: IFunctionIdentifier, callback: () => boolean | Promise<boolean>): IDisposable;
24
24
  registerOscHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable;
25
- registerApcHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable;
25
+ registerApcHandler(id: IFunctionIdentifier, callback: (data: string) => boolean | Promise<boolean>): IDisposable;
26
26
  }
27
27
 
28
28
  export interface IDisposable {
@@ -476,7 +476,7 @@ export interface IInputHandler {
476
476
  registerDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean | Promise<boolean>): IDisposable;
477
477
  registerEscHandler(id: IFunctionIdentifier, callback: () => boolean | Promise<boolean>): IDisposable;
478
478
  registerOscHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable;
479
- registerApcHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable;
479
+ registerApcHandler(id: IFunctionIdentifier, callback: (data: string) => boolean | Promise<boolean>): IDisposable;
480
480
 
481
481
  /** C0 BEL */ bell(): boolean;
482
482
  /** C0 LF */ lineFeed(): boolean;
@@ -6,4 +6,4 @@
6
6
  /**
7
7
  * The xterm.js version. This is updated by the publish script from package.json.
8
8
  */
9
- export const XTERM_VERSION = '6.1.0-beta.211';
9
+ export const XTERM_VERSION = '6.1.0-beta.212';
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { IApcHandler, IHandlerCollection, ApcFallbackHandlerType, IApcParser, ISubParserStackState } from 'common/parser/Types';
7
- import { ApcState, ParserConstants } from 'common/parser/Constants';
7
+ import { ParserConstants } from 'common/parser/Constants';
8
8
  import { utf32ToString } from 'common/input/TextDecoder';
9
9
  import { IDisposable } from 'common/Types';
10
10
 
@@ -19,10 +19,9 @@ const EMPTY_HANDLERS: IApcHandler[] = [];
19
19
  * The identifier is the character code of the first byte after ESC _.
20
20
  */
21
21
  export class ApcParser implements IApcParser {
22
- private _state = ApcState.START;
23
- private _active = EMPTY_HANDLERS;
24
- private _id = -1;
25
22
  private _handlers: IHandlerCollection<IApcHandler> = Object.create(null);
23
+ private _active = EMPTY_HANDLERS;
24
+ private _ident: number = 0;
26
25
  private _handlerFb: ApcFallbackHandlerType = () => { };
27
26
  private _stack: ISubParserStackState = {
28
27
  paused: false,
@@ -64,22 +63,24 @@ export class ApcParser implements IApcParser {
64
63
  }
65
64
 
66
65
  public reset(): void {
67
- // force cleanup handlers if payload was already sent
68
- if (this._state === ApcState.PAYLOAD) {
66
+ // force cleanup handlers
67
+ if (this._active.length) {
69
68
  for (let j = this._stack.paused ? this._stack.loopPosition - 1 : this._active.length - 1; j >= 0; --j) {
70
69
  this._active[j].end(false);
71
70
  }
72
71
  }
73
72
  this._stack.paused = false;
74
73
  this._active = EMPTY_HANDLERS;
75
- this._id = -1;
76
- this._state = ApcState.START;
74
+ this._ident = 0;
77
75
  }
78
76
 
79
- private _start(): void {
80
- this._active = this._handlers[this._id] || EMPTY_HANDLERS;
77
+ public start(ident: number): void {
78
+ // always reset leftover handlers
79
+ this.reset();
80
+ this._ident = ident;
81
+ this._active = this._handlers[ident] || EMPTY_HANDLERS;
81
82
  if (!this._active.length) {
82
- this._handlerFb(this._id, 'START');
83
+ this._handlerFb(this._ident, 'START');
83
84
  } else {
84
85
  for (let j = this._active.length - 1; j >= 0; j--) {
85
86
  this._active[j].start();
@@ -87,9 +88,9 @@ export class ApcParser implements IApcParser {
87
88
  }
88
89
  }
89
90
 
90
- private _put(data: Uint32Array, start: number, end: number): void {
91
+ public put(data: Uint32Array, start: number, end: number): void {
91
92
  if (!this._active.length) {
92
- this._handlerFb(this._id, 'PUT', utf32ToString(data, start, end));
93
+ this._handlerFb(this._ident, 'PUT', utf32ToString(data, start, end));
93
94
  } else {
94
95
  for (let j = this._active.length - 1; j >= 0; j--) {
95
96
  this._active[j].put(data, start, end);
@@ -97,100 +98,51 @@ export class ApcParser implements IApcParser {
97
98
  }
98
99
  }
99
100
 
100
- public start(): void {
101
- // always reset leftover handlers
102
- this.reset();
103
- this._state = ApcState.ID;
104
- }
105
-
106
- /**
107
- * Put data to current APC command.
108
- * For APC, the first character is used as the identifier.
109
- * Format: ESC _ <identifier><payload> ESC \
110
- * Example: ESC _ G f=100,a=T;... ESC \ (Kitty graphics, identifier='G')
111
- */
112
- public put(data: Uint32Array, start: number, end: number): void {
113
- if (this._state === ApcState.ABORT) {
114
- return;
115
- }
116
- if (this._state === ApcState.ID) {
117
- // The first character is the identifier
118
- if (start < end) {
119
- this._id = data[start++];
120
- this._state = ApcState.PAYLOAD;
121
- this._start();
122
- }
123
- }
124
- if (this._state === ApcState.PAYLOAD && end - start > 0) {
125
- this._put(data, start, end);
126
- }
127
- }
128
-
129
101
  /**
130
102
  * Indicates end of an APC command.
131
103
  * Whether the APC got aborted or finished normally
132
104
  * is indicated by `success`.
133
105
  */
134
106
  public end(success: boolean, promiseResult: boolean = true): void | Promise<boolean> {
135
- if (this._state === ApcState.START) {
136
- return;
137
- }
138
- // do nothing if command was faulty
139
- if (this._state !== ApcState.ABORT) {
140
- // if we are still in ID state and get an early end
141
- // means we got an empty APC sequence with no identifier,
142
- // which is invalid - just reset and return
143
- if (this._state === ApcState.ID) {
144
- this._active = EMPTY_HANDLERS;
145
- this._id = -1;
146
- this._state = ApcState.START;
147
- return;
107
+ if (!this._active.length) {
108
+ this._handlerFb(this._ident, 'END', success);
109
+ } else {
110
+ let handlerResult: boolean | Promise<boolean> = false;
111
+ let j = this._active.length - 1;
112
+ let fallThrough = false;
113
+ if (this._stack.paused) {
114
+ j = this._stack.loopPosition - 1;
115
+ handlerResult = promiseResult;
116
+ fallThrough = this._stack.fallThrough;
117
+ this._stack.paused = false;
148
118
  }
149
-
150
- if (!this._active.length) {
151
- this._handlerFb(this._id, 'END', success);
152
- } else {
153
- let handlerResult: boolean | Promise<boolean> = false;
154
- let j = this._active.length - 1;
155
- let fallThrough = false;
156
- if (this._stack.paused) {
157
- j = this._stack.loopPosition - 1;
158
- handlerResult = promiseResult;
159
- fallThrough = this._stack.fallThrough;
160
- this._stack.paused = false;
161
- }
162
- if (!fallThrough && handlerResult === false) {
163
- for (; j >= 0; j--) {
164
- handlerResult = this._active[j].end(success);
165
- if (handlerResult === true) {
166
- break;
167
- } else if (handlerResult instanceof Promise) {
168
- this._stack.paused = true;
169
- this._stack.loopPosition = j;
170
- this._stack.fallThrough = false;
171
- return handlerResult;
172
- }
173
- }
174
- j--;
175
- }
176
- // cleanup left over handlers
177
- // we always have to call .end for proper cleanup,
178
- // here we use `success` to indicate whether a handler should execute
119
+ if (!fallThrough && handlerResult === false) {
179
120
  for (; j >= 0; j--) {
180
- handlerResult = this._active[j].end(false);
181
- if (handlerResult instanceof Promise) {
121
+ handlerResult = this._active[j].end(success);
122
+ if (handlerResult === true) {
123
+ break;
124
+ } else if (handlerResult instanceof Promise) {
182
125
  this._stack.paused = true;
183
126
  this._stack.loopPosition = j;
184
- this._stack.fallThrough = true;
127
+ this._stack.fallThrough = false;
185
128
  return handlerResult;
186
129
  }
187
130
  }
131
+ j--;
132
+ }
133
+ // cleanup left over handlers (fallThrough for async)
134
+ for (; j >= 0; j--) {
135
+ handlerResult = this._active[j].end(false);
136
+ if (handlerResult instanceof Promise) {
137
+ this._stack.paused = true;
138
+ this._stack.loopPosition = j;
139
+ this._stack.fallThrough = true;
140
+ return handlerResult;
141
+ }
188
142
  }
189
-
190
143
  }
191
144
  this._active = EMPTY_HANDLERS;
192
- this._id = -1;
193
- this._state = ApcState.START;
145
+ this._ident = 0;
194
146
  }
195
147
  }
196
148
 
@@ -21,9 +21,11 @@ export const enum ParserState {
21
21
  DCS_IGNORE = 11,
22
22
  DCS_INTERMEDIATE = 12,
23
23
  DCS_PASSTHROUGH = 13,
24
- APC_STRING = 14,
24
+ APC_ENTRY = 14,
25
+ APC_INTERMEDIATE = 15,
26
+ APC_PASSTHROUGH = 16,
25
27
  // Number of states, meaning LAST_STATE + 1.
26
- STATE_LENGTH = 15
28
+ STATE_LENGTH = 17
27
29
  }
28
30
 
29
31
  /**
@@ -60,16 +62,6 @@ export const enum OscState {
60
62
  ABORT = 3
61
63
  }
62
64
 
63
- /**
64
- * Internal states of ApcParser.
65
- */
66
- export const enum ApcState {
67
- START = 0,
68
- ID = 1,
69
- PAYLOAD = 2,
70
- ABORT = 3
71
- }
72
-
73
65
  // payload limit for OSC and DCS
74
66
  export const enum ParserConstants {
75
67
  PAYLOAD_LIMIT = 10000000
@@ -12,6 +12,24 @@ import { OscParser } from 'common/parser/OscParser';
12
12
  import { DcsParser } from 'common/parser/DcsParser';
13
13
  import { ApcParser } from 'common/parser/ApcParser';
14
14
 
15
+ /**
16
+ * VT commands done by the parser
17
+ */
18
+ // @vt: #Y ESC CSI "Control Sequence Introducer" "ESC [" "Start of a CSI sequence."
19
+ // @vt: #Y ESC OSC "Operating System Command" "ESC ]" "Start of an OSC sequence."
20
+ // @vt: #Y ESC DCS "Device Control String" "ESC P" "Start of a DCS sequence."
21
+ // @vt: #Y ESC ST "String Terminator" "ESC \" "Terminator used for string type sequences."
22
+ // @vt: #Y ESC PM "Privacy Message" "ESC ^" "Start of a privacy message."
23
+ // @vt: #Y ESC APC "Application Program Command" "ESC _" "Start of an APC sequence."
24
+ // @vt: #Y C1 CSI "Control Sequence Introducer" "\x9B" "Start of a CSI sequence."
25
+ // @vt: #Y C1 OSC "Operating System Command" "\x9D" "Start of an OSC sequence."
26
+ // @vt: #Y C1 DCS "Device Control String" "\x90" "Start of a DCS sequence."
27
+ // @vt: #Y C1 ST "String Terminator" "\x9C" "Terminator used for string type sequences."
28
+ // @vt: #Y C1 PM "Privacy Message" "\x9E" "Start of a privacy message."
29
+ // @vt: #Y C1 APC "Application Program Command" "\x9F" "Start of an APC sequence."
30
+ // @vt: #Y C0 NUL "Null" "\0, \x00" "NUL is ignored."
31
+ // @vt: #Y C0 ESC "Escape" "\e, \x1B" "Start of a sequence. Cancels any other sequence."
32
+
15
33
  /**
16
34
  * Table values are generated like this:
17
35
  * index: currentState << TableValue.INDEX_STATE_SHIFT | charCode
@@ -77,7 +95,9 @@ const NON_ASCII_PRINTABLE = 0xA0;
77
95
  * Taken from https://vt100.net/emu/dec_ansi_parser.
78
96
  */
79
97
  export const VT500_TRANSITION_TABLE = (function (): TransitionTable {
80
- const table: TransitionTable = new TransitionTable(4095);
98
+ // table size:
99
+ // (ParserState.STATE_LENGTH - 1) << TableAccess.INDEX_STATE_SHIFT | NON_ASCII_PRINTABLE + 1
100
+ const table: TransitionTable = new TransitionTable(4257);
81
101
 
82
102
  // range macro for byte
83
103
  const BYTE_VALUES = 256;
@@ -105,7 +125,7 @@ export const VT500_TRANSITION_TABLE = (function (): TransitionTable {
105
125
  table.add(0x1b, state, ParserAction.CLEAR, ParserState.ESCAPE); // ESC
106
126
  table.add(0x9d, state, ParserAction.OSC_START, ParserState.OSC_STRING); // OSC
107
127
  table.addMany([0x98, 0x9e], state, ParserAction.IGNORE, ParserState.SOS_PM_STRING); // SOS, PM
108
- table.add(0x9f, state, ParserAction.APC_START, ParserState.APC_STRING); // APC
128
+ table.add(0x9f, state, ParserAction.CLEAR, ParserState.APC_ENTRY); // APC
109
129
  table.add(0x9b, state, ParserAction.CLEAR, ParserState.CSI_ENTRY); // CSI
110
130
  table.add(0x90, state, ParserAction.CLEAR, ParserState.DCS_ENTRY); // DCS
111
131
  }
@@ -136,11 +156,20 @@ export const VT500_TRANSITION_TABLE = (function (): TransitionTable {
136
156
  table.add(0x9c, ParserState.SOS_PM_STRING, ParserAction.IGNORE, ParserState.GROUND);
137
157
  table.add(0x7f, ParserState.SOS_PM_STRING, ParserAction.IGNORE, ParserState.SOS_PM_STRING);
138
158
  // apc
139
- table.add(0x5f, ParserState.ESCAPE, ParserAction.APC_START, ParserState.APC_STRING);
140
- table.addMany(PRINTABLES, ParserState.APC_STRING, ParserAction.APC_PUT, ParserState.APC_STRING);
141
- table.addMany(EXECUTABLES, ParserState.APC_STRING, ParserAction.IGNORE, ParserState.APC_STRING);
142
- table.add(0x7f, ParserState.APC_STRING, ParserAction.IGNORE, ParserState.APC_STRING);
143
- table.addMany([0x1b, 0x9c, 0x18, 0x1a], ParserState.APC_STRING, ParserAction.APC_END, ParserState.GROUND);
159
+ table.add(0x5f, ParserState.ESCAPE, ParserAction.CLEAR, ParserState.APC_ENTRY);
160
+ table.addMany(EXECUTABLES, ParserState.APC_ENTRY, ParserAction.IGNORE, ParserState.APC_ENTRY);
161
+ table.add(0x7f, ParserState.APC_ENTRY, ParserAction.IGNORE, ParserState.APC_ENTRY);
162
+ table.addMany(r(0x20, 0x30), ParserState.APC_ENTRY, ParserAction.COLLECT, ParserState.APC_INTERMEDIATE);
163
+ table.addMany(r(0x30, 0x7f), ParserState.APC_ENTRY, ParserAction.APC_START, ParserState.APC_PASSTHROUGH);
164
+ table.addMany(r(0x30, 0x7f), ParserState.APC_INTERMEDIATE, ParserAction.APC_START, ParserState.APC_PASSTHROUGH);
165
+ table.addMany(EXECUTABLES, ParserState.APC_INTERMEDIATE, ParserAction.IGNORE, ParserState.APC_INTERMEDIATE);
166
+ table.addMany(r(0x20, 0x30), ParserState.APC_INTERMEDIATE, ParserAction.COLLECT, ParserState.APC_INTERMEDIATE);
167
+ table.add(0x7f, ParserState.APC_INTERMEDIATE, ParserAction.IGNORE, ParserState.APC_INTERMEDIATE);
168
+ table.addMany(PRINTABLES, ParserState.APC_PASSTHROUGH, ParserAction.APC_PUT, ParserState.APC_PASSTHROUGH);
169
+ table.addMany(EXECUTABLES, ParserState.APC_PASSTHROUGH, ParserAction.IGNORE, ParserState.APC_PASSTHROUGH);
170
+ table.addMany(r(0x08, 0x0e), ParserState.APC_PASSTHROUGH, ParserAction.APC_PUT, ParserState.APC_PASSTHROUGH);
171
+ table.add(0x7f, ParserState.APC_PASSTHROUGH, ParserAction.IGNORE, ParserState.APC_PASSTHROUGH);
172
+ table.addMany([0x1b, 0x9c, 0x18, 0x1a], ParserState.APC_PASSTHROUGH, ParserAction.APC_END, ParserState.GROUND);
144
173
  // csi entries
145
174
  table.add(0x5b, ParserState.ESCAPE, ParserAction.CLEAR, ParserState.CSI_ENTRY);
146
175
  table.addMany(r(0x40, 0x7f), ParserState.CSI_ENTRY, ParserAction.CSI_DISPATCH, ParserState.GROUND);
@@ -169,22 +198,18 @@ export const VT500_TRANSITION_TABLE = (function (): TransitionTable {
169
198
  table.add(0x50, ParserState.ESCAPE, ParserAction.CLEAR, ParserState.DCS_ENTRY);
170
199
  table.addMany(EXECUTABLES, ParserState.DCS_ENTRY, ParserAction.IGNORE, ParserState.DCS_ENTRY);
171
200
  table.add(0x7f, ParserState.DCS_ENTRY, ParserAction.IGNORE, ParserState.DCS_ENTRY);
172
- table.addMany(r(0x1c, 0x20), ParserState.DCS_ENTRY, ParserAction.IGNORE, ParserState.DCS_ENTRY);
173
201
  table.addMany(r(0x20, 0x30), ParserState.DCS_ENTRY, ParserAction.COLLECT, ParserState.DCS_INTERMEDIATE);
174
202
  table.addMany(r(0x30, 0x3c), ParserState.DCS_ENTRY, ParserAction.PARAM, ParserState.DCS_PARAM);
175
203
  table.addMany([0x3c, 0x3d, 0x3e, 0x3f], ParserState.DCS_ENTRY, ParserAction.COLLECT, ParserState.DCS_PARAM);
176
204
  table.addMany(EXECUTABLES, ParserState.DCS_IGNORE, ParserAction.IGNORE, ParserState.DCS_IGNORE);
177
205
  table.addMany(r(0x20, 0x80), ParserState.DCS_IGNORE, ParserAction.IGNORE, ParserState.DCS_IGNORE);
178
- table.addMany(r(0x1c, 0x20), ParserState.DCS_IGNORE, ParserAction.IGNORE, ParserState.DCS_IGNORE);
179
206
  table.addMany(EXECUTABLES, ParserState.DCS_PARAM, ParserAction.IGNORE, ParserState.DCS_PARAM);
180
207
  table.add(0x7f, ParserState.DCS_PARAM, ParserAction.IGNORE, ParserState.DCS_PARAM);
181
- table.addMany(r(0x1c, 0x20), ParserState.DCS_PARAM, ParserAction.IGNORE, ParserState.DCS_PARAM);
182
208
  table.addMany(r(0x30, 0x3c), ParserState.DCS_PARAM, ParserAction.PARAM, ParserState.DCS_PARAM);
183
209
  table.addMany([0x3c, 0x3d, 0x3e, 0x3f], ParserState.DCS_PARAM, ParserAction.IGNORE, ParserState.DCS_IGNORE);
184
210
  table.addMany(r(0x20, 0x30), ParserState.DCS_PARAM, ParserAction.COLLECT, ParserState.DCS_INTERMEDIATE);
185
211
  table.addMany(EXECUTABLES, ParserState.DCS_INTERMEDIATE, ParserAction.IGNORE, ParserState.DCS_INTERMEDIATE);
186
212
  table.add(0x7f, ParserState.DCS_INTERMEDIATE, ParserAction.IGNORE, ParserState.DCS_INTERMEDIATE);
187
- table.addMany(r(0x1c, 0x20), ParserState.DCS_INTERMEDIATE, ParserAction.IGNORE, ParserState.DCS_INTERMEDIATE);
188
213
  table.addMany(r(0x20, 0x30), ParserState.DCS_INTERMEDIATE, ParserAction.COLLECT, ParserState.DCS_INTERMEDIATE);
189
214
  table.addMany(r(0x30, 0x40), ParserState.DCS_INTERMEDIATE, ParserAction.IGNORE, ParserState.DCS_IGNORE);
190
215
  table.addMany(r(0x40, 0x7f), ParserState.DCS_INTERMEDIATE, ParserAction.DCS_HOOK, ParserState.DCS_PASSTHROUGH);
@@ -200,7 +225,7 @@ export const VT500_TRANSITION_TABLE = (function (): TransitionTable {
200
225
  table.add(NON_ASCII_PRINTABLE, ParserState.CSI_IGNORE, ParserAction.IGNORE, ParserState.CSI_IGNORE);
201
226
  table.add(NON_ASCII_PRINTABLE, ParserState.DCS_IGNORE, ParserAction.IGNORE, ParserState.DCS_IGNORE);
202
227
  table.add(NON_ASCII_PRINTABLE, ParserState.DCS_PASSTHROUGH, ParserAction.DCS_PUT, ParserState.DCS_PASSTHROUGH);
203
- table.add(NON_ASCII_PRINTABLE, ParserState.APC_STRING, ParserAction.APC_PUT, ParserState.APC_STRING);
228
+ table.add(NON_ASCII_PRINTABLE, ParserState.APC_PASSTHROUGH, ParserAction.APC_PUT, ParserState.APC_PASSTHROUGH);
204
229
  return table;
205
230
  })();
206
231
 
@@ -439,11 +464,13 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
439
464
  this._oscParser.setHandlerFallback(handler);
440
465
  }
441
466
 
442
- public registerApcHandler(ident: number, handler: IApcHandler): IDisposable {
443
- return this._apcParser.registerHandler(ident, handler);
467
+ public registerApcHandler(id: IFunctionIdentifier, handler: IApcHandler): IDisposable {
468
+ id.prefix = undefined; // APC does not support prefix byte
469
+ return this._apcParser.registerHandler(this._identifier(id, [0x30, 0x7e]), handler);
444
470
  }
445
- public clearApcHandler(ident: number): void {
446
- this._apcParser.clearHandler(ident);
471
+ public clearApcHandler(id: IFunctionIdentifier): void {
472
+ id.prefix = undefined; // APC does not support prefix byte
473
+ this._apcParser.clearHandler(this._identifier(id, [0x30, 0x7e]));
447
474
  }
448
475
  public setApcHandlerFallback(handler: ApcFallbackHandlerType): void {
449
476
  this._apcParser.setHandlerFallback(handler);
@@ -719,7 +746,10 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
719
746
  }
720
747
 
721
748
  // normal transition & action lookup
722
- transition = this._transitions.table[this.currentState << TableAccess.INDEX_STATE_SHIFT | (code < 0xa0 ? code : NON_ASCII_PRINTABLE)];
749
+ transition = this._transitions.table[
750
+ this.currentState << TableAccess.INDEX_STATE_SHIFT |
751
+ (code < NON_ASCII_PRINTABLE ? code : NON_ASCII_PRINTABLE)
752
+ ];
723
753
  switch (transition >> TableAccess.TRANSITION_ACTION_SHIFT) {
724
754
  case ParserAction.PRINT:
725
755
  // Note: 0x20 (SP) is included, 0x7F (DEL) is excluded
@@ -872,16 +902,18 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
872
902
  this.precedingJoinState = 0;
873
903
  break;
874
904
  case ParserAction.APC_START:
875
- this._apcParser.start();
905
+ this._apcParser.start(this._collect << 8 | code);
876
906
  break;
877
907
  case ParserAction.APC_PUT:
878
908
  // inner loop - exit APC_PUT: 0x18, 0x1a, 0x1b, 0x9c
909
+ // allowed: 00/08 .. 00/13, 02/00 .. 07/14 + NON_ASCII_PRINTABLE
879
910
  for (let j = i + 1; ; ++j) {
880
- if (j >= length || (code = data[j]) === 0x18 || code === 0x1a || code === 0x1b || code === 0x9c || (code > 0x7f && code < NON_ASCII_PRINTABLE)) {
881
- this._apcParser.put(data, i, j);
882
- i = j - 1;
883
- break;
884
- }
911
+ if (j < length && (
912
+ (data[j] >= 0x20 && data[j] < 0x7f) || (data[j] >= 0x08 && data[j] < 0x0e) || data[j] >= NON_ASCII_PRINTABLE
913
+ )) continue;
914
+ this._apcParser.put(data, i, j);
915
+ i = j - 1;
916
+ break;
885
917
  }
886
918
  break;
887
919
  case ParserAction.APC_END:
@@ -220,8 +220,8 @@ export interface IEscapeSequenceParser extends IDisposable {
220
220
  clearOscHandler(ident: number): void;
221
221
  setOscHandlerFallback(handler: OscFallbackHandlerType): void;
222
222
 
223
- registerApcHandler(ident: number, handler: IApcHandler): IDisposable;
224
- clearApcHandler(ident: number): void;
223
+ registerApcHandler(id: IFunctionIdentifier, handler: IApcHandler): IDisposable;
224
+ clearApcHandler(id: IFunctionIdentifier): void;
225
225
  setApcHandlerFallback(handler: ApcFallbackHandlerType): void;
226
226
 
227
227
  setErrorHandler(handler: (state: IParsingState) => IParsingState): void;
@@ -252,7 +252,7 @@ export interface IDcsParser extends ISubParser<IDcsHandler, DcsFallbackHandlerTy
252
252
  }
253
253
 
254
254
  export interface IApcParser extends ISubParser<IApcHandler, ApcFallbackHandlerType> {
255
- start(): void;
255
+ start(ident: number): void;
256
256
  end(success: boolean, promiseResult?: boolean): void | Promise<boolean>;
257
257
  }
258
258
 
@@ -34,7 +34,7 @@ export class ParserApi implements IParser {
34
34
  public addOscHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable {
35
35
  return this.registerOscHandler(ident, callback);
36
36
  }
37
- public registerApcHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable {
38
- return this._core.registerApcHandler(ident, callback);
37
+ public registerApcHandler(id: IFunctionIdentifier, callback: (data: string) => boolean | Promise<boolean>): IDisposable {
38
+ return this._core.registerApcHandler(id, callback);
39
39
  }
40
40
  }
@@ -1909,12 +1909,12 @@ declare module '@xterm/xterm' {
1909
1909
  prefix?: string;
1910
1910
  /**
1911
1911
  * Optional intermediate bytes, must be in range \x20 .. \x2f.
1912
- * Usable in CSI, DCS and ESC.
1912
+ * Usable in CSI, DCS, ESC and APC.
1913
1913
  */
1914
1914
  intermediates?: string;
1915
1915
  /**
1916
1916
  * Final byte, must be in range \x40 .. \x7e for CSI and DCS,
1917
- * \x30 .. \x7e for ESC.
1917
+ * \x30 .. \x7e for ESC and APC.
1918
1918
  */
1919
1919
  final: string;
1920
1920
  }
@@ -2002,8 +2002,8 @@ declare module '@xterm/xterm' {
2002
2002
 
2003
2003
  /**
2004
2004
  * Adds a handler for APC escape sequences.
2005
- * @param ident The identifier (first character) of the sequence as a
2006
- * character code, e.g. 71 for 'G' (Kitty graphics protocol).
2005
+ * @param id Specifies the function identifier under which the callback
2006
+ * gets registered, e.g. {final: 'G'} for Kitty graphics protocol.
2007
2007
  * @param callback The function to handle the sequence. Note that the
2008
2008
  * function will only be called once if the sequence finished successfully.
2009
2009
  * There is currently no way to intercept smaller data chunks, data chunks
@@ -2016,7 +2016,7 @@ declare module '@xterm/xterm' {
2016
2016
  * handler. The most recently added handler is tried first.
2017
2017
  * @returns An IDisposable you can call to remove this handler.
2018
2018
  */
2019
- registerApcHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable;
2019
+ registerApcHandler(id: IFunctionIdentifier, callback: (data: string) => boolean | Promise<boolean>): IDisposable;
2020
2020
  }
2021
2021
 
2022
2022
  /**