@xterm/xterm 6.1.0-beta.27 → 6.1.0-beta.270

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 -48
  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 +251 -85
  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 +7 -7
  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 +303 -104
  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 +9 -0
  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 +145 -73
  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 +1 -1
  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,52 +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';
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';
25
27
 
26
28
  /**
27
29
  * Map collect to glevel. Used in `selectCharset`.
28
30
  */
29
31
  const GLEVEL: { [key: string]: number } = { '(': 0, ')': 1, '*': 2, '+': 3, '-': 1, '.': 2 };
30
32
 
31
- /**
32
- * VT commands done by the parser - FIXME: move this to the parser?
33
- */
34
- // @vt: #Y ESC CSI "Control Sequence Introducer" "ESC [" "Start of a CSI sequence."
35
- // @vt: #Y ESC OSC "Operating System Command" "ESC ]" "Start of an OSC sequence."
36
- // @vt: #Y ESC DCS "Device Control String" "ESC P" "Start of a DCS sequence."
37
- // @vt: #Y ESC ST "String Terminator" "ESC \" "Terminator used for string type sequences."
38
- // @vt: #Y ESC PM "Privacy Message" "ESC ^" "Start of a privacy message."
39
- // @vt: #Y ESC APC "Application Program Command" "ESC _" "Start of an APC sequence."
40
- // @vt: #Y C1 CSI "Control Sequence Introducer" "\x9B" "Start of a CSI sequence."
41
- // @vt: #Y C1 OSC "Operating System Command" "\x9D" "Start of an OSC sequence."
42
- // @vt: #Y C1 DCS "Device Control String" "\x90" "Start of a DCS sequence."
43
- // @vt: #Y C1 ST "String Terminator" "\x9C" "Terminator used for string type sequences."
44
- // @vt: #Y C1 PM "Privacy Message" "\x9E" "Start of a privacy message."
45
- // @vt: #Y C1 APC "Application Program Command" "\x9F" "Start of an APC sequence."
46
- // @vt: #Y C0 NUL "Null" "\0, \x00" "NUL is ignored."
47
- // @vt: #Y C0 ESC "Escape" "\e, \x1B" "Start of a sequence. Cancels any other sequence."
48
-
49
33
  /**
50
34
  * Document xterm VT features here that are currently unsupported
51
35
  */
52
- // @vt: #E[Supported via @xterm/addon-image.] DCS SIXEL "SIXEL Graphics" "DCS Ps ; Ps ; Ps ; q Pt ST" "Draw SIXEL image."
53
36
  // @vt: #N DCS DECUDK "User Defined Keys" "DCS Ps ; Ps \| Pt ST" "Definitions for user-defined keys."
54
37
  // @vt: #N DCS XTGETTCAP "Request Terminfo String" "DCS + q Pt ST" "Request Terminfo String."
55
38
  // @vt: #N DCS XTSETTCAP "Set Terminfo Data" "DCS + p Pt ST" "Set Terminfo Data."
@@ -58,12 +41,13 @@ const GLEVEL: { [key: string]: number } = { '(': 0, ')': 1, '*': 2, '+': 3, '-':
58
41
  /**
59
42
  * Max length of the UTF32 input buffer. Real memory consumption is 4 times higher.
60
43
  */
61
- const MAX_PARSEBUFFER_LENGTH = 131072;
62
-
63
- /**
64
- * Limit length of title and icon name stacks.
65
- */
66
- 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
+ }
67
51
 
68
52
  // map params to window option
69
53
  function paramToWindowOption(n: number, opts: IWindowOptions): boolean {
@@ -102,9 +86,6 @@ export enum WindowsOptionsReportType {
102
86
  GET_CELL_SIZE_PIXELS = 1
103
87
  }
104
88
 
105
- // create a warning log if an async handler takes longer than the limit (in ms)
106
- const SLOW_ASYNC_LIMIT = 5000;
107
-
108
89
  // Work variables to avoid garbage collection
109
90
  let $temp = 0;
110
91
 
@@ -158,6 +139,8 @@ export class InputHandler extends Disposable implements IInputHandler {
158
139
  public readonly onTitleChange = this._onTitleChange.event;
159
140
  private readonly _onColor = this._register(new Emitter<IColorEvent>());
160
141
  public readonly onColor = this._onColor.event;
142
+ private readonly _onRequestColorSchemeQuery = this._register(new Emitter<void>());
143
+ public readonly onRequestColorSchemeQuery = this._onRequestColorSchemeQuery.event;
161
144
 
162
145
  private _parseStack: IParseStack = {
163
146
  paused: false,
@@ -174,7 +157,7 @@ export class InputHandler extends Disposable implements IInputHandler {
174
157
  private readonly _logService: ILogService,
175
158
  private readonly _optionsService: IOptionsService,
176
159
  private readonly _oscLinkService: IOscLinkService,
177
- private readonly _coreMouseService: ICoreMouseService,
160
+ private readonly _mouseStateService: IMouseStateService,
178
161
  private readonly _unicodeService: IUnicodeService,
179
162
  private readonly _parser: IEscapeSequenceParser = new EscapeSequenceParser()
180
163
  ) {
@@ -207,6 +190,9 @@ export class InputHandler extends Disposable implements IInputHandler {
207
190
  }
208
191
  this._logService.debug('Unknown DCS code: ', { identifier: this._parser.identToString(ident), action, payload });
209
192
  });
193
+ this._parser.setApcHandlerFallback((ident, action, payload) => {
194
+ this._logService.debug('Unknown APC code: ', { identifier: this._parser.identToString(ident), action, payload });
195
+ });
210
196
 
211
197
  /**
212
198
  * print handler
@@ -239,6 +225,7 @@ export class InputHandler extends Disposable implements IInputHandler {
239
225
  this._parser.registerCsiHandler({ final: 'T' }, params => this.scrollDown(params));
240
226
  this._parser.registerCsiHandler({ final: 'X' }, params => this.eraseChars(params));
241
227
  this._parser.registerCsiHandler({ final: 'Z' }, params => this.cursorBackwardTab(params));
228
+ this._parser.registerCsiHandler({ final: '^' }, params => this.scrollDown(params));
242
229
  this._parser.registerCsiHandler({ final: '`' }, params => this.charPosAbsolute(params));
243
230
  this._parser.registerCsiHandler({ final: 'a' }, params => this.hPositionRelative(params));
244
231
  this._parser.registerCsiHandler({ final: 'b' }, params => this.repeatPrecedingCharacter(params));
@@ -256,6 +243,7 @@ export class InputHandler extends Disposable implements IInputHandler {
256
243
  this._parser.registerCsiHandler({ final: 'n' }, params => this.deviceStatus(params));
257
244
  this._parser.registerCsiHandler({ prefix: '?', final: 'n' }, params => this.deviceStatusPrivate(params));
258
245
  this._parser.registerCsiHandler({ intermediates: '!', final: 'p' }, params => this.softReset(params));
246
+ this._parser.registerCsiHandler({ prefix: '>', final: 'q' }, params => this.sendXtVersion(params));
259
247
  this._parser.registerCsiHandler({ intermediates: ' ', final: 'q' }, params => this.setCursorStyle(params));
260
248
  this._parser.registerCsiHandler({ final: 'r' }, params => this.setScrollRegion(params));
261
249
  this._parser.registerCsiHandler({ final: 's' }, params => this.saveCursor(params));
@@ -267,6 +255,12 @@ export class InputHandler extends Disposable implements IInputHandler {
267
255
  this._parser.registerCsiHandler({ intermediates: '$', final: 'p' }, params => this.requestMode(params, true));
268
256
  this._parser.registerCsiHandler({ prefix: '?', intermediates: '$', final: 'p' }, params => this.requestMode(params, false));
269
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
+
270
264
  /**
271
265
  * execute handler
272
266
  */
@@ -395,12 +389,23 @@ export class InputHandler extends Disposable implements IInputHandler {
395
389
  private _logSlowResolvingAsync(p: Promise<boolean>): void {
396
390
  // log a limited warning about an async handler taking too long
397
391
  if (this._logService.logLevel <= LogLevelEnum.WARN) {
398
- Promise.race([p, new Promise((res, rej) => setTimeout(() => rej('#SLOW_TIMEOUT'), SLOW_ASYNC_LIMIT))])
399
- .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
+ }
400
405
  if (err !== '#SLOW_TIMEOUT') {
401
406
  throw err;
402
407
  }
403
- 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`);
404
409
  });
405
410
  }
406
411
  }
@@ -438,8 +443,8 @@ export class InputHandler extends Disposable implements IInputHandler {
438
443
  cursorStartX = this._parseStack.cursorStartX;
439
444
  cursorStartY = this._parseStack.cursorStartY;
440
445
  this._parseStack.paused = false;
441
- if (data.length > MAX_PARSEBUFFER_LENGTH) {
442
- start = this._parseStack.position + MAX_PARSEBUFFER_LENGTH;
446
+ if (data.length > Constants.MAX_PARSEBUFFER_LENGTH) {
447
+ start = this._parseStack.position + Constants.MAX_PARSEBUFFER_LENGTH;
443
448
  }
444
449
  }
445
450
 
@@ -456,8 +461,8 @@ export class InputHandler extends Disposable implements IInputHandler {
456
461
 
457
462
  // resize input buffer if needed
458
463
  if (this._parseBuffer.length < data.length) {
459
- if (this._parseBuffer.length < MAX_PARSEBUFFER_LENGTH) {
460
- 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));
461
466
  }
462
467
  }
463
468
 
@@ -468,9 +473,9 @@ export class InputHandler extends Disposable implements IInputHandler {
468
473
  }
469
474
 
470
475
  // process big data in smaller chunks
471
- if (data.length > MAX_PARSEBUFFER_LENGTH) {
472
- for (let i = start; i < data.length; i += MAX_PARSEBUFFER_LENGTH) {
473
- 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;
474
479
  const len = (typeof data === 'string')
475
480
  ? this._stringDecoder.decode(data.substring(i, end), this._parseBuffer)
476
481
  : this._utf8Decoder.decode(data.subarray(i, end), this._parseBuffer);
@@ -518,7 +523,13 @@ export class InputHandler extends Disposable implements IInputHandler {
518
523
  const wraparoundMode = this._coreService.decPrivateModes.wraparound;
519
524
  const insertMode = this._coreService.modes.insertMode;
520
525
  const curAttr = this._curAttrData;
521
- 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
+ }
522
533
 
523
534
  this._dirtyRowTracker.markDirty(this._activeBuffer.y);
524
535
 
@@ -531,6 +542,12 @@ export class InputHandler extends Disposable implements IInputHandler {
531
542
  for (let pos = start; pos < end; ++pos) {
532
543
  code = data[pos];
533
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
+
534
551
  // get charset replacement character
535
552
  // charset is only defined for ASCII, therefore we only
536
553
  // search for an replacement char if code < 127
@@ -550,8 +567,9 @@ export class InputHandler extends Disposable implements IInputHandler {
550
567
  if (screenReaderMode) {
551
568
  this._onA11yChar.fire(stringFromCodePoint(code));
552
569
  }
553
- if (this._getCurrentLinkId()) {
554
- 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);
555
573
  }
556
574
 
557
575
  // goto next line if ch would overflow
@@ -577,7 +595,10 @@ export class InputHandler extends Disposable implements IInputHandler {
577
595
  this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y)!.isWrapped = true;
578
596
  }
579
597
  // row changed, get it again
580
- 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
+ }
581
602
  if (oldWidth > 0 && bufferRow instanceof BufferLine) {
582
603
  // Combining character widens 1 column to 2.
583
604
  // Move old character to next line.
@@ -688,6 +709,13 @@ export class InputHandler extends Disposable implements IInputHandler {
688
709
  return this._parser.registerOscHandler(ident, new OscHandler(callback));
689
710
  }
690
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
+
691
719
  /**
692
720
  * BEL
693
721
  * Bell (Ctrl-G).
@@ -1145,7 +1173,10 @@ export class InputHandler extends Disposable implements IInputHandler {
1145
1173
  * @param respectProtect Whether to respect the protection attribute (DECSCA).
1146
1174
  */
1147
1175
  private _eraseInBufferLine(y: number, start: number, end: number, clearWrap: boolean = false, respectProtect: boolean = false): void {
1148
- 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
+ }
1149
1180
  line.replaceCells(
1150
1181
  start,
1151
1182
  end,
@@ -1215,7 +1246,10 @@ export class InputHandler extends Disposable implements IInputHandler {
1215
1246
  this._eraseInBufferLine(j, 0, this._activeBuffer.x + 1, true, respectProtect);
1216
1247
  if (this._activeBuffer.x + 1 >= this._bufferService.cols) {
1217
1248
  // Deleted entire previous line. This next line can no longer be wrapped.
1218
- 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
+ }
1219
1253
  }
1220
1254
  while (j--) {
1221
1255
  this._resetBufferLine(j, respectProtect);
@@ -1721,12 +1755,28 @@ export class InputHandler extends Disposable implements IInputHandler {
1721
1755
  return true;
1722
1756
  }
1723
1757
 
1758
+ /**
1759
+ * CSI > Ps q
1760
+ * Ps = 0 => Report xterm name and version (XTVERSION).
1761
+ *
1762
+ * The response is a DCS sequence identifying the version: DCS > | text ST
1763
+ *
1764
+ * @vt: #Y CSI XTVERSION "Report Xterm Version" "CSI > q" "Report the terminal name and version."
1765
+ */
1766
+ public sendXtVersion(params: IParams): boolean {
1767
+ if (params.params[0] > 0) {
1768
+ return true;
1769
+ }
1770
+ this._coreService.triggerDataEvent(`${C0.ESC}P>|xterm.js(${XTERM_VERSION})${C0.ESC}\\`);
1771
+ return true;
1772
+ }
1773
+
1724
1774
  /**
1725
1775
  * Evaluate if the current terminal is the given argument.
1726
1776
  * @param term The terminal name to evaluate
1727
1777
  */
1728
1778
  private _is(term: string): boolean {
1729
- return (this._optionsService.rawOptions.termName + '').indexOf(term) === 0;
1779
+ return (this._optionsService.rawOptions.termName + '').startsWith(term);
1730
1780
  }
1731
1781
 
1732
1782
  /**
@@ -1853,7 +1903,7 @@ export class InputHandler extends Disposable implements IInputHandler {
1853
1903
  * | 7 | Auto-wrap Mode (DECAWM). | #Y |
1854
1904
  * | 8 | Auto-repeat Keys (DECARM). Always on. | #N |
1855
1905
  * | 9 | X10 xterm mouse protocol. | #Y |
1856
- * | 12 | Start Blinking Cursor. | #Y |
1906
+ * | 12 | Start Blinking Cursor. | #P[Requires the allowSetCursorBlink quirk option enabled.] |
1857
1907
  * | 25 | Show Cursor (DECTCEM). | #Y |
1858
1908
  * | 45 | Reverse wrap-around. | #Y |
1859
1909
  * | 47 | Use Alternate Screen Buffer. | #Y |
@@ -1906,7 +1956,9 @@ export class InputHandler extends Disposable implements IInputHandler {
1906
1956
  this._coreService.decPrivateModes.wraparound = true;
1907
1957
  break;
1908
1958
  case 12:
1909
- this._optionsService.options.cursorBlink = true;
1959
+ if (this._optionsService.rawOptions.quirks?.allowSetCursorBlink) {
1960
+ this._optionsService.options.cursorBlink = true;
1961
+ }
1910
1962
  break;
1911
1963
  case 45:
1912
1964
  this._coreService.decPrivateModes.reverseWraparound = true;
@@ -1918,19 +1970,19 @@ export class InputHandler extends Disposable implements IInputHandler {
1918
1970
  break;
1919
1971
  case 9: // X10 Mouse
1920
1972
  // no release, no motion, no wheel, no modifiers.
1921
- this._coreMouseService.activeProtocol = 'X10';
1973
+ this._mouseStateService.activeProtocol = 'X10';
1922
1974
  break;
1923
1975
  case 1000: // vt200 mouse
1924
1976
  // no motion.
1925
- this._coreMouseService.activeProtocol = 'VT200';
1977
+ this._mouseStateService.activeProtocol = 'VT200';
1926
1978
  break;
1927
1979
  case 1002: // button event mouse
1928
- this._coreMouseService.activeProtocol = 'DRAG';
1980
+ this._mouseStateService.activeProtocol = 'DRAG';
1929
1981
  break;
1930
1982
  case 1003: // any event mouse
1931
1983
  // any event - sends motion events,
1932
1984
  // even if there is no button held down.
1933
- this._coreMouseService.activeProtocol = 'ANY';
1985
+ this._mouseStateService.activeProtocol = 'ANY';
1934
1986
  break;
1935
1987
  case 1004: // send focusin/focusout events
1936
1988
  // focusin: ^[[I
@@ -1942,13 +1994,13 @@ export class InputHandler extends Disposable implements IInputHandler {
1942
1994
  this._logService.debug('DECSET 1005 not supported (see #2507)');
1943
1995
  break;
1944
1996
  case 1006: // sgr ext mode mouse
1945
- this._coreMouseService.activeEncoding = 'SGR';
1997
+ this._mouseStateService.activeEncoding = 'SGR';
1946
1998
  break;
1947
1999
  case 1015: // urxvt ext mode mouse - removed in #2507
1948
2000
  this._logService.debug('DECSET 1015 not supported (see #2507)');
1949
2001
  break;
1950
2002
  case 1016: // sgr pixels mode mouse
1951
- this._coreMouseService.activeEncoding = 'SGR_PIXELS';
2003
+ this._mouseStateService.activeEncoding = 'SGR_PIXELS';
1952
2004
  break;
1953
2005
  case 25: // show cursor
1954
2006
  this._coreService.isCursorHidden = false;
@@ -1961,6 +2013,12 @@ export class InputHandler extends Disposable implements IInputHandler {
1961
2013
  // FALL-THROUGH
1962
2014
  case 47: // alt screen buffer
1963
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
+ }
1964
2022
  this._bufferService.buffers.activateAltBuffer(this._eraseAttrData());
1965
2023
  this._coreService.isCursorInitialized = true;
1966
2024
  this._onRequestRefreshRows.fire(undefined);
@@ -1972,6 +2030,16 @@ export class InputHandler extends Disposable implements IInputHandler {
1972
2030
  case 2026: // synchronized output (https://github.com/contour-terminal/vt-extensions/blob/master/synchronized-output.md)
1973
2031
  this._coreService.decPrivateModes.synchronizedOutput = true;
1974
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;
1975
2043
  }
1976
2044
  }
1977
2045
  return true;
@@ -2101,7 +2169,7 @@ export class InputHandler extends Disposable implements IInputHandler {
2101
2169
  * | 7 | No Wraparound Mode (DECAWM). | #Y |
2102
2170
  * | 8 | No Auto-repeat Keys (DECARM). | #N |
2103
2171
  * | 9 | Don't send Mouse X & Y on button press. | #Y |
2104
- * | 12 | Stop Blinking Cursor. | #Y |
2172
+ * | 12 | Stop Blinking Cursor. | #P[Requires the allowSetCursorBlink quirk option enabled.] |
2105
2173
  * | 25 | Hide Cursor (DECTCEM). | #Y |
2106
2174
  * | 45 | No reverse wrap-around. | #Y |
2107
2175
  * | 47 | Use Normal Screen Buffer. | #Y |
@@ -2147,7 +2215,9 @@ export class InputHandler extends Disposable implements IInputHandler {
2147
2215
  this._coreService.decPrivateModes.wraparound = false;
2148
2216
  break;
2149
2217
  case 12:
2150
- this._optionsService.options.cursorBlink = false;
2218
+ if (this._optionsService.rawOptions.quirks?.allowSetCursorBlink) {
2219
+ this._optionsService.options.cursorBlink = false;
2220
+ }
2151
2221
  break;
2152
2222
  case 45:
2153
2223
  this._coreService.decPrivateModes.reverseWraparound = false;
@@ -2161,7 +2231,7 @@ export class InputHandler extends Disposable implements IInputHandler {
2161
2231
  case 1000: // vt200 mouse
2162
2232
  case 1002: // button event mouse
2163
2233
  case 1003: // any event mouse
2164
- this._coreMouseService.activeProtocol = 'NONE';
2234
+ this._mouseStateService.activeProtocol = 'NONE';
2165
2235
  break;
2166
2236
  case 1004: // send focusin/focusout events
2167
2237
  this._coreService.decPrivateModes.sendFocus = false;
@@ -2170,13 +2240,13 @@ export class InputHandler extends Disposable implements IInputHandler {
2170
2240
  this._logService.debug('DECRST 1005 not supported (see #2507)');
2171
2241
  break;
2172
2242
  case 1006: // sgr ext mode mouse
2173
- this._coreMouseService.activeEncoding = 'DEFAULT';
2243
+ this._mouseStateService.activeEncoding = 'DEFAULT';
2174
2244
  break;
2175
2245
  case 1015: // urxvt ext mode mouse - removed in #2507
2176
2246
  this._logService.debug('DECRST 1015 not supported (see #2507)');
2177
2247
  break;
2178
2248
  case 1016: // sgr pixels mode mouse
2179
- this._coreMouseService.activeEncoding = 'DEFAULT';
2249
+ this._mouseStateService.activeEncoding = 'DEFAULT';
2180
2250
  break;
2181
2251
  case 25: // hide cursor
2182
2252
  this._coreService.isCursorHidden = true;
@@ -2188,6 +2258,12 @@ export class InputHandler extends Disposable implements IInputHandler {
2188
2258
  // FALL-THROUGH
2189
2259
  case 47: // normal screen buffer
2190
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
+ }
2191
2267
  // Ensure the selection manager has the correct buffer
2192
2268
  this._bufferService.buffers.activateNormalBuffer();
2193
2269
  if (params.params[i] === 1049) {
@@ -2204,6 +2280,16 @@ export class InputHandler extends Disposable implements IInputHandler {
2204
2280
  this._coreService.decPrivateModes.synchronizedOutput = false;
2205
2281
  this._onRequestRefreshRows.fire(undefined);
2206
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;
2207
2293
  }
2208
2294
  }
2209
2295
  return true;
@@ -2254,7 +2340,7 @@ export class InputHandler extends Disposable implements IInputHandler {
2254
2340
 
2255
2341
  // access helpers
2256
2342
  const dm = this._coreService.decPrivateModes;
2257
- const { activeProtocol: mouseProtocol, activeEncoding: mouseEncoding } = this._coreMouseService;
2343
+ const { activeProtocol: mouseProtocol, activeEncoding: mouseEncoding } = this._mouseStateService;
2258
2344
  const cs = this._coreService;
2259
2345
  const { buffers, cols } = this._bufferService;
2260
2346
  const { active, alt } = buffers;
@@ -2299,6 +2385,7 @@ export class InputHandler extends Disposable implements IInputHandler {
2299
2385
  if (p === 47 || p === 1047 || p === 1049) return f(p, b2v(active === alt));
2300
2386
  if (p === 2004) return f(p, b2v(dm.bracketedPasteMode));
2301
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);
2302
2389
  return f(p, V.NOT_RECOGNIZED);
2303
2390
  }
2304
2391
 
@@ -2311,7 +2398,7 @@ export class InputHandler extends Disposable implements IInputHandler {
2311
2398
  color &= ~Attributes.RGB_MASK;
2312
2399
  color |= AttributeData.fromColorRGB([c1, c2, c3]);
2313
2400
  } else if (mode === 5) {
2314
- color &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);
2401
+ color &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2315
2402
  color |= Attributes.CM_P256 | (c1 & 0xff);
2316
2403
  }
2317
2404
  return color;
@@ -2476,6 +2563,8 @@ export class InputHandler extends Disposable implements IInputHandler {
2476
2563
  * | 53 | Overlined. | #Y |
2477
2564
  * | 55 | Not Overlined. | #Y |
2478
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 |
2479
2568
  * | 90 - 97 | Bright foreground color (analogous to 30 - 37). | #Y |
2480
2569
  * | 100 - 107 | Bright background color (analogous to 40 - 47). | #Y |
2481
2570
  *
@@ -2502,10 +2591,6 @@ export class InputHandler extends Disposable implements IInputHandler {
2502
2591
  * | 3 | CMY color. | #N |
2503
2592
  * | 4 | CMYK color. | #N |
2504
2593
  * | 5 | Indexed (256 colors) as `Ps ; 5 ; INDEX` or `Ps : 5 : INDEX`. | #Y |
2505
- *
2506
- *
2507
- * FIXME: blinking is implemented in attrs, but not working in renderers?
2508
- * FIXME: remove dead branch for p=100
2509
2594
  */
2510
2595
  public charAttributes(params: IParams): boolean {
2511
2596
  // Optimize a single SGR0.
@@ -2522,19 +2607,19 @@ export class InputHandler extends Disposable implements IInputHandler {
2522
2607
  p = params.params[i];
2523
2608
  if (p >= 30 && p <= 37) {
2524
2609
  // fg color 8
2525
- attr.fg &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);
2610
+ attr.fg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2526
2611
  attr.fg |= Attributes.CM_P16 | (p - 30);
2527
2612
  } else if (p >= 40 && p <= 47) {
2528
2613
  // bg color 8
2529
- attr.bg &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);
2614
+ attr.bg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2530
2615
  attr.bg |= Attributes.CM_P16 | (p - 40);
2531
2616
  } else if (p >= 90 && p <= 97) {
2532
2617
  // fg color 16
2533
- attr.fg &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);
2618
+ attr.fg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2534
2619
  attr.fg |= Attributes.CM_P16 | (p - 90) | 8;
2535
2620
  } else if (p >= 100 && p <= 107) {
2536
2621
  // bg color 16
2537
- attr.bg &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);
2622
+ attr.bg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2538
2623
  attr.bg |= Attributes.CM_P16 | (p - 100) | 8;
2539
2624
  } else if (p === 0) {
2540
2625
  // default
@@ -2594,11 +2679,11 @@ export class InputHandler extends Disposable implements IInputHandler {
2594
2679
  } else if (p === 39) {
2595
2680
  // reset fg
2596
2681
  attr.fg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2597
- attr.fg |= DEFAULT_ATTR_DATA.fg & (Attributes.PCOLOR_MASK | Attributes.RGB_MASK);
2682
+ attr.fg |= DEFAULT_ATTR_DATA.fg & Attributes.RGB_MASK;
2598
2683
  } else if (p === 49) {
2599
2684
  // reset bg
2600
2685
  attr.bg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2601
- attr.bg |= DEFAULT_ATTR_DATA.bg & (Attributes.PCOLOR_MASK | Attributes.RGB_MASK);
2686
+ attr.bg |= DEFAULT_ATTR_DATA.bg & Attributes.RGB_MASK;
2602
2687
  } else if (p === 38 || p === 48 || p === 58) {
2603
2688
  // fg color 256 and RGB
2604
2689
  i += this._extractColor(params, i, attr);
@@ -2608,16 +2693,16 @@ export class InputHandler extends Disposable implements IInputHandler {
2608
2693
  } else if (p === 55) {
2609
2694
  // not overline
2610
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;
2611
2702
  } else if (p === 59) {
2612
2703
  attr.extended = attr.extended.clone();
2613
2704
  attr.extended.underlineColor = -1;
2614
2705
  attr.updateExtended();
2615
- } else if (p === 100) { // FIXME: dead branch, p=100 already handled above!
2616
- // reset fg/bg
2617
- attr.fg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2618
- attr.fg |= DEFAULT_ATTR_DATA.fg & (Attributes.PCOLOR_MASK | Attributes.RGB_MASK);
2619
- attr.bg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2620
- attr.bg |= DEFAULT_ATTR_DATA.bg & (Attributes.PCOLOR_MASK | Attributes.RGB_MASK);
2621
2706
  } else {
2622
2707
  this._logService.debug('Unknown SGR attribute: %d.', p);
2623
2708
  }
@@ -2693,6 +2778,12 @@ export class InputHandler extends Disposable implements IInputHandler {
2693
2778
  // no dec locator/mouse
2694
2779
  // this.handler(C0.ESC + '[?50n');
2695
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;
2696
2787
  }
2697
2788
  return true;
2698
2789
  }
@@ -2859,13 +2950,13 @@ export class InputHandler extends Disposable implements IInputHandler {
2859
2950
  case 22: // PushTitle
2860
2951
  if (second === 0 || second === 2) {
2861
2952
  this._windowTitleStack.push(this._windowTitle);
2862
- if (this._windowTitleStack.length > STACK_LIMIT) {
2953
+ if (this._windowTitleStack.length > Constants.STACK_LIMIT) {
2863
2954
  this._windowTitleStack.shift();
2864
2955
  }
2865
2956
  }
2866
2957
  if (second === 0 || second === 1) {
2867
2958
  this._iconNameStack.push(this._iconName);
2868
- if (this._iconNameStack.length > STACK_LIMIT) {
2959
+ if (this._iconNameStack.length > Constants.STACK_LIMIT) {
2869
2960
  this._iconNameStack.shift();
2870
2961
  }
2871
2962
  }
@@ -2901,6 +2992,10 @@ export class InputHandler extends Disposable implements IInputHandler {
2901
2992
  this._activeBuffer.savedCurAttrData.fg = this._curAttrData.fg;
2902
2993
  this._activeBuffer.savedCurAttrData.bg = this._curAttrData.bg;
2903
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;
2904
2999
  return true;
2905
3000
  }
2906
3001
 
@@ -2918,15 +3013,16 @@ export class InputHandler extends Disposable implements IInputHandler {
2918
3013
  this._activeBuffer.y = Math.max(this._activeBuffer.savedY - this._activeBuffer.ybase, 0);
2919
3014
  this._curAttrData.fg = this._activeBuffer.savedCurAttrData.fg;
2920
3015
  this._curAttrData.bg = this._activeBuffer.savedCurAttrData.bg;
2921
- this._charsetService.charset = (this as any)._savedCharset;
2922
- if (this._activeBuffer.savedCharset) {
2923
- 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]);
2924
3018
  }
3019
+ this._charsetService.setgLevel(this._activeBuffer.savedGlevel);
3020
+ this._coreService.decPrivateModes.origin = this._activeBuffer.savedOriginMode;
3021
+ this._coreService.decPrivateModes.wraparound = this._activeBuffer.savedWraparoundMode;
2925
3022
  this._restrictCursor();
2926
3023
  return true;
2927
3024
  }
2928
3025
 
2929
-
2930
3026
  /**
2931
3027
  * OSC 2; <data> ST (set window title)
2932
3028
  * Proxy to set window title.
@@ -2969,7 +3065,7 @@ export class InputHandler extends Disposable implements IInputHandler {
2969
3065
  const idx = slots.shift() as string;
2970
3066
  const spec = slots.shift() as string;
2971
3067
  if (/^\d+$/.exec(idx)) {
2972
- const index = parseInt(idx);
3068
+ const index = parseInt(idx, 10);
2973
3069
  if (isValidColorIndex(index)) {
2974
3070
  if (spec === '?') {
2975
3071
  event.push({ type: ColorRequestType.REPORT, index });
@@ -3132,7 +3228,7 @@ export class InputHandler extends Disposable implements IInputHandler {
3132
3228
  const slots = data.split(';');
3133
3229
  for (let i = 0; i < slots.length; ++i) {
3134
3230
  if (/^\d+$/.exec(slots[i])) {
3135
- const index = parseInt(slots[i]);
3231
+ const index = parseInt(slots[i], 10);
3136
3232
  if (isValidColorIndex(index)) {
3137
3233
  event.push({ type: ColorRequestType.RESTORE, index });
3138
3234
  }
@@ -3249,7 +3345,7 @@ export class InputHandler extends Disposable implements IInputHandler {
3249
3345
  if (collectAndFlag[0] === '/') {
3250
3346
  return true; // TODO: Is this supported?
3251
3347
  }
3252
- this._charsetService.setgCharset(GLEVEL[collectAndFlag[0]], CHARSETS[collectAndFlag[1]] || DEFAULT_CHARSET);
3348
+ this._charsetService.setgCharset(GLEVEL[collectAndFlag[0]], CHARSETS[collectAndFlag[1]] ?? DEFAULT_CHARSET);
3253
3349
  return true;
3254
3350
  }
3255
3351
 
@@ -3320,6 +3416,8 @@ export class InputHandler extends Disposable implements IInputHandler {
3320
3416
  * ESC c
3321
3417
  * DEC mnemonic: RIS (https://vt100.net/docs/vt510-rm/RIS.html)
3322
3418
  * Reset to initial state.
3419
+ *
3420
+ * @vt: #Y ESC RIS "Full Reset" "ESC c" "Reset to initial state."
3323
3421
  */
3324
3422
  public fullReset(): boolean {
3325
3423
  this._parser.reset();
@@ -3436,6 +3534,107 @@ export class InputHandler extends Disposable implements IInputHandler {
3436
3534
  public markRangeDirty(y1: number, y2: number): void {
3437
3535
  this._dirtyRowTracker.markRangeDirty(y1, y2);
3438
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
3439
3638
  }
3440
3639
 
3441
3640
  export interface IDirtyRowTracker {