@xterm/xterm 6.1.0-beta.28 → 6.1.0-beta.280

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.
Files changed (181) hide show
  1. package/README.md +62 -38
  2. package/css/xterm.css +29 -22
  3. package/lib/xterm.js +1 -1
  4. package/lib/xterm.js.map +1 -1
  5. package/lib/xterm.mjs +8 -34
  6. package/lib/xterm.mjs.map +4 -4
  7. package/package.json +56 -45
  8. package/src/browser/AccessibilityManager.ts +18 -13
  9. package/src/browser/Clipboard.ts +8 -5
  10. package/src/browser/ColorContrastCache.ts +3 -3
  11. package/src/browser/CoreBrowserTerminal.ts +179 -348
  12. package/src/browser/Dom.ts +178 -0
  13. package/src/browser/Linkifier.ts +14 -14
  14. package/src/browser/OscLinkProvider.ts +86 -18
  15. package/src/browser/RenderDebouncer.ts +7 -9
  16. package/src/browser/TimeBasedDebouncer.ts +12 -5
  17. package/src/browser/Types.ts +16 -14
  18. package/src/browser/Viewport.ts +58 -23
  19. package/src/browser/decorations/BufferDecorationRenderer.ts +3 -3
  20. package/src/browser/decorations/ColorZoneStore.ts +1 -1
  21. package/src/browser/decorations/OverviewRulerRenderer.ts +36 -20
  22. package/src/browser/input/CompositionHelper.ts +47 -11
  23. package/src/browser/input/Mouse.ts +5 -9
  24. package/src/browser/input/MoveToCell.ts +3 -3
  25. package/src/browser/public/Terminal.ts +33 -36
  26. package/src/browser/renderer/dom/DomRenderer.ts +265 -89
  27. package/src/browser/renderer/dom/DomRendererRowFactory.ts +34 -27
  28. package/src/browser/renderer/dom/WidthCache.ts +57 -55
  29. package/src/browser/renderer/shared/Constants.ts +7 -0
  30. package/src/browser/renderer/shared/RendererUtils.ts +1 -1
  31. package/src/browser/renderer/shared/SelectionRenderModel.ts +2 -2
  32. package/src/browser/renderer/shared/TextBlinkStateManager.ts +97 -0
  33. package/src/browser/renderer/shared/Types.ts +10 -4
  34. package/src/browser/scrollable/abstractScrollbar.ts +300 -0
  35. package/src/browser/scrollable/fastDomNode.ts +126 -0
  36. package/src/browser/scrollable/globalPointerMoveMonitor.ts +90 -0
  37. package/src/browser/scrollable/horizontalScrollbar.ts +85 -0
  38. package/src/browser/scrollable/mouseEvent.ts +292 -0
  39. package/src/browser/scrollable/scrollable.ts +486 -0
  40. package/src/browser/scrollable/scrollableElement.ts +581 -0
  41. package/src/browser/scrollable/scrollableElementOptions.ts +161 -0
  42. package/src/browser/scrollable/scrollbarArrow.ts +110 -0
  43. package/src/browser/scrollable/scrollbarState.ts +246 -0
  44. package/src/browser/scrollable/scrollbarVisibilityController.ts +113 -0
  45. package/src/browser/scrollable/touch.ts +485 -0
  46. package/src/browser/scrollable/verticalScrollbar.ts +143 -0
  47. package/src/browser/scrollable/widget.ts +23 -0
  48. package/src/browser/selection/SelectionModel.ts +1 -1
  49. package/src/browser/services/CharSizeService.ts +4 -4
  50. package/src/browser/services/CharacterJoinerService.ts +13 -11
  51. package/src/browser/services/CoreBrowserService.ts +7 -5
  52. package/src/browser/services/KeyboardService.ts +67 -0
  53. package/src/browser/services/LinkProviderService.ts +3 -3
  54. package/src/browser/services/MouseCoordsService.ts +47 -0
  55. package/src/browser/services/MouseService.ts +619 -23
  56. package/src/browser/services/RenderService.ts +33 -21
  57. package/src/browser/services/SelectionService.ts +72 -54
  58. package/src/browser/services/Services.ts +44 -21
  59. package/src/browser/services/ThemeService.ts +9 -9
  60. package/src/common/Async.ts +141 -0
  61. package/src/common/CircularList.ts +24 -3
  62. package/src/common/Color.ts +13 -5
  63. package/src/common/CoreTerminal.ts +61 -35
  64. package/src/common/Event.ts +118 -0
  65. package/src/common/InputHandler.ts +286 -105
  66. package/src/common/Lifecycle.ts +113 -0
  67. package/src/common/Platform.ts +15 -5
  68. package/src/common/SortedList.ts +8 -4
  69. package/src/common/StringBuilder.ts +67 -0
  70. package/src/common/TaskQueue.ts +17 -8
  71. package/src/common/Types.ts +68 -206
  72. package/src/common/Version.ts +1 -1
  73. package/src/common/WindowsMode.ts +2 -2
  74. package/src/common/buffer/AttributeData.ts +3 -2
  75. package/src/common/buffer/Buffer.ts +47 -32
  76. package/src/common/buffer/BufferLine.ts +175 -100
  77. package/src/common/buffer/BufferLineStringCache.ts +69 -0
  78. package/src/common/buffer/BufferReflow.ts +7 -4
  79. package/src/common/buffer/BufferSet.ts +13 -9
  80. package/src/common/buffer/CellData.ts +61 -4
  81. package/src/common/buffer/Constants.ts +13 -13
  82. package/src/common/buffer/Marker.ts +4 -4
  83. package/src/common/buffer/Types.ts +153 -3
  84. package/src/common/data/Charsets.ts +4 -7
  85. package/src/common/data/EscapeSequences.ts +71 -70
  86. package/src/common/input/Keyboard.ts +17 -10
  87. package/src/common/input/KittyKeyboard.ts +526 -0
  88. package/src/common/input/TextDecoder.ts +3 -3
  89. package/src/common/input/UnicodeV6.ts +3 -2
  90. package/src/common/input/Win32InputMode.ts +297 -0
  91. package/src/common/input/WriteBuffer.ts +108 -39
  92. package/src/common/input/XParseColor.ts +2 -2
  93. package/src/common/parser/ApcParser.ts +196 -0
  94. package/src/common/parser/Constants.ts +14 -4
  95. package/src/common/parser/DcsParser.ts +15 -16
  96. package/src/common/parser/EscapeSequenceParser.ts +214 -72
  97. package/src/common/parser/OscParser.ts +14 -15
  98. package/src/common/parser/Params.ts +31 -12
  99. package/src/common/parser/Types.ts +40 -30
  100. package/src/common/public/BufferApiView.ts +3 -3
  101. package/src/common/public/BufferLineApiView.ts +4 -4
  102. package/src/common/public/BufferNamespaceApi.ts +5 -5
  103. package/src/common/public/ParserApi.ts +5 -2
  104. package/src/common/public/UnicodeApi.ts +1 -1
  105. package/src/common/services/BufferService.ts +17 -13
  106. package/src/common/services/CharsetService.ts +6 -2
  107. package/src/common/services/CoreService.ts +23 -10
  108. package/src/common/services/DecorationService.ts +260 -15
  109. package/src/common/services/InstantiationService.ts +2 -2
  110. package/src/common/services/LogService.ts +2 -32
  111. package/src/common/services/{CoreMouseService.ts → MouseStateService.ts} +22 -133
  112. package/src/common/services/OptionsService.ts +17 -7
  113. package/src/common/services/OscLinkService.ts +3 -2
  114. package/src/common/services/ServiceRegistry.ts +14 -8
  115. package/src/common/services/Services.ts +54 -50
  116. package/src/common/services/UnicodeService.ts +6 -11
  117. package/typings/xterm.d.ts +329 -34
  118. package/src/common/Clone.ts +0 -23
  119. package/src/common/TypedArrayUtils.ts +0 -17
  120. package/src/vs/base/browser/browser.ts +0 -141
  121. package/src/vs/base/browser/canIUse.ts +0 -49
  122. package/src/vs/base/browser/dom.ts +0 -2369
  123. package/src/vs/base/browser/fastDomNode.ts +0 -316
  124. package/src/vs/base/browser/globalPointerMoveMonitor.ts +0 -112
  125. package/src/vs/base/browser/iframe.ts +0 -135
  126. package/src/vs/base/browser/keyboardEvent.ts +0 -213
  127. package/src/vs/base/browser/mouseEvent.ts +0 -229
  128. package/src/vs/base/browser/touch.ts +0 -372
  129. package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +0 -303
  130. package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +0 -114
  131. package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +0 -720
  132. package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +0 -165
  133. package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +0 -114
  134. package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +0 -243
  135. package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +0 -118
  136. package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +0 -116
  137. package/src/vs/base/browser/ui/widget.ts +0 -57
  138. package/src/vs/base/browser/window.ts +0 -14
  139. package/src/vs/base/common/arrays.ts +0 -887
  140. package/src/vs/base/common/arraysFind.ts +0 -202
  141. package/src/vs/base/common/assert.ts +0 -71
  142. package/src/vs/base/common/async.ts +0 -1992
  143. package/src/vs/base/common/cancellation.ts +0 -148
  144. package/src/vs/base/common/charCode.ts +0 -450
  145. package/src/vs/base/common/collections.ts +0 -140
  146. package/src/vs/base/common/decorators.ts +0 -130
  147. package/src/vs/base/common/equals.ts +0 -146
  148. package/src/vs/base/common/errors.ts +0 -303
  149. package/src/vs/base/common/event.ts +0 -1778
  150. package/src/vs/base/common/functional.ts +0 -32
  151. package/src/vs/base/common/hash.ts +0 -316
  152. package/src/vs/base/common/iterator.ts +0 -159
  153. package/src/vs/base/common/keyCodes.ts +0 -526
  154. package/src/vs/base/common/keybindings.ts +0 -284
  155. package/src/vs/base/common/lazy.ts +0 -47
  156. package/src/vs/base/common/lifecycle.ts +0 -801
  157. package/src/vs/base/common/linkedList.ts +0 -142
  158. package/src/vs/base/common/map.ts +0 -202
  159. package/src/vs/base/common/numbers.ts +0 -98
  160. package/src/vs/base/common/observable.ts +0 -76
  161. package/src/vs/base/common/observableInternal/api.ts +0 -31
  162. package/src/vs/base/common/observableInternal/autorun.ts +0 -281
  163. package/src/vs/base/common/observableInternal/base.ts +0 -489
  164. package/src/vs/base/common/observableInternal/debugName.ts +0 -145
  165. package/src/vs/base/common/observableInternal/derived.ts +0 -428
  166. package/src/vs/base/common/observableInternal/lazyObservableValue.ts +0 -146
  167. package/src/vs/base/common/observableInternal/logging.ts +0 -328
  168. package/src/vs/base/common/observableInternal/promise.ts +0 -209
  169. package/src/vs/base/common/observableInternal/utils.ts +0 -610
  170. package/src/vs/base/common/platform.ts +0 -281
  171. package/src/vs/base/common/scrollable.ts +0 -522
  172. package/src/vs/base/common/sequence.ts +0 -34
  173. package/src/vs/base/common/stopwatch.ts +0 -43
  174. package/src/vs/base/common/strings.ts +0 -557
  175. package/src/vs/base/common/symbols.ts +0 -9
  176. package/src/vs/base/common/uint.ts +0 -59
  177. package/src/vs/patches/nls.ts +0 -90
  178. package/src/vs/typings/base-common.d.ts +0 -20
  179. package/src/vs/typings/require.d.ts +0 -42
  180. package/src/vs/typings/vscode-globals-nls.d.ts +0 -36
  181. package/src/vs/typings/vscode-globals-product.d.ts +0 -33
@@ -4,53 +4,35 @@
4
4
  * @license MIT
5
5
  */
6
6
 
7
- import { IInputHandler, IAttributeData, IDisposable, IWindowOptions, IColorEvent, IParseStack, ColorIndex, ColorRequestType, SpecialColorIndex } from 'common/Types';
8
- import { C0, C1 } from 'common/data/EscapeSequences';
9
- import { CHARSETS, DEFAULT_CHARSET } from 'common/data/Charsets';
10
- import { EscapeSequenceParser } from 'common/parser/EscapeSequenceParser';
11
- import { Disposable } from 'vs/base/common/lifecycle';
12
- import { StringToUtf32, stringFromCodePoint, Utf8ToUtf32 } from 'common/input/TextDecoder';
13
- import { BufferLine, DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
14
- import { IParsingState, IEscapeSequenceParser, IParams, IFunctionIdentifier } from 'common/parser/Types';
15
- import { NULL_CELL_CODE, NULL_CELL_WIDTH, Attributes, FgFlags, BgFlags, Content, UnderlineStyle } from 'common/buffer/Constants';
16
- import { CellData } from 'common/buffer/CellData';
17
- import { AttributeData } from 'common/buffer/AttributeData';
18
- import { ICoreService, IBufferService, IOptionsService, ILogService, ICoreMouseService, ICharsetService, IUnicodeService, LogLevelEnum, IOscLinkService } from 'common/services/Services';
19
- import { UnicodeService } from 'common/services/UnicodeService';
20
- import { OscHandler } from 'common/parser/OscParser';
21
- import { DcsHandler } from 'common/parser/DcsParser';
22
- import { IBuffer } from 'common/buffer/Types';
23
- import { parseColor } from 'common/input/XParseColor';
24
- import { Emitter } from 'vs/base/common/event';
25
- import { XTERM_VERSION } from 'common/Version';
7
+ import { IInputHandler, IDisposable, IWindowOptions, IColorEvent, IParseStack, ColorIndex, ColorRequestType, SpecialColorIndex } from './Types';
8
+ import { IAttributeData, IBuffer } from './buffer/Types';
9
+ import { C0, C1 } from './data/EscapeSequences';
10
+ import { CHARSETS, DEFAULT_CHARSET } from './data/Charsets';
11
+ import { EscapeSequenceParser } from './parser/EscapeSequenceParser';
12
+ import { Disposable } from './Lifecycle';
13
+ import { StringToUtf32, stringFromCodePoint, Utf8ToUtf32 } from './input/TextDecoder';
14
+ import { BufferLine, DEFAULT_ATTR_DATA } from './buffer/BufferLine';
15
+ import { IParsingState, IEscapeSequenceParser, IParams, IFunctionIdentifier } from './parser/Types';
16
+ import { NULL_CELL_CODE, NULL_CELL_WIDTH, Attributes, FgFlags, BgFlags, Content, UnderlineStyle } from './buffer/Constants';
17
+ import { CellData } from './buffer/CellData';
18
+ import { AttributeData } from './buffer/AttributeData';
19
+ import { ICoreService, IBufferService, IOptionsService, ILogService, IMouseStateService, ICharsetService, IUnicodeService, LogLevelEnum, IOscLinkService } from './services/Services';
20
+ import { UnicodeService } from './services/UnicodeService';
21
+ import { OscHandler } from './parser/OscParser';
22
+ import { DcsHandler } from './parser/DcsParser';
23
+ import { ApcHandler } from './parser/ApcParser';
24
+ import { parseColor } from './input/XParseColor';
25
+ import { Emitter } from './Event';
26
+ import { XTERM_VERSION } from './Version';
26
27
 
27
28
  /**
28
29
  * Map collect to glevel. Used in `selectCharset`.
29
30
  */
30
31
  const GLEVEL: { [key: string]: number } = { '(': 0, ')': 1, '*': 2, '+': 3, '-': 1, '.': 2 };
31
32
 
32
- /**
33
- * VT commands done by the parser - FIXME: move this to the parser?
34
- */
35
- // @vt: #Y ESC CSI "Control Sequence Introducer" "ESC [" "Start of a CSI sequence."
36
- // @vt: #Y ESC OSC "Operating System Command" "ESC ]" "Start of an OSC sequence."
37
- // @vt: #Y ESC DCS "Device Control String" "ESC P" "Start of a DCS sequence."
38
- // @vt: #Y ESC ST "String Terminator" "ESC \" "Terminator used for string type sequences."
39
- // @vt: #Y ESC PM "Privacy Message" "ESC ^" "Start of a privacy message."
40
- // @vt: #Y ESC APC "Application Program Command" "ESC _" "Start of an APC sequence."
41
- // @vt: #Y C1 CSI "Control Sequence Introducer" "\x9B" "Start of a CSI sequence."
42
- // @vt: #Y C1 OSC "Operating System Command" "\x9D" "Start of an OSC sequence."
43
- // @vt: #Y C1 DCS "Device Control String" "\x90" "Start of a DCS sequence."
44
- // @vt: #Y C1 ST "String Terminator" "\x9C" "Terminator used for string type sequences."
45
- // @vt: #Y C1 PM "Privacy Message" "\x9E" "Start of a privacy message."
46
- // @vt: #Y C1 APC "Application Program Command" "\x9F" "Start of an APC sequence."
47
- // @vt: #Y C0 NUL "Null" "\0, \x00" "NUL is ignored."
48
- // @vt: #Y C0 ESC "Escape" "\e, \x1B" "Start of a sequence. Cancels any other sequence."
49
-
50
33
  /**
51
34
  * Document xterm VT features here that are currently unsupported
52
35
  */
53
- // @vt: #E[Supported via @xterm/addon-image.] DCS SIXEL "SIXEL Graphics" "DCS Ps ; Ps ; Ps ; q Pt ST" "Draw SIXEL image."
54
36
  // @vt: #N DCS DECUDK "User Defined Keys" "DCS Ps ; Ps \| Pt ST" "Definitions for user-defined keys."
55
37
  // @vt: #N DCS XTGETTCAP "Request Terminfo String" "DCS + q Pt ST" "Request Terminfo String."
56
38
  // @vt: #N DCS XTSETTCAP "Set Terminfo Data" "DCS + p Pt ST" "Set Terminfo Data."
@@ -59,12 +41,13 @@ const GLEVEL: { [key: string]: number } = { '(': 0, ')': 1, '*': 2, '+': 3, '-':
59
41
  /**
60
42
  * Max length of the UTF32 input buffer. Real memory consumption is 4 times higher.
61
43
  */
62
- const MAX_PARSEBUFFER_LENGTH = 131072;
63
-
64
- /**
65
- * Limit length of title and icon name stacks.
66
- */
67
- const STACK_LIMIT = 10;
44
+ const enum Constants {
45
+ MAX_PARSEBUFFER_LENGTH = 131072,
46
+ /** Limit length of title and icon name stacks. */
47
+ STACK_LIMIT = 10,
48
+ // create a warning log if an async handler takes longer than the limit (in ms)
49
+ SLOW_ASYNC_LIMIT = 5000
50
+ }
68
51
 
69
52
  // map params to window option
70
53
  function paramToWindowOption(n: number, opts: IWindowOptions): boolean {
@@ -103,9 +86,6 @@ export enum WindowsOptionsReportType {
103
86
  GET_CELL_SIZE_PIXELS = 1
104
87
  }
105
88
 
106
- // create a warning log if an async handler takes longer than the limit (in ms)
107
- const SLOW_ASYNC_LIMIT = 5000;
108
-
109
89
  // Work variables to avoid garbage collection
110
90
  let $temp = 0;
111
91
 
@@ -159,6 +139,8 @@ export class InputHandler extends Disposable implements IInputHandler {
159
139
  public readonly onTitleChange = this._onTitleChange.event;
160
140
  private readonly _onColor = this._register(new Emitter<IColorEvent>());
161
141
  public readonly onColor = this._onColor.event;
142
+ private readonly _onRequestColorSchemeQuery = this._register(new Emitter<void>());
143
+ public readonly onRequestColorSchemeQuery = this._onRequestColorSchemeQuery.event;
162
144
 
163
145
  private _parseStack: IParseStack = {
164
146
  paused: false,
@@ -175,7 +157,7 @@ export class InputHandler extends Disposable implements IInputHandler {
175
157
  private readonly _logService: ILogService,
176
158
  private readonly _optionsService: IOptionsService,
177
159
  private readonly _oscLinkService: IOscLinkService,
178
- private readonly _coreMouseService: ICoreMouseService,
160
+ private readonly _mouseStateService: IMouseStateService,
179
161
  private readonly _unicodeService: IUnicodeService,
180
162
  private readonly _parser: IEscapeSequenceParser = new EscapeSequenceParser()
181
163
  ) {
@@ -208,6 +190,9 @@ export class InputHandler extends Disposable implements IInputHandler {
208
190
  }
209
191
  this._logService.debug('Unknown DCS code: ', { identifier: this._parser.identToString(ident), action, payload });
210
192
  });
193
+ this._parser.setApcHandlerFallback((ident, action, payload) => {
194
+ this._logService.debug('Unknown APC code: ', { identifier: this._parser.identToString(ident), action, payload });
195
+ });
211
196
 
212
197
  /**
213
198
  * print handler
@@ -240,6 +225,7 @@ export class InputHandler extends Disposable implements IInputHandler {
240
225
  this._parser.registerCsiHandler({ final: 'T' }, params => this.scrollDown(params));
241
226
  this._parser.registerCsiHandler({ final: 'X' }, params => this.eraseChars(params));
242
227
  this._parser.registerCsiHandler({ final: 'Z' }, params => this.cursorBackwardTab(params));
228
+ this._parser.registerCsiHandler({ final: '^' }, params => this.scrollDown(params));
243
229
  this._parser.registerCsiHandler({ final: '`' }, params => this.charPosAbsolute(params));
244
230
  this._parser.registerCsiHandler({ final: 'a' }, params => this.hPositionRelative(params));
245
231
  this._parser.registerCsiHandler({ final: 'b' }, params => this.repeatPrecedingCharacter(params));
@@ -269,6 +255,12 @@ export class InputHandler extends Disposable implements IInputHandler {
269
255
  this._parser.registerCsiHandler({ intermediates: '$', final: 'p' }, params => this.requestMode(params, true));
270
256
  this._parser.registerCsiHandler({ prefix: '?', intermediates: '$', final: 'p' }, params => this.requestMode(params, false));
271
257
 
258
+ // Kitty keyboard protocol handlers
259
+ this._parser.registerCsiHandler({ prefix: '=', final: 'u' }, params => this.kittyKeyboardSet(params));
260
+ this._parser.registerCsiHandler({ prefix: '?', final: 'u' }, params => this.kittyKeyboardQuery(params));
261
+ this._parser.registerCsiHandler({ prefix: '>', final: 'u' }, params => this.kittyKeyboardPush(params));
262
+ this._parser.registerCsiHandler({ prefix: '<', final: 'u' }, params => this.kittyKeyboardPop(params));
263
+
272
264
  /**
273
265
  * execute handler
274
266
  */
@@ -397,12 +389,23 @@ export class InputHandler extends Disposable implements IInputHandler {
397
389
  private _logSlowResolvingAsync(p: Promise<boolean>): void {
398
390
  // log a limited warning about an async handler taking too long
399
391
  if (this._logService.logLevel <= LogLevelEnum.WARN) {
400
- Promise.race([p, new Promise((res, rej) => setTimeout(() => rej('#SLOW_TIMEOUT'), SLOW_ASYNC_LIMIT))])
401
- .catch(err => {
392
+ let slowTimeout: ReturnType<typeof setTimeout> | undefined;
393
+ const slowPromise = new Promise<never>((_res, rej) => {
394
+ slowTimeout = setTimeout(() => rej('#SLOW_TIMEOUT'), Constants.SLOW_ASYNC_LIMIT);
395
+ });
396
+ Promise.race([p, slowPromise])
397
+ .then(() => {
398
+ if (slowTimeout !== undefined) {
399
+ clearTimeout(slowTimeout);
400
+ }
401
+ }, err => {
402
+ if (slowTimeout !== undefined) {
403
+ clearTimeout(slowTimeout);
404
+ }
402
405
  if (err !== '#SLOW_TIMEOUT') {
403
406
  throw err;
404
407
  }
405
- console.warn(`async parser handler taking longer than ${SLOW_ASYNC_LIMIT} ms`);
408
+ console.warn(`async parser handler taking longer than ${Constants.SLOW_ASYNC_LIMIT} ms`);
406
409
  });
407
410
  }
408
411
  }
@@ -440,8 +443,8 @@ export class InputHandler extends Disposable implements IInputHandler {
440
443
  cursorStartX = this._parseStack.cursorStartX;
441
444
  cursorStartY = this._parseStack.cursorStartY;
442
445
  this._parseStack.paused = false;
443
- if (data.length > MAX_PARSEBUFFER_LENGTH) {
444
- start = this._parseStack.position + MAX_PARSEBUFFER_LENGTH;
446
+ if (data.length > Constants.MAX_PARSEBUFFER_LENGTH) {
447
+ start = this._parseStack.position + Constants.MAX_PARSEBUFFER_LENGTH;
445
448
  }
446
449
  }
447
450
 
@@ -458,8 +461,8 @@ export class InputHandler extends Disposable implements IInputHandler {
458
461
 
459
462
  // resize input buffer if needed
460
463
  if (this._parseBuffer.length < data.length) {
461
- if (this._parseBuffer.length < MAX_PARSEBUFFER_LENGTH) {
462
- this._parseBuffer = new Uint32Array(Math.min(data.length, MAX_PARSEBUFFER_LENGTH));
464
+ if (this._parseBuffer.length < Constants.MAX_PARSEBUFFER_LENGTH) {
465
+ this._parseBuffer = new Uint32Array(Math.min(data.length, Constants.MAX_PARSEBUFFER_LENGTH));
463
466
  }
464
467
  }
465
468
 
@@ -470,9 +473,9 @@ export class InputHandler extends Disposable implements IInputHandler {
470
473
  }
471
474
 
472
475
  // process big data in smaller chunks
473
- if (data.length > MAX_PARSEBUFFER_LENGTH) {
474
- for (let i = start; i < data.length; i += MAX_PARSEBUFFER_LENGTH) {
475
- const end = i + MAX_PARSEBUFFER_LENGTH < data.length ? i + MAX_PARSEBUFFER_LENGTH : data.length;
476
+ if (data.length > Constants.MAX_PARSEBUFFER_LENGTH) {
477
+ for (let i = start; i < data.length; i += Constants.MAX_PARSEBUFFER_LENGTH) {
478
+ const end = i + Constants.MAX_PARSEBUFFER_LENGTH < data.length ? i + Constants.MAX_PARSEBUFFER_LENGTH : data.length;
476
479
  const len = (typeof data === 'string')
477
480
  ? this._stringDecoder.decode(data.substring(i, end), this._parseBuffer)
478
481
  : this._utf8Decoder.decode(data.subarray(i, end), this._parseBuffer);
@@ -520,7 +523,13 @@ export class InputHandler extends Disposable implements IInputHandler {
520
523
  const wraparoundMode = this._coreService.decPrivateModes.wraparound;
521
524
  const insertMode = this._coreService.modes.insertMode;
522
525
  const curAttr = this._curAttrData;
523
- let bufferRow = this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y)!;
526
+ let bufferRow = this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y);
527
+
528
+ // Defensive check: bufferRow can be undefined if a resize occurred mid-write due to async
529
+ // scheduling gaps in WriteBuffer. See https://github.com/xtermjs/xterm.js/issues/5597
530
+ if (!bufferRow) {
531
+ return;
532
+ }
524
533
 
525
534
  this._dirtyRowTracker.markDirty(this._activeBuffer.y);
526
535
 
@@ -533,6 +542,12 @@ export class InputHandler extends Disposable implements IInputHandler {
533
542
  for (let pos = start; pos < end; ++pos) {
534
543
  code = data[pos];
535
544
 
545
+ // Soft hyphen's (U+00AD) behavior is ambiguous and differs across terminals. We opt to treat
546
+ // it as a zero-width hint to text layout engines and simply ignore it.
547
+ if (code === 0xAD) {
548
+ continue;
549
+ }
550
+
536
551
  // get charset replacement character
537
552
  // charset is only defined for ASCII, therefore we only
538
553
  // search for an replacement char if code < 127
@@ -552,8 +567,9 @@ export class InputHandler extends Disposable implements IInputHandler {
552
567
  if (screenReaderMode) {
553
568
  this._onA11yChar.fire(stringFromCodePoint(code));
554
569
  }
555
- if (this._getCurrentLinkId()) {
556
- this._oscLinkService.addLineToLink(this._getCurrentLinkId(), this._activeBuffer.ybase + this._activeBuffer.y);
570
+ const linkId = this._getCurrentLinkId();
571
+ if (linkId) {
572
+ this._oscLinkService.addLineToLink(linkId, this._activeBuffer.ybase + this._activeBuffer.y);
557
573
  }
558
574
 
559
575
  // goto next line if ch would overflow
@@ -579,7 +595,10 @@ export class InputHandler extends Disposable implements IInputHandler {
579
595
  this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y)!.isWrapped = true;
580
596
  }
581
597
  // row changed, get it again
582
- bufferRow = this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y)!;
598
+ bufferRow = this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y);
599
+ if (!bufferRow) {
600
+ return;
601
+ }
583
602
  if (oldWidth > 0 && bufferRow instanceof BufferLine) {
584
603
  // Combining character widens 1 column to 2.
585
604
  // Move old character to next line.
@@ -690,6 +709,13 @@ export class InputHandler extends Disposable implements IInputHandler {
690
709
  return this._parser.registerOscHandler(ident, new OscHandler(callback));
691
710
  }
692
711
 
712
+ /**
713
+ * Forward registerApcHandler from parser.
714
+ */
715
+ public registerApcHandler(id: IFunctionIdentifier, callback: (data: string) => boolean | Promise<boolean>): IDisposable {
716
+ return this._parser.registerApcHandler(id, new ApcHandler(callback));
717
+ }
718
+
693
719
  /**
694
720
  * BEL
695
721
  * Bell (Ctrl-G).
@@ -1147,7 +1173,10 @@ export class InputHandler extends Disposable implements IInputHandler {
1147
1173
  * @param respectProtect Whether to respect the protection attribute (DECSCA).
1148
1174
  */
1149
1175
  private _eraseInBufferLine(y: number, start: number, end: number, clearWrap: boolean = false, respectProtect: boolean = false): void {
1150
- const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!;
1176
+ const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y);
1177
+ if (!line) {
1178
+ return;
1179
+ }
1151
1180
  line.replaceCells(
1152
1181
  start,
1153
1182
  end,
@@ -1217,7 +1246,10 @@ export class InputHandler extends Disposable implements IInputHandler {
1217
1246
  this._eraseInBufferLine(j, 0, this._activeBuffer.x + 1, true, respectProtect);
1218
1247
  if (this._activeBuffer.x + 1 >= this._bufferService.cols) {
1219
1248
  // Deleted entire previous line. This next line can no longer be wrapped.
1220
- this._activeBuffer.lines.get(j + 1)!.isWrapped = false;
1249
+ const nextLine = this._activeBuffer.lines.get(j + 1);
1250
+ if (nextLine) {
1251
+ nextLine.isWrapped = false;
1252
+ }
1221
1253
  }
1222
1254
  while (j--) {
1223
1255
  this._resetBufferLine(j, respectProtect);
@@ -1744,7 +1776,7 @@ export class InputHandler extends Disposable implements IInputHandler {
1744
1776
  * @param term The terminal name to evaluate
1745
1777
  */
1746
1778
  private _is(term: string): boolean {
1747
- return (this._optionsService.rawOptions.termName + '').indexOf(term) === 0;
1779
+ return (this._optionsService.rawOptions.termName + '').startsWith(term);
1748
1780
  }
1749
1781
 
1750
1782
  /**
@@ -1871,7 +1903,7 @@ export class InputHandler extends Disposable implements IInputHandler {
1871
1903
  * | 7 | Auto-wrap Mode (DECAWM). | #Y |
1872
1904
  * | 8 | Auto-repeat Keys (DECARM). Always on. | #N |
1873
1905
  * | 9 | X10 xterm mouse protocol. | #Y |
1874
- * | 12 | Start Blinking Cursor. | #Y |
1906
+ * | 12 | Start Blinking Cursor. | #P[Requires the allowSetCursorBlink quirk option enabled.] |
1875
1907
  * | 25 | Show Cursor (DECTCEM). | #Y |
1876
1908
  * | 45 | Reverse wrap-around. | #Y |
1877
1909
  * | 47 | Use Alternate Screen Buffer. | #Y |
@@ -1924,7 +1956,9 @@ export class InputHandler extends Disposable implements IInputHandler {
1924
1956
  this._coreService.decPrivateModes.wraparound = true;
1925
1957
  break;
1926
1958
  case 12:
1927
- this._optionsService.options.cursorBlink = true;
1959
+ if (this._optionsService.rawOptions.quirks?.allowSetCursorBlink) {
1960
+ this._optionsService.options.cursorBlink = true;
1961
+ }
1928
1962
  break;
1929
1963
  case 45:
1930
1964
  this._coreService.decPrivateModes.reverseWraparound = true;
@@ -1936,19 +1970,19 @@ export class InputHandler extends Disposable implements IInputHandler {
1936
1970
  break;
1937
1971
  case 9: // X10 Mouse
1938
1972
  // no release, no motion, no wheel, no modifiers.
1939
- this._coreMouseService.activeProtocol = 'X10';
1973
+ this._mouseStateService.activeProtocol = 'X10';
1940
1974
  break;
1941
1975
  case 1000: // vt200 mouse
1942
1976
  // no motion.
1943
- this._coreMouseService.activeProtocol = 'VT200';
1977
+ this._mouseStateService.activeProtocol = 'VT200';
1944
1978
  break;
1945
1979
  case 1002: // button event mouse
1946
- this._coreMouseService.activeProtocol = 'DRAG';
1980
+ this._mouseStateService.activeProtocol = 'DRAG';
1947
1981
  break;
1948
1982
  case 1003: // any event mouse
1949
1983
  // any event - sends motion events,
1950
1984
  // even if there is no button held down.
1951
- this._coreMouseService.activeProtocol = 'ANY';
1985
+ this._mouseStateService.activeProtocol = 'ANY';
1952
1986
  break;
1953
1987
  case 1004: // send focusin/focusout events
1954
1988
  // focusin: ^[[I
@@ -1960,13 +1994,13 @@ export class InputHandler extends Disposable implements IInputHandler {
1960
1994
  this._logService.debug('DECSET 1005 not supported (see #2507)');
1961
1995
  break;
1962
1996
  case 1006: // sgr ext mode mouse
1963
- this._coreMouseService.activeEncoding = 'SGR';
1997
+ this._mouseStateService.activeEncoding = 'SGR';
1964
1998
  break;
1965
1999
  case 1015: // urxvt ext mode mouse - removed in #2507
1966
2000
  this._logService.debug('DECSET 1015 not supported (see #2507)');
1967
2001
  break;
1968
2002
  case 1016: // sgr pixels mode mouse
1969
- this._coreMouseService.activeEncoding = 'SGR_PIXELS';
2003
+ this._mouseStateService.activeEncoding = 'SGR_PIXELS';
1970
2004
  break;
1971
2005
  case 25: // show cursor
1972
2006
  this._coreService.isCursorHidden = false;
@@ -1979,6 +2013,12 @@ export class InputHandler extends Disposable implements IInputHandler {
1979
2013
  // FALL-THROUGH
1980
2014
  case 47: // alt screen buffer
1981
2015
  case 1047: // alt screen buffer
2016
+ // Swap kitty keyboard flags: save main, restore alt
2017
+ if (this._optionsService.rawOptions.vtExtensions?.kittyKeyboard) {
2018
+ const state = this._coreService.kittyKeyboard;
2019
+ state.mainFlags = state.flags;
2020
+ state.flags = state.altFlags;
2021
+ }
1982
2022
  this._bufferService.buffers.activateAltBuffer(this._eraseAttrData());
1983
2023
  this._coreService.isCursorInitialized = true;
1984
2024
  this._onRequestRefreshRows.fire(undefined);
@@ -1990,6 +2030,16 @@ export class InputHandler extends Disposable implements IInputHandler {
1990
2030
  case 2026: // synchronized output (https://github.com/contour-terminal/vt-extensions/blob/master/synchronized-output.md)
1991
2031
  this._coreService.decPrivateModes.synchronizedOutput = true;
1992
2032
  break;
2033
+ case 2031: // color scheme updates (https://contour-terminal.org/vt-extensions/color-palette-update-notifications/)
2034
+ if (this._optionsService.rawOptions.vtExtensions?.colorSchemeQuery ?? true) {
2035
+ this._coreService.decPrivateModes.colorSchemeUpdates = true;
2036
+ }
2037
+ break;
2038
+ case 9001: // win32-input-mode (https://github.com/microsoft/terminal/blob/main/doc/specs/%234999%20-%20Improved%20keyboard%20handling%20in%20Conpty.md)
2039
+ if (this._optionsService.rawOptions.vtExtensions?.win32InputMode) {
2040
+ this._coreService.decPrivateModes.win32InputMode = true;
2041
+ }
2042
+ break;
1993
2043
  }
1994
2044
  }
1995
2045
  return true;
@@ -2119,7 +2169,7 @@ export class InputHandler extends Disposable implements IInputHandler {
2119
2169
  * | 7 | No Wraparound Mode (DECAWM). | #Y |
2120
2170
  * | 8 | No Auto-repeat Keys (DECARM). | #N |
2121
2171
  * | 9 | Don't send Mouse X & Y on button press. | #Y |
2122
- * | 12 | Stop Blinking Cursor. | #Y |
2172
+ * | 12 | Stop Blinking Cursor. | #P[Requires the allowSetCursorBlink quirk option enabled.] |
2123
2173
  * | 25 | Hide Cursor (DECTCEM). | #Y |
2124
2174
  * | 45 | No reverse wrap-around. | #Y |
2125
2175
  * | 47 | Use Normal Screen Buffer. | #Y |
@@ -2165,7 +2215,9 @@ export class InputHandler extends Disposable implements IInputHandler {
2165
2215
  this._coreService.decPrivateModes.wraparound = false;
2166
2216
  break;
2167
2217
  case 12:
2168
- this._optionsService.options.cursorBlink = false;
2218
+ if (this._optionsService.rawOptions.quirks?.allowSetCursorBlink) {
2219
+ this._optionsService.options.cursorBlink = false;
2220
+ }
2169
2221
  break;
2170
2222
  case 45:
2171
2223
  this._coreService.decPrivateModes.reverseWraparound = false;
@@ -2179,7 +2231,7 @@ export class InputHandler extends Disposable implements IInputHandler {
2179
2231
  case 1000: // vt200 mouse
2180
2232
  case 1002: // button event mouse
2181
2233
  case 1003: // any event mouse
2182
- this._coreMouseService.activeProtocol = 'NONE';
2234
+ this._mouseStateService.activeProtocol = 'NONE';
2183
2235
  break;
2184
2236
  case 1004: // send focusin/focusout events
2185
2237
  this._coreService.decPrivateModes.sendFocus = false;
@@ -2188,13 +2240,13 @@ export class InputHandler extends Disposable implements IInputHandler {
2188
2240
  this._logService.debug('DECRST 1005 not supported (see #2507)');
2189
2241
  break;
2190
2242
  case 1006: // sgr ext mode mouse
2191
- this._coreMouseService.activeEncoding = 'DEFAULT';
2243
+ this._mouseStateService.activeEncoding = 'DEFAULT';
2192
2244
  break;
2193
2245
  case 1015: // urxvt ext mode mouse - removed in #2507
2194
2246
  this._logService.debug('DECRST 1015 not supported (see #2507)');
2195
2247
  break;
2196
2248
  case 1016: // sgr pixels mode mouse
2197
- this._coreMouseService.activeEncoding = 'DEFAULT';
2249
+ this._mouseStateService.activeEncoding = 'DEFAULT';
2198
2250
  break;
2199
2251
  case 25: // hide cursor
2200
2252
  this._coreService.isCursorHidden = true;
@@ -2206,6 +2258,12 @@ export class InputHandler extends Disposable implements IInputHandler {
2206
2258
  // FALL-THROUGH
2207
2259
  case 47: // normal screen buffer
2208
2260
  case 1047: // normal screen buffer - clearing it first
2261
+ // Swap kitty keyboard flags: save alt, restore main
2262
+ if (this._optionsService.rawOptions.vtExtensions?.kittyKeyboard) {
2263
+ const state = this._coreService.kittyKeyboard;
2264
+ state.altFlags = state.flags;
2265
+ state.flags = state.mainFlags;
2266
+ }
2209
2267
  // Ensure the selection manager has the correct buffer
2210
2268
  this._bufferService.buffers.activateNormalBuffer();
2211
2269
  if (params.params[i] === 1049) {
@@ -2222,6 +2280,16 @@ export class InputHandler extends Disposable implements IInputHandler {
2222
2280
  this._coreService.decPrivateModes.synchronizedOutput = false;
2223
2281
  this._onRequestRefreshRows.fire(undefined);
2224
2282
  break;
2283
+ case 2031: // color scheme updates (https://contour-terminal.org/vt-extensions/color-palette-update-notifications/)
2284
+ if (this._optionsService.rawOptions.vtExtensions?.colorSchemeQuery ?? true) {
2285
+ this._coreService.decPrivateModes.colorSchemeUpdates = false;
2286
+ }
2287
+ break;
2288
+ case 9001: // win32-input-mode
2289
+ if (this._optionsService.rawOptions.vtExtensions?.win32InputMode) {
2290
+ this._coreService.decPrivateModes.win32InputMode = false;
2291
+ }
2292
+ break;
2225
2293
  }
2226
2294
  }
2227
2295
  return true;
@@ -2272,7 +2340,7 @@ export class InputHandler extends Disposable implements IInputHandler {
2272
2340
 
2273
2341
  // access helpers
2274
2342
  const dm = this._coreService.decPrivateModes;
2275
- const { activeProtocol: mouseProtocol, activeEncoding: mouseEncoding } = this._coreMouseService;
2343
+ const { activeProtocol: mouseProtocol, activeEncoding: mouseEncoding } = this._mouseStateService;
2276
2344
  const cs = this._coreService;
2277
2345
  const { buffers, cols } = this._bufferService;
2278
2346
  const { active, alt } = buffers;
@@ -2317,6 +2385,7 @@ export class InputHandler extends Disposable implements IInputHandler {
2317
2385
  if (p === 47 || p === 1047 || p === 1049) return f(p, b2v(active === alt));
2318
2386
  if (p === 2004) return f(p, b2v(dm.bracketedPasteMode));
2319
2387
  if (p === 2026) return f(p, b2v(dm.synchronizedOutput));
2388
+ if (p === 9001) return this._optionsService.rawOptions.vtExtensions?.win32InputMode ? f(p, b2v(dm.win32InputMode)) : f(p, V.NOT_RECOGNIZED);
2320
2389
  return f(p, V.NOT_RECOGNIZED);
2321
2390
  }
2322
2391
 
@@ -2329,7 +2398,7 @@ export class InputHandler extends Disposable implements IInputHandler {
2329
2398
  color &= ~Attributes.RGB_MASK;
2330
2399
  color |= AttributeData.fromColorRGB([c1, c2, c3]);
2331
2400
  } else if (mode === 5) {
2332
- color &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);
2401
+ color &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2333
2402
  color |= Attributes.CM_P256 | (c1 & 0xff);
2334
2403
  }
2335
2404
  return color;
@@ -2494,6 +2563,8 @@ export class InputHandler extends Disposable implements IInputHandler {
2494
2563
  * | 53 | Overlined. | #Y |
2495
2564
  * | 55 | Not Overlined. | #Y |
2496
2565
  * | 58 | Underline color: Extended color. | #P[Support for RGB and indexed colors, see below.] |
2566
+ * | 221 | Not bold (kitty extension). | #Y |
2567
+ * | 222 | Not faint (kitty extension). | #Y |
2497
2568
  * | 90 - 97 | Bright foreground color (analogous to 30 - 37). | #Y |
2498
2569
  * | 100 - 107 | Bright background color (analogous to 40 - 47). | #Y |
2499
2570
  *
@@ -2520,10 +2591,6 @@ export class InputHandler extends Disposable implements IInputHandler {
2520
2591
  * | 3 | CMY color. | #N |
2521
2592
  * | 4 | CMYK color. | #N |
2522
2593
  * | 5 | Indexed (256 colors) as `Ps ; 5 ; INDEX` or `Ps : 5 : INDEX`. | #Y |
2523
- *
2524
- *
2525
- * FIXME: blinking is implemented in attrs, but not working in renderers?
2526
- * FIXME: remove dead branch for p=100
2527
2594
  */
2528
2595
  public charAttributes(params: IParams): boolean {
2529
2596
  // Optimize a single SGR0.
@@ -2540,19 +2607,19 @@ export class InputHandler extends Disposable implements IInputHandler {
2540
2607
  p = params.params[i];
2541
2608
  if (p >= 30 && p <= 37) {
2542
2609
  // fg color 8
2543
- attr.fg &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);
2610
+ attr.fg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2544
2611
  attr.fg |= Attributes.CM_P16 | (p - 30);
2545
2612
  } else if (p >= 40 && p <= 47) {
2546
2613
  // bg color 8
2547
- attr.bg &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);
2614
+ attr.bg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2548
2615
  attr.bg |= Attributes.CM_P16 | (p - 40);
2549
2616
  } else if (p >= 90 && p <= 97) {
2550
2617
  // fg color 16
2551
- attr.fg &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);
2618
+ attr.fg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2552
2619
  attr.fg |= Attributes.CM_P16 | (p - 90) | 8;
2553
2620
  } else if (p >= 100 && p <= 107) {
2554
2621
  // bg color 16
2555
- attr.bg &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);
2622
+ attr.bg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2556
2623
  attr.bg |= Attributes.CM_P16 | (p - 100) | 8;
2557
2624
  } else if (p === 0) {
2558
2625
  // default
@@ -2612,11 +2679,11 @@ export class InputHandler extends Disposable implements IInputHandler {
2612
2679
  } else if (p === 39) {
2613
2680
  // reset fg
2614
2681
  attr.fg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2615
- attr.fg |= DEFAULT_ATTR_DATA.fg & (Attributes.PCOLOR_MASK | Attributes.RGB_MASK);
2682
+ attr.fg |= DEFAULT_ATTR_DATA.fg & Attributes.RGB_MASK;
2616
2683
  } else if (p === 49) {
2617
2684
  // reset bg
2618
2685
  attr.bg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2619
- attr.bg |= DEFAULT_ATTR_DATA.bg & (Attributes.PCOLOR_MASK | Attributes.RGB_MASK);
2686
+ attr.bg |= DEFAULT_ATTR_DATA.bg & Attributes.RGB_MASK;
2620
2687
  } else if (p === 38 || p === 48 || p === 58) {
2621
2688
  // fg color 256 and RGB
2622
2689
  i += this._extractColor(params, i, attr);
@@ -2626,16 +2693,16 @@ export class InputHandler extends Disposable implements IInputHandler {
2626
2693
  } else if (p === 55) {
2627
2694
  // not overline
2628
2695
  attr.bg &= ~BgFlags.OVERLINE;
2696
+ } else if (p === 221 && (this._optionsService.rawOptions.vtExtensions?.kittySgrBoldFaintControl ?? true)) {
2697
+ // not bold (kitty extension)
2698
+ attr.fg &= ~FgFlags.BOLD;
2699
+ } else if (p === 222 && (this._optionsService.rawOptions.vtExtensions?.kittySgrBoldFaintControl ?? true)) {
2700
+ // not faint (kitty extension)
2701
+ attr.bg &= ~BgFlags.DIM;
2629
2702
  } else if (p === 59) {
2630
2703
  attr.extended = attr.extended.clone();
2631
2704
  attr.extended.underlineColor = -1;
2632
2705
  attr.updateExtended();
2633
- } else if (p === 100) { // FIXME: dead branch, p=100 already handled above!
2634
- // reset fg/bg
2635
- attr.fg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2636
- attr.fg |= DEFAULT_ATTR_DATA.fg & (Attributes.PCOLOR_MASK | Attributes.RGB_MASK);
2637
- attr.bg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2638
- attr.bg |= DEFAULT_ATTR_DATA.bg & (Attributes.PCOLOR_MASK | Attributes.RGB_MASK);
2639
2706
  } else {
2640
2707
  this._logService.debug('Unknown SGR attribute: %d.', p);
2641
2708
  }
@@ -2711,6 +2778,12 @@ export class InputHandler extends Disposable implements IInputHandler {
2711
2778
  // no dec locator/mouse
2712
2779
  // this.handler(C0.ESC + '[?50n');
2713
2780
  break;
2781
+ case 996:
2782
+ // color scheme query (https://contour-terminal.org/vt-extensions/color-palette-update-notifications/)
2783
+ if (this._optionsService.rawOptions.vtExtensions?.colorSchemeQuery ?? true) {
2784
+ this._onRequestColorSchemeQuery.fire();
2785
+ }
2786
+ break;
2714
2787
  }
2715
2788
  return true;
2716
2789
  }
@@ -2877,13 +2950,13 @@ export class InputHandler extends Disposable implements IInputHandler {
2877
2950
  case 22: // PushTitle
2878
2951
  if (second === 0 || second === 2) {
2879
2952
  this._windowTitleStack.push(this._windowTitle);
2880
- if (this._windowTitleStack.length > STACK_LIMIT) {
2953
+ if (this._windowTitleStack.length > Constants.STACK_LIMIT) {
2881
2954
  this._windowTitleStack.shift();
2882
2955
  }
2883
2956
  }
2884
2957
  if (second === 0 || second === 1) {
2885
2958
  this._iconNameStack.push(this._iconName);
2886
- if (this._iconNameStack.length > STACK_LIMIT) {
2959
+ if (this._iconNameStack.length > Constants.STACK_LIMIT) {
2887
2960
  this._iconNameStack.shift();
2888
2961
  }
2889
2962
  }
@@ -2919,6 +2992,10 @@ export class InputHandler extends Disposable implements IInputHandler {
2919
2992
  this._activeBuffer.savedCurAttrData.fg = this._curAttrData.fg;
2920
2993
  this._activeBuffer.savedCurAttrData.bg = this._curAttrData.bg;
2921
2994
  this._activeBuffer.savedCharset = this._charsetService.charset;
2995
+ this._activeBuffer.savedCharsets = this._charsetService.charsets.slice();
2996
+ this._activeBuffer.savedGlevel = this._charsetService.glevel;
2997
+ this._activeBuffer.savedOriginMode = this._coreService.decPrivateModes.origin;
2998
+ this._activeBuffer.savedWraparoundMode = this._coreService.decPrivateModes.wraparound;
2922
2999
  return true;
2923
3000
  }
2924
3001
 
@@ -2936,15 +3013,16 @@ export class InputHandler extends Disposable implements IInputHandler {
2936
3013
  this._activeBuffer.y = Math.max(this._activeBuffer.savedY - this._activeBuffer.ybase, 0);
2937
3014
  this._curAttrData.fg = this._activeBuffer.savedCurAttrData.fg;
2938
3015
  this._curAttrData.bg = this._activeBuffer.savedCurAttrData.bg;
2939
- this._charsetService.charset = (this as any)._savedCharset;
2940
- if (this._activeBuffer.savedCharset) {
2941
- this._charsetService.charset = this._activeBuffer.savedCharset;
3016
+ for (let i = 0; i < this._activeBuffer.savedCharsets.length; i++) {
3017
+ this._charsetService.setgCharset(i, this._activeBuffer.savedCharsets[i]);
2942
3018
  }
3019
+ this._charsetService.setgLevel(this._activeBuffer.savedGlevel);
3020
+ this._coreService.decPrivateModes.origin = this._activeBuffer.savedOriginMode;
3021
+ this._coreService.decPrivateModes.wraparound = this._activeBuffer.savedWraparoundMode;
2943
3022
  this._restrictCursor();
2944
3023
  return true;
2945
3024
  }
2946
3025
 
2947
-
2948
3026
  /**
2949
3027
  * OSC 2; <data> ST (set window title)
2950
3028
  * Proxy to set window title.
@@ -2987,7 +3065,7 @@ export class InputHandler extends Disposable implements IInputHandler {
2987
3065
  const idx = slots.shift() as string;
2988
3066
  const spec = slots.shift() as string;
2989
3067
  if (/^\d+$/.exec(idx)) {
2990
- const index = parseInt(idx);
3068
+ const index = parseInt(idx, 10);
2991
3069
  if (isValidColorIndex(index)) {
2992
3070
  if (spec === '?') {
2993
3071
  event.push({ type: ColorRequestType.REPORT, index });
@@ -3150,7 +3228,7 @@ export class InputHandler extends Disposable implements IInputHandler {
3150
3228
  const slots = data.split(';');
3151
3229
  for (let i = 0; i < slots.length; ++i) {
3152
3230
  if (/^\d+$/.exec(slots[i])) {
3153
- const index = parseInt(slots[i]);
3231
+ const index = parseInt(slots[i], 10);
3154
3232
  if (isValidColorIndex(index)) {
3155
3233
  event.push({ type: ColorRequestType.RESTORE, index });
3156
3234
  }
@@ -3267,7 +3345,7 @@ export class InputHandler extends Disposable implements IInputHandler {
3267
3345
  if (collectAndFlag[0] === '/') {
3268
3346
  return true; // TODO: Is this supported?
3269
3347
  }
3270
- this._charsetService.setgCharset(GLEVEL[collectAndFlag[0]], CHARSETS[collectAndFlag[1]] || DEFAULT_CHARSET);
3348
+ this._charsetService.setgCharset(GLEVEL[collectAndFlag[0]], CHARSETS[collectAndFlag[1]] ?? DEFAULT_CHARSET);
3271
3349
  return true;
3272
3350
  }
3273
3351
 
@@ -3338,6 +3416,8 @@ export class InputHandler extends Disposable implements IInputHandler {
3338
3416
  * ESC c
3339
3417
  * DEC mnemonic: RIS (https://vt100.net/docs/vt510-rm/RIS.html)
3340
3418
  * Reset to initial state.
3419
+ *
3420
+ * @vt: #Y ESC RIS "Full Reset" "ESC c" "Reset to initial state."
3341
3421
  */
3342
3422
  public fullReset(): boolean {
3343
3423
  this._parser.reset();
@@ -3454,6 +3534,107 @@ export class InputHandler extends Disposable implements IInputHandler {
3454
3534
  public markRangeDirty(y1: number, y2: number): void {
3455
3535
  this._dirtyRowTracker.markRangeDirty(y1, y2);
3456
3536
  }
3537
+
3538
+ // #region Kitty keyboard
3539
+
3540
+ /**
3541
+ * CSI = flags ; mode u
3542
+ * Set Kitty keyboard protocol flags.
3543
+ * mode: 1=set, 2=set-only-specified, 3=reset-only-specified
3544
+ *
3545
+ * @vt: #Y CSI KKBDSET "Kitty Keyboard Set" "CSI = Ps ; Pm u" "Set Kitty keyboard protocol flags."
3546
+ */
3547
+ public kittyKeyboardSet(params: IParams): boolean {
3548
+ if (!this._optionsService.rawOptions.vtExtensions?.kittyKeyboard) {
3549
+ return true;
3550
+ }
3551
+ const flags = params.params[0] || 0;
3552
+ const mode = params.length > 1 ? (params.params[1] || 1) : 1;
3553
+ const state = this._coreService.kittyKeyboard;
3554
+
3555
+ switch (mode) {
3556
+ case 1: // Set all flags
3557
+ state.flags = flags;
3558
+ break;
3559
+ case 2: // Set only specified flags (OR)
3560
+ state.flags |= flags;
3561
+ break;
3562
+ case 3: // Reset only specified flags (AND NOT)
3563
+ state.flags &= ~flags;
3564
+ break;
3565
+ }
3566
+ return true;
3567
+ }
3568
+
3569
+ /**
3570
+ * CSI ? u
3571
+ * Query Kitty keyboard protocol flags.
3572
+ * Terminal responds with CSI ? flags u
3573
+ *
3574
+ * @vt: #Y CSI KKBDQUERY "Kitty Keyboard Query" "CSI ? u" "Query Kitty keyboard protocol flags."
3575
+ */
3576
+ public kittyKeyboardQuery(params: IParams): boolean {
3577
+ if (!this._optionsService.rawOptions.vtExtensions?.kittyKeyboard) {
3578
+ return true;
3579
+ }
3580
+ const flags = this._coreService.kittyKeyboard.flags;
3581
+ this._coreService.triggerDataEvent(`${C0.ESC}[?${flags}u`);
3582
+ return true;
3583
+ }
3584
+
3585
+ /**
3586
+ * CSI > flags u
3587
+ * Push Kitty keyboard flags onto stack and set new flags.
3588
+ *
3589
+ * @vt: #Y CSI KKBDPUSH "Kitty Keyboard Push" "CSI > Ps u" "Push keyboard flags to stack and set new flags."
3590
+ */
3591
+ public kittyKeyboardPush(params: IParams): boolean {
3592
+ if (!this._optionsService.rawOptions.vtExtensions?.kittyKeyboard) {
3593
+ return true;
3594
+ }
3595
+ const flags = params.params[0] || 0;
3596
+ const state = this._coreService.kittyKeyboard;
3597
+ const isAlt = this._bufferService.buffer === this._bufferService.buffers.alt;
3598
+ const stack = isAlt ? state.altStack : state.mainStack;
3599
+
3600
+ // Evict oldest entry if stack is full (DoS protection, limit of 16)
3601
+ if (stack.length >= 16) {
3602
+ stack.shift();
3603
+ }
3604
+
3605
+ // Push current flags onto stack and set new flags
3606
+ stack.push(state.flags);
3607
+ state.flags = flags;
3608
+ return true;
3609
+ }
3610
+
3611
+ /**
3612
+ * CSI < count u
3613
+ * Pop Kitty keyboard flags from stack.
3614
+ *
3615
+ * @vt: #Y CSI KKBDPOP "Kitty Keyboard Pop" "CSI < Ps u" "Pop keyboard flags from stack."
3616
+ */
3617
+ public kittyKeyboardPop(params: IParams): boolean {
3618
+ if (!this._optionsService.rawOptions.vtExtensions?.kittyKeyboard) {
3619
+ return true;
3620
+ }
3621
+ const count = Math.max(1, params.params[0] || 1);
3622
+ const state = this._coreService.kittyKeyboard;
3623
+ const isAlt = this._bufferService.buffer === this._bufferService.buffers.alt;
3624
+ const stack = isAlt ? state.altStack : state.mainStack;
3625
+
3626
+ // Pop specified number of entries from stack
3627
+ for (let i = 0; i < count && stack.length > 0; i++) {
3628
+ state.flags = stack.pop()!;
3629
+ }
3630
+ // If stack is empty after popping, reset to 0
3631
+ if (stack.length === 0 && count > 0) {
3632
+ state.flags = 0;
3633
+ }
3634
+ return true;
3635
+ }
3636
+
3637
+ // #endregion
3457
3638
  }
3458
3639
 
3459
3640
  export interface IDirtyRowTracker {