diff --git a/src/Buffer.ts b/src/Buffer.ts index 46fe6ba8e5..642ec0f9cd 100644 --- a/src/Buffer.ts +++ b/src/Buffer.ts @@ -6,8 +6,9 @@ import { ITerminal, IBuffer } from './Interfaces'; import { CircularList } from './utils/CircularList'; import { LineData, CharData } from './Types'; -export const CHAR_DATA_CHAR_INDEX = 1; -export const CHAR_DATA_WIDTH_INDEX = 2; +export const CHAR_DATA_CHAR_INDEX = 0; +export const CHAR_DATA_WIDTH_INDEX = 1; +export const CHAR_DATA_ATTR_INDEX = 2; /** * This class represents a terminal buffer (an internal state of the terminal), where the @@ -87,7 +88,7 @@ export class Buffer implements IBuffer { // Deal with columns increasing (we don't do anything when columns reduce) if (this._terminal.cols < newCols) { - const ch: CharData = [this._terminal.defAttr, ' ', 1]; // does xterm use the default attr? + const ch: CharData = [' ', 1, this._terminal.defAttr]; // does xterm use the default attr? for (let i = 0; i < this._lines.length; i++) { if (this._lines.get(i) === undefined) { this._lines.set(i, this._terminal.blankLine()); diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 1c54abef15..55f80cc5d1 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -81,21 +81,21 @@ export class InputHandler implements IInputHandler { if (removed[CHAR_DATA_WIDTH_INDEX] === 0 && this._terminal.buffer.lines.get(row)[this._terminal.cols - 2] && this._terminal.buffer.lines.get(row)[this._terminal.cols - 2][CHAR_DATA_WIDTH_INDEX] === 2) { - this._terminal.buffer.lines.get(row)[this._terminal.cols - 2] = [this._terminal.curAttr, ' ', 1]; + this._terminal.buffer.lines.get(row)[this._terminal.cols - 2] = [' ', 1, this._terminal.curAttr]; } // insert empty cell at cursor - this._terminal.buffer.lines.get(row).splice(this._terminal.buffer.x, 0, [this._terminal.curAttr, ' ', 1]); + this._terminal.buffer.lines.get(row).splice(this._terminal.buffer.x, 0, [' ', 1, this._terminal.curAttr]); } } - this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, char, ch_width]; + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [char, ch_width, this._terminal.curAttr]; this._terminal.buffer.x++; this._terminal.updateRange(this._terminal.buffer.y); // fullwidth char - set next cell width to zero and advance cursor if (ch_width === 2) { - this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, '', 0]; + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = ['', 0, this._terminal.curAttr]; this._terminal.buffer.x++; } } @@ -195,7 +195,7 @@ export class InputHandler implements IInputHandler { const row = this._terminal.buffer.y + this._terminal.buffer.ybase; let j = this._terminal.buffer.x; - const ch: CharData = [this._terminal.eraseAttr(), ' ', 1]; // xterm + const ch: CharData = [' ', 1, this._terminal.eraseAttr()]; // xterm while (param-- && j < this._terminal.cols) { this._terminal.buffer.lines.get(row).splice(j++, 0, ch); @@ -511,7 +511,7 @@ export class InputHandler implements IInputHandler { } const row = this._terminal.buffer.y + this._terminal.buffer.ybase; - const ch: CharData = [this._terminal.eraseAttr(), ' ', 1]; // xterm + const ch: CharData = [' ', 1, this._terminal.eraseAttr()]; // xterm while (param--) { this._terminal.buffer.lines.get(row).splice(this._terminal.buffer.x, 1); @@ -559,7 +559,7 @@ export class InputHandler implements IInputHandler { const row = this._terminal.buffer.y + this._terminal.buffer.ybase; let j = this._terminal.buffer.x; - const ch: CharData = [this._terminal.eraseAttr(), ' ', 1]; // xterm + const ch: CharData = [' ', 1, this._terminal.eraseAttr()]; // xterm while (param-- && j < this._terminal.cols) { this._terminal.buffer.lines.get(row)[j++] = ch; @@ -613,7 +613,7 @@ export class InputHandler implements IInputHandler { public repeatPrecedingCharacter(params: number[]): void { let param = params[0] || 1; const line = this._terminal.buffer.lines.get(this._terminal.buffer.ybase + this._terminal.buffer.y); - const ch = line[this._terminal.buffer.x - 1] || [this._terminal.defAttr, ' ', 1]; + const ch = line[this._terminal.buffer.x - 1] || [' ', 1, this._terminal.defAttr]; while (param--) { line[this._terminal.buffer.x++] = ch; diff --git a/src/Renderer.ts b/src/Renderer.ts index f2999afaf5..a40770d339 100644 --- a/src/Renderer.ts +++ b/src/Renderer.ts @@ -4,7 +4,7 @@ import { ITerminal } from './Interfaces'; import { DomElementObjectPool } from './utils/DomElementObjectPool'; -import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from './Buffer'; +import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_ATTR_INDEX } from './Buffer'; /** * The maximum number of refresh frames to skip when the write buffer is non- @@ -168,7 +168,7 @@ export class Renderer { for (let i = 0; i < width; i++) { // TODO: Could data be a more specific type? - let data: any = line[i][0]; + let data: any = line[i][CHAR_DATA_ATTR_INDEX]; const ch = line[i][CHAR_DATA_CHAR_INDEX]; const ch_width: any = line[i][CHAR_DATA_WIDTH_INDEX]; const isCursor: boolean = i === x; diff --git a/src/SelectionManager.test.ts b/src/SelectionManager.test.ts index 4774b3bb9d..cd782f5b59 100644 --- a/src/SelectionManager.test.ts +++ b/src/SelectionManager.test.ts @@ -62,7 +62,7 @@ describe('SelectionManager', () => { function stringToRow(text: string): LineData { let result: LineData = []; for (let i = 0; i < text.length; i++) { - result.push([0, text.charAt(i), 1]); + result.push([text.charAt(i), 1, 0]); } return result; } @@ -101,21 +101,21 @@ describe('SelectionManager', () => { it('should expand selection for wide characters', () => { // Wide characters use a special format buffer.lines.set(0, [ - [null, '中', 2], - [null, '', 0], - [null, '文', 2], - [null, '', 0], - [null, ' ', 1], - [null, 'a', 1], - [null, '中', 2], - [null, '', 0], - [null, '文', 2], - [null, '', 0], - [null, 'b', 1], - [null, ' ', 1], - [null, 'f', 1], - [null, 'o', 1], - [null, 'o', 1] + ['中', 2, 0], + ['', 0, 0], + ['文', 2, 0], + ['', 0, 0], + [' ', 1, 0], + ['a', 1, 0], + ['中', 2, 0], + ['', 0, 0], + ['文', 2, 0], + ['', 0, 0], + ['b', 1, 0], + [' ', 1, 0], + ['f', 1, 0], + ['o', 1, 0], + ['o', 1, 0] ]); // Ensure wide characters take up 2 columns selectionManager.selectWordAt([0, 0]); diff --git a/src/Terminal.ts b/src/Terminal.ts index b1c538598d..acf0de310f 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -2036,7 +2036,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT if (!line) { return; } - const ch: CharData = [this.eraseAttr(), ' ', 1]; // xterm + const ch: CharData = [' ', 1, this.eraseAttr()]; // xterm for (; x < this.cols; x++) { line[x] = ch; } @@ -2053,7 +2053,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT if (!line) { return; } - const ch: CharData = [this.eraseAttr(), ' ', 1]; // xterm + const ch: CharData = [' ', 1, this.eraseAttr()]; // xterm x++; while (x--) { line[x] = ch; @@ -2097,7 +2097,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT public blankLine(cur?: boolean, isWrapped?: boolean): LineData { const attr = cur ? this.eraseAttr() : this.defAttr; - const ch: CharData = [attr, ' ', 1]; // width defaults to 1 halfwidth character + const ch: CharData = [' ', 1, attr]; // width defaults to 1 halfwidth character const line: LineData = []; // TODO: It is not ideal that this is a property on an array, a buffer line @@ -2118,7 +2118,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT * @param cur */ public ch(cur?: boolean): CharData { - return cur ? [this.eraseAttr(), ' ', 1] : [this.defAttr, ' ', 1]; + return cur ? [' ', 1, this.eraseAttr()] : [' ', 1, this.defAttr]; } /** diff --git a/src/Types.ts b/src/Types.ts index 0de78d5261..3fd6c3f061 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -16,7 +16,7 @@ export type LinkMatcherValidationCallback = (uri: string, element: HTMLElement, export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean; export type Charset = {[key: string]: string}; -export type CharData = [number, string, number]; +export type CharData = [string, number, number]; export type LineData = CharData[]; export type Option = BooleanOption | StringOption | StringArrayOption | NumberOption | GeometryOption | HandlerOption; diff --git a/src/utils/TestUtils.test.ts b/src/utils/TestUtils.test.ts index 3bd1277109..47d817b4ba 100644 --- a/src/utils/TestUtils.test.ts +++ b/src/utils/TestUtils.test.ts @@ -55,7 +55,7 @@ export class MockTerminal implements ITerminal { blankLine(cur?: boolean, isWrapped?: boolean): LineData { const line: LineData = []; for (let i = 0; i < this.cols; i++) { - line.push([0, ' ', 1]); + line.push([' ', 1, 0]); } return line; } @@ -120,7 +120,7 @@ export class MockInputHandlingTerminal implements IInputHandlingTerminal { eraseLeft(x: number, y: number): void { throw new Error('Method not implemented.'); } - blankLine(cur?: boolean, isWrapped?: boolean): [number, string, number][] { + blankLine(cur?: boolean, isWrapped?: boolean): LineData { throw new Error('Method not implemented.'); } prevStop(x?: number): number { @@ -171,7 +171,7 @@ export class MockInputHandlingTerminal implements IInputHandlingTerminal { } export class MockBuffer implements IBuffer { - lines: ICircularList<[number, string, number][]>; + lines: ICircularList; ydisp: number; ybase: number; y: number;