@wendongfly/myhi 1.0.2 → 1.0.3
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/dist/index.js +1 -1
- package/dist/lib/xterm/LICENSE +21 -0
- package/dist/lib/xterm/README.md +225 -0
- package/dist/lib/xterm/css/xterm.css +190 -0
- package/dist/lib/xterm/lib/xterm.js +2 -0
- package/dist/lib/xterm/lib/xterm.js.map +1 -0
- package/dist/lib/xterm/package.json +90 -0
- package/dist/lib/xterm/src/browser/AccessibilityManager.ts +301 -0
- package/dist/lib/xterm/src/browser/Clipboard.ts +99 -0
- package/dist/lib/xterm/src/browser/ColorContrastCache.ts +39 -0
- package/dist/lib/xterm/src/browser/ColorManager.ts +268 -0
- package/dist/lib/xterm/src/browser/Dom.ts +10 -0
- package/dist/lib/xterm/src/browser/Lifecycle.ts +30 -0
- package/dist/lib/xterm/src/browser/Linkifier.ts +356 -0
- package/dist/lib/xterm/src/browser/Linkifier2.ts +397 -0
- package/dist/lib/xterm/src/browser/LocalizableStrings.ts +10 -0
- package/dist/lib/xterm/src/browser/MouseZoneManager.ts +236 -0
- package/dist/lib/xterm/src/browser/RenderDebouncer.ts +82 -0
- package/dist/lib/xterm/src/browser/ScreenDprMonitor.ts +69 -0
- package/dist/lib/xterm/src/browser/Terminal.ts +1447 -0
- package/dist/lib/xterm/src/browser/TimeBasedDebouncer.ts +86 -0
- package/dist/lib/xterm/src/browser/Types.d.ts +317 -0
- package/dist/lib/xterm/src/browser/Viewport.ts +276 -0
- package/dist/lib/xterm/src/browser/decorations/BufferDecorationRenderer.ts +131 -0
- package/dist/lib/xterm/src/browser/decorations/ColorZoneStore.ts +117 -0
- package/dist/lib/xterm/src/browser/decorations/OverviewRulerRenderer.ts +228 -0
- package/dist/lib/xterm/src/browser/input/CompositionHelper.ts +237 -0
- package/dist/lib/xterm/src/browser/input/Mouse.ts +64 -0
- package/dist/lib/xterm/src/browser/input/MoveToCell.ts +249 -0
- package/dist/lib/xterm/src/browser/public/Terminal.ts +298 -0
- package/dist/lib/xterm/src/browser/renderer/BaseRenderLayer.ts +582 -0
- package/dist/lib/xterm/src/browser/renderer/CursorRenderLayer.ts +378 -0
- package/dist/lib/xterm/src/browser/renderer/CustomGlyphs.ts +632 -0
- package/dist/lib/xterm/src/browser/renderer/GridCache.ts +33 -0
- package/dist/lib/xterm/src/browser/renderer/LinkRenderLayer.ts +84 -0
- package/dist/lib/xterm/src/browser/renderer/Renderer.ts +219 -0
- package/dist/lib/xterm/src/browser/renderer/RendererUtils.ts +26 -0
- package/dist/lib/xterm/src/browser/renderer/SelectionRenderLayer.ts +131 -0
- package/dist/lib/xterm/src/browser/renderer/TextRenderLayer.ts +344 -0
- package/dist/lib/xterm/src/browser/renderer/Types.d.ts +109 -0
- package/dist/lib/xterm/src/browser/renderer/atlas/BaseCharAtlas.ts +58 -0
- package/dist/lib/xterm/src/browser/renderer/atlas/CharAtlasCache.ts +95 -0
- package/dist/lib/xterm/src/browser/renderer/atlas/CharAtlasUtils.ts +54 -0
- package/dist/lib/xterm/src/browser/renderer/atlas/Constants.ts +15 -0
- package/dist/lib/xterm/src/browser/renderer/atlas/DynamicCharAtlas.ts +404 -0
- package/dist/lib/xterm/src/browser/renderer/atlas/LRUMap.ts +136 -0
- package/dist/lib/xterm/src/browser/renderer/atlas/Types.d.ts +29 -0
- package/dist/lib/xterm/src/browser/renderer/dom/DomRenderer.ts +403 -0
- package/dist/lib/xterm/src/browser/renderer/dom/DomRendererRowFactory.ts +344 -0
- package/dist/lib/xterm/src/browser/selection/SelectionModel.ts +144 -0
- package/dist/lib/xterm/src/browser/selection/Types.d.ts +15 -0
- package/dist/lib/xterm/src/browser/services/CharSizeService.ts +87 -0
- package/dist/lib/xterm/src/browser/services/CharacterJoinerService.ts +339 -0
- package/dist/lib/xterm/src/browser/services/CoreBrowserService.ts +20 -0
- package/dist/lib/xterm/src/browser/services/MouseService.ts +36 -0
- package/dist/lib/xterm/src/browser/services/RenderService.ts +237 -0
- package/dist/lib/xterm/src/browser/services/SelectionService.ts +1027 -0
- package/dist/lib/xterm/src/browser/services/Services.ts +123 -0
- package/dist/lib/xterm/src/browser/services/SoundService.ts +63 -0
- package/dist/lib/xterm/src/common/CircularList.ts +239 -0
- package/dist/lib/xterm/src/common/Clone.ts +23 -0
- package/dist/lib/xterm/src/common/Color.ts +285 -0
- package/dist/lib/xterm/src/common/CoreTerminal.ts +300 -0
- package/dist/lib/xterm/src/common/EventEmitter.ts +69 -0
- package/dist/lib/xterm/src/common/InputHandler.ts +3230 -0
- package/dist/lib/xterm/src/common/Lifecycle.ts +68 -0
- package/dist/lib/xterm/src/common/Platform.ts +31 -0
- package/dist/lib/xterm/src/common/SortedList.ts +88 -0
- package/dist/lib/xterm/src/common/TypedArrayUtils.ts +50 -0
- package/dist/lib/xterm/src/common/Types.d.ts +489 -0
- package/dist/lib/xterm/src/common/WindowsMode.ts +27 -0
- package/dist/lib/xterm/src/common/buffer/AttributeData.ts +148 -0
- package/dist/lib/xterm/src/common/buffer/Buffer.ts +711 -0
- package/dist/lib/xterm/src/common/buffer/BufferLine.ts +441 -0
- package/dist/lib/xterm/src/common/buffer/BufferRange.ts +13 -0
- package/dist/lib/xterm/src/common/buffer/BufferReflow.ts +220 -0
- package/dist/lib/xterm/src/common/buffer/BufferSet.ts +131 -0
- package/dist/lib/xterm/src/common/buffer/CellData.ts +94 -0
- package/dist/lib/xterm/src/common/buffer/Constants.ts +139 -0
- package/dist/lib/xterm/src/common/buffer/Marker.ts +37 -0
- package/dist/lib/xterm/src/common/buffer/Types.d.ts +64 -0
- package/dist/lib/xterm/src/common/data/Charsets.ts +256 -0
- package/dist/lib/xterm/src/common/data/EscapeSequences.ts +153 -0
- package/dist/lib/xterm/src/common/input/Keyboard.ts +398 -0
- package/dist/lib/xterm/src/common/input/TextDecoder.ts +346 -0
- package/dist/lib/xterm/src/common/input/UnicodeV6.ts +133 -0
- package/dist/lib/xterm/src/common/input/WriteBuffer.ts +229 -0
- package/dist/lib/xterm/src/common/input/XParseColor.ts +80 -0
- package/dist/lib/xterm/src/common/parser/Constants.ts +58 -0
- package/dist/lib/xterm/src/common/parser/DcsParser.ts +192 -0
- package/dist/lib/xterm/src/common/parser/EscapeSequenceParser.ts +796 -0
- package/dist/lib/xterm/src/common/parser/OscParser.ts +238 -0
- package/dist/lib/xterm/src/common/parser/Params.ts +229 -0
- package/dist/lib/xterm/src/common/parser/Types.d.ts +274 -0
- package/dist/lib/xterm/src/common/public/AddonManager.ts +56 -0
- package/dist/lib/xterm/src/common/public/BufferApiView.ts +35 -0
- package/dist/lib/xterm/src/common/public/BufferLineApiView.ts +29 -0
- package/dist/lib/xterm/src/common/public/BufferNamespaceApi.ts +33 -0
- package/dist/lib/xterm/src/common/public/ParserApi.ts +37 -0
- package/dist/lib/xterm/src/common/public/UnicodeApi.ts +27 -0
- package/dist/lib/xterm/src/common/services/BufferService.ts +185 -0
- package/dist/lib/xterm/src/common/services/CharsetService.ts +34 -0
- package/dist/lib/xterm/src/common/services/CoreMouseService.ts +309 -0
- package/dist/lib/xterm/src/common/services/CoreService.ts +92 -0
- package/dist/lib/xterm/src/common/services/DecorationService.ts +139 -0
- package/dist/lib/xterm/src/common/services/DirtyRowService.ts +53 -0
- package/dist/lib/xterm/src/common/services/InstantiationService.ts +83 -0
- package/dist/lib/xterm/src/common/services/LogService.ts +88 -0
- package/dist/lib/xterm/src/common/services/OptionsService.ts +178 -0
- package/dist/lib/xterm/src/common/services/ServiceRegistry.ts +49 -0
- package/dist/lib/xterm/src/common/services/Services.ts +323 -0
- package/dist/lib/xterm/src/common/services/UnicodeService.ts +82 -0
- package/dist/lib/xterm/src/headless/Terminal.ts +170 -0
- package/dist/lib/xterm/src/headless/Types.d.ts +31 -0
- package/dist/lib/xterm/src/headless/public/Terminal.ts +216 -0
- package/dist/lib/xterm/typings/xterm.d.ts +1872 -0
- package/dist/lib/xterm-fit/LICENSE +19 -0
- package/dist/lib/xterm-fit/README.md +24 -0
- package/dist/lib/xterm-fit/lib/xterm-addon-fit.js +2 -0
- package/dist/lib/xterm-fit/lib/xterm-addon-fit.js.map +1 -0
- package/dist/lib/xterm-fit/out/FitAddon.js +58 -0
- package/dist/lib/xterm-fit/out/FitAddon.js.map +1 -0
- package/dist/lib/xterm-fit/out-test/FitAddon.api.js.map +1 -0
- package/dist/lib/xterm-fit/package.json +21 -0
- package/dist/lib/xterm-fit/src/FitAddon.ts +86 -0
- package/dist/lib/xterm-fit/typings/xterm-addon-fit.d.ts +55 -0
- package/dist/lib/xterm-links/LICENSE +19 -0
- package/dist/lib/xterm-links/README.md +21 -0
- package/dist/lib/xterm-links/lib/xterm-addon-web-links.js +2 -0
- package/dist/lib/xterm-links/lib/xterm-addon-web-links.js.map +1 -0
- package/dist/lib/xterm-links/package.json +26 -0
- package/dist/lib/xterm-links/src/WebLinkProvider.ts +145 -0
- package/dist/lib/xterm-links/src/WebLinksAddon.ts +77 -0
- package/dist/lib/xterm-links/typings/xterm-addon-web-links.d.ts +58 -0
- package/package.json +1 -1
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
|
|
3
|
+
* @license MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { CharData, IBufferLine, ICellData, IAttributeData, IExtendedAttrs } from 'common/Types';
|
|
7
|
+
import { stringFromCodePoint } from 'common/input/TextDecoder';
|
|
8
|
+
import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_ATTR_INDEX, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, WHITESPACE_CELL_CHAR, Content, BgFlags } from 'common/buffer/Constants';
|
|
9
|
+
import { CellData } from 'common/buffer/CellData';
|
|
10
|
+
import { AttributeData, ExtendedAttrs } from 'common/buffer/AttributeData';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* buffer memory layout:
|
|
14
|
+
*
|
|
15
|
+
* | uint32_t | uint32_t | uint32_t |
|
|
16
|
+
* | `content` | `FG` | `BG` |
|
|
17
|
+
* | wcwidth(2) comb(1) codepoint(21) | flags(8) R(8) G(8) B(8) | flags(8) R(8) G(8) B(8) |
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
/** typed array slots taken by one cell */
|
|
22
|
+
const CELL_SIZE = 3;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Cell member indices.
|
|
26
|
+
*
|
|
27
|
+
* Direct access:
|
|
28
|
+
* `content = data[column * CELL_SIZE + Cell.CONTENT];`
|
|
29
|
+
* `fg = data[column * CELL_SIZE + Cell.FG];`
|
|
30
|
+
* `bg = data[column * CELL_SIZE + Cell.BG];`
|
|
31
|
+
*/
|
|
32
|
+
const enum Cell {
|
|
33
|
+
CONTENT = 0,
|
|
34
|
+
FG = 1, // currently simply holds all known attrs
|
|
35
|
+
BG = 2 // currently unused
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const DEFAULT_ATTR_DATA = Object.freeze(new AttributeData());
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Typed array based bufferline implementation.
|
|
42
|
+
*
|
|
43
|
+
* There are 2 ways to insert data into the cell buffer:
|
|
44
|
+
* - `setCellFromCodepoint` + `addCodepointToCell`
|
|
45
|
+
* Use these for data that is already UTF32.
|
|
46
|
+
* Used during normal input in `InputHandler` for faster buffer access.
|
|
47
|
+
* - `setCell`
|
|
48
|
+
* This method takes a CellData object and stores the data in the buffer.
|
|
49
|
+
* Use `CellData.fromCharData` to create the CellData object (e.g. from JS string).
|
|
50
|
+
*
|
|
51
|
+
* To retrieve data from the buffer use either one of the primitive methods
|
|
52
|
+
* (if only one particular value is needed) or `loadCell`. For `loadCell` in a loop
|
|
53
|
+
* memory allocs / GC pressure can be greatly reduced by reusing the CellData object.
|
|
54
|
+
*/
|
|
55
|
+
export class BufferLine implements IBufferLine {
|
|
56
|
+
protected _data: Uint32Array;
|
|
57
|
+
protected _combined: {[index: number]: string} = {};
|
|
58
|
+
protected _extendedAttrs: {[index: number]: ExtendedAttrs} = {};
|
|
59
|
+
public length: number;
|
|
60
|
+
|
|
61
|
+
constructor(cols: number, fillCellData?: ICellData, public isWrapped: boolean = false) {
|
|
62
|
+
this._data = new Uint32Array(cols * CELL_SIZE);
|
|
63
|
+
const cell = fillCellData || CellData.fromCharData([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]);
|
|
64
|
+
for (let i = 0; i < cols; ++i) {
|
|
65
|
+
this.setCell(i, cell);
|
|
66
|
+
}
|
|
67
|
+
this.length = cols;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Get cell data CharData.
|
|
72
|
+
* @deprecated
|
|
73
|
+
*/
|
|
74
|
+
public get(index: number): CharData {
|
|
75
|
+
const content = this._data[index * CELL_SIZE + Cell.CONTENT];
|
|
76
|
+
const cp = content & Content.CODEPOINT_MASK;
|
|
77
|
+
return [
|
|
78
|
+
this._data[index * CELL_SIZE + Cell.FG],
|
|
79
|
+
(content & Content.IS_COMBINED_MASK)
|
|
80
|
+
? this._combined[index]
|
|
81
|
+
: (cp) ? stringFromCodePoint(cp) : '',
|
|
82
|
+
content >> Content.WIDTH_SHIFT,
|
|
83
|
+
(content & Content.IS_COMBINED_MASK)
|
|
84
|
+
? this._combined[index].charCodeAt(this._combined[index].length - 1)
|
|
85
|
+
: cp
|
|
86
|
+
];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Set cell data from CharData.
|
|
91
|
+
* @deprecated
|
|
92
|
+
*/
|
|
93
|
+
public set(index: number, value: CharData): void {
|
|
94
|
+
this._data[index * CELL_SIZE + Cell.FG] = value[CHAR_DATA_ATTR_INDEX];
|
|
95
|
+
if (value[CHAR_DATA_CHAR_INDEX].length > 1) {
|
|
96
|
+
this._combined[index] = value[1];
|
|
97
|
+
this._data[index * CELL_SIZE + Cell.CONTENT] = index | Content.IS_COMBINED_MASK | (value[CHAR_DATA_WIDTH_INDEX] << Content.WIDTH_SHIFT);
|
|
98
|
+
} else {
|
|
99
|
+
this._data[index * CELL_SIZE + Cell.CONTENT] = value[CHAR_DATA_CHAR_INDEX].charCodeAt(0) | (value[CHAR_DATA_WIDTH_INDEX] << Content.WIDTH_SHIFT);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* primitive getters
|
|
105
|
+
* use these when only one value is needed, otherwise use `loadCell`
|
|
106
|
+
*/
|
|
107
|
+
public getWidth(index: number): number {
|
|
108
|
+
return this._data[index * CELL_SIZE + Cell.CONTENT] >> Content.WIDTH_SHIFT;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Test whether content has width. */
|
|
112
|
+
public hasWidth(index: number): number {
|
|
113
|
+
return this._data[index * CELL_SIZE + Cell.CONTENT] & Content.WIDTH_MASK;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** Get FG cell component. */
|
|
117
|
+
public getFg(index: number): number {
|
|
118
|
+
return this._data[index * CELL_SIZE + Cell.FG];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** Get BG cell component. */
|
|
122
|
+
public getBg(index: number): number {
|
|
123
|
+
return this._data[index * CELL_SIZE + Cell.BG];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Test whether contains any chars.
|
|
128
|
+
* Basically an empty has no content, but other cells might differ in FG/BG
|
|
129
|
+
* from real empty cells.
|
|
130
|
+
* */
|
|
131
|
+
public hasContent(index: number): number {
|
|
132
|
+
return this._data[index * CELL_SIZE + Cell.CONTENT] & Content.HAS_CONTENT_MASK;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Get codepoint of the cell.
|
|
137
|
+
* To be in line with `code` in CharData this either returns
|
|
138
|
+
* a single UTF32 codepoint or the last codepoint of a combined string.
|
|
139
|
+
*/
|
|
140
|
+
public getCodePoint(index: number): number {
|
|
141
|
+
const content = this._data[index * CELL_SIZE + Cell.CONTENT];
|
|
142
|
+
if (content & Content.IS_COMBINED_MASK) {
|
|
143
|
+
return this._combined[index].charCodeAt(this._combined[index].length - 1);
|
|
144
|
+
}
|
|
145
|
+
return content & Content.CODEPOINT_MASK;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** Test whether the cell contains a combined string. */
|
|
149
|
+
public isCombined(index: number): number {
|
|
150
|
+
return this._data[index * CELL_SIZE + Cell.CONTENT] & Content.IS_COMBINED_MASK;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** Returns the string content of the cell. */
|
|
154
|
+
public getString(index: number): string {
|
|
155
|
+
const content = this._data[index * CELL_SIZE + Cell.CONTENT];
|
|
156
|
+
if (content & Content.IS_COMBINED_MASK) {
|
|
157
|
+
return this._combined[index];
|
|
158
|
+
}
|
|
159
|
+
if (content & Content.CODEPOINT_MASK) {
|
|
160
|
+
return stringFromCodePoint(content & Content.CODEPOINT_MASK);
|
|
161
|
+
}
|
|
162
|
+
// return empty string for empty cells
|
|
163
|
+
return '';
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Load data at `index` into `cell`. This is used to access cells in a way that's more friendly
|
|
168
|
+
* to GC as it significantly reduced the amount of new objects/references needed.
|
|
169
|
+
*/
|
|
170
|
+
public loadCell(index: number, cell: ICellData): ICellData {
|
|
171
|
+
const startIndex = index * CELL_SIZE;
|
|
172
|
+
cell.content = this._data[startIndex + Cell.CONTENT];
|
|
173
|
+
cell.fg = this._data[startIndex + Cell.FG];
|
|
174
|
+
cell.bg = this._data[startIndex + Cell.BG];
|
|
175
|
+
if (cell.content & Content.IS_COMBINED_MASK) {
|
|
176
|
+
cell.combinedData = this._combined[index];
|
|
177
|
+
}
|
|
178
|
+
if (cell.bg & BgFlags.HAS_EXTENDED) {
|
|
179
|
+
cell.extended = this._extendedAttrs[index];
|
|
180
|
+
}
|
|
181
|
+
return cell;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Set data at `index` to `cell`.
|
|
186
|
+
*/
|
|
187
|
+
public setCell(index: number, cell: ICellData): void {
|
|
188
|
+
if (cell.content & Content.IS_COMBINED_MASK) {
|
|
189
|
+
this._combined[index] = cell.combinedData;
|
|
190
|
+
}
|
|
191
|
+
if (cell.bg & BgFlags.HAS_EXTENDED) {
|
|
192
|
+
this._extendedAttrs[index] = cell.extended;
|
|
193
|
+
}
|
|
194
|
+
this._data[index * CELL_SIZE + Cell.CONTENT] = cell.content;
|
|
195
|
+
this._data[index * CELL_SIZE + Cell.FG] = cell.fg;
|
|
196
|
+
this._data[index * CELL_SIZE + Cell.BG] = cell.bg;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Set cell data from input handler.
|
|
201
|
+
* Since the input handler see the incoming chars as UTF32 codepoints,
|
|
202
|
+
* it gets an optimized access method.
|
|
203
|
+
*/
|
|
204
|
+
public setCellFromCodePoint(index: number, codePoint: number, width: number, fg: number, bg: number, eAttrs: IExtendedAttrs): void {
|
|
205
|
+
if (bg & BgFlags.HAS_EXTENDED) {
|
|
206
|
+
this._extendedAttrs[index] = eAttrs;
|
|
207
|
+
}
|
|
208
|
+
this._data[index * CELL_SIZE + Cell.CONTENT] = codePoint | (width << Content.WIDTH_SHIFT);
|
|
209
|
+
this._data[index * CELL_SIZE + Cell.FG] = fg;
|
|
210
|
+
this._data[index * CELL_SIZE + Cell.BG] = bg;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Add a codepoint to a cell from input handler.
|
|
215
|
+
* During input stage combining chars with a width of 0 follow and stack
|
|
216
|
+
* onto a leading char. Since we already set the attrs
|
|
217
|
+
* by the previous `setDataFromCodePoint` call, we can omit it here.
|
|
218
|
+
*/
|
|
219
|
+
public addCodepointToCell(index: number, codePoint: number): void {
|
|
220
|
+
let content = this._data[index * CELL_SIZE + Cell.CONTENT];
|
|
221
|
+
if (content & Content.IS_COMBINED_MASK) {
|
|
222
|
+
// we already have a combined string, simply add
|
|
223
|
+
this._combined[index] += stringFromCodePoint(codePoint);
|
|
224
|
+
} else {
|
|
225
|
+
if (content & Content.CODEPOINT_MASK) {
|
|
226
|
+
// normal case for combining chars:
|
|
227
|
+
// - move current leading char + new one into combined string
|
|
228
|
+
// - set combined flag
|
|
229
|
+
this._combined[index] = stringFromCodePoint(content & Content.CODEPOINT_MASK) + stringFromCodePoint(codePoint);
|
|
230
|
+
content &= ~Content.CODEPOINT_MASK; // set codepoint in buffer to 0
|
|
231
|
+
content |= Content.IS_COMBINED_MASK;
|
|
232
|
+
} else {
|
|
233
|
+
// should not happen - we actually have no data in the cell yet
|
|
234
|
+
// simply set the data in the cell buffer with a width of 1
|
|
235
|
+
content = codePoint | (1 << Content.WIDTH_SHIFT);
|
|
236
|
+
}
|
|
237
|
+
this._data[index * CELL_SIZE + Cell.CONTENT] = content;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
public insertCells(pos: number, n: number, fillCellData: ICellData, eraseAttr?: IAttributeData): void {
|
|
242
|
+
pos %= this.length;
|
|
243
|
+
|
|
244
|
+
// handle fullwidth at pos: reset cell one to the left if pos is second cell of a wide char
|
|
245
|
+
if (pos && this.getWidth(pos - 1) === 2) {
|
|
246
|
+
this.setCellFromCodePoint(pos - 1, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs());
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (n < this.length - pos) {
|
|
250
|
+
const cell = new CellData();
|
|
251
|
+
for (let i = this.length - pos - n - 1; i >= 0; --i) {
|
|
252
|
+
this.setCell(pos + n + i, this.loadCell(pos + i, cell));
|
|
253
|
+
}
|
|
254
|
+
for (let i = 0; i < n; ++i) {
|
|
255
|
+
this.setCell(pos + i, fillCellData);
|
|
256
|
+
}
|
|
257
|
+
} else {
|
|
258
|
+
for (let i = pos; i < this.length; ++i) {
|
|
259
|
+
this.setCell(i, fillCellData);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// handle fullwidth at line end: reset last cell if it is first cell of a wide char
|
|
264
|
+
if (this.getWidth(this.length - 1) === 2) {
|
|
265
|
+
this.setCellFromCodePoint(this.length - 1, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs());
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
public deleteCells(pos: number, n: number, fillCellData: ICellData, eraseAttr?: IAttributeData): void {
|
|
270
|
+
pos %= this.length;
|
|
271
|
+
if (n < this.length - pos) {
|
|
272
|
+
const cell = new CellData();
|
|
273
|
+
for (let i = 0; i < this.length - pos - n; ++i) {
|
|
274
|
+
this.setCell(pos + i, this.loadCell(pos + n + i, cell));
|
|
275
|
+
}
|
|
276
|
+
for (let i = this.length - n; i < this.length; ++i) {
|
|
277
|
+
this.setCell(i, fillCellData);
|
|
278
|
+
}
|
|
279
|
+
} else {
|
|
280
|
+
for (let i = pos; i < this.length; ++i) {
|
|
281
|
+
this.setCell(i, fillCellData);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// handle fullwidth at pos:
|
|
286
|
+
// - reset pos-1 if wide char
|
|
287
|
+
// - reset pos if width==0 (previous second cell of a wide char)
|
|
288
|
+
if (pos && this.getWidth(pos - 1) === 2) {
|
|
289
|
+
this.setCellFromCodePoint(pos - 1, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs());
|
|
290
|
+
}
|
|
291
|
+
if (this.getWidth(pos) === 0 && !this.hasContent(pos)) {
|
|
292
|
+
this.setCellFromCodePoint(pos, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs());
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
public replaceCells(start: number, end: number, fillCellData: ICellData, eraseAttr?: IAttributeData): void {
|
|
297
|
+
// handle fullwidth at start: reset cell one to the left if start is second cell of a wide char
|
|
298
|
+
if (start && this.getWidth(start - 1) === 2) {
|
|
299
|
+
this.setCellFromCodePoint(start - 1, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs());
|
|
300
|
+
}
|
|
301
|
+
// handle fullwidth at last cell + 1: reset to empty cell if it is second part of a wide char
|
|
302
|
+
if (end < this.length && this.getWidth(end - 1) === 2) {
|
|
303
|
+
this.setCellFromCodePoint(end, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs());
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
while (start < end && start < this.length) {
|
|
307
|
+
this.setCell(start++, fillCellData);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
public resize(cols: number, fillCellData: ICellData): void {
|
|
312
|
+
if (cols === this.length) {
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
if (cols > this.length) {
|
|
316
|
+
const data = new Uint32Array(cols * CELL_SIZE);
|
|
317
|
+
if (this.length) {
|
|
318
|
+
if (cols * CELL_SIZE < this._data.length) {
|
|
319
|
+
data.set(this._data.subarray(0, cols * CELL_SIZE));
|
|
320
|
+
} else {
|
|
321
|
+
data.set(this._data);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
this._data = data;
|
|
325
|
+
for (let i = this.length; i < cols; ++i) {
|
|
326
|
+
this.setCell(i, fillCellData);
|
|
327
|
+
}
|
|
328
|
+
} else {
|
|
329
|
+
if (cols) {
|
|
330
|
+
const data = new Uint32Array(cols * CELL_SIZE);
|
|
331
|
+
data.set(this._data.subarray(0, cols * CELL_SIZE));
|
|
332
|
+
this._data = data;
|
|
333
|
+
// Remove any cut off combined data, FIXME: repeat this for extended attrs
|
|
334
|
+
const keys = Object.keys(this._combined);
|
|
335
|
+
for (let i = 0; i < keys.length; i++) {
|
|
336
|
+
const key = parseInt(keys[i], 10);
|
|
337
|
+
if (key >= cols) {
|
|
338
|
+
delete this._combined[key];
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
} else {
|
|
342
|
+
this._data = new Uint32Array(0);
|
|
343
|
+
this._combined = {};
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
this.length = cols;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/** fill a line with fillCharData */
|
|
350
|
+
public fill(fillCellData: ICellData): void {
|
|
351
|
+
this._combined = {};
|
|
352
|
+
this._extendedAttrs = {};
|
|
353
|
+
for (let i = 0; i < this.length; ++i) {
|
|
354
|
+
this.setCell(i, fillCellData);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/** alter to a full copy of line */
|
|
359
|
+
public copyFrom(line: BufferLine): void {
|
|
360
|
+
if (this.length !== line.length) {
|
|
361
|
+
this._data = new Uint32Array(line._data);
|
|
362
|
+
} else {
|
|
363
|
+
// use high speed copy if lengths are equal
|
|
364
|
+
this._data.set(line._data);
|
|
365
|
+
}
|
|
366
|
+
this.length = line.length;
|
|
367
|
+
this._combined = {};
|
|
368
|
+
for (const el in line._combined) {
|
|
369
|
+
this._combined[el] = line._combined[el];
|
|
370
|
+
}
|
|
371
|
+
this._extendedAttrs = {};
|
|
372
|
+
for (const el in line._extendedAttrs) {
|
|
373
|
+
this._extendedAttrs[el] = line._extendedAttrs[el];
|
|
374
|
+
}
|
|
375
|
+
this.isWrapped = line.isWrapped;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/** create a new clone */
|
|
379
|
+
public clone(): IBufferLine {
|
|
380
|
+
const newLine = new BufferLine(0);
|
|
381
|
+
newLine._data = new Uint32Array(this._data);
|
|
382
|
+
newLine.length = this.length;
|
|
383
|
+
for (const el in this._combined) {
|
|
384
|
+
newLine._combined[el] = this._combined[el];
|
|
385
|
+
}
|
|
386
|
+
for (const el in this._extendedAttrs) {
|
|
387
|
+
newLine._extendedAttrs[el] = this._extendedAttrs[el];
|
|
388
|
+
}
|
|
389
|
+
newLine.isWrapped = this.isWrapped;
|
|
390
|
+
return newLine;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
public getTrimmedLength(): number {
|
|
394
|
+
for (let i = this.length - 1; i >= 0; --i) {
|
|
395
|
+
if ((this._data[i * CELL_SIZE + Cell.CONTENT] & Content.HAS_CONTENT_MASK)) {
|
|
396
|
+
return i + (this._data[i * CELL_SIZE + Cell.CONTENT] >> Content.WIDTH_SHIFT);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
return 0;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
public copyCellsFrom(src: BufferLine, srcCol: number, destCol: number, length: number, applyInReverse: boolean): void {
|
|
403
|
+
const srcData = src._data;
|
|
404
|
+
if (applyInReverse) {
|
|
405
|
+
for (let cell = length - 1; cell >= 0; cell--) {
|
|
406
|
+
for (let i = 0; i < CELL_SIZE; i++) {
|
|
407
|
+
this._data[(destCol + cell) * CELL_SIZE + i] = srcData[(srcCol + cell) * CELL_SIZE + i];
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
} else {
|
|
411
|
+
for (let cell = 0; cell < length; cell++) {
|
|
412
|
+
for (let i = 0; i < CELL_SIZE; i++) {
|
|
413
|
+
this._data[(destCol + cell) * CELL_SIZE + i] = srcData[(srcCol + cell) * CELL_SIZE + i];
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Move any combined data over as needed, FIXME: repeat for extended attrs
|
|
419
|
+
const srcCombinedKeys = Object.keys(src._combined);
|
|
420
|
+
for (let i = 0; i < srcCombinedKeys.length; i++) {
|
|
421
|
+
const key = parseInt(srcCombinedKeys[i], 10);
|
|
422
|
+
if (key >= srcCol) {
|
|
423
|
+
this._combined[key - srcCol + destCol] = src._combined[key];
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
public translateToString(trimRight: boolean = false, startCol: number = 0, endCol: number = this.length): string {
|
|
429
|
+
if (trimRight) {
|
|
430
|
+
endCol = Math.min(endCol, this.getTrimmedLength());
|
|
431
|
+
}
|
|
432
|
+
let result = '';
|
|
433
|
+
while (startCol < endCol) {
|
|
434
|
+
const content = this._data[startCol * CELL_SIZE + Cell.CONTENT];
|
|
435
|
+
const cp = content & Content.CODEPOINT_MASK;
|
|
436
|
+
result += (content & Content.IS_COMBINED_MASK) ? this._combined[startCol] : (cp) ? stringFromCodePoint(cp) : WHITESPACE_CELL_CHAR;
|
|
437
|
+
startCol += (content >> Content.WIDTH_SHIFT) || 1; // always advance by 1
|
|
438
|
+
}
|
|
439
|
+
return result;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2021 The xterm.js authors. All rights reserved.
|
|
3
|
+
* @license MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { IBufferRange } from 'xterm';
|
|
7
|
+
|
|
8
|
+
export function getRangeLength(range: IBufferRange, bufferCols: number): number {
|
|
9
|
+
if (range.start.y > range.end.y) {
|
|
10
|
+
throw new Error(`Buffer range end (${range.end.x}, ${range.end.y}) cannot be before start (${range.start.x}, ${range.start.y})`);
|
|
11
|
+
}
|
|
12
|
+
return bufferCols * (range.end.y - range.start.y) + (range.end.x - range.start.x + 1);
|
|
13
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
|
3
|
+
* @license MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { BufferLine } from 'common/buffer/BufferLine';
|
|
7
|
+
import { CircularList } from 'common/CircularList';
|
|
8
|
+
import { IBufferLine, ICellData } from 'common/Types';
|
|
9
|
+
|
|
10
|
+
export interface INewLayoutResult {
|
|
11
|
+
layout: number[];
|
|
12
|
+
countRemoved: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Evaluates and returns indexes to be removed after a reflow larger occurs. Lines will be removed
|
|
17
|
+
* when a wrapped line unwraps.
|
|
18
|
+
* @param lines The buffer lines.
|
|
19
|
+
* @param newCols The columns after resize.
|
|
20
|
+
*/
|
|
21
|
+
export function reflowLargerGetLinesToRemove(lines: CircularList<IBufferLine>, oldCols: number, newCols: number, bufferAbsoluteY: number, nullCell: ICellData): number[] {
|
|
22
|
+
// Gather all BufferLines that need to be removed from the Buffer here so that they can be
|
|
23
|
+
// batched up and only committed once
|
|
24
|
+
const toRemove: number[] = [];
|
|
25
|
+
|
|
26
|
+
for (let y = 0; y < lines.length - 1; y++) {
|
|
27
|
+
// Check if this row is wrapped
|
|
28
|
+
let i = y;
|
|
29
|
+
let nextLine = lines.get(++i) as BufferLine;
|
|
30
|
+
if (!nextLine.isWrapped) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Check how many lines it's wrapped for
|
|
35
|
+
const wrappedLines: BufferLine[] = [lines.get(y) as BufferLine];
|
|
36
|
+
while (i < lines.length && nextLine.isWrapped) {
|
|
37
|
+
wrappedLines.push(nextLine);
|
|
38
|
+
nextLine = lines.get(++i) as BufferLine;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// If these lines contain the cursor don't touch them, the program will handle fixing up wrapped
|
|
42
|
+
// lines with the cursor
|
|
43
|
+
if (bufferAbsoluteY >= y && bufferAbsoluteY < i) {
|
|
44
|
+
y += wrappedLines.length - 1;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Copy buffer data to new locations
|
|
49
|
+
let destLineIndex = 0;
|
|
50
|
+
let destCol = getWrappedLineTrimmedLength(wrappedLines, destLineIndex, oldCols);
|
|
51
|
+
let srcLineIndex = 1;
|
|
52
|
+
let srcCol = 0;
|
|
53
|
+
while (srcLineIndex < wrappedLines.length) {
|
|
54
|
+
const srcTrimmedTineLength = getWrappedLineTrimmedLength(wrappedLines, srcLineIndex, oldCols);
|
|
55
|
+
const srcRemainingCells = srcTrimmedTineLength - srcCol;
|
|
56
|
+
const destRemainingCells = newCols - destCol;
|
|
57
|
+
const cellsToCopy = Math.min(srcRemainingCells, destRemainingCells);
|
|
58
|
+
|
|
59
|
+
wrappedLines[destLineIndex].copyCellsFrom(wrappedLines[srcLineIndex], srcCol, destCol, cellsToCopy, false);
|
|
60
|
+
|
|
61
|
+
destCol += cellsToCopy;
|
|
62
|
+
if (destCol === newCols) {
|
|
63
|
+
destLineIndex++;
|
|
64
|
+
destCol = 0;
|
|
65
|
+
}
|
|
66
|
+
srcCol += cellsToCopy;
|
|
67
|
+
if (srcCol === srcTrimmedTineLength) {
|
|
68
|
+
srcLineIndex++;
|
|
69
|
+
srcCol = 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Make sure the last cell isn't wide, if it is copy it to the current dest
|
|
73
|
+
if (destCol === 0 && destLineIndex !== 0) {
|
|
74
|
+
if (wrappedLines[destLineIndex - 1].getWidth(newCols - 1) === 2) {
|
|
75
|
+
wrappedLines[destLineIndex].copyCellsFrom(wrappedLines[destLineIndex - 1], newCols - 1, destCol++, 1, false);
|
|
76
|
+
// Null out the end of the last row
|
|
77
|
+
wrappedLines[destLineIndex - 1].setCell(newCols - 1, nullCell);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Clear out remaining cells or fragments could remain;
|
|
83
|
+
wrappedLines[destLineIndex].replaceCells(destCol, newCols, nullCell);
|
|
84
|
+
|
|
85
|
+
// Work backwards and remove any rows at the end that only contain null cells
|
|
86
|
+
let countToRemove = 0;
|
|
87
|
+
for (let i = wrappedLines.length - 1; i > 0; i--) {
|
|
88
|
+
if (i > destLineIndex || wrappedLines[i].getTrimmedLength() === 0) {
|
|
89
|
+
countToRemove++;
|
|
90
|
+
} else {
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (countToRemove > 0) {
|
|
96
|
+
toRemove.push(y + wrappedLines.length - countToRemove); // index
|
|
97
|
+
toRemove.push(countToRemove);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
y += wrappedLines.length - 1;
|
|
101
|
+
}
|
|
102
|
+
return toRemove;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Creates and return the new layout for lines given an array of indexes to be removed.
|
|
107
|
+
* @param lines The buffer lines.
|
|
108
|
+
* @param toRemove The indexes to remove.
|
|
109
|
+
*/
|
|
110
|
+
export function reflowLargerCreateNewLayout(lines: CircularList<IBufferLine>, toRemove: number[]): INewLayoutResult {
|
|
111
|
+
const layout: number[] = [];
|
|
112
|
+
// First iterate through the list and get the actual indexes to use for rows
|
|
113
|
+
let nextToRemoveIndex = 0;
|
|
114
|
+
let nextToRemoveStart = toRemove[nextToRemoveIndex];
|
|
115
|
+
let countRemovedSoFar = 0;
|
|
116
|
+
for (let i = 0; i < lines.length; i++) {
|
|
117
|
+
if (nextToRemoveStart === i) {
|
|
118
|
+
const countToRemove = toRemove[++nextToRemoveIndex];
|
|
119
|
+
|
|
120
|
+
// Tell markers that there was a deletion
|
|
121
|
+
lines.onDeleteEmitter.fire({
|
|
122
|
+
index: i - countRemovedSoFar,
|
|
123
|
+
amount: countToRemove
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
i += countToRemove - 1;
|
|
127
|
+
countRemovedSoFar += countToRemove;
|
|
128
|
+
nextToRemoveStart = toRemove[++nextToRemoveIndex];
|
|
129
|
+
} else {
|
|
130
|
+
layout.push(i);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
layout,
|
|
135
|
+
countRemoved: countRemovedSoFar
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Applies a new layout to the buffer. This essentially does the same as many splice calls but it's
|
|
141
|
+
* done all at once in a single iteration through the list since splice is very expensive.
|
|
142
|
+
* @param lines The buffer lines.
|
|
143
|
+
* @param newLayout The new layout to apply.
|
|
144
|
+
*/
|
|
145
|
+
export function reflowLargerApplyNewLayout(lines: CircularList<IBufferLine>, newLayout: number[]): void {
|
|
146
|
+
// Record original lines so they don't get overridden when we rearrange the list
|
|
147
|
+
const newLayoutLines: BufferLine[] = [];
|
|
148
|
+
for (let i = 0; i < newLayout.length; i++) {
|
|
149
|
+
newLayoutLines.push(lines.get(newLayout[i]) as BufferLine);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Rearrange the list
|
|
153
|
+
for (let i = 0; i < newLayoutLines.length; i++) {
|
|
154
|
+
lines.set(i, newLayoutLines[i]);
|
|
155
|
+
}
|
|
156
|
+
lines.length = newLayout.length;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Gets the new line lengths for a given wrapped line. The purpose of this function it to pre-
|
|
161
|
+
* compute the wrapping points since wide characters may need to be wrapped onto the following line.
|
|
162
|
+
* This function will return an array of numbers of where each line wraps to, the resulting array
|
|
163
|
+
* will only contain the values `newCols` (when the line does not end with a wide character) and
|
|
164
|
+
* `newCols - 1` (when the line does end with a wide character), except for the last value which
|
|
165
|
+
* will contain the remaining items to fill the line.
|
|
166
|
+
*
|
|
167
|
+
* Calling this with a `newCols` value of `1` will lock up.
|
|
168
|
+
*
|
|
169
|
+
* @param wrappedLines The wrapped lines to evaluate.
|
|
170
|
+
* @param oldCols The columns before resize.
|
|
171
|
+
* @param newCols The columns after resize.
|
|
172
|
+
*/
|
|
173
|
+
export function reflowSmallerGetNewLineLengths(wrappedLines: BufferLine[], oldCols: number, newCols: number): number[] {
|
|
174
|
+
const newLineLengths: number[] = [];
|
|
175
|
+
const cellsNeeded = wrappedLines.map((l, i) => getWrappedLineTrimmedLength(wrappedLines, i, oldCols)).reduce((p, c) => p + c);
|
|
176
|
+
|
|
177
|
+
// Use srcCol and srcLine to find the new wrapping point, use that to get the cellsAvailable and
|
|
178
|
+
// linesNeeded
|
|
179
|
+
let srcCol = 0;
|
|
180
|
+
let srcLine = 0;
|
|
181
|
+
let cellsAvailable = 0;
|
|
182
|
+
while (cellsAvailable < cellsNeeded) {
|
|
183
|
+
if (cellsNeeded - cellsAvailable < newCols) {
|
|
184
|
+
// Add the final line and exit the loop
|
|
185
|
+
newLineLengths.push(cellsNeeded - cellsAvailable);
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
srcCol += newCols;
|
|
189
|
+
const oldTrimmedLength = getWrappedLineTrimmedLength(wrappedLines, srcLine, oldCols);
|
|
190
|
+
if (srcCol > oldTrimmedLength) {
|
|
191
|
+
srcCol -= oldTrimmedLength;
|
|
192
|
+
srcLine++;
|
|
193
|
+
}
|
|
194
|
+
const endsWithWide = wrappedLines[srcLine].getWidth(srcCol - 1) === 2;
|
|
195
|
+
if (endsWithWide) {
|
|
196
|
+
srcCol--;
|
|
197
|
+
}
|
|
198
|
+
const lineLength = endsWithWide ? newCols - 1 : newCols;
|
|
199
|
+
newLineLengths.push(lineLength);
|
|
200
|
+
cellsAvailable += lineLength;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return newLineLengths;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function getWrappedLineTrimmedLength(lines: BufferLine[], i: number, cols: number): number {
|
|
207
|
+
// If this is the last row in the wrapped line, get the actual trimmed length
|
|
208
|
+
if (i === lines.length - 1) {
|
|
209
|
+
return lines[i].getTrimmedLength();
|
|
210
|
+
}
|
|
211
|
+
// Detect whether the following line starts with a wide character and the end of the current line
|
|
212
|
+
// is null, if so then we can be pretty sure the null character should be excluded from the line
|
|
213
|
+
// length]
|
|
214
|
+
const endsInNull = !(lines[i].hasContent(cols - 1)) && lines[i].getWidth(cols - 1) === 1;
|
|
215
|
+
const followingLineStartsWithWide = lines[i + 1].getWidth(0) === 2;
|
|
216
|
+
if (endsInNull && followingLineStartsWithWide) {
|
|
217
|
+
return cols - 1;
|
|
218
|
+
}
|
|
219
|
+
return cols;
|
|
220
|
+
}
|