diff --git a/src/Buffer.ts b/src/Buffer.ts index 69a36e43..9cc1adba 100644 --- a/src/Buffer.ts +++ b/src/Buffer.ts @@ -29,7 +29,7 @@ export const NULL_CELL_WIDTH = 1; export const NULL_CELL_CODE = 0; /** - * Whilespace cell. + * Whitespace cell. * This is meant as a replacement for empty cells when needed * during rendering lines to preserve correct aligment. */ diff --git a/src/BufferLine.test.ts b/src/BufferLine.test.ts index 7dfcbd2c..29a783ae 100644 --- a/src/BufferLine.test.ts +++ b/src/BufferLine.test.ts @@ -3,7 +3,7 @@ * @license MIT */ import * as chai from 'chai'; -import { BufferLine, CellData, Content } from './BufferLine'; +import { BufferLine, CellData, ContentMasks } from './BufferLine'; import { CharData, IBufferLine } from './Types'; import { NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, DEFAULT_ATTR } from './Buffer'; @@ -32,7 +32,7 @@ describe('CellData', () => { // combining cell.setFromCharData([123, 'e\u0301', 1, '\u0301'.charCodeAt(0)]); chai.assert.deepEqual(cell.getAsCharData(), [123, 'e\u0301', 1, '\u0301'.charCodeAt(0)]); - chai.assert.equal(cell.isCombined(), Content.IS_COMBINED); + chai.assert.equal(cell.isCombined(), ContentMasks.IS_COMBINED); // surrogate cell.setFromCharData([123, '𝄞', 1, 0x1D11E]); chai.assert.deepEqual(cell.getAsCharData(), [123, '𝄞', 1, 0x1D11E]); @@ -40,7 +40,7 @@ describe('CellData', () => { // surrogate + combining cell.setFromCharData([123, '𓂀\u0301', 1, '𓂀\u0301'.charCodeAt(2)]); chai.assert.deepEqual(cell.getAsCharData(), [123, '𓂀\u0301', 1, '𓂀\u0301'.charCodeAt(2)]); - chai.assert.equal(cell.isCombined(), Content.IS_COMBINED); + chai.assert.equal(cell.isCombined(), ContentMasks.IS_COMBINED); // wide char cell.setFromCharData([123, '1', 2, '1'.charCodeAt(0)]); chai.assert.deepEqual(cell.getAsCharData(), [123, '1', 2, '1'.charCodeAt(0)]); @@ -350,7 +350,7 @@ describe('BufferLine', function(): void { // width is set to 1 chai.assert.deepEqual(cell.getAsCharData(), [123, 'e\u0301\u0301', 1, 0x0301]); // do not account a single combining char as combined - chai.assert.equal(cell.isCombined(), Content.IS_COMBINED); + chai.assert.equal(cell.isCombined(), ContentMasks.IS_COMBINED); }); it('should create combining string on taken cell', () => { const line = new TestBufferLine(3, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false); @@ -363,7 +363,7 @@ describe('BufferLine', function(): void { // width is set to 1 chai.assert.deepEqual(cell.getAsCharData(), [123, 'e\u0301', 1, 0x0301]); // do not account a single combining char as combined - chai.assert.equal(cell.isCombined(), Content.IS_COMBINED); + chai.assert.equal(cell.isCombined(), ContentMasks.IS_COMBINED); }); }); }); diff --git a/src/BufferLine.ts b/src/BufferLine.ts index 14518454..c4aa55be 100644 --- a/src/BufferLine.ts +++ b/src/BufferLine.ts @@ -34,9 +34,9 @@ const enum Cell { } /** - * Bitmasks and helper for accessing data in `content`. + * Bitmasks for accessing data in `content`. */ -export const enum Content { +export const enum ContentMasks { /** * bit 1..21 codepoint, max allowed in UTF32 is 0x10FFFF (21 bits taken) * read: `codepoint = content & Content.codepointMask;` @@ -44,7 +44,7 @@ export const enum Content { * shortcut if precondition `codepoint <= 0x10FFFF` is met: * `content |= codepoint;` */ - CODEPOINT_MASK = 0x1FFFFF, + CODEPOINT = 0x1FFFFF, /** * bit 22 flag indication whether a cell contains combined content @@ -72,10 +72,11 @@ export const enum Content { * shortcut if precondition `0 <= width <= 3` is met: * `content |= width << Content.widthShift;` */ - WIDTH_MASK = 0xC00000, // 3 << 22 - WIDTH_SHIFT = 22 + WIDTH = 0xC00000 // 3 << 22 } +const WIDTH_MASK_SHIFT = 22; + /** * CellData - represents a single Cell in the terminal buffer. */ @@ -96,21 +97,21 @@ export class CellData implements ICellData { /** Whether cell contains a combined string. */ public isCombined(): number { - return this.content & Content.IS_COMBINED; + return this.content & ContentMasks.IS_COMBINED; } /** Width of the cell. */ public getWidth(): number { - return this.content >> Content.WIDTH_SHIFT; + return this.content >> WIDTH_MASK_SHIFT; } /** JS string of the content. */ public getChars(): string { - if (this.content & Content.IS_COMBINED) { + if (this.content & ContentMasks.IS_COMBINED) { return this.combinedData; } - if (this.content & Content.CODEPOINT_MASK) { - return stringFromCodePoint(this.content & Content.CODEPOINT_MASK); + if (this.content & ContentMasks.CODEPOINT) { + return stringFromCodePoint(this.content & ContentMasks.CODEPOINT); } return ''; } @@ -124,7 +125,7 @@ export class CellData implements ICellData { public getCode(): number { return (this.isCombined()) ? this.combinedData.charCodeAt(this.combinedData.length - 1) - : this.content & Content.CODEPOINT_MASK; + : this.content & ContentMasks.CODEPOINT; } /** Set data from CharData */ @@ -143,7 +144,7 @@ export class CellData implements ICellData { if (0xD800 <= code && code <= 0xDBFF) { const second = value[CHAR_DATA_CHAR_INDEX].charCodeAt(1); if (0xDC00 <= second && second <= 0xDFFF) { - this.content = ((code - 0xD800) * 0x400 + second - 0xDC00 + 0x10000) | (value[CHAR_DATA_WIDTH_INDEX] << Content.WIDTH_SHIFT); + this.content = ((code - 0xD800) * 0x400 + second - 0xDC00 + 0x10000) | (value[CHAR_DATA_WIDTH_INDEX] << WIDTH_MASK_SHIFT); } else { combined = true; } @@ -151,11 +152,11 @@ export class CellData implements ICellData { combined = true; } } else { - this.content = value[CHAR_DATA_CHAR_INDEX].charCodeAt(0) | (value[CHAR_DATA_WIDTH_INDEX] << Content.WIDTH_SHIFT); + this.content = value[CHAR_DATA_CHAR_INDEX].charCodeAt(0) | (value[CHAR_DATA_WIDTH_INDEX] << WIDTH_MASK_SHIFT); } if (combined) { this.combinedData = value[CHAR_DATA_CHAR_INDEX]; - this.content = Content.IS_COMBINED | (value[CHAR_DATA_WIDTH_INDEX] << Content.WIDTH_SHIFT); + this.content = ContentMasks.IS_COMBINED | (value[CHAR_DATA_WIDTH_INDEX] << WIDTH_MASK_SHIFT); } } @@ -203,14 +204,14 @@ export class BufferLine implements IBufferLine { */ public get(index: number): CharData { const content = this._data[index * CELL_SIZE + Cell.CONTENT]; - const cp = content & Content.CODEPOINT_MASK; + const cp = content & ContentMasks.CODEPOINT; return [ this._data[index * CELL_SIZE + Cell.FG], - (content & Content.IS_COMBINED) + (content & ContentMasks.IS_COMBINED) ? this._combined[index] : (cp) ? stringFromCodePoint(cp) : '', - content >> Content.WIDTH_SHIFT, - (content & Content.IS_COMBINED) + content >> WIDTH_MASK_SHIFT, + (content & ContentMasks.IS_COMBINED) ? this._combined[index].charCodeAt(this._combined[index].length - 1) : cp ]; @@ -224,9 +225,9 @@ export class BufferLine implements IBufferLine { this._data[index * CELL_SIZE + Cell.FG] = value[CHAR_DATA_ATTR_INDEX]; if (value[CHAR_DATA_CHAR_INDEX].length > 1) { this._combined[index] = value[1]; - this._data[index * CELL_SIZE + Cell.CONTENT] = index | Content.IS_COMBINED | (value[CHAR_DATA_WIDTH_INDEX] << Content.WIDTH_SHIFT); + this._data[index * CELL_SIZE + Cell.CONTENT] = index | ContentMasks.IS_COMBINED | (value[CHAR_DATA_WIDTH_INDEX] << WIDTH_MASK_SHIFT); } else { - this._data[index * CELL_SIZE + Cell.CONTENT] = value[CHAR_DATA_CHAR_INDEX].charCodeAt(0) | (value[CHAR_DATA_WIDTH_INDEX] << Content.WIDTH_SHIFT); + this._data[index * CELL_SIZE + Cell.CONTENT] = value[CHAR_DATA_CHAR_INDEX].charCodeAt(0) | (value[CHAR_DATA_WIDTH_INDEX] << WIDTH_MASK_SHIFT); } } @@ -235,21 +236,21 @@ export class BufferLine implements IBufferLine { * use these when only one value is needed, otherwise use `loadCell` */ public getWidth(index: number): number { - return this._data[index * CELL_SIZE + Cell.CONTENT] >> Content.WIDTH_SHIFT; + return this._data[index * CELL_SIZE + Cell.CONTENT] >> WIDTH_MASK_SHIFT; } /** Test whether content has width. */ public hasWidth(index: number): number { - return this._data[index * CELL_SIZE + Cell.CONTENT] & Content.WIDTH_MASK; + return this._data[index * CELL_SIZE + Cell.CONTENT] & ContentMasks.WIDTH; } /** Get FG cell component. */ - public getFG(index: number): number { + public getFg(index: number): number { return this._data[index * CELL_SIZE + Cell.FG]; } /** Get BG cell component. */ - public getBG(index: number): number { + public getBg(index: number): number { return this._data[index * CELL_SIZE + Cell.BG]; } @@ -259,7 +260,7 @@ export class BufferLine implements IBufferLine { * from real empty cells. * */ public hasContent(index: number): number { - return this._data[index * CELL_SIZE + Cell.CONTENT] & Content.HAS_CONTENT; + return this._data[index * CELL_SIZE + Cell.CONTENT] & ContentMasks.HAS_CONTENT; } /** @@ -269,38 +270,40 @@ export class BufferLine implements IBufferLine { */ public getCodePoint(index: number): number { const content = this._data[index * CELL_SIZE + Cell.CONTENT]; - if (content & Content.IS_COMBINED) { + if (content & ContentMasks.IS_COMBINED) { return this._combined[index].charCodeAt(this._combined[index].length - 1); } - return content & Content.CODEPOINT_MASK; + return content & ContentMasks.CODEPOINT; } /** Test whether the cell contains a combined string. */ public isCombined(index: number): number { - return this._data[index * CELL_SIZE + Cell.CONTENT] & Content.IS_COMBINED; + return this._data[index * CELL_SIZE + Cell.CONTENT] & ContentMasks.IS_COMBINED; } /** Returns the string content of the cell. */ public getString(index: number): string { const content = this._data[index * CELL_SIZE + Cell.CONTENT]; - if (content & Content.IS_COMBINED) { + if (content & ContentMasks.IS_COMBINED) { return this._combined[index]; } - if (content & Content.CODEPOINT_MASK) { - return stringFromCodePoint(content & Content.CODEPOINT_MASK); + if (content & ContentMasks.CODEPOINT) { + return stringFromCodePoint(content & ContentMasks.CODEPOINT); } // return empty string for empty cells return ''; } /** - * Load data at `index` into `cell`. + * Load data at `index` into `cell`. This is used to access cells in a way that's more friendly + * to GC as it significantly reduced the amount of new objects/references needed. */ public loadCell(index: number, cell: ICellData): ICellData { - cell.content = this._data[index * CELL_SIZE + Cell.CONTENT]; - cell.fg = this._data[index * CELL_SIZE + Cell.FG]; - cell.bg = this._data[index * CELL_SIZE + Cell.BG]; - if (cell.content & Content.IS_COMBINED) { + const startIndex = index * CELL_SIZE; + cell.content = this._data[startIndex + Cell.CONTENT]; + cell.fg = this._data[startIndex + Cell.FG]; + cell.bg = this._data[startIndex + Cell.BG]; + if (cell.content & ContentMasks.IS_COMBINED) { cell.combinedData = this._combined[index]; } return cell; @@ -310,7 +313,7 @@ export class BufferLine implements IBufferLine { * Set data at `index` to `cell`. */ public setCell(index: number, cell: ICellData): void { - if (cell.content & Content.IS_COMBINED) { + if (cell.content & ContentMasks.IS_COMBINED) { this._combined[index] = cell.combinedData; } this._data[index * CELL_SIZE + Cell.CONTENT] = cell.content; @@ -324,7 +327,7 @@ export class BufferLine implements IBufferLine { * it gets an optimized access method. */ public setCellFromCodePoint(index: number, codePoint: number, width: number, fg: number, bg: number): void { - this._data[index * CELL_SIZE + Cell.CONTENT] = codePoint | (width << Content.WIDTH_SHIFT); + this._data[index * CELL_SIZE + Cell.CONTENT] = codePoint | (width << WIDTH_MASK_SHIFT); this._data[index * CELL_SIZE + Cell.FG] = fg; this._data[index * CELL_SIZE + Cell.BG] = bg; } @@ -337,21 +340,21 @@ export class BufferLine implements IBufferLine { */ public addCodepointToCell(index: number, codePoint: number): void { let content = this._data[index * CELL_SIZE + Cell.CONTENT]; - if (content & Content.IS_COMBINED) { + if (content & ContentMasks.IS_COMBINED) { // we already have a combined string, simply add this._combined[index] += stringFromCodePoint(codePoint); } else { - if (content & Content.CODEPOINT_MASK) { + if (content & ContentMasks.CODEPOINT) { // normal case for combining chars: // - move current leading char + new one into combined string // - set combined flag - this._combined[index] = stringFromCodePoint(content & Content.CODEPOINT_MASK) + stringFromCodePoint(codePoint); - content &= ~Content.CODEPOINT_MASK; // set codepoint in buffer to 0 - content |= Content.IS_COMBINED; + this._combined[index] = stringFromCodePoint(content & ContentMasks.CODEPOINT) + stringFromCodePoint(codePoint); + content &= ~ContentMasks.CODEPOINT; // set codepoint in buffer to 0 + content |= ContentMasks.IS_COMBINED; } else { // should not happen - we actually have no data in the cell yet // simply set the data in the cell buffer with a width of 1 - content = codePoint | (1 << Content.WIDTH_SHIFT); + content = codePoint | (1 << WIDTH_MASK_SHIFT); } this._data[index * CELL_SIZE + Cell.CONTENT] = content; } @@ -473,8 +476,8 @@ export class BufferLine implements IBufferLine { public getTrimmedLength(): number { for (let i = this.length - 1; i >= 0; --i) { - if ((this._data[i * CELL_SIZE + Cell.CONTENT] & Content.HAS_CONTENT)) { - return i + (this._data[i * CELL_SIZE + Cell.CONTENT] >> Content.WIDTH_SHIFT); + if ((this._data[i * CELL_SIZE + Cell.CONTENT] & ContentMasks.HAS_CONTENT)) { + return i + (this._data[i * CELL_SIZE + Cell.CONTENT] >> WIDTH_MASK_SHIFT); } } return 0; @@ -513,9 +516,9 @@ export class BufferLine implements IBufferLine { let result = ''; while (startCol < endCol) { const content = this._data[startCol * CELL_SIZE + Cell.CONTENT]; - const cp = content & Content.CODEPOINT_MASK; - result += (content & Content.IS_COMBINED) ? this._combined[startCol] : (cp) ? stringFromCodePoint(cp) : WHITESPACE_CELL_CHAR; - startCol += (content >> Content.WIDTH_SHIFT) || 1; // always advance by 1 + const cp = content & ContentMasks.CODEPOINT; + result += (content & ContentMasks.IS_COMBINED) ? this._combined[startCol] : (cp) ? stringFromCodePoint(cp) : WHITESPACE_CELL_CHAR; + startCol += (content >> WIDTH_MASK_SHIFT) || 1; // always advance by 1 } return result; } diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 65f4aaaf..37c9bbe5 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -106,7 +106,7 @@ class DECRQSS implements IDcsHandler { export class InputHandler extends Disposable implements IInputHandler { private _parseBuffer: Uint32Array = new Uint32Array(4096); private _stringDecoder: StringToUtf32 = new StringToUtf32(); - private _cell: CellData = new CellData(); + private _workCell: CellData = new CellData(); constructor( protected _terminal: IInputHandlingTerminal, @@ -351,7 +351,7 @@ export class InputHandler extends Disposable implements IInputHandler { // since they always follow a cell consuming char // therefore we can test for buffer.x to avoid overflow left if (!chWidth && buffer.x) { - if (!bufferRow.loadCell(buffer.x - 1, this._cell).getWidth()) { + if (!bufferRow.getWidth(buffer.x - 1)) { // found empty cell after fullwidth, need to go 2 cells back // it is save to step 2 cells back here // since an empty cell is only set by fullwidth chars @@ -400,7 +400,7 @@ export class InputHandler extends Disposable implements IInputHandler { // test last cell - since the last cell has only room for // a halfwidth char any fullwidth shifted there is lost // and will be set to empty cell - if (bufferRow.loadCell(cols - 1, this._cell).getWidth() === 2) { + if (bufferRow.getWidth(cols - 1) === 2) { bufferRow.setCellFromCodePoint(cols - 1, NULL_CELL_CODE, NULL_CELL_WIDTH, curAttr, 0); } } @@ -970,10 +970,10 @@ export class InputHandler extends Disposable implements IInputHandler { // make buffer local for faster access const buffer = this._terminal.buffer; const line = buffer.lines.get(buffer.ybase + buffer.y); - line.loadCell(buffer.x - 1, this._cell); + line.loadCell(buffer.x - 1, this._workCell); line.replaceCells(buffer.x, buffer.x + (params[0] || 1), - (this._cell.content !== undefined) ? this._cell : buffer.getNullCell(DEFAULT_ATTR) + (this._workCell.content !== undefined) ? this._workCell : buffer.getNullCell(DEFAULT_ATTR) ); // FIXME: no updateRange here? } diff --git a/src/Linkifier.ts b/src/Linkifier.ts index a2b9045b..80399904 100644 --- a/src/Linkifier.ts +++ b/src/Linkifier.ts @@ -231,7 +231,7 @@ export class Linkifier extends EventEmitter implements ILinkifier { } const line = this._terminal.buffer.lines.get(bufferIndex[0]); - const attr = line.getFG(bufferIndex[1]); + const attr = line.getFg(bufferIndex[1]); let fg: number | undefined; if (attr) { fg = (attr >> 9) & 0x1ff; diff --git a/src/SelectionManager.ts b/src/SelectionManager.ts index 9d49a860..361b1123 100644 --- a/src/SelectionManager.ts +++ b/src/SelectionManager.ts @@ -103,7 +103,7 @@ export class SelectionManager extends EventEmitter implements ISelectionManager private _mouseMoveListener: EventListener; private _mouseUpListener: EventListener; private _trimListener: XtermListener; - private _cell: CellData = new CellData(); + private _workCell: CellData = new CellData(); private _mouseDownTimeStamp: number; @@ -669,8 +669,8 @@ export class SelectionManager extends EventEmitter implements ISelectionManager private _convertViewportColToCharacterIndex(bufferLine: IBufferLine, coords: [number, number]): number { let charIndex = coords[0]; for (let i = 0; coords[0] >= i; i++) { - const length = bufferLine.loadCell(i, this._cell).getChars().length; - if (this._cell.getWidth() === 0) { + const length = bufferLine.loadCell(i, this._workCell).getChars().length; + if (this._workCell.getWidth() === 0) { // Wide characters aren't included in the line string so decrement the // index so the index is back on the wide character. charIndex--; @@ -755,10 +755,10 @@ export class SelectionManager extends EventEmitter implements ISelectionManager } // Expand the string in both directions until a space is hit - while (startCol > 0 && startIndex > 0 && !this._isCharWordSeparator(bufferLine.loadCell(startCol - 1, this._cell))) { - bufferLine.loadCell(startCol - 1, this._cell); - const length = this._cell.getChars().length; - if (this._cell.getWidth() === 0) { + while (startCol > 0 && startIndex > 0 && !this._isCharWordSeparator(bufferLine.loadCell(startCol - 1, this._workCell))) { + bufferLine.loadCell(startCol - 1, this._workCell); + const length = this._workCell.getChars().length; + if (this._workCell.getWidth() === 0) { // If the next character is a wide char, record it and skip the column leftWideCharCount++; startCol--; @@ -771,10 +771,10 @@ export class SelectionManager extends EventEmitter implements ISelectionManager startIndex--; startCol--; } - while (endCol < bufferLine.length && endIndex + 1 < line.length && !this._isCharWordSeparator(bufferLine.loadCell(endCol + 1, this._cell))) { - bufferLine.loadCell(endCol + 1, this._cell); - const length = this._cell.getChars().length; - if (this._cell.getWidth() === 2) { + while (endCol < bufferLine.length && endIndex + 1 < line.length && !this._isCharWordSeparator(bufferLine.loadCell(endCol + 1, this._workCell))) { + bufferLine.loadCell(endCol + 1, this._workCell); + const length = this._workCell.getChars().length; + if (this._workCell.getWidth() === 2) { // If the next character is a wide char, record it and skip the column rightWideCharCount++; endCol++; diff --git a/src/Terminal.ts b/src/Terminal.ts index f3ec6e31..db696bd6 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -1181,7 +1181,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II public scroll(isWrapped: boolean = false): void { let newLine: IBufferLine; newLine = this._blankLine; - if (!newLine || newLine.length !== this.cols || newLine.getFG(0) !== this.eraseAttr()) { + if (!newLine || newLine.length !== this.cols || newLine.getFg(0) !== this.eraseAttr()) { newLine = this.buffer.getBlankLine(this.eraseAttr(), isWrapped); this._blankLine = newLine; } diff --git a/src/Types.ts b/src/Types.ts index a08bd485..10665f25 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -560,8 +560,8 @@ export interface IBufferLine { /* direct access to cell attrs */ getWidth(index: number): number; hasWidth(index: number): number; - getFG(index: number): number; - getBG(index: number): number; + getFg(index: number): number; + getBg(index: number): number; hasContent(index: number): number; getCodePoint(index: number): number; isCombined(index: number): number; diff --git a/src/renderer/CharacterJoinerRegistry.ts b/src/renderer/CharacterJoinerRegistry.ts index eb44bb58..4a899d72 100644 --- a/src/renderer/CharacterJoinerRegistry.ts +++ b/src/renderer/CharacterJoinerRegistry.ts @@ -6,7 +6,7 @@ export class CharacterJoinerRegistry implements ICharacterJoinerRegistry { private _characterJoiners: ICharacterJoiner[] = []; private _nextCharacterJoinerId: number = 0; - private _cell: CellData = new CellData(); + private _workCell: CellData = new CellData(); constructor(private _terminal: ITerminal) { } @@ -52,13 +52,13 @@ export class CharacterJoinerRegistry implements ICharacterJoinerRegistry { let rangeStartColumn = 0; let currentStringIndex = 0; let rangeStartStringIndex = 0; - let rangeAttr = line.getFG(0) >> 9; + let rangeAttr = line.getFg(0) >> 9; for (let x = 0; x < this._terminal.cols; x++) { - line.loadCell(x, this._cell); - const chars = this._cell.getChars(); - const width = this._cell.getWidth(); - const attr = this._cell.fg >> 9; + line.loadCell(x, this._workCell); + const chars = this._workCell.getChars(); + const width = this._workCell.getWidth(); + const attr = this._workCell.fg >> 9; if (width === 0) { // If this character is of width 0, skip it. diff --git a/src/renderer/TextRenderLayer.ts b/src/renderer/TextRenderLayer.ts index be022239..f56ccf3a 100644 --- a/src/renderer/TextRenderLayer.ts +++ b/src/renderer/TextRenderLayer.ts @@ -25,7 +25,7 @@ export class TextRenderLayer extends BaseRenderLayer { private _characterFont: string; private _characterOverlapCache: { [key: string]: boolean } = {}; private _characterJoinerRegistry: ICharacterJoinerRegistry; - private _cell = new CellData(); + private _workCell = new CellData(); constructor(container: HTMLElement, zIndex: number, colors: IColorSet, characterJoinerRegistry: ICharacterJoinerRegistry, alpha: boolean) { super(container, 'text', zIndex, alpha, colors); @@ -74,14 +74,14 @@ export class TextRenderLayer extends BaseRenderLayer { const line = terminal.buffer.lines.get(row); const joinedRanges = joinerRegistry ? joinerRegistry.getJoinedCharacters(row) : []; for (let x = 0; x < terminal.cols; x++) { - (line as any).loadCell(x, this._cell); - let code: number = this._cell.getCode() || WHITESPACE_CELL_CODE; + line.loadCell(x, this._workCell); + let code: number = this._workCell.getCode() || WHITESPACE_CELL_CODE; // Can either represent character(s) for a single cell or multiple cells // if indicated by a character joiner. - let chars = this._cell.getChars() || WHITESPACE_CELL_CHAR; - const attr = this._cell.fg; - let width = this._cell.getWidth(); + let chars = this._workCell.getChars() || WHITESPACE_CELL_CHAR; + const attr = this._workCell.fg; + let width = this._workCell.getWidth(); // If true, indicates that the current character(s) to draw were joined. let isJoined = false; @@ -127,7 +127,7 @@ export class TextRenderLayer extends BaseRenderLayer { // get removed, and `a` would not re-render because it thinks it's // already in the correct state. // this._state.cache[x][y] = OVERLAP_OWNED_CHAR_DATA; - if (lastCharX < line.length - 1 && line.loadCell(lastCharX + 1, this._cell).getCode() === NULL_CELL_CODE) { + if (lastCharX < line.length - 1 && line.loadCell(lastCharX + 1, this._workCell).getCode() === NULL_CELL_CODE) { width = 2; // this._clearChar(x + 1, y); // The overlapping char's char data will force a clear and render when the diff --git a/src/renderer/dom/DomRendererRowFactory.ts b/src/renderer/dom/DomRendererRowFactory.ts index dfd3a154..47232981 100644 --- a/src/renderer/dom/DomRendererRowFactory.ts +++ b/src/renderer/dom/DomRendererRowFactory.ts @@ -18,7 +18,8 @@ export const CURSOR_STYLE_BAR_CLASS = 'xterm-cursor-bar'; export const CURSOR_STYLE_UNDERLINE_CLASS = 'xterm-cursor-underline'; export class DomRendererRowFactory { - private _cell: CellData = new CellData(); + private _workCell: CellData = new CellData(); + constructor( private _terminalOptions: ITerminalOptions, private _document: Document @@ -35,16 +36,16 @@ export class DomRendererRowFactory { // the viewport). let lineLength = 0; for (let x = Math.min(lineData.length, cols) - 1; x >= 0; x--) { - if (lineData.loadCell(x, this._cell).getCode() !== NULL_CELL_CODE || (isCursorRow && x === cursorX)) { + if (lineData.loadCell(x, this._workCell).getCode() !== NULL_CELL_CODE || (isCursorRow && x === cursorX)) { lineLength = x + 1; break; } } for (let x = 0; x < lineLength; x++) { - lineData.loadCell(x, this._cell); - const attr = this._cell.fg; - const width = this._cell.getWidth(); + lineData.loadCell(x, this._workCell); + const attr = this._workCell.fg; + const width = this._workCell.getWidth(); // The character to the left is a wide character, drawing is owned by the char at x-1 if (width === 0) { @@ -106,7 +107,7 @@ export class DomRendererRowFactory { charElement.classList.add(ITALIC_CLASS); } - charElement.textContent = this._cell.getChars() || WHITESPACE_CELL_CHAR; + charElement.textContent = this._workCell.getChars() || WHITESPACE_CELL_CHAR; if (fg !== DEFAULT_COLOR) { charElement.classList.add(`xterm-fg-${fg}`); }