diff --git a/src/Buffer.test.ts b/src/Buffer.test.ts index d866fd56..087d0ae5 100644 --- a/src/Buffer.test.ts +++ b/src/Buffer.test.ts @@ -5,10 +5,10 @@ import { assert, expect } from 'chai'; import { ITerminal } from './Types'; -import { Buffer, DEFAULT_ATTR_DATA } from './Buffer'; +import { Buffer } from './Buffer'; import { CircularList } from './common/CircularList'; import { MockTerminal, TestTerminal } from './TestUtils.test'; -import { BufferLine, CellData } from './BufferLine'; +import { BufferLine, CellData, DEFAULT_ATTR_DATA } from './core/buffer/BufferLine'; const INIT_COLS = 80; const INIT_ROWS = 24; diff --git a/src/Buffer.ts b/src/Buffer.ts index c1c08c85..14bf53aa 100644 --- a/src/Buffer.ts +++ b/src/Buffer.ts @@ -4,42 +4,16 @@ */ import { CircularList, IInsertEvent } from './common/CircularList'; -import { ITerminal, IBuffer, IBufferLine, BufferIndex, IBufferStringIterator, IBufferStringIteratorResult, ICellData, IAttributeData } from './Types'; +import { ITerminal, IBuffer, BufferIndex, IBufferStringIterator, IBufferStringIteratorResult } from './Types'; +import { IBufferLine, ICellData, IAttributeData } from './core/Types'; import { IMarker } from 'xterm'; -import { BufferLine, CellData, AttributeData } from './BufferLine'; +import { BufferLine, CellData, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_WIDTH, WHITESPACE_CELL_CODE, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX, DEFAULT_ATTR_DATA } from './core/buffer/BufferLine'; import { reflowLargerApplyNewLayout, reflowLargerCreateNewLayout, reflowLargerGetLinesToRemove, reflowSmallerGetNewLineLengths, getWrappedLineTrimmedLength } from './BufferReflow'; -import { DEFAULT_COLOR } from './renderer/atlas/Types'; import { EventEmitter2, IEvent } from './common/EventEmitter2'; import { Disposable } from '../lib/common/Lifecycle'; -export const DEFAULT_ATTR = (0 << 18) | (DEFAULT_COLOR << 9) | (256 << 0); - -export const DEFAULT_ATTR_DATA = new AttributeData(); - -export const CHAR_DATA_ATTR_INDEX = 0; -export const CHAR_DATA_CHAR_INDEX = 1; -export const CHAR_DATA_WIDTH_INDEX = 2; -export const CHAR_DATA_CODE_INDEX = 3; export const MAX_BUFFER_SIZE = 4294967295; // 2^32 - 1 -/** - * Null cell - a real empty cell (containing nothing). - * Note that code should always be 0 for a null cell as - * several test condition of the buffer line rely on this. - */ -export const NULL_CELL_CHAR = ''; -export const NULL_CELL_WIDTH = 1; -export const NULL_CELL_CODE = 0; - -/** - * Whitespace cell. - * This is meant as a replacement for empty cells when needed - * during rendering lines to preserve correct aligment. - */ -export const WHITESPACE_CELL_CHAR = ' '; -export const WHITESPACE_CELL_WIDTH = 1; -export const WHITESPACE_CELL_CODE = 32; - /** * This class represents a terminal buffer (an internal state of the terminal), where the * following information is stored (in high-level): diff --git a/src/BufferReflow.test.ts b/src/BufferReflow.test.ts index 9c978dc0..91454e2a 100644 --- a/src/BufferReflow.test.ts +++ b/src/BufferReflow.test.ts @@ -3,9 +3,8 @@ * @license MIT */ import { assert } from 'chai'; -import { BufferLine } from './BufferLine'; +import { BufferLine, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE } from './core/buffer/BufferLine'; import { reflowSmallerGetNewLineLengths } from './BufferReflow'; -import { NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE } from './Buffer'; describe('BufferReflow', () => { describe('reflowSmallerGetNewLineLengths', () => { diff --git a/src/BufferReflow.ts b/src/BufferReflow.ts index 40e16c74..c1068967 100644 --- a/src/BufferReflow.ts +++ b/src/BufferReflow.ts @@ -3,9 +3,9 @@ * @license MIT */ -import { BufferLine } from './BufferLine'; +import { BufferLine } from './core/buffer/BufferLine'; import { CircularList } from './common/CircularList'; -import { IBufferLine, ICellData } from './Types'; +import { IBufferLine, ICellData } from './core/Types'; export interface INewLayoutResult { layout: number[]; diff --git a/src/BufferSet.ts b/src/BufferSet.ts index ba885a0e..f22b92dc 100644 --- a/src/BufferSet.ts +++ b/src/BufferSet.ts @@ -3,7 +3,8 @@ * @license MIT */ -import { ITerminal, IBufferSet, IAttributeData, IBuffer } from './Types'; +import { ITerminal, IBufferSet, IBuffer } from './Types'; +import { IAttributeData } from './core/Types'; import { Buffer } from './Buffer'; import { EventEmitter2, IEvent } from './common/EventEmitter2'; diff --git a/src/CharWidth.test.ts b/src/CharWidth.test.ts index ff6f17ed..17822fa2 100644 --- a/src/CharWidth.test.ts +++ b/src/CharWidth.test.ts @@ -7,8 +7,7 @@ import { TestTerminal } from './TestUtils.test'; import { assert } from 'chai'; import { getStringCellWidth, wcwidth } from './CharWidth'; import { IBuffer } from './Types'; -import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from './Buffer'; -import { CellData } from './BufferLine'; +import { CellData, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from './core/buffer/BufferLine'; describe('getStringCellWidth', function(): void { diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index dcd4d1b4..f2e8d93e 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -6,10 +6,9 @@ import { assert, expect } from 'chai'; import { InputHandler } from './InputHandler'; import { MockInputHandlingTerminal, TestTerminal } from './TestUtils.test'; -import { DEFAULT_ATTR_DATA } from './Buffer'; import { Terminal } from './Terminal'; -import { IBufferLine } from './Types'; -import { CellData, Attributes, AttributeData } from './BufferLine'; +import { IBufferLine } from './core/Types'; +import { CellData, Attributes, AttributeData, DEFAULT_ATTR_DATA } from './core/buffer/BufferLine'; describe('InputHandler', () => { describe('save and restore cursor', () => { diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 66d16c04..b5b98dd9 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -7,14 +7,13 @@ import { IInputHandler, IDcsHandler, IEscapeSequenceParser, IInputHandlingTerminal } from './Types'; import { C0, C1 } from './common/data/EscapeSequences'; import { CHARSETS, DEFAULT_CHARSET } from './core/data/Charsets'; -import { NULL_CELL_WIDTH, NULL_CELL_CODE, DEFAULT_ATTR_DATA } from './Buffer'; import { wcwidth } from './CharWidth'; import { EscapeSequenceParser } from './EscapeSequenceParser'; import { IDisposable } from 'xterm'; import { Disposable } from './common/Lifecycle'; import { concat } from './common/TypedArrayUtils'; import { StringToUtf32, stringFromCodePoint, utf32ToString } from './core/input/TextDecoder'; -import { CellData, Attributes, FgFlags, BgFlags, AttributeData } from './BufferLine'; +import { CellData, Attributes, FgFlags, BgFlags, AttributeData, NULL_CELL_WIDTH, NULL_CELL_CODE, DEFAULT_ATTR_DATA } from './core/buffer/BufferLine'; import { EventEmitter2, IEvent } from './common/EventEmitter2'; /** diff --git a/src/Linkifier.test.ts b/src/Linkifier.test.ts index 8f734bac..6a2f0ee9 100644 --- a/src/Linkifier.test.ts +++ b/src/Linkifier.test.ts @@ -4,11 +4,12 @@ */ import { assert } from 'chai'; -import { IMouseZoneManager, IMouseZone, ILinkMatcher, ITerminal, IBufferLine } from './Types'; +import { IMouseZoneManager, IMouseZone, ILinkMatcher, ITerminal } from './Types'; +import { IBufferLine } from './core/Types'; import { Linkifier } from './Linkifier'; import { MockBuffer, MockTerminal, TestTerminal } from './TestUtils.test'; import { CircularList } from './common/CircularList'; -import { BufferLine, CellData } from './BufferLine'; +import { BufferLine, CellData } from './core/buffer/BufferLine'; class TestLinkifier extends Linkifier { constructor(terminal: ITerminal) { diff --git a/src/SelectionManager.test.ts b/src/SelectionManager.test.ts index 9a2ac405..24ba0100 100644 --- a/src/SelectionManager.test.ts +++ b/src/SelectionManager.test.ts @@ -8,9 +8,10 @@ import { CharMeasure } from './CharMeasure'; import { SelectionManager, SelectionMode } from './SelectionManager'; import { SelectionModel } from './SelectionModel'; import { BufferSet } from './BufferSet'; -import { ITerminal, IBuffer, IBufferLine } from './Types'; +import { ITerminal, IBuffer } from './Types'; +import { IBufferLine } from './core/Types'; import { MockTerminal } from './TestUtils.test'; -import { BufferLine, CellData } from './BufferLine'; +import { BufferLine, CellData } from './core/buffer/BufferLine'; class TestMockTerminal extends MockTerminal { emit(event: string, data: any): void {} diff --git a/src/SelectionManager.ts b/src/SelectionManager.ts index dcd60068..dabcc9a4 100644 --- a/src/SelectionManager.ts +++ b/src/SelectionManager.ts @@ -3,13 +3,14 @@ * @license MIT */ -import { ITerminal, ISelectionManager, IBuffer, IBufferLine, ISelectionRedrawRequestEvent } from './Types'; +import { ITerminal, ISelectionManager, IBuffer, ISelectionRedrawRequestEvent } from './Types'; +import { IBufferLine } from './core/Types'; import { MouseHelper } from './MouseHelper'; import * as Browser from './common/Platform'; import { CharMeasure } from './CharMeasure'; import { SelectionModel } from './SelectionModel'; import { AltClickHandler } from './handlers/AltClickHandler'; -import { CellData } from './BufferLine'; +import { CellData } from './core/buffer/BufferLine'; import { IDisposable } from 'xterm'; import { EventEmitter2, IEvent } from './common/EventEmitter2'; diff --git a/src/Terminal.integration.ts b/src/Terminal.integration.ts index 10043006..5e12d2a3 100644 --- a/src/Terminal.integration.ts +++ b/src/Terminal.integration.ts @@ -13,9 +13,8 @@ import * as path from 'path'; import * as pty from 'node-pty'; import { assert } from 'chai'; import { Terminal } from './Terminal'; -import { WHITESPACE_CELL_CHAR } from './Buffer'; import { IViewport } from './Types'; -import { CellData } from './BufferLine'; +import { CellData, WHITESPACE_CELL_CHAR } from './core/buffer/BufferLine'; class TestTerminal extends Terminal { innerWrite(): void { this._innerWrite(); } diff --git a/src/Terminal.test.ts b/src/Terminal.test.ts index 69fbb8e2..9b5fa9c8 100644 --- a/src/Terminal.test.ts +++ b/src/Terminal.test.ts @@ -6,8 +6,7 @@ import { assert, expect } from 'chai'; import { Terminal } from './Terminal'; import { MockViewport, MockCompositionHelper, MockRenderer } from './TestUtils.test'; -import { DEFAULT_ATTR_DATA } from './Buffer'; -import { CellData } from './BufferLine'; +import { CellData, DEFAULT_ATTR_DATA } from './core/buffer/BufferLine'; const INIT_COLS = 80; const INIT_ROWS = 24; diff --git a/src/Terminal.ts b/src/Terminal.ts index 3fe5b590..6da60458 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -21,10 +21,10 @@ * http://linux.die.net/man/7/urxvt */ -import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminalOptions, ITerminal, IBrowser, ILinkifier, ILinkMatcherOptions, CustomKeyEventHandler, LinkMatcherHandler, CharacterJoinerHandler, IBufferLine, IAttributeData, IMouseZoneManager } from './Types'; +import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminalOptions, ITerminal, IBrowser, ILinkifier, ILinkMatcherOptions, CustomKeyEventHandler, LinkMatcherHandler, CharacterJoinerHandler, IMouseZoneManager } from './Types'; import { IRenderer } from './renderer/Types'; import { BufferSet } from './BufferSet'; -import { Buffer, MAX_BUFFER_SIZE, DEFAULT_ATTR_DATA } from './Buffer'; +import { Buffer, MAX_BUFFER_SIZE } from './Buffer'; import { CompositionHelper } from './CompositionHelper'; import { EventEmitter } from './common/EventEmitter'; import { Viewport } from './Viewport'; @@ -48,10 +48,10 @@ import { removeTerminalFromCache } from './renderer/atlas/CharAtlasCache'; import { DomRenderer } from './renderer/dom/DomRenderer'; import { IKeyboardEvent } from './common/Types'; import { evaluateKeyboardEvent } from './core/input/Keyboard'; -import { KeyboardResultType, ICharset } from './core/Types'; +import { KeyboardResultType, ICharset, IBufferLine, IAttributeData } from './core/Types'; import { clone } from './common/Clone'; import { EventEmitter2, IEvent } from './common/EventEmitter2'; -import { Attributes } from './BufferLine'; +import { Attributes, DEFAULT_ATTR_DATA } from './core/buffer/BufferLine'; import { applyWindowsMode } from './WindowsMode'; // Let it work inside Node.js for automated testing purposes. diff --git a/src/TestUtils.test.ts b/src/TestUtils.test.ts index 92018d1f..1d5008c8 100644 --- a/src/TestUtils.test.ts +++ b/src/TestUtils.test.ts @@ -4,13 +4,14 @@ */ import { IColorSet, IRenderer, IRenderDimensions, IColorManager } from './renderer/Types'; -import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, ILinkifier, IMouseHelper, ILinkMatcherOptions, CharacterJoinerHandler, IBufferLine, IBufferStringIterator, ICellData, IAttributeData } from './Types'; +import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, ILinkifier, IMouseHelper, ILinkMatcherOptions, CharacterJoinerHandler, IBufferStringIterator } from './Types'; +import { IBufferLine, ICellData, IAttributeData } from './core/Types'; import { ICircularList, XtermListener } from './common/Types'; import { Buffer } from './Buffer'; import * as Browser from './common/Platform'; import { ITheme, IDisposable, IMarker, IEvent } from 'xterm'; import { Terminal } from './Terminal'; -import { AttributeData } from './BufferLine'; +import { AttributeData } from './core/buffer/BufferLine'; export class TestTerminal extends Terminal { writeSync(data: string): void { diff --git a/src/Types.ts b/src/Types.ts index e603e92b..56feb71f 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -5,13 +5,12 @@ import { Terminal as PublicTerminal, ITerminalOptions as IPublicTerminalOptions, IEventEmitter, IDisposable } from 'xterm'; import { IColorSet, IRenderer } from './renderer/Types'; -import { ICharset } from './core/Types'; +import { ICharset, IAttributeData, ICellData, IBufferLine, CharData } from './core/Types'; import { ICircularList } from './common/Types'; import { IEvent } from './common/EventEmitter2'; export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean; -export type CharData = [number, string, number, number]; export type LineData = CharData[]; export type LinkMatcherHandler = (event: MouseEvent, uri: string) => void; @@ -525,85 +524,6 @@ export interface IEscapeSequenceParser extends IDisposable { clearErrorHandler(): void; } -/** RGB color type */ -export type IColorRGB = [number, number, number]; - -/** Attribute data */ -export interface IAttributeData { - fg: number; - bg: number; - - clone(): IAttributeData; - - // flags - isInverse(): number; - isBold(): number; - isUnderline(): number; - isBlink(): number; - isInvisible(): number; - isItalic(): number; - isDim(): number; - - // color modes - getFgColorMode(): number; - getBgColorMode(): number; - isFgRGB(): boolean; - isBgRGB(): boolean; - isFgPalette(): boolean; - isBgPalette(): boolean; - isFgDefault(): boolean; - isBgDefault(): boolean; - - // colors - getFgColor(): number; - getBgColor(): number; -} - -/** Cell data */ -export interface ICellData extends IAttributeData { - content: number; - combinedData: string; - isCombined(): number; - getWidth(): number; - getChars(): string; - getCode(): number; - setFromCharData(value: CharData): void; - getAsCharData(): CharData; -} - -/** - * Interface for a line in the terminal buffer. - */ -export interface IBufferLine { - length: number; - isWrapped: boolean; - get(index: number): CharData; - set(index: number, value: CharData): void; - loadCell(index: number, cell: ICellData): ICellData; - setCell(index: number, cell: ICellData): void; - setCellFromCodePoint(index: number, codePoint: number, width: number, fg: number, bg: number): void; - addCodepointToCell(index: number, codePoint: number): void; - insertCells(pos: number, n: number, ch: ICellData): void; - deleteCells(pos: number, n: number, fill: ICellData): void; - replaceCells(start: number, end: number, fill: ICellData): void; - resize(cols: number, fill: ICellData): void; - fill(fillCellData: ICellData): void; - copyFrom(line: IBufferLine): void; - clone(): IBufferLine; - getTrimmedLength(): number; - translateToString(trimRight?: boolean, startCol?: number, endCol?: number): string; - - /* direct access to cell attrs */ - getWidth(index: number): number; - hasWidth(index: number): number; - getFg(index: number): number; - getBg(index: number): number; - hasContent(index: number): number; - getCodePoint(index: number): number; - isCombined(index: number): number; - getString(index: number): string; -} - export interface IMouseZoneManager extends IDisposable { add(zone: IMouseZone): void; clearAll(start?: number, end?: number): void; diff --git a/src/WindowsMode.ts b/src/WindowsMode.ts index ac1d193e..d7b4bcae 100644 --- a/src/WindowsMode.ts +++ b/src/WindowsMode.ts @@ -5,7 +5,7 @@ import { IDisposable } from 'xterm'; import { ITerminal } from './Types'; -import { CHAR_DATA_CODE_INDEX, NULL_CELL_CODE, WHITESPACE_CELL_CODE } from './Buffer'; +import { CHAR_DATA_CODE_INDEX, NULL_CELL_CODE, WHITESPACE_CELL_CODE } from './core/buffer/BufferLine'; export function applyWindowsMode(terminal: ITerminal): IDisposable { // Winpty does not support wraparound mode which means that lines will never diff --git a/src/common/Types.ts b/src/common/Types.ts index b2111bfc..717de359 100644 --- a/src/common/Types.ts +++ b/src/common/Types.ts @@ -6,6 +6,8 @@ import { IEvent, EventEmitter2 } from './EventEmitter2'; import { IDeleteEvent, IInsertEvent } from './CircularList'; +export const DEFAULT_COLOR = 256; + export interface IDisposable { dispose(): void; } diff --git a/src/core/Types.ts b/src/core/Types.ts index 4001e448..ae9274b8 100644 --- a/src/core/Types.ts +++ b/src/core/Types.ts @@ -19,3 +19,82 @@ export interface IKeyboardResult { export interface ICharset { [key: string]: string; } + +export type CharData = [number, string, number, number]; +export type IColorRGB = [number, number, number]; + +/** Attribute data */ +export interface IAttributeData { + fg: number; + bg: number; + + clone(): IAttributeData; + + // flags + isInverse(): number; + isBold(): number; + isUnderline(): number; + isBlink(): number; + isInvisible(): number; + isItalic(): number; + isDim(): number; + + // color modes + getFgColorMode(): number; + getBgColorMode(): number; + isFgRGB(): boolean; + isBgRGB(): boolean; + isFgPalette(): boolean; + isBgPalette(): boolean; + isFgDefault(): boolean; + isBgDefault(): boolean; + + // colors + getFgColor(): number; + getBgColor(): number; +} + +/** Cell data */ +export interface ICellData extends IAttributeData { + content: number; + combinedData: string; + isCombined(): number; + getWidth(): number; + getChars(): string; + getCode(): number; + setFromCharData(value: CharData): void; + getAsCharData(): CharData; +} + +/** + * Interface for a line in the terminal buffer. + */ +export interface IBufferLine { + length: number; + isWrapped: boolean; + get(index: number): CharData; + set(index: number, value: CharData): void; + loadCell(index: number, cell: ICellData): ICellData; + setCell(index: number, cell: ICellData): void; + setCellFromCodePoint(index: number, codePoint: number, width: number, fg: number, bg: number): void; + addCodepointToCell(index: number, codePoint: number): void; + insertCells(pos: number, n: number, ch: ICellData): void; + deleteCells(pos: number, n: number, fill: ICellData): void; + replaceCells(start: number, end: number, fill: ICellData): void; + resize(cols: number, fill: ICellData): void; + fill(fillCellData: ICellData): void; + copyFrom(line: IBufferLine): void; + clone(): IBufferLine; + getTrimmedLength(): number; + translateToString(trimRight?: boolean, startCol?: number, endCol?: number): string; + + /* direct access to cell attrs */ + getWidth(index: number): number; + hasWidth(index: number): number; + getFg(index: number): number; + getBg(index: number): number; + hasContent(index: number): number; + getCodePoint(index: number): number; + isCombined(index: number): number; + getString(index: number): string; +} diff --git a/src/BufferLine.test.ts b/src/core/buffer/BufferLine.test.ts similarity index 95% rename from src/BufferLine.test.ts rename to src/core/buffer/BufferLine.test.ts index 5b029cb8..c42b372e 100644 --- a/src/BufferLine.test.ts +++ b/src/core/buffer/BufferLine.test.ts @@ -3,10 +3,8 @@ * @license MIT */ import * as chai from 'chai'; -import { BufferLine, CellData, Content } from './BufferLine'; -import { CharData, IBufferLine } from './Types'; -import { NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, DEFAULT_ATTR } from './Buffer'; - +import { BufferLine, CellData, Content, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, DEFAULT_ATTR } from './BufferLine'; +import { CharData, IBufferLine } from '../Types'; class TestBufferLine extends BufferLine { public get combined(): {[index: number]: string} { @@ -57,7 +55,7 @@ describe('BufferLine', function(): void { chai.expect(line.length).equals(10); chai.expect(line.loadCell(0, new CellData()).getAsCharData()).eql([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]); chai.expect(line.isWrapped).equals(false); - line = new TestBufferLine(10, null, true); + line = new TestBufferLine(10, undefined, true); chai.expect(line.length).equals(10); chai.expect(line.loadCell(0, new CellData()).getAsCharData()).eql([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]); chai.expect(line.isWrapped).equals(true); @@ -127,7 +125,7 @@ describe('BufferLine', function(): void { ]); }); it('clone', function(): void { - const line = new TestBufferLine(5, null, true); + const line = new TestBufferLine(5, undefined, true); line.setCell(0, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); line.setCell(1, CellData.fromCharData([2, 'b', 0, 'b'.charCodeAt(0)])); line.setCell(2, CellData.fromCharData([3, 'c', 0, 'c'.charCodeAt(0)])); @@ -167,27 +165,27 @@ describe('BufferLine', function(): void { it('enlarge(false)', function(): void { const line = new TestBufferLine(5, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), false); line.resize(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); - chai.expect(line.toArray()).eql(Array(10).fill([1, 'a', 0, 'a'.charCodeAt(0)])); + chai.expect(line.toArray()).eql((Array(10) as any).fill([1, 'a', 0, 'a'.charCodeAt(0)])); }); it('enlarge(true)', function(): void { const line = new TestBufferLine(5, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), false); line.resize(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); - chai.expect(line.toArray()).eql(Array(10).fill([1, 'a', 0, 'a'.charCodeAt(0)])); + chai.expect(line.toArray()).eql((Array(10) as any).fill([1, 'a', 0, 'a'.charCodeAt(0)])); }); it('shrink(true) - should apply new size', function(): void { const line = new TestBufferLine(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), false); line.resize(5, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); - chai.expect(line.toArray()).eql(Array(5).fill([1, 'a', 0, 'a'.charCodeAt(0)])); + chai.expect(line.toArray()).eql((Array(5) as any).fill([1, 'a', 0, 'a'.charCodeAt(0)])); }); it('shrink to 0 length', function(): void { const line = new TestBufferLine(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), false); line.resize(0, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); - chai.expect(line.toArray()).eql(Array(0).fill([1, 'a', 0, 'a'.charCodeAt(0)])); + chai.expect(line.toArray()).eql((Array(0) as any).fill([1, 'a', 0, 'a'.charCodeAt(0)])); }); it('should remove combining data on replaced cells after shrinking then enlarging', () => { const line = new TestBufferLine(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), false); - line.set(2, [ null, '😁', 1, '😁'.charCodeAt(0) ]); - line.set(9, [ null, '😁', 1, '😁'.charCodeAt(0) ]); + line.set(2, [ 0, '😁', 1, '😁'.charCodeAt(0) ]); + line.set(9, [ 0, '😁', 1, '😁'.charCodeAt(0) ]); chai.expect(line.translateToString()).eql('aa😁aaaaaa😁'); chai.expect(Object.keys(line.combined).length).eql(2); line.resize(5, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); @@ -224,7 +222,7 @@ describe('BufferLine', function(): void { const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false); line.setCell(0, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); line.setCell(2, CellData.fromCharData([1, '1', 2, '1'.charCodeAt(0)])); - line.setCell(3, CellData.fromCharData([0, '', 0, undefined])); + line.setCell(3, CellData.fromCharData([0, '', 0, 0])); chai.expect(line.getTrimmedLength()).equal(4); // also counts null cell after fullwidth }); }); @@ -284,11 +282,11 @@ describe('BufferLine', function(): void { const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false); line.setCell(0, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); line.setCell(2, CellData.fromCharData([1, '1', 2, '1'.charCodeAt(0)])); - line.setCell(3, CellData.fromCharData([0, '', 0, undefined])); + line.setCell(3, CellData.fromCharData([0, '', 0, 0])); line.setCell(5, CellData.fromCharData([1, '1', 2, '1'.charCodeAt(0)])); - line.setCell(6, CellData.fromCharData([0, '', 0, undefined])); + line.setCell(6, CellData.fromCharData([0, '', 0, 0])); line.setCell(7, CellData.fromCharData([1, '1', 2, '1'.charCodeAt(0)])); - line.setCell(8, CellData.fromCharData([0, '', 0, undefined])); + line.setCell(8, CellData.fromCharData([0, '', 0, 0])); chai.expect(line.translateToString(false)).equal('a 1 11 '); chai.expect(line.translateToString(true)).equal('a 1 11'); chai.expect(line.translateToString(false, 0, 7)).equal('a 1 1'); diff --git a/src/BufferLine.ts b/src/core/buffer/BufferLine.ts similarity index 94% rename from src/BufferLine.ts rename to src/core/buffer/BufferLine.ts index d2f7af40..154cc598 100644 --- a/src/BufferLine.ts +++ b/src/core/buffer/BufferLine.ts @@ -2,10 +2,34 @@ * Copyright (c) 2018 The xterm.js authors. All rights reserved. * @license MIT */ -import { CharData, IBufferLine, ICellData, IColorRGB, IAttributeData } from './Types'; -import { NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, WHITESPACE_CELL_CHAR, CHAR_DATA_ATTR_INDEX } from './Buffer'; -import { stringFromCodePoint } from './core/input/TextDecoder'; +import { CharData, IBufferLine, ICellData, IColorRGB, IAttributeData } from '../Types'; +import { stringFromCodePoint } from '../input/TextDecoder'; +import { DEFAULT_COLOR } from '../../common/Types'; +export const DEFAULT_ATTR = (0 << 18) | (DEFAULT_COLOR << 9) | (256 << 0); + +export const CHAR_DATA_ATTR_INDEX = 0; +export const CHAR_DATA_CHAR_INDEX = 1; +export const CHAR_DATA_WIDTH_INDEX = 2; +export const CHAR_DATA_CODE_INDEX = 3; + +/** + * Null cell - a real empty cell (containing nothing). + * Note that code should always be 0 for a null cell as + * several test condition of the buffer line rely on this. + */ +export const NULL_CELL_CHAR = ''; +export const NULL_CELL_WIDTH = 1; +export const NULL_CELL_CODE = 0; + +/** + * Whitespace cell. + * This is meant as a replacement for empty cells when needed + * during rendering lines to preserve correct aligment. + */ +export const WHITESPACE_CELL_CHAR = ' '; +export const WHITESPACE_CELL_WIDTH = 1; +export const WHITESPACE_CELL_CODE = 32; /** * buffer memory layout: @@ -193,6 +217,8 @@ export class AttributeData implements IAttributeData { } } +export const DEFAULT_ATTR_DATA = new AttributeData(); + /** * CellData - represents a single Cell in the terminal buffer. */ @@ -299,17 +325,15 @@ export class CellData extends AttributeData implements ICellData { * memory allocs / GC pressure can be greatly reduced by reusing the CellData object. */ export class BufferLine implements IBufferLine { - protected _data: Uint32Array | null = null; + protected _data: Uint32Array; protected _combined: {[index: number]: string} = {}; public length: number; constructor(cols: number, fillCellData?: ICellData, public isWrapped: boolean = false) { - if (cols) { - this._data = new Uint32Array(cols * CELL_SIZE); - const cell = fillCellData || CellData.fromCharData([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]); - for (let i = 0; i < cols; ++i) { - this.setCell(i, cell); - } + this._data = new Uint32Array(cols * CELL_SIZE); + const cell = fillCellData || CellData.fromCharData([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]); + for (let i = 0; i < cols; ++i) { + this.setCell(i, cell); } this.length = cols; } @@ -547,7 +571,7 @@ export class BufferLine implements IBufferLine { } } } else { - this._data = null; + this._data = new Uint32Array(0); this._combined = {}; } } diff --git a/src/handlers/AltClickHandler.ts b/src/handlers/AltClickHandler.ts index 9286421e..5cf60fa6 100644 --- a/src/handlers/AltClickHandler.ts +++ b/src/handlers/AltClickHandler.ts @@ -3,7 +3,8 @@ * @license MIT */ -import { ITerminal, IBufferLine } from '../Types'; +import { ITerminal } from '../Types'; +import { IBufferLine } from '../core/Types'; import { ICircularList } from '../common/Types'; import { C0 } from '../common/data/EscapeSequences'; diff --git a/src/renderer/BaseRenderLayer.ts b/src/renderer/BaseRenderLayer.ts index ace1f678..ce50a651 100644 --- a/src/renderer/BaseRenderLayer.ts +++ b/src/renderer/BaseRenderLayer.ts @@ -4,12 +4,13 @@ */ import { IRenderLayer, IColorSet, IRenderDimensions } from './Types'; -import { ITerminal, ICellData } from '../Types'; -import { DIM_OPACITY, INVERTED_DEFAULT_COLOR, IGlyphIdentifier, DEFAULT_COLOR } from './atlas/Types'; +import { ITerminal } from '../Types'; +import { ICellData } from '../core/Types'; +import { DEFAULT_COLOR } from '../common/Types'; +import { DIM_OPACITY, INVERTED_DEFAULT_COLOR, IGlyphIdentifier } from './atlas/Types'; import BaseCharAtlas from './atlas/BaseCharAtlas'; import { acquireCharAtlas } from './atlas/CharAtlasCache'; -import { CellData, AttributeData } from '../BufferLine'; -import { WHITESPACE_CELL_CHAR, WHITESPACE_CELL_CODE } from '../Buffer'; +import { CellData, AttributeData, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_CODE } from '../core/buffer/BufferLine'; import { JoinedCellData } from './CharacterJoinerRegistry'; export abstract class BaseRenderLayer implements IRenderLayer { diff --git a/src/renderer/CharacterJoinerRegistry.test.ts b/src/renderer/CharacterJoinerRegistry.test.ts index 2ccfd197..948985a4 100644 --- a/src/renderer/CharacterJoinerRegistry.test.ts +++ b/src/renderer/CharacterJoinerRegistry.test.ts @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2018 The xterm.js authors. All rights reserved. + * @license MIT + */ + import { assert } from 'chai'; import { MockTerminal, MockBuffer } from '../TestUtils.test'; @@ -5,8 +10,8 @@ import { CircularList } from '../common/CircularList'; import { ICharacterJoinerRegistry } from './Types'; import { CharacterJoinerRegistry } from './CharacterJoinerRegistry'; -import { BufferLine, CellData } from '../BufferLine'; -import { IBufferLine } from '../Types'; +import { BufferLine, CellData } from '../core/buffer/BufferLine'; +import { IBufferLine } from '../core/Types'; describe('CharacterJoinerRegistry', () => { let registry: ICharacterJoinerRegistry; diff --git a/src/renderer/CharacterJoinerRegistry.ts b/src/renderer/CharacterJoinerRegistry.ts index 7a3bb8e0..3302c312 100644 --- a/src/renderer/CharacterJoinerRegistry.ts +++ b/src/renderer/CharacterJoinerRegistry.ts @@ -1,7 +1,12 @@ -import { ITerminal, IBufferLine, ICellData, CharData } from '../Types'; +/** + * Copyright (c) 2018 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { ITerminal } from '../Types'; +import { IBufferLine, ICellData, CharData } from '../core/Types'; import { ICharacterJoinerRegistry, ICharacterJoiner } from './Types'; -import { CellData, Content, AttributeData } from '../BufferLine'; -import { WHITESPACE_CELL_CHAR } from '../Buffer'; +import { CellData, Content, AttributeData, WHITESPACE_CELL_CHAR } from '../core/buffer/BufferLine'; export class JoinedCellData extends AttributeData implements ICellData { private _width: number; diff --git a/src/renderer/CursorRenderLayer.ts b/src/renderer/CursorRenderLayer.ts index c3b751fa..3e8af02d 100644 --- a/src/renderer/CursorRenderLayer.ts +++ b/src/renderer/CursorRenderLayer.ts @@ -5,8 +5,9 @@ import { IColorSet, IRenderDimensions } from './Types'; import { BaseRenderLayer } from './BaseRenderLayer'; -import { ITerminal, ICellData } from '../Types'; -import { CellData } from '../BufferLine'; +import { ITerminal } from '../Types'; +import { ICellData } from '../core/Types'; +import { CellData } from '../core/buffer/BufferLine'; interface ICursorState { x: number; diff --git a/src/renderer/TextRenderLayer.ts b/src/renderer/TextRenderLayer.ts index d54008b8..8be5665c 100644 --- a/src/renderer/TextRenderLayer.ts +++ b/src/renderer/TextRenderLayer.ts @@ -3,12 +3,12 @@ * @license MIT */ -import { NULL_CELL_CODE } from '../Buffer'; import { IColorSet, IRenderDimensions, ICharacterJoinerRegistry } from './Types'; -import { CharData, ITerminal, ICellData } from '../Types'; +import { ITerminal } from '../Types'; +import { CharData, ICellData } from '../core/Types'; import { GridCache } from './GridCache'; import { BaseRenderLayer } from './BaseRenderLayer'; -import { CellData, AttributeData, Content } from '../BufferLine'; +import { CellData, AttributeData, Content, NULL_CELL_CODE } from '../core/buffer/BufferLine'; import { JoinedCellData } from './CharacterJoinerRegistry'; /** diff --git a/src/renderer/atlas/CharAtlasUtils.ts b/src/renderer/atlas/CharAtlasUtils.ts index 5b1add39..c2eb2e1e 100644 --- a/src/renderer/atlas/CharAtlasUtils.ts +++ b/src/renderer/atlas/CharAtlasUtils.ts @@ -5,7 +5,8 @@ import { ITerminal } from '../../Types'; import { IColorSet } from '../Types'; -import { DEFAULT_COLOR, ICharAtlasConfig } from './Types'; +import { ICharAtlasConfig } from './Types'; +import { DEFAULT_COLOR } from '../../common/Types'; export function generateConfig(scaledCharWidth: number, scaledCharHeight: number, terminal: ITerminal, colors: IColorSet): ICharAtlasConfig { // null out some fields that don't matter diff --git a/src/renderer/atlas/StaticCharAtlas.ts b/src/renderer/atlas/StaticCharAtlas.ts index b54c833e..66beb363 100644 --- a/src/renderer/atlas/StaticCharAtlas.ts +++ b/src/renderer/atlas/StaticCharAtlas.ts @@ -3,10 +3,11 @@ * @license MIT */ -import { DIM_OPACITY, IGlyphIdentifier, DEFAULT_COLOR, ICharAtlasConfig, CHAR_ATLAS_CELL_SPACING } from './Types'; +import { DIM_OPACITY, IGlyphIdentifier, ICharAtlasConfig, CHAR_ATLAS_CELL_SPACING } from './Types'; import { generateStaticCharAtlasTexture } from './CharAtlasGenerator'; import BaseCharAtlas from './BaseCharAtlas'; import { is256Color } from './CharAtlasUtils'; +import { DEFAULT_COLOR } from '../../common/Types'; export default class StaticCharAtlas extends BaseCharAtlas { private _texture: HTMLCanvasElement | ImageBitmap; diff --git a/src/renderer/atlas/Types.ts b/src/renderer/atlas/Types.ts index 38923b2f..2459c72f 100644 --- a/src/renderer/atlas/Types.ts +++ b/src/renderer/atlas/Types.ts @@ -6,7 +6,6 @@ import { FontWeight } from 'xterm'; import { IColorSet } from '../Types'; -export const DEFAULT_COLOR = 256; export const INVERTED_DEFAULT_COLOR = 257; export const DIM_OPACITY = 0.5; diff --git a/src/renderer/dom/DomRendererRowFactory.test.ts b/src/renderer/dom/DomRendererRowFactory.test.ts index 076f5d6a..b2530595 100644 --- a/src/renderer/dom/DomRendererRowFactory.test.ts +++ b/src/renderer/dom/DomRendererRowFactory.test.ts @@ -6,9 +6,9 @@ import jsdom = require('jsdom'); import { assert } from 'chai'; import { DomRendererRowFactory } from './DomRendererRowFactory'; -import { DEFAULT_ATTR, NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR, DEFAULT_ATTR_DATA } from '../../Buffer'; -import { BufferLine, CellData, FgFlags, BgFlags, Attributes } from '../../BufferLine'; -import { IBufferLine, ITerminalOptions } from '../../Types'; +import { BufferLine, CellData, FgFlags, BgFlags, Attributes, NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR, DEFAULT_ATTR, DEFAULT_ATTR_DATA } from '../../core/buffer/BufferLine'; +import { ITerminalOptions } from '../../Types'; +import { IBufferLine } from '../../core/Types'; describe('DomRendererRowFactory', () => { let dom: jsdom.JSDOM; diff --git a/src/renderer/dom/DomRendererRowFactory.ts b/src/renderer/dom/DomRendererRowFactory.ts index 60e2d509..85ef586e 100644 --- a/src/renderer/dom/DomRendererRowFactory.ts +++ b/src/renderer/dom/DomRendererRowFactory.ts @@ -3,10 +3,10 @@ * @license MIT */ -import { NULL_CELL_CODE, WHITESPACE_CELL_CHAR } from '../../Buffer'; -import { IBufferLine, ITerminalOptions } from '../../Types'; +import { ITerminalOptions } from '../../Types'; +import { IBufferLine } from '../../core/Types'; import { INVERTED_DEFAULT_COLOR } from '../atlas/Types'; -import { CellData, AttributeData } from '../../BufferLine'; +import { CellData, AttributeData, NULL_CELL_CODE, WHITESPACE_CELL_CHAR } from '../../core/buffer/BufferLine'; export const BOLD_CLASS = 'xterm-bold'; export const DIM_CLASS = 'xterm-dim';