diff --git a/src/Terminal.ts b/src/Terminal.ts index 5934650523..b28cfcfa07 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -691,7 +691,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp private _createRenderer(): IRenderer { switch (this.options.rendererType) { case 'canvas': return new Renderer(this, this._colorManager.colors, this._charSizeService); break; - case 'dom': return new DomRenderer(this, this._colorManager.colors, this._charSizeService); break; + case 'dom': return new DomRenderer(this, this._colorManager.colors, this._charSizeService, this.optionsService); break; default: throw new Error(`Unrecognized rendererType "${this.options.rendererType}"`); } } diff --git a/src/renderer/CharacterJoinerRegistry.test.ts b/src/browser/renderer/CharacterJoinerRegistry.test.ts similarity index 94% rename from src/renderer/CharacterJoinerRegistry.test.ts rename to src/browser/renderer/CharacterJoinerRegistry.test.ts index a73672a21c..bca12d6bdd 100644 --- a/src/renderer/CharacterJoinerRegistry.test.ts +++ b/src/browser/renderer/CharacterJoinerRegistry.test.ts @@ -4,24 +4,19 @@ */ import { assert } from 'chai'; - -import { MockTerminal, MockBuffer } from '../TestUtils.test'; -import { CircularList } from 'common/CircularList'; - -import { ICharacterJoinerRegistry } from './Types'; -import { CharacterJoinerRegistry } from './CharacterJoinerRegistry'; +import { ICharacterJoinerRegistry } from 'browser/renderer/Types'; +import { CharacterJoinerRegistry } from 'browser/renderer/CharacterJoinerRegistry'; import { BufferLine } from 'common/buffer/BufferLine'; import { IBufferLine } from 'common/Types'; import { CellData } from 'common/buffer/CellData'; +import { MockBufferService } from 'common/TestUtils.test'; describe('CharacterJoinerRegistry', () => { let registry: ICharacterJoinerRegistry; beforeEach(() => { - const terminal = new MockTerminal(); - terminal.cols = 16; - terminal.buffer = new MockBuffer(); - const lines = new CircularList(7); + const bufferService = new MockBufferService(16, 10); + const lines = bufferService.buffer.lines; lines.set(0, lineData([['a -> b -> c -> d']])); lines.set(1, lineData([['a -> b => c -> d']])); lines.set(2, lineData([['a -> b -', 0xFFFFFFFF], ['> c -> d', 0]])); @@ -31,7 +26,7 @@ describe('CharacterJoinerRegistry', () => { lines.set(5, lineData([['a', 0x11111111], [' -> b -> c -> '], ['d', 0x22222222]])); const line6 = lineData([['wi']]); line6.resize(line6.length + 1, CellData.fromCharData([0, '¥', 2, '¥'.charCodeAt(0)])); - line6.resize(line6.length + 1, CellData.fromCharData([0, '', 0, null])); + line6.resize(line6.length + 1, CellData.fromCharData([0, '', 0, 0])); let sub = lineData([['deemo']]); let oldSize = line6.length; line6.resize(oldSize + sub.length, CellData.fromCharData([0, '', 0, 0])); @@ -44,9 +39,7 @@ describe('CharacterJoinerRegistry', () => { for (let i = 0; i < sub.length; ++i) line6.setCell(i + oldSize, sub.loadCell(i, new CellData())); lines.set(6, line6); - (terminal.buffer).setLines(lines); - terminal.buffer.ydisp = 0; - registry = new CharacterJoinerRegistry(terminal); + registry = new CharacterJoinerRegistry(bufferService); }); it('has no joiners upon creation', () => { diff --git a/src/renderer/CharacterJoinerRegistry.ts b/src/browser/renderer/CharacterJoinerRegistry.ts similarity index 95% rename from src/renderer/CharacterJoinerRegistry.ts rename to src/browser/renderer/CharacterJoinerRegistry.ts index 80fff2b18e..a5abe80f56 100644 --- a/src/renderer/CharacterJoinerRegistry.ts +++ b/src/browser/renderer/CharacterJoinerRegistry.ts @@ -3,12 +3,12 @@ * @license MIT */ -import { ITerminal } from '../Types'; import { IBufferLine, ICellData, CharData } from 'common/Types'; -import { ICharacterJoinerRegistry, ICharacterJoiner } from './Types'; +import { ICharacterJoinerRegistry, ICharacterJoiner } from 'browser/renderer/Types'; import { AttributeData } from 'common/buffer/AttributeData'; import { WHITESPACE_CELL_CHAR, Content } from 'common/buffer/Constants'; import { CellData } from 'common/buffer/CellData'; +import { IBufferService } from 'common/services/Services'; export class JoinedCellData extends AttributeData implements ICellData { private _width: number; @@ -61,8 +61,7 @@ export class CharacterJoinerRegistry implements ICharacterJoinerRegistry { private _nextCharacterJoinerId: number = 0; private _workCell: CellData = new CellData(); - constructor(private _terminal: ITerminal) { - } + constructor(private _bufferService: IBufferService) { } public registerCharacterJoiner(handler: (text: string) => [number, number][]): number { const joiner: ICharacterJoiner = { @@ -90,8 +89,8 @@ export class CharacterJoinerRegistry implements ICharacterJoinerRegistry { return []; } - const line = this._terminal.buffer.lines.get(row); - if (line.length === 0) { + const line = this._bufferService.buffer.lines.get(row); + if (!line || line.length === 0) { return []; } @@ -144,7 +143,7 @@ export class CharacterJoinerRegistry implements ICharacterJoinerRegistry { } // Process any trailing ranges. - if (this._terminal.cols - rangeStartColumn > 1) { + if (this._bufferService.cols - rangeStartColumn > 1) { const joinedRanges = this._getJoinedRanges( lineStr, rangeStartStringIndex, @@ -204,7 +203,7 @@ export class CharacterJoinerRegistry implements ICharacterJoinerRegistry { return; } - for (let x = startCol; x < this._terminal.cols; x++) { + for (let x = startCol; x < this._bufferService.cols; x++) { const width = line.getWidth(x); const length = line.getString(x).length || WHITESPACE_CELL_CHAR.length; @@ -252,7 +251,7 @@ export class CharacterJoinerRegistry implements ICharacterJoinerRegistry { // If there is still a range left at the end, it must extend all the way to // the end of the line. if (currentRange) { - currentRange[1] = this._terminal.cols; + currentRange[1] = this._bufferService.cols; } } diff --git a/src/renderer/GridCache.test.ts b/src/browser/renderer/GridCache.test.ts similarity index 96% rename from src/renderer/GridCache.test.ts rename to src/browser/renderer/GridCache.test.ts index c4b1c220ee..30d22e8113 100644 --- a/src/renderer/GridCache.test.ts +++ b/src/browser/renderer/GridCache.test.ts @@ -4,7 +4,7 @@ */ import { assert } from 'chai'; -import { GridCache } from './GridCache'; +import { GridCache } from 'browser/renderer/GridCache'; describe('GridCache', () => { let grid: GridCache; diff --git a/src/renderer/GridCache.ts b/src/browser/renderer/GridCache.ts similarity index 84% rename from src/renderer/GridCache.ts rename to src/browser/renderer/GridCache.ts index dd188c6269..b48798d2ca 100644 --- a/src/renderer/GridCache.ts +++ b/src/browser/renderer/GridCache.ts @@ -4,7 +4,7 @@ */ export class GridCache { - public cache: T[][]; + public cache: (T | undefined)[][]; public constructor() { this.cache = []; @@ -16,7 +16,7 @@ export class GridCache { this.cache.push([]); } for (let y = this.cache[x].length; y < height; y++) { - this.cache[x].push(null); + this.cache[x].push(undefined); } this.cache[x].length = height; } @@ -26,7 +26,7 @@ export class GridCache { public clear(): void { for (let x = 0; x < this.cache.length; x++) { for (let y = 0; y < this.cache[x].length; y++) { - this.cache[x][y] = null; + this.cache[x][y] = undefined; } } } diff --git a/src/browser/renderer/Types.d.ts b/src/browser/renderer/Types.d.ts index e580ff8d49..df8f00312d 100644 --- a/src/browser/renderer/Types.d.ts +++ b/src/browser/renderer/Types.d.ts @@ -45,3 +45,14 @@ export interface IRenderer extends IDisposable { registerCharacterJoiner(handler: CharacterJoinerHandler): number; deregisterCharacterJoiner(joinerId: number): boolean; } + +export interface ICharacterJoiner { + id: number; + handler: CharacterJoinerHandler; +} + +export interface ICharacterJoinerRegistry { + registerCharacterJoiner(handler: (text: string) => [number, number][]): number; + deregisterCharacterJoiner(joinerId: number): boolean; + getJoinedCharacters(row: number): [number, number][]; +} diff --git a/src/renderer/atlas/Constants.ts b/src/browser/renderer/atlas/Constants.ts similarity index 100% rename from src/renderer/atlas/Constants.ts rename to src/browser/renderer/atlas/Constants.ts diff --git a/src/renderer/atlas/LRUMap.test.ts b/src/browser/renderer/atlas/LRUMap.test.ts similarity index 96% rename from src/renderer/atlas/LRUMap.test.ts rename to src/browser/renderer/atlas/LRUMap.test.ts index b24ad2af03..792f85a718 100644 --- a/src/renderer/atlas/LRUMap.test.ts +++ b/src/browser/renderer/atlas/LRUMap.test.ts @@ -4,7 +4,7 @@ */ import { assert } from 'chai'; -import { LRUMap } from './LRUMap'; +import { LRUMap } from 'browser/renderer/atlas/LRUMap'; describe('LRUMap', () => { it('can be used to store and retrieve values', () => { diff --git a/src/renderer/atlas/LRUMap.ts b/src/browser/renderer/atlas/LRUMap.ts similarity index 91% rename from src/renderer/atlas/LRUMap.ts rename to src/browser/renderer/atlas/LRUMap.ts index 0db5621f2a..f70962fe1f 100644 --- a/src/renderer/atlas/LRUMap.ts +++ b/src/browser/renderer/atlas/LRUMap.ts @@ -4,16 +4,16 @@ */ interface ILinkedListNode { - prev: ILinkedListNode; - next: ILinkedListNode; - key: number; - value: T; + prev: ILinkedListNode | null; + next: ILinkedListNode | null; + key: number | null; + value: T | null; } export class LRUMap { private _map: { [key: number]: ILinkedListNode } = {}; - private _head: ILinkedListNode = null; - private _tail: ILinkedListNode = null; + private _head: ILinkedListNode | null = null; + private _tail: ILinkedListNode | null = null; private _nodePool: ILinkedListNode[] = []; public size: number = 0; @@ -106,9 +106,9 @@ export class LRUMap { node.value = value; } else if (this.size >= this.capacity) { // we're out of space: recycle the head node, move it to the tail - node = this._head; + node = this._head!; this._unlinkNode(node); - delete this._map[node.key]; + delete this._map[node.key!]; node.key = key; node.value = value; this._map[key] = node; @@ -117,7 +117,7 @@ export class LRUMap { const nodePool = this._nodePool; if (nodePool.length > 0) { // use a preallocated node if we can - node = nodePool.pop(); + node = nodePool.pop()!; node.key = key; node.value = value; } else { diff --git a/src/renderer/dom/DomRendererRowFactory.test.ts b/src/browser/renderer/dom/DomRendererRowFactory.test.ts similarity index 96% rename from src/renderer/dom/DomRendererRowFactory.test.ts rename to src/browser/renderer/dom/DomRendererRowFactory.test.ts index 6ad9641c6f..b76d644d67 100644 --- a/src/renderer/dom/DomRendererRowFactory.test.ts +++ b/src/browser/renderer/dom/DomRendererRowFactory.test.ts @@ -5,25 +5,21 @@ import jsdom = require('jsdom'); import { assert } from 'chai'; -import { DomRendererRowFactory } from './DomRendererRowFactory'; +import { DomRendererRowFactory } from 'browser/renderer/dom/DomRendererRowFactory'; import { NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR, DEFAULT_ATTR, FgFlags, BgFlags, Attributes } from 'common/buffer/Constants'; import { BufferLine, DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; -import { ITerminalOptions } from '../../Types'; import { IBufferLine } from 'common/Types'; import { CellData } from 'common/buffer/CellData'; +import { MockOptionsService } from 'common/TestUtils.test'; describe('DomRendererRowFactory', () => { let dom: jsdom.JSDOM; - const options: ITerminalOptions = {}; let rowFactory: DomRendererRowFactory; let lineData: IBufferLine; beforeEach(() => { dom = new jsdom.JSDOM(''); - - options.drawBoldTextInBrightColors = true; - - rowFactory = new DomRendererRowFactory(options, dom.window.document); + rowFactory = new DomRendererRowFactory(dom.window.document, new MockOptionsService({ drawBoldTextInBrightColors: true })); lineData = createEmptyLineData(2); }); @@ -38,7 +34,7 @@ describe('DomRendererRowFactory', () => { it('should set correct attributes for double width characters', () => { lineData.setCell(0, CellData.fromCharData([DEFAULT_ATTR, '語', 2, '語'.charCodeAt(0)])); // There should be no element for the following "empty" cell - lineData.setCell(1, CellData.fromCharData([DEFAULT_ATTR, '', 0, undefined])); + lineData.setCell(1, CellData.fromCharData([DEFAULT_ATTR, '', 0, 0])); const fragment = rowFactory.createRow(lineData, false, undefined, 0, false, 5, 20); assert.equal(getFragmentHtml(fragment), '' diff --git a/src/renderer/dom/DomRendererRowFactory.ts b/src/browser/renderer/dom/DomRendererRowFactory.ts similarity index 94% rename from src/renderer/dom/DomRendererRowFactory.ts rename to src/browser/renderer/dom/DomRendererRowFactory.ts index 687d207d7d..316645f829 100644 --- a/src/renderer/dom/DomRendererRowFactory.ts +++ b/src/browser/renderer/dom/DomRendererRowFactory.ts @@ -3,12 +3,12 @@ * @license MIT */ -import { ITerminalOptions } from '../../Types'; import { IBufferLine } from 'common/Types'; -import { INVERTED_DEFAULT_COLOR } from '../atlas/Constants'; +import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants'; import { AttributeData } from 'common/buffer/AttributeData'; import { NULL_CELL_CODE, WHITESPACE_CELL_CHAR } from 'common/buffer/Constants'; import { CellData } from 'common/buffer/CellData'; +import { ITerminalOptions, IOptionsService } from 'common/services/Services'; export const BOLD_CLASS = 'xterm-bold'; export const DIM_CLASS = 'xterm-dim'; @@ -24,8 +24,8 @@ export class DomRendererRowFactory { private _workCell: CellData = new CellData(); constructor( - private _terminalOptions: ITerminalOptions, - private _document: Document + private _document: Document, + private _optionsService: IOptionsService ) { } @@ -106,7 +106,7 @@ export class DomRendererRowFactory { charElement.setAttribute('style', style); } else if (this._workCell.isFgPalette()) { let fg = this._workCell.getFgColor(); - if (this._workCell.isBold() && fg < 8 && !swapColor && this._terminalOptions.drawBoldTextInBrightColors) { + if (this._workCell.isBold() && fg < 8 && !swapColor && this._optionsService.options.drawBoldTextInBrightColors) { fg += 8; } charElement.classList.add(`xterm-${swapColor ? 'b' : 'f'}g-${fg}`); diff --git a/src/renderer/BaseRenderLayer.ts b/src/renderer/BaseRenderLayer.ts index 5101fdd535..b47434e2fc 100644 --- a/src/renderer/BaseRenderLayer.ts +++ b/src/renderer/BaseRenderLayer.ts @@ -9,7 +9,7 @@ import { ITerminal } from '../Types'; import { ICellData } from 'common/Types'; import { DEFAULT_COLOR, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_CODE } from 'common/buffer/Constants'; import { IGlyphIdentifier } from './atlas/Types'; -import { DIM_OPACITY, INVERTED_DEFAULT_COLOR } from './atlas/Constants'; +import { DIM_OPACITY, INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants'; import { BaseCharAtlas } from './atlas/BaseCharAtlas'; import { acquireCharAtlas } from './atlas/CharAtlasCache'; import { AttributeData } from 'common/buffer/AttributeData'; diff --git a/src/renderer/LinkRenderLayer.ts b/src/renderer/LinkRenderLayer.ts index 99eff4a2e1..8c6976d79c 100644 --- a/src/renderer/LinkRenderLayer.ts +++ b/src/renderer/LinkRenderLayer.ts @@ -6,7 +6,7 @@ import { ILinkifierEvent, ITerminal, ILinkifierAccessor } from '../Types'; import { IRenderDimensions } from 'browser/renderer/Types'; import { BaseRenderLayer } from './BaseRenderLayer'; -import { INVERTED_DEFAULT_COLOR } from './atlas/Constants'; +import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants'; import { is256Color } from './atlas/CharAtlasUtils'; import { IColorSet } from 'browser/Types'; diff --git a/src/renderer/Renderer.ts b/src/renderer/Renderer.ts index 56e12b5792..a6e8fca7c2 100644 --- a/src/renderer/Renderer.ts +++ b/src/renderer/Renderer.ts @@ -6,11 +6,11 @@ import { TextRenderLayer } from './TextRenderLayer'; import { SelectionRenderLayer } from './SelectionRenderLayer'; import { CursorRenderLayer } from './CursorRenderLayer'; -import { IRenderLayer, ICharacterJoinerRegistry } from './Types'; -import { IRenderer, IRenderDimensions, CharacterJoinerHandler } from 'browser/renderer/Types'; +import { IRenderLayer } from './Types'; +import { IRenderer, IRenderDimensions, CharacterJoinerHandler, ICharacterJoinerRegistry } from 'browser/renderer/Types'; import { ITerminal } from '../Types'; import { LinkRenderLayer } from './LinkRenderLayer'; -import { CharacterJoinerRegistry } from '../renderer/CharacterJoinerRegistry'; +import { CharacterJoinerRegistry } from 'browser/renderer/CharacterJoinerRegistry'; import { Disposable } from 'common/Lifecycle'; import { IColorSet } from 'browser/Types'; import { ICharSizeService } from 'browser/services/Services'; diff --git a/src/renderer/TextRenderLayer.ts b/src/renderer/TextRenderLayer.ts index db3bec1919..96678a5d2b 100644 --- a/src/renderer/TextRenderLayer.ts +++ b/src/renderer/TextRenderLayer.ts @@ -3,15 +3,14 @@ * @license MIT */ -import { ICharacterJoinerRegistry } from './Types'; -import { IRenderDimensions } from 'browser/renderer/Types'; +import { ICharacterJoinerRegistry, IRenderDimensions } from 'browser/renderer/Types'; import { ITerminal } from '../Types'; import { CharData, ICellData } from 'common/Types'; -import { GridCache } from './GridCache'; +import { GridCache } from 'browser/renderer/GridCache'; import { BaseRenderLayer } from './BaseRenderLayer'; import { AttributeData } from 'common/buffer/AttributeData'; import { NULL_CELL_CODE, Content } from 'common/buffer/Constants'; -import { JoinedCellData } from './CharacterJoinerRegistry'; +import { JoinedCellData } from 'browser/renderer/CharacterJoinerRegistry'; import { IColorSet } from 'browser/Types'; import { CellData } from 'common/buffer/CellData'; diff --git a/src/renderer/Types.d.ts b/src/renderer/Types.d.ts index 5f7d67a8d5..1546248ab4 100644 --- a/src/renderer/Types.d.ts +++ b/src/renderer/Types.d.ts @@ -6,7 +6,7 @@ import { ITerminal } from '../Types'; import { IDisposable } from 'xterm'; import { IColorSet } from 'browser/Types'; -import { IRenderDimensions, CharacterJoinerHandler } from 'browser/renderer/Types'; +import { IRenderDimensions, CharacterJoinerHandler, ICharacterJoiner } from 'browser/renderer/Types'; export interface IRenderLayer extends IDisposable { /** @@ -65,14 +65,3 @@ export interface IRenderLayer extends IDisposable { */ reset(terminal: ITerminal): void; } - -export interface ICharacterJoiner { - id: number; - handler: CharacterJoinerHandler; -} - -export interface ICharacterJoinerRegistry { - registerCharacterJoiner(handler: (text: string) => [number, number][]): number; - deregisterCharacterJoiner(joinerId: number): boolean; - getJoinedCharacters(row: number): [number, number][]; -} diff --git a/src/renderer/atlas/DynamicCharAtlas.ts b/src/renderer/atlas/DynamicCharAtlas.ts index fdae4e8029..6e669d9194 100644 --- a/src/renderer/atlas/DynamicCharAtlas.ts +++ b/src/renderer/atlas/DynamicCharAtlas.ts @@ -4,10 +4,10 @@ */ import { IGlyphIdentifier, ICharAtlasConfig } from './Types'; -import { DIM_OPACITY, INVERTED_DEFAULT_COLOR } from './Constants'; +import { DIM_OPACITY, INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants'; import { BaseCharAtlas } from './BaseCharAtlas'; import { DEFAULT_ANSI_COLORS } from 'browser/ColorManager'; -import { LRUMap } from './LRUMap'; +import { LRUMap } from 'browser/renderer/atlas/LRUMap'; import { isFirefox, isSafari } from 'common/Platform'; import { IColor } from 'browser/Types'; diff --git a/src/renderer/dom/DomRenderer.ts b/src/renderer/dom/DomRenderer.ts index fe6ab4d1b9..a6b6e86822 100644 --- a/src/renderer/dom/DomRenderer.ts +++ b/src/renderer/dom/DomRenderer.ts @@ -5,11 +5,12 @@ import { IRenderer, IRenderDimensions, CharacterJoinerHandler } from 'browser/renderer/Types'; import { ILinkifierEvent, ITerminal } from '../../Types'; -import { BOLD_CLASS, ITALIC_CLASS, CURSOR_CLASS, CURSOR_STYLE_BLOCK_CLASS, CURSOR_BLINK_CLASS, CURSOR_STYLE_BAR_CLASS, CURSOR_STYLE_UNDERLINE_CLASS, DomRendererRowFactory } from './DomRendererRowFactory'; -import { INVERTED_DEFAULT_COLOR } from '../atlas/Constants'; +import { BOLD_CLASS, ITALIC_CLASS, CURSOR_CLASS, CURSOR_STYLE_BLOCK_CLASS, CURSOR_BLINK_CLASS, CURSOR_STYLE_BAR_CLASS, CURSOR_STYLE_UNDERLINE_CLASS, DomRendererRowFactory } from 'browser/renderer/dom/DomRendererRowFactory'; +import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants'; import { Disposable } from 'common/Lifecycle'; import { IColorSet } from 'browser/Types'; import { ICharSizeService } from 'browser/services/Services'; +import { IOptionsService } from 'common/services/Services'; const TERMINAL_CLASS_PREFIX = 'xterm-dom-renderer-owner-'; const ROW_CONTAINER_CLASS = 'xterm-rows'; @@ -43,7 +44,8 @@ export class DomRenderer extends Disposable implements IRenderer { constructor( private _terminal: ITerminal, private _colors: IColorSet, - private _charSizeService: ICharSizeService + private _charSizeService: ICharSizeService, + private _optionsService: IOptionsService ) { super(); @@ -73,7 +75,7 @@ export class DomRenderer extends Disposable implements IRenderer { this._updateDimensions(); this._injectCss(); - this._rowFactory = new DomRendererRowFactory(_terminal.options, document); + this._rowFactory = new DomRendererRowFactory(document, this._optionsService); this._terminal.element.classList.add(TERMINAL_CLASS_PREFIX + this._terminalClass); this._terminal.screenElement.appendChild(this._rowContainer);