@xterm/xterm 5.4.0-beta.9 → 5.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/css/xterm.css +10 -1
- package/lib/xterm.js +1 -1
- package/lib/xterm.js.map +1 -1
- package/package.json +3 -3
- package/src/browser/AccessibilityManager.ts +132 -3
- package/src/browser/{Linkifier2.ts → Linkifier.ts} +36 -61
- package/src/browser/OscLinkProvider.ts +2 -1
- package/src/browser/RenderDebouncer.ts +6 -5
- package/src/browser/Terminal.ts +41 -33
- package/src/browser/Types.d.ts +2 -9
- package/src/browser/public/Terminal.ts +6 -0
- package/src/browser/renderer/dom/DomRendererRowFactory.ts +5 -5
- package/src/browser/renderer/dom/WidthCache.ts +11 -4
- package/src/browser/renderer/shared/CellColorResolver.ts +94 -8
- package/src/browser/renderer/shared/RendererUtils.ts +1 -1
- package/src/browser/renderer/shared/TextureAtlas.ts +14 -10
- package/src/browser/services/CharSizeService.ts +53 -28
- package/src/browser/services/LinkProviderService.ts +28 -0
- package/src/browser/services/RenderService.ts +14 -9
- package/src/browser/services/Services.ts +12 -1
- package/src/common/Color.ts +28 -12
- package/src/common/CoreTerminal.ts +5 -0
- package/src/common/InputHandler.ts +15 -19
- package/src/common/Types.d.ts +7 -7
- package/src/common/buffer/BufferLine.ts +47 -20
- package/src/common/services/OptionsService.ts +8 -1
- package/src/headless/Terminal.ts +4 -0
- package/src/headless/public/Terminal.ts +3 -0
- package/typings/xterm.d.ts +34 -0
|
@@ -8,12 +8,6 @@ import { EventEmitter } from 'common/EventEmitter';
|
|
|
8
8
|
import { ICharSizeService } from 'browser/services/Services';
|
|
9
9
|
import { Disposable } from 'common/Lifecycle';
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
const enum MeasureSettings {
|
|
13
|
-
REPEAT = 32
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
11
|
export class CharSizeService extends Disposable implements ICharSizeService {
|
|
18
12
|
public serviceBrand: undefined;
|
|
19
13
|
|
|
@@ -32,7 +26,11 @@ export class CharSizeService extends Disposable implements ICharSizeService {
|
|
|
32
26
|
@IOptionsService private readonly _optionsService: IOptionsService
|
|
33
27
|
) {
|
|
34
28
|
super();
|
|
35
|
-
|
|
29
|
+
try {
|
|
30
|
+
this._measureStrategy = this.register(new TextMetricsMeasureStrategy(this._optionsService));
|
|
31
|
+
} catch {
|
|
32
|
+
this._measureStrategy = this.register(new DomMeasureStrategy(document, parentElement, this._optionsService));
|
|
33
|
+
}
|
|
36
34
|
this.register(this._optionsService.onMultipleOptionChange(['fontFamily', 'fontSize'], () => this.measure()));
|
|
37
35
|
}
|
|
38
36
|
|
|
@@ -47,12 +45,7 @@ export class CharSizeService extends Disposable implements ICharSizeService {
|
|
|
47
45
|
}
|
|
48
46
|
|
|
49
47
|
interface IMeasureStrategy {
|
|
50
|
-
measure():
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
interface IReadonlyMeasureResult {
|
|
54
|
-
readonly width: number;
|
|
55
|
-
readonly height: number;
|
|
48
|
+
measure(): Readonly<IMeasureResult>;
|
|
56
49
|
}
|
|
57
50
|
|
|
58
51
|
interface IMeasureResult {
|
|
@@ -60,10 +53,26 @@ interface IMeasureResult {
|
|
|
60
53
|
height: number;
|
|
61
54
|
}
|
|
62
55
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
56
|
+
const enum DomMeasureStrategyConstants {
|
|
57
|
+
REPEAT = 32
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
abstract class BaseMeasureStategy extends Disposable implements IMeasureStrategy {
|
|
61
|
+
protected _result: IMeasureResult = { width: 0, height: 0 };
|
|
62
|
+
|
|
63
|
+
protected _validateAndSet(width: number | undefined, height: number | undefined): void {
|
|
64
|
+
// If values are 0 then the element is likely currently display:none, in which case we should
|
|
65
|
+
// retain the previous value.
|
|
66
|
+
if (width !== undefined && width > 0 && height !== undefined && height > 0) {
|
|
67
|
+
this._result.width = width;
|
|
68
|
+
this._result.height = height;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public abstract measure(): Readonly<IMeasureResult>;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
class DomMeasureStrategy extends BaseMeasureStategy {
|
|
67
76
|
private _measureElement: HTMLElement;
|
|
68
77
|
|
|
69
78
|
constructor(
|
|
@@ -71,32 +80,48 @@ class DomMeasureStrategy implements IMeasureStrategy {
|
|
|
71
80
|
private _parentElement: HTMLElement,
|
|
72
81
|
private _optionsService: IOptionsService
|
|
73
82
|
) {
|
|
83
|
+
super();
|
|
74
84
|
this._measureElement = this._document.createElement('span');
|
|
75
85
|
this._measureElement.classList.add('xterm-char-measure-element');
|
|
76
|
-
this._measureElement.textContent = 'W'.repeat(
|
|
86
|
+
this._measureElement.textContent = 'W'.repeat(DomMeasureStrategyConstants.REPEAT);
|
|
77
87
|
this._measureElement.setAttribute('aria-hidden', 'true');
|
|
78
88
|
this._measureElement.style.whiteSpace = 'pre';
|
|
79
89
|
this._measureElement.style.fontKerning = 'none';
|
|
80
90
|
this._parentElement.appendChild(this._measureElement);
|
|
81
91
|
}
|
|
82
92
|
|
|
83
|
-
public measure():
|
|
93
|
+
public measure(): Readonly<IMeasureResult> {
|
|
84
94
|
this._measureElement.style.fontFamily = this._optionsService.rawOptions.fontFamily;
|
|
85
95
|
this._measureElement.style.fontSize = `${this._optionsService.rawOptions.fontSize}px`;
|
|
86
96
|
|
|
87
97
|
// Note that this triggers a synchronous layout
|
|
88
|
-
|
|
89
|
-
height: Number(this._measureElement.offsetHeight),
|
|
90
|
-
width: Number(this._measureElement.offsetWidth)
|
|
91
|
-
};
|
|
98
|
+
this._validateAndSet(Number(this._measureElement.offsetWidth) / DomMeasureStrategyConstants.REPEAT, Number(this._measureElement.offsetHeight));
|
|
92
99
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
100
|
+
return this._result;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
class TextMetricsMeasureStrategy extends BaseMeasureStategy {
|
|
105
|
+
private _canvas: OffscreenCanvas;
|
|
106
|
+
private _ctx: OffscreenCanvasRenderingContext2D;
|
|
107
|
+
|
|
108
|
+
constructor(
|
|
109
|
+
private _optionsService: IOptionsService
|
|
110
|
+
) {
|
|
111
|
+
super();
|
|
112
|
+
// This will throw if any required API is not supported
|
|
113
|
+
this._canvas = new OffscreenCanvas(100, 100);
|
|
114
|
+
this._ctx = this._canvas.getContext('2d')!;
|
|
115
|
+
const a = this._ctx.measureText('W');
|
|
116
|
+
if (!('width' in a && 'fontBoundingBoxAscent' in a && 'fontBoundingBoxDescent' in a)) {
|
|
117
|
+
throw new Error('Required font metrics not supported');
|
|
98
118
|
}
|
|
119
|
+
}
|
|
99
120
|
|
|
121
|
+
public measure(): Readonly<IMeasureResult> {
|
|
122
|
+
this._ctx.font = `${this._optionsService.rawOptions.fontSize}px ${this._optionsService.rawOptions.fontFamily}`;
|
|
123
|
+
const metrics = this._ctx.measureText('W');
|
|
124
|
+
this._validateAndSet(metrics.width, metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent);
|
|
100
125
|
return this._result;
|
|
101
126
|
}
|
|
102
127
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ILinkProvider, ILinkProviderService } from 'browser/services/Services';
|
|
2
|
+
import { Disposable, toDisposable } from 'common/Lifecycle';
|
|
3
|
+
import { IDisposable } from 'common/Types';
|
|
4
|
+
|
|
5
|
+
export class LinkProviderService extends Disposable implements ILinkProviderService {
|
|
6
|
+
declare public serviceBrand: undefined;
|
|
7
|
+
|
|
8
|
+
public readonly linkProviders: ILinkProvider[] = [];
|
|
9
|
+
|
|
10
|
+
constructor() {
|
|
11
|
+
super();
|
|
12
|
+
this.register(toDisposable(() => this.linkProviders.length = 0));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public registerLinkProvider(linkProvider: ILinkProvider): IDisposable {
|
|
16
|
+
this.linkProviders.push(linkProvider);
|
|
17
|
+
return {
|
|
18
|
+
dispose: () => {
|
|
19
|
+
// Remove the link provider from the list
|
|
20
|
+
const providerIndex = this.linkProviders.indexOf(linkProvider);
|
|
21
|
+
|
|
22
|
+
if (providerIndex !== -1) {
|
|
23
|
+
this.linkProviders.splice(providerIndex, 1);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -8,9 +8,9 @@ import { IRenderDebouncerWithCallback } from 'browser/Types';
|
|
|
8
8
|
import { IRenderDimensions, IRenderer } from 'browser/renderer/shared/Types';
|
|
9
9
|
import { ICharSizeService, ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services';
|
|
10
10
|
import { EventEmitter } from 'common/EventEmitter';
|
|
11
|
-
import { Disposable, MutableDisposable } from 'common/Lifecycle';
|
|
11
|
+
import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
|
|
12
12
|
import { DebouncedIdleTask } from 'common/TaskQueue';
|
|
13
|
-
import { IBufferService, IDecorationService,
|
|
13
|
+
import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services';
|
|
14
14
|
|
|
15
15
|
interface ISelectionState {
|
|
16
16
|
start: [number, number] | undefined;
|
|
@@ -24,6 +24,7 @@ export class RenderService extends Disposable implements IRenderService {
|
|
|
24
24
|
private _renderer: MutableDisposable<IRenderer> = this.register(new MutableDisposable());
|
|
25
25
|
private _renderDebouncer: IRenderDebouncerWithCallback;
|
|
26
26
|
private _pausedResizeTask = new DebouncedIdleTask();
|
|
27
|
+
private _observerDisposable = this.register(new MutableDisposable());
|
|
27
28
|
|
|
28
29
|
private _isPaused: boolean = false;
|
|
29
30
|
private _needsFullRefresh: boolean = false;
|
|
@@ -38,7 +39,7 @@ export class RenderService extends Disposable implements IRenderService {
|
|
|
38
39
|
};
|
|
39
40
|
|
|
40
41
|
private readonly _onDimensionsChange = this.register(new EventEmitter<IRenderDimensions>());
|
|
41
|
-
public readonly onDimensionsChange =
|
|
42
|
+
public readonly onDimensionsChange = this._onDimensionsChange.event;
|
|
42
43
|
private readonly _onRenderedViewportChange = this.register(new EventEmitter<{ start: number, end: number }>());
|
|
43
44
|
public readonly onRenderedViewportChange = this._onRenderedViewportChange.event;
|
|
44
45
|
private readonly _onRender = this.register(new EventEmitter<{ start: number, end: number }>());
|
|
@@ -56,12 +57,11 @@ export class RenderService extends Disposable implements IRenderService {
|
|
|
56
57
|
@IDecorationService decorationService: IDecorationService,
|
|
57
58
|
@IBufferService bufferService: IBufferService,
|
|
58
59
|
@ICoreBrowserService coreBrowserService: ICoreBrowserService,
|
|
59
|
-
@IInstantiationService instantiationService: IInstantiationService,
|
|
60
60
|
@IThemeService themeService: IThemeService
|
|
61
61
|
) {
|
|
62
62
|
super();
|
|
63
63
|
|
|
64
|
-
this._renderDebouncer = new RenderDebouncer(
|
|
64
|
+
this._renderDebouncer = new RenderDebouncer((start, end) => this._renderRows(start, end), coreBrowserService);
|
|
65
65
|
this.register(this._renderDebouncer);
|
|
66
66
|
|
|
67
67
|
this.register(coreBrowserService.onDprChange(() => this.handleDevicePixelRatioChange()));
|
|
@@ -102,12 +102,17 @@ export class RenderService extends Disposable implements IRenderService {
|
|
|
102
102
|
|
|
103
103
|
this.register(themeService.onChangeColors(() => this._fullRefresh()));
|
|
104
104
|
|
|
105
|
+
this._registerIntersectionObserver(coreBrowserService.window, screenElement);
|
|
106
|
+
this.register(coreBrowserService.onWindowChange((w) => this._registerIntersectionObserver(w, screenElement)));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private _registerIntersectionObserver(w: Window & typeof globalThis, screenElement: HTMLElement): void {
|
|
105
110
|
// Detect whether IntersectionObserver is detected and enable renderer pause
|
|
106
111
|
// and resume based on terminal visibility if so
|
|
107
|
-
if ('IntersectionObserver' in
|
|
108
|
-
const observer = new
|
|
112
|
+
if ('IntersectionObserver' in w) {
|
|
113
|
+
const observer = new w.IntersectionObserver(e => this._handleIntersectionChange(e[e.length - 1]), { threshold: 0 });
|
|
109
114
|
observer.observe(screenElement);
|
|
110
|
-
this.
|
|
115
|
+
this._observerDisposable.value = toDisposable(() => observer.disconnect());
|
|
111
116
|
}
|
|
112
117
|
}
|
|
113
118
|
|
|
@@ -242,7 +247,7 @@ export class RenderService extends Disposable implements IRenderService {
|
|
|
242
247
|
return;
|
|
243
248
|
}
|
|
244
249
|
if (this._isPaused) {
|
|
245
|
-
this._pausedResizeTask.set(() => this._renderer.value
|
|
250
|
+
this._pausedResizeTask.set(() => this._renderer.value?.handleResize(cols, rows));
|
|
246
251
|
} else {
|
|
247
252
|
this._renderer.value.handleResize(cols, rows);
|
|
248
253
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { IEvent } from 'common/EventEmitter';
|
|
7
7
|
import { IRenderDimensions, IRenderer } from 'browser/renderer/shared/Types';
|
|
8
|
-
import { IColorSet, ReadonlyColorSet } from 'browser/Types';
|
|
8
|
+
import { IColorSet, ILink, ReadonlyColorSet } from 'browser/Types';
|
|
9
9
|
import { ISelectionRedrawRequestEvent as ISelectionRequestRedrawEvent, ISelectionRequestScrollLinesEvent } from 'browser/selection/Types';
|
|
10
10
|
import { createDecorator } from 'common/services/ServiceRegistry';
|
|
11
11
|
import { AllColorIndex, IDisposable } from 'common/Types';
|
|
@@ -145,3 +145,14 @@ export interface IThemeService {
|
|
|
145
145
|
*/
|
|
146
146
|
modifyColors(callback: (colors: IColorSet) => void): void;
|
|
147
147
|
}
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
export const ILinkProviderService = createDecorator<ILinkProviderService>('LinkProviderService');
|
|
151
|
+
export interface ILinkProviderService extends IDisposable {
|
|
152
|
+
serviceBrand: undefined;
|
|
153
|
+
readonly linkProviders: ReadonlyArray<ILinkProvider>;
|
|
154
|
+
registerLinkProvider(linkProvider: ILinkProvider): IDisposable;
|
|
155
|
+
}
|
|
156
|
+
export interface ILinkProvider {
|
|
157
|
+
provideLinks(y: number, callback: (links: ILink[] | undefined) => void): void;
|
|
158
|
+
}
|
package/src/common/Color.ts
CHANGED
|
@@ -33,6 +33,13 @@ export namespace channels {
|
|
|
33
33
|
// >>> 0 forces an unsigned int
|
|
34
34
|
return (r << 24 | g << 16 | b << 8 | a) >>> 0;
|
|
35
35
|
}
|
|
36
|
+
|
|
37
|
+
export function toColor(r: number, g: number, b: number, a?: number): IColor {
|
|
38
|
+
return {
|
|
39
|
+
css: channels.toCss(r, g, b, a),
|
|
40
|
+
rgba: channels.toRgba(r, g, b, a)
|
|
41
|
+
};
|
|
42
|
+
}
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
/**
|
|
@@ -70,7 +77,7 @@ export namespace color {
|
|
|
70
77
|
if (!result) {
|
|
71
78
|
return undefined;
|
|
72
79
|
}
|
|
73
|
-
return
|
|
80
|
+
return channels.toColor(
|
|
74
81
|
(result >> 24 & 0xFF),
|
|
75
82
|
(result >> 16 & 0xFF),
|
|
76
83
|
(result >> 8 & 0xFF)
|
|
@@ -142,14 +149,14 @@ export namespace css {
|
|
|
142
149
|
$r = parseInt(css.slice(1, 2).repeat(2), 16);
|
|
143
150
|
$g = parseInt(css.slice(2, 3).repeat(2), 16);
|
|
144
151
|
$b = parseInt(css.slice(3, 4).repeat(2), 16);
|
|
145
|
-
return
|
|
152
|
+
return channels.toColor($r, $g, $b);
|
|
146
153
|
}
|
|
147
154
|
case 5: { // #rgba
|
|
148
155
|
$r = parseInt(css.slice(1, 2).repeat(2), 16);
|
|
149
156
|
$g = parseInt(css.slice(2, 3).repeat(2), 16);
|
|
150
157
|
$b = parseInt(css.slice(3, 4).repeat(2), 16);
|
|
151
158
|
$a = parseInt(css.slice(4, 5).repeat(2), 16);
|
|
152
|
-
return
|
|
159
|
+
return channels.toColor($r, $g, $b, $a);
|
|
153
160
|
}
|
|
154
161
|
case 7: // #rrggbb
|
|
155
162
|
return {
|
|
@@ -171,7 +178,7 @@ export namespace css {
|
|
|
171
178
|
$g = parseInt(rgbaMatch[2]);
|
|
172
179
|
$b = parseInt(rgbaMatch[3]);
|
|
173
180
|
$a = Math.round((rgbaMatch[5] === undefined ? 1 : parseFloat(rgbaMatch[5])) * 0xFF);
|
|
174
|
-
return
|
|
181
|
+
return channels.toColor($r, $g, $b, $a);
|
|
175
182
|
}
|
|
176
183
|
|
|
177
184
|
// Validate the context is available for canvas-based color parsing
|
|
@@ -245,6 +252,23 @@ export namespace rgb {
|
|
|
245
252
|
* Helper functions where the source type is "rgba" (number: 0xrrggbbaa).
|
|
246
253
|
*/
|
|
247
254
|
export namespace rgba {
|
|
255
|
+
export function blend(bg: number, fg: number): number {
|
|
256
|
+
$a = (fg & 0xFF) / 0xFF;
|
|
257
|
+
if ($a === 1) {
|
|
258
|
+
return fg;
|
|
259
|
+
}
|
|
260
|
+
const fgR = (fg >> 24) & 0xFF;
|
|
261
|
+
const fgG = (fg >> 16) & 0xFF;
|
|
262
|
+
const fgB = (fg >> 8) & 0xFF;
|
|
263
|
+
const bgR = (bg >> 24) & 0xFF;
|
|
264
|
+
const bgG = (bg >> 16) & 0xFF;
|
|
265
|
+
const bgB = (bg >> 8) & 0xFF;
|
|
266
|
+
$r = bgR + Math.round((fgR - bgR) * $a);
|
|
267
|
+
$g = bgG + Math.round((fgG - bgG) * $a);
|
|
268
|
+
$b = bgB + Math.round((fgB - bgB) * $a);
|
|
269
|
+
return channels.toRgba($r, $g, $b);
|
|
270
|
+
}
|
|
271
|
+
|
|
248
272
|
/**
|
|
249
273
|
* Given a foreground color and a background color, either increase or reduce the luminance of the
|
|
250
274
|
* foreground color until the specified contrast ratio is met. If pure white or black is hit
|
|
@@ -325,17 +349,9 @@ export namespace rgba {
|
|
|
325
349
|
return (fgR << 24 | fgG << 16 | fgB << 8 | 0xFF) >>> 0;
|
|
326
350
|
}
|
|
327
351
|
|
|
328
|
-
// FIXME: Move this to channels NS?
|
|
329
352
|
export function toChannels(value: number): [number, number, number, number] {
|
|
330
353
|
return [(value >> 24) & 0xFF, (value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF];
|
|
331
354
|
}
|
|
332
|
-
|
|
333
|
-
export function toColor(r: number, g: number, b: number, a?: number): IColor {
|
|
334
|
-
return {
|
|
335
|
-
css: channels.toCss(r, g, b, a),
|
|
336
|
-
rgba: channels.toRgba(r, g, b, a)
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
355
|
}
|
|
340
356
|
|
|
341
357
|
export function toPaddedHex(c: number): string {
|
|
@@ -120,6 +120,7 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
|
|
|
120
120
|
this._oscLinkService = this._instantiationService.createInstance(OscLinkService);
|
|
121
121
|
this._instantiationService.setService(IOscLinkService, this._oscLinkService);
|
|
122
122
|
|
|
123
|
+
|
|
123
124
|
// Register input handler and handle/forward events
|
|
124
125
|
this._inputHandler = this.register(new InputHandler(this._bufferService, this._charsetService, this.coreService, this._logService, this.optionsService, this._oscLinkService, this.coreMouseService, this.unicodeService));
|
|
125
126
|
this.register(forwardEvent(this._inputHandler.onLineFeed, this._onLineFeed));
|
|
@@ -167,6 +168,10 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
|
|
|
167
168
|
this._writeBuffer.writeSync(data, maxSubsequentCalls);
|
|
168
169
|
}
|
|
169
170
|
|
|
171
|
+
public input(data: string, wasUserInput: boolean = true): void {
|
|
172
|
+
this.coreService.triggerDataEvent(data, wasUserInput);
|
|
173
|
+
}
|
|
174
|
+
|
|
170
175
|
public resize(x: number, y: number): void {
|
|
171
176
|
if (isNaN(x) || isNaN(y)) {
|
|
172
177
|
return;
|
|
@@ -519,7 +519,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|
|
519
519
|
|
|
520
520
|
// handle wide chars: reset start_cell-1 if we would overwrite the second cell of a wide char
|
|
521
521
|
if (this._activeBuffer.x && end - start > 0 && bufferRow.getWidth(this._activeBuffer.x - 1) === 2) {
|
|
522
|
-
bufferRow.
|
|
522
|
+
bufferRow.setCellFromCodepoint(this._activeBuffer.x - 1, 0, 1, curAttr);
|
|
523
523
|
}
|
|
524
524
|
|
|
525
525
|
let precedingJoinState = this._parser.precedingJoinState;
|
|
@@ -581,7 +581,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|
|
581
581
|
}
|
|
582
582
|
// clear left over cells to the right
|
|
583
583
|
while (oldCol < cols) {
|
|
584
|
-
oldRow.
|
|
584
|
+
oldRow.setCellFromCodepoint(oldCol++, 0, 1, curAttr);
|
|
585
585
|
}
|
|
586
586
|
} else {
|
|
587
587
|
this._activeBuffer.x = cols - 1;
|
|
@@ -605,7 +605,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|
|
605
605
|
bufferRow.addCodepointToCell(this._activeBuffer.x - offset,
|
|
606
606
|
code, chWidth);
|
|
607
607
|
for (let delta = chWidth - oldWidth; --delta >= 0; ) {
|
|
608
|
-
bufferRow.
|
|
608
|
+
bufferRow.setCellFromCodepoint(this._activeBuffer.x++, 0, 0, curAttr);
|
|
609
609
|
}
|
|
610
610
|
continue;
|
|
611
611
|
}
|
|
@@ -613,17 +613,17 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|
|
613
613
|
// insert mode: move characters to right
|
|
614
614
|
if (insertMode) {
|
|
615
615
|
// right shift cells according to the width
|
|
616
|
-
bufferRow.insertCells(this._activeBuffer.x, chWidth - oldWidth, this._activeBuffer.getNullCell(curAttr)
|
|
616
|
+
bufferRow.insertCells(this._activeBuffer.x, chWidth - oldWidth, this._activeBuffer.getNullCell(curAttr));
|
|
617
617
|
// test last cell - since the last cell has only room for
|
|
618
618
|
// a halfwidth char any fullwidth shifted there is lost
|
|
619
619
|
// and will be set to empty cell
|
|
620
620
|
if (bufferRow.getWidth(cols - 1) === 2) {
|
|
621
|
-
bufferRow.
|
|
621
|
+
bufferRow.setCellFromCodepoint(cols - 1, NULL_CELL_CODE, NULL_CELL_WIDTH, curAttr);
|
|
622
622
|
}
|
|
623
623
|
}
|
|
624
624
|
|
|
625
625
|
// write current char to buffer and advance cursor
|
|
626
|
-
bufferRow.
|
|
626
|
+
bufferRow.setCellFromCodepoint(this._activeBuffer.x++, code, chWidth, curAttr);
|
|
627
627
|
|
|
628
628
|
// fullwidth char - also set next cell to placeholder stub and advance cursor
|
|
629
629
|
// for graphemes bigger than fullwidth we can simply loop to zero
|
|
@@ -631,7 +631,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|
|
631
631
|
if (chWidth > 0) {
|
|
632
632
|
while (--chWidth) {
|
|
633
633
|
// other than a regular empty cell a cell following a wide char has no width
|
|
634
|
-
bufferRow.
|
|
634
|
+
bufferRow.setCellFromCodepoint(this._activeBuffer.x++, 0, 0, curAttr);
|
|
635
635
|
}
|
|
636
636
|
}
|
|
637
637
|
}
|
|
@@ -640,7 +640,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|
|
640
640
|
|
|
641
641
|
// handle wide chars: reset cell to the right if it is second cell of a wide char
|
|
642
642
|
if (this._activeBuffer.x < cols && end - start > 0 && bufferRow.getWidth(this._activeBuffer.x) === 0 && !bufferRow.hasContent(this._activeBuffer.x)) {
|
|
643
|
-
bufferRow.
|
|
643
|
+
bufferRow.setCellFromCodepoint(this._activeBuffer.x, 0, 1, curAttr);
|
|
644
644
|
}
|
|
645
645
|
|
|
646
646
|
this._dirtyRowTracker.markDirty(this._activeBuffer.y);
|
|
@@ -1145,7 +1145,6 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|
|
1145
1145
|
start,
|
|
1146
1146
|
end,
|
|
1147
1147
|
this._activeBuffer.getNullCell(this._eraseAttrData()),
|
|
1148
|
-
this._eraseAttrData(),
|
|
1149
1148
|
respectProtect
|
|
1150
1149
|
);
|
|
1151
1150
|
if (clearWrap) {
|
|
@@ -1366,8 +1365,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|
|
1366
1365
|
line.insertCells(
|
|
1367
1366
|
this._activeBuffer.x,
|
|
1368
1367
|
params.params[0] || 1,
|
|
1369
|
-
this._activeBuffer.getNullCell(this._eraseAttrData())
|
|
1370
|
-
this._eraseAttrData()
|
|
1368
|
+
this._activeBuffer.getNullCell(this._eraseAttrData())
|
|
1371
1369
|
);
|
|
1372
1370
|
this._dirtyRowTracker.markDirty(this._activeBuffer.y);
|
|
1373
1371
|
}
|
|
@@ -1393,8 +1391,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|
|
1393
1391
|
line.deleteCells(
|
|
1394
1392
|
this._activeBuffer.x,
|
|
1395
1393
|
params.params[0] || 1,
|
|
1396
|
-
this._activeBuffer.getNullCell(this._eraseAttrData())
|
|
1397
|
-
this._eraseAttrData()
|
|
1394
|
+
this._activeBuffer.getNullCell(this._eraseAttrData())
|
|
1398
1395
|
);
|
|
1399
1396
|
this._dirtyRowTracker.markDirty(this._activeBuffer.y);
|
|
1400
1397
|
}
|
|
@@ -1461,7 +1458,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|
|
1461
1458
|
const param = params.params[0] || 1;
|
|
1462
1459
|
for (let y = this._activeBuffer.scrollTop; y <= this._activeBuffer.scrollBottom; ++y) {
|
|
1463
1460
|
const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!;
|
|
1464
|
-
line.deleteCells(0, param, this._activeBuffer.getNullCell(this._eraseAttrData())
|
|
1461
|
+
line.deleteCells(0, param, this._activeBuffer.getNullCell(this._eraseAttrData()));
|
|
1465
1462
|
line.isWrapped = false;
|
|
1466
1463
|
}
|
|
1467
1464
|
this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom);
|
|
@@ -1494,7 +1491,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|
|
1494
1491
|
const param = params.params[0] || 1;
|
|
1495
1492
|
for (let y = this._activeBuffer.scrollTop; y <= this._activeBuffer.scrollBottom; ++y) {
|
|
1496
1493
|
const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!;
|
|
1497
|
-
line.insertCells(0, param, this._activeBuffer.getNullCell(this._eraseAttrData())
|
|
1494
|
+
line.insertCells(0, param, this._activeBuffer.getNullCell(this._eraseAttrData()));
|
|
1498
1495
|
line.isWrapped = false;
|
|
1499
1496
|
}
|
|
1500
1497
|
this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom);
|
|
@@ -1517,7 +1514,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|
|
1517
1514
|
const param = params.params[0] || 1;
|
|
1518
1515
|
for (let y = this._activeBuffer.scrollTop; y <= this._activeBuffer.scrollBottom; ++y) {
|
|
1519
1516
|
const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!;
|
|
1520
|
-
line.insertCells(this._activeBuffer.x, param, this._activeBuffer.getNullCell(this._eraseAttrData())
|
|
1517
|
+
line.insertCells(this._activeBuffer.x, param, this._activeBuffer.getNullCell(this._eraseAttrData()));
|
|
1521
1518
|
line.isWrapped = false;
|
|
1522
1519
|
}
|
|
1523
1520
|
this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom);
|
|
@@ -1540,7 +1537,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|
|
1540
1537
|
const param = params.params[0] || 1;
|
|
1541
1538
|
for (let y = this._activeBuffer.scrollTop; y <= this._activeBuffer.scrollBottom; ++y) {
|
|
1542
1539
|
const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!;
|
|
1543
|
-
line.deleteCells(this._activeBuffer.x, param, this._activeBuffer.getNullCell(this._eraseAttrData())
|
|
1540
|
+
line.deleteCells(this._activeBuffer.x, param, this._activeBuffer.getNullCell(this._eraseAttrData()));
|
|
1544
1541
|
line.isWrapped = false;
|
|
1545
1542
|
}
|
|
1546
1543
|
this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom);
|
|
@@ -1562,8 +1559,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|
|
1562
1559
|
line.replaceCells(
|
|
1563
1560
|
this._activeBuffer.x,
|
|
1564
1561
|
this._activeBuffer.x + (params.params[0] || 1),
|
|
1565
|
-
this._activeBuffer.getNullCell(this._eraseAttrData())
|
|
1566
|
-
this._eraseAttrData()
|
|
1562
|
+
this._activeBuffer.getNullCell(this._eraseAttrData())
|
|
1567
1563
|
);
|
|
1568
1564
|
this._dirtyRowTracker.markDirty(this._activeBuffer.y);
|
|
1569
1565
|
}
|
package/src/common/Types.d.ts
CHANGED
|
@@ -110,8 +110,8 @@ export interface ICharset {
|
|
|
110
110
|
export type CharData = [number, string, number, number];
|
|
111
111
|
|
|
112
112
|
export interface IColor {
|
|
113
|
-
css: string;
|
|
114
|
-
rgba: number; // 32-bit int with rgba in each byte
|
|
113
|
+
readonly css: string;
|
|
114
|
+
readonly rgba: number; // 32-bit int with rgba in each byte
|
|
115
115
|
}
|
|
116
116
|
export type IColorRGB = [number, number, number];
|
|
117
117
|
|
|
@@ -235,11 +235,11 @@ export interface IBufferLine {
|
|
|
235
235
|
set(index: number, value: CharData): void;
|
|
236
236
|
loadCell(index: number, cell: ICellData): ICellData;
|
|
237
237
|
setCell(index: number, cell: ICellData): void;
|
|
238
|
-
|
|
238
|
+
setCellFromCodepoint(index: number, codePoint: number, width: number, attrs: IAttributeData): void;
|
|
239
239
|
addCodepointToCell(index: number, codePoint: number, width: number): void;
|
|
240
|
-
insertCells(pos: number, n: number, ch: ICellData
|
|
241
|
-
deleteCells(pos: number, n: number, fill: ICellData
|
|
242
|
-
replaceCells(start: number, end: number, fill: ICellData,
|
|
240
|
+
insertCells(pos: number, n: number, ch: ICellData): void;
|
|
241
|
+
deleteCells(pos: number, n: number, fill: ICellData): void;
|
|
242
|
+
replaceCells(start: number, end: number, fill: ICellData, respectProtect?: boolean): void;
|
|
243
243
|
resize(cols: number, fill: ICellData): boolean;
|
|
244
244
|
cleanupMemory(): number;
|
|
245
245
|
fill(fillCellData: ICellData, respectProtect?: boolean): void;
|
|
@@ -247,7 +247,7 @@ export interface IBufferLine {
|
|
|
247
247
|
clone(): IBufferLine;
|
|
248
248
|
getTrimmedLength(): number;
|
|
249
249
|
getNoBgTrimmedLength(): number;
|
|
250
|
-
translateToString(trimRight?: boolean, startCol?: number, endCol?: number): string;
|
|
250
|
+
translateToString(trimRight?: boolean, startCol?: number, endCol?: number, outColumns?: number[]): string;
|
|
251
251
|
|
|
252
252
|
/* direct access to cell attrs */
|
|
253
253
|
getWidth(index: number): number;
|