diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index 37a54e39a..5a3dc2b5a 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -4,7 +4,7 @@ */ import { assert, expect } from 'chai'; -import { InputHandler } from './InputHandler'; +import { InputHandler } from './common/InputHandler'; import { TestTerminal } from './TestUtils.test'; import { Terminal } from './Terminal'; import { IBufferLine, IAttributeData } from 'common/Types'; diff --git a/src/Terminal.ts b/src/Terminal.ts index e3af555b7..61c997bd0 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -27,7 +27,7 @@ import { CompositionHelper } from 'browser/input/CompositionHelper'; import { Viewport } from 'browser/Viewport'; import { rightClickHandler, moveTextAreaUnderMouseCursor, handlePasteEvent, copyHandler, paste } from 'browser/Clipboard'; import { C0 } from 'common/data/EscapeSequences'; -import { InputHandler, WindowsOptionsReportType } from './InputHandler'; +import { InputHandler, WindowsOptionsReportType } from './common/InputHandler'; import { Renderer } from 'browser/renderer/Renderer'; import { Linkifier } from 'browser/Linkifier'; import { SelectionService } from 'browser/services/SelectionService'; diff --git a/src/Types.d.ts b/src/Types.d.ts index 2f57e99c0..05c89e158 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -23,91 +23,6 @@ export interface ICompositionHelper { keydown(ev: KeyboardEvent): boolean; } -/** - * Calls the parser and handles actions generated by the parser. - */ -export interface IInputHandler { - onTitleChange: IEvent; - onRequestScroll: IEvent; - - parse(data: string | Uint8Array): void; - print(data: Uint32Array, start: number, end: number): void; - - /** C0 BEL */ bell(): void; - /** C0 LF */ lineFeed(): void; - /** C0 CR */ carriageReturn(): void; - /** C0 BS */ backspace(): void; - /** C0 HT */ tab(): void; - /** C0 SO */ shiftOut(): void; - /** C0 SI */ shiftIn(): void; - - /** CSI @ */ insertChars(params: IParams): void; - /** CSI SP @ */ scrollLeft(params: IParams): void; - /** CSI A */ cursorUp(params: IParams): void; - /** CSI SP A */ scrollRight(params: IParams): void; - /** CSI B */ cursorDown(params: IParams): void; - /** CSI C */ cursorForward(params: IParams): void; - /** CSI D */ cursorBackward(params: IParams): void; - /** CSI E */ cursorNextLine(params: IParams): void; - /** CSI F */ cursorPrecedingLine(params: IParams): void; - /** CSI G */ cursorCharAbsolute(params: IParams): void; - /** CSI H */ cursorPosition(params: IParams): void; - /** CSI I */ cursorForwardTab(params: IParams): void; - /** CSI J */ eraseInDisplay(params: IParams): void; - /** CSI K */ eraseInLine(params: IParams): void; - /** CSI L */ insertLines(params: IParams): void; - /** CSI M */ deleteLines(params: IParams): void; - /** CSI P */ deleteChars(params: IParams): void; - /** CSI S */ scrollUp(params: IParams): void; - /** CSI T */ scrollDown(params: IParams, collect?: string): void; - /** CSI X */ eraseChars(params: IParams): void; - /** CSI Z */ cursorBackwardTab(params: IParams): void; - /** CSI ` */ charPosAbsolute(params: IParams): void; - /** CSI a */ hPositionRelative(params: IParams): void; - /** CSI b */ repeatPrecedingCharacter(params: IParams): void; - /** CSI c */ sendDeviceAttributesPrimary(params: IParams): void; - /** CSI > c */ sendDeviceAttributesSecondary(params: IParams): void; - /** CSI d */ linePosAbsolute(params: IParams): void; - /** CSI e */ vPositionRelative(params: IParams): void; - /** CSI f */ hVPosition(params: IParams): void; - /** CSI g */ tabClear(params: IParams): void; - /** CSI h */ setMode(params: IParams, collect?: string): void; - /** CSI l */ resetMode(params: IParams, collect?: string): void; - /** CSI m */ charAttributes(params: IParams): void; - /** CSI n */ deviceStatus(params: IParams, collect?: string): void; - /** CSI p */ softReset(params: IParams, collect?: string): void; - /** CSI q */ setCursorStyle(params: IParams, collect?: string): void; - /** CSI r */ setScrollRegion(params: IParams, collect?: string): void; - /** CSI s */ saveCursor(params: IParams): void; - /** CSI u */ restoreCursor(params: IParams): void; - /** CSI ' } */ insertColumns(params: IParams): void; - /** CSI ' ~ */ deleteColumns(params: IParams): void; - /** OSC 0 - OSC 2 */ setTitle(data: string): void; - /** ESC E */ nextLine(): void; - /** ESC = */ keypadApplicationMode(): void; - /** ESC > */ keypadNumericMode(): void; - /** ESC % G - ESC % @ */ selectDefaultCharset(): void; - /** ESC ( C - ESC ) C - ESC * C - ESC + C - ESC - C - ESC . C - ESC / C */ selectCharset(collectAndFlag: string): void; - /** ESC D */ index(): void; - /** ESC H */ tabSet(): void; - /** ESC M */ reverseIndex(): void; - /** ESC c */ fullReset(): void; - /** ESC n - ESC o - ESC | - ESC } - ESC ~ */ setgLevel(level: number): void; - /** ESC # 8 */ screenAlignmentPattern(): void; -} - export interface ITerminal extends IPublicTerminal, IElementAccessor, IBufferAccessor, ILinkifierAccessor { screenElement: HTMLElement; browser: IBrowser; diff --git a/src/InputHandler.ts b/src/common/InputHandler.ts similarity index 99% rename from src/InputHandler.ts rename to src/common/InputHandler.ts index 61ef55463..70ec8859c 100644 --- a/src/InputHandler.ts +++ b/src/common/InputHandler.ts @@ -4,7 +4,7 @@ * @license MIT */ -import { IInputHandler } from './Types'; +import { IInputHandler, IAttributeData, IDisposable, IWindowOptions } from 'common/Types'; import { C0, C1 } from 'common/data/EscapeSequences'; import { CHARSETS, DEFAULT_CHARSET } from 'common/data/Charsets'; import { EscapeSequenceParser } from 'common/parser/EscapeSequenceParser'; @@ -17,7 +17,6 @@ import { IParsingState, IDcsHandler, IEscapeSequenceParser, IParams, IFunctionId import { NULL_CELL_CODE, NULL_CELL_WIDTH, Attributes, FgFlags, BgFlags, Content } from 'common/buffer/Constants'; import { CellData } from 'common/buffer/CellData'; import { AttributeData } from 'common/buffer/AttributeData'; -import { IAttributeData, IDisposable, IWindowOptions } from 'common/Types'; import { ICoreService, IBufferService, IOptionsService, ILogService, IDirtyRowService, ICoreMouseService, ICharsetService, IUnicodeService } from 'common/services/Services'; import { OscHandler } from 'common/parser/OscParser'; import { DcsHandler } from 'common/parser/DcsParser'; @@ -504,7 +503,7 @@ export class InputHandler extends Disposable implements IInputHandler { const wraparoundMode = this._coreService.decPrivateModes.wraparound; const insertMode = this._coreService.modes.insertMode; const curAttr = this._curAttrData; - let bufferRow = buffer.lines.get(buffer.y + buffer.ybase); + let bufferRow = buffer.lines.get(buffer.y + buffer.ybase)!; this._dirtyRowService.markDirty(buffer.y); @@ -568,10 +567,10 @@ export class InputHandler extends Disposable implements IInputHandler { } // The line already exists (eg. the initial viewport), mark it as a // wrapped line - buffer.lines.get(buffer.y).isWrapped = true; + buffer.lines.get(buffer.y)!.isWrapped = true; } // row changed, get it again - bufferRow = buffer.lines.get(buffer.y + buffer.ybase); + bufferRow = buffer.lines.get(buffer.y + buffer.ybase)!; } else { buffer.x = cols - 1; if (chWidth === 2) { @@ -1037,7 +1036,7 @@ export class InputHandler extends Disposable implements IInputHandler { * @param end end - 1 is last erased cell */ private _eraseInBufferLine(y: number, start: number, end: number, clearWrap: boolean = false): void { - const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y); + const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y)!; line.replaceCells( start, end, @@ -1055,7 +1054,7 @@ export class InputHandler extends Disposable implements IInputHandler { * @param y row index */ private _resetBufferLine(y: number): void { - const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y); + const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y)!; line.fill(this._bufferService.buffer.getNullCell(this._eraseAttrData())); line.isWrapped = false; } @@ -1104,7 +1103,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._eraseInBufferLine(j, 0, this._bufferService.buffer.x + 1, true); if (this._bufferService.buffer.x + 1 >= this._bufferService.cols) { // Deleted entire previous line. This next line can no longer be wrapped. - this._bufferService.buffer.lines.get(j + 1).isWrapped = false; + this._bufferService.buffer.lines.get(j + 1)!.isWrapped = false; } while (j--) { this._resetBufferLine(j); @@ -1356,7 +1355,7 @@ export class InputHandler extends Disposable implements IInputHandler { } const param = params.params[0] || 1; for (let y = buffer.scrollTop; y <= buffer.scrollBottom; ++y) { - const line = buffer.lines.get(buffer.ybase + y); + const line = buffer.lines.get(buffer.ybase + y)!; line.deleteCells(0, param, buffer.getNullCell(this._eraseAttrData()), this._eraseAttrData()); line.isWrapped = false; } @@ -1389,7 +1388,7 @@ export class InputHandler extends Disposable implements IInputHandler { } const param = params.params[0] || 1; for (let y = buffer.scrollTop; y <= buffer.scrollBottom; ++y) { - const line = buffer.lines.get(buffer.ybase + y); + const line = buffer.lines.get(buffer.ybase + y)!; line.insertCells(0, param, buffer.getNullCell(this._eraseAttrData()), this._eraseAttrData()); line.isWrapped = false; } @@ -1412,7 +1411,7 @@ export class InputHandler extends Disposable implements IInputHandler { } const param = params.params[0] || 1; for (let y = buffer.scrollTop; y <= buffer.scrollBottom; ++y) { - const line = this._bufferService.buffer.lines.get(buffer.ybase + y); + const line = this._bufferService.buffer.lines.get(buffer.ybase + y)!; line.insertCells(buffer.x, param, buffer.getNullCell(this._eraseAttrData()), this._eraseAttrData()); line.isWrapped = false; } @@ -1435,7 +1434,7 @@ export class InputHandler extends Disposable implements IInputHandler { } const param = params.params[0] || 1; for (let y = buffer.scrollTop; y <= buffer.scrollBottom; ++y) { - const line = buffer.lines.get(buffer.ybase + y); + const line = buffer.lines.get(buffer.ybase + y)!; line.deleteCells(buffer.x, param, buffer.getNullCell(this._eraseAttrData()), this._eraseAttrData()); line.isWrapped = false; } @@ -2064,7 +2063,7 @@ export class InputHandler extends Disposable implements IInputHandler { do { accu[advance + cSpace] = params.params[pos + advance]; if (params.hasSubParams(pos + advance)) { - const subparams = params.getSubParams(pos + advance); + const subparams = params.getSubParams(pos + advance)!; let i = 0; do { if (accu[1] === 5) { @@ -2519,12 +2518,12 @@ export class InputHandler extends Disposable implements IInputHandler { case 23: // PopTitle if (second === 0 || second === 2) { if (this._windowTitleStack.length) { - this.setTitle(this._windowTitleStack.pop()); + this.setTitle(this._windowTitleStack.pop()!); } } if (second === 0 || second === 1) { if (this._iconNameStack.length) { - this.setIconName(this._iconNameStack.pop()); + this.setIconName(this._iconNameStack.pop()!); } } break; @@ -2788,8 +2787,11 @@ export class InputHandler extends Disposable implements IInputHandler { this._setCursor(0, 0); for (let yOffset = 0; yOffset < this._bufferService.rows; ++yOffset) { const row = buffer.y + buffer.ybase + yOffset; - buffer.lines.get(row).fill(cell); - buffer.lines.get(row).isWrapped = false; + const line = buffer.lines.get(row); + if (line) { + line.fill(cell); + line.isWrapped = false; + } } this._dirtyRowService.markAllDirty(); this._setCursor(0, 0); diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index eacf92fe8..55e34084b 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -49,7 +49,6 @@ export class MockCharsetService implements ICharsetService { public serviceBrand: any; public charset: ICharset | undefined; public glevel: number = 0; - public charsets: ReadonlyArray = []; public reset(): void {} public setgLevel(g: number): void {} public setgCharset(g: number, charset: ICharset): void {} diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index cc7928c30..49a723b21 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -6,6 +6,7 @@ import { ITerminalOptions as IPublicTerminalOptions } from 'xterm'; import { IEvent, IEventEmitter } from 'common/EventEmitter'; import { IDeleteEvent, IInsertEvent } from 'common/CircularList'; +import { IParams } from 'common/parser/Types'; export interface IDisposable { dispose(): void; @@ -300,3 +301,88 @@ export interface IWindowOptions { popTitle?: boolean; setWinLines?: boolean; } + +/** + * Calls the parser and handles actions generated by the parser. + */ +export interface IInputHandler { + onTitleChange: IEvent; + onRequestScroll: IEvent; + + parse(data: string | Uint8Array): void; + print(data: Uint32Array, start: number, end: number): void; + + /** C0 BEL */ bell(): void; + /** C0 LF */ lineFeed(): void; + /** C0 CR */ carriageReturn(): void; + /** C0 BS */ backspace(): void; + /** C0 HT */ tab(): void; + /** C0 SO */ shiftOut(): void; + /** C0 SI */ shiftIn(): void; + + /** CSI @ */ insertChars(params: IParams): void; + /** CSI SP @ */ scrollLeft(params: IParams): void; + /** CSI A */ cursorUp(params: IParams): void; + /** CSI SP A */ scrollRight(params: IParams): void; + /** CSI B */ cursorDown(params: IParams): void; + /** CSI C */ cursorForward(params: IParams): void; + /** CSI D */ cursorBackward(params: IParams): void; + /** CSI E */ cursorNextLine(params: IParams): void; + /** CSI F */ cursorPrecedingLine(params: IParams): void; + /** CSI G */ cursorCharAbsolute(params: IParams): void; + /** CSI H */ cursorPosition(params: IParams): void; + /** CSI I */ cursorForwardTab(params: IParams): void; + /** CSI J */ eraseInDisplay(params: IParams): void; + /** CSI K */ eraseInLine(params: IParams): void; + /** CSI L */ insertLines(params: IParams): void; + /** CSI M */ deleteLines(params: IParams): void; + /** CSI P */ deleteChars(params: IParams): void; + /** CSI S */ scrollUp(params: IParams): void; + /** CSI T */ scrollDown(params: IParams, collect?: string): void; + /** CSI X */ eraseChars(params: IParams): void; + /** CSI Z */ cursorBackwardTab(params: IParams): void; + /** CSI ` */ charPosAbsolute(params: IParams): void; + /** CSI a */ hPositionRelative(params: IParams): void; + /** CSI b */ repeatPrecedingCharacter(params: IParams): void; + /** CSI c */ sendDeviceAttributesPrimary(params: IParams): void; + /** CSI > c */ sendDeviceAttributesSecondary(params: IParams): void; + /** CSI d */ linePosAbsolute(params: IParams): void; + /** CSI e */ vPositionRelative(params: IParams): void; + /** CSI f */ hVPosition(params: IParams): void; + /** CSI g */ tabClear(params: IParams): void; + /** CSI h */ setMode(params: IParams, collect?: string): void; + /** CSI l */ resetMode(params: IParams, collect?: string): void; + /** CSI m */ charAttributes(params: IParams): void; + /** CSI n */ deviceStatus(params: IParams, collect?: string): void; + /** CSI p */ softReset(params: IParams, collect?: string): void; + /** CSI q */ setCursorStyle(params: IParams, collect?: string): void; + /** CSI r */ setScrollRegion(params: IParams, collect?: string): void; + /** CSI s */ saveCursor(params: IParams): void; + /** CSI u */ restoreCursor(params: IParams): void; + /** CSI ' } */ insertColumns(params: IParams): void; + /** CSI ' ~ */ deleteColumns(params: IParams): void; + /** OSC 0 + OSC 2 */ setTitle(data: string): void; + /** ESC E */ nextLine(): void; + /** ESC = */ keypadApplicationMode(): void; + /** ESC > */ keypadNumericMode(): void; + /** ESC % G + ESC % @ */ selectDefaultCharset(): void; + /** ESC ( C + ESC ) C + ESC * C + ESC + C + ESC - C + ESC . C + ESC / C */ selectCharset(collectAndFlag: string): void; + /** ESC D */ index(): void; + /** ESC H */ tabSet(): void; + /** ESC M */ reverseIndex(): void; + /** ESC c */ fullReset(): void; + /** ESC n + ESC o + ESC | + ESC } + ESC ~ */ setgLevel(level: number): void; + /** ESC # 8 */ screenAlignmentPattern(): void; +} diff --git a/src/common/buffer/Buffer.ts b/src/common/buffer/Buffer.ts index 152bab7a3..1de39dbd2 100644 --- a/src/common/buffer/Buffer.ts +++ b/src/common/buffer/Buffer.ts @@ -36,7 +36,7 @@ export class Buffer implements IBuffer { public savedY: number = 0; public savedX: number = 0; public savedCurAttrData = DEFAULT_ATTR_DATA.clone(); - public savedCharset: ICharset | null = DEFAULT_CHARSET; + public savedCharset: ICharset | undefined = DEFAULT_CHARSET; public markers: Marker[] = []; private _nullCell: ICellData = CellData.fromCharData([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]); private _whitespaceCell: ICellData = CellData.fromCharData([0, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_WIDTH, WHITESPACE_CELL_CODE]); diff --git a/src/common/buffer/Types.d.ts b/src/common/buffer/Types.d.ts index e229d69c3..c271f33c7 100644 --- a/src/common/buffer/Types.d.ts +++ b/src/common/buffer/Types.d.ts @@ -31,7 +31,7 @@ export interface IBuffer { hasScrollback: boolean; savedY: number; savedX: number; - savedCharset: ICharset | null; + savedCharset: ICharset | undefined; savedCurAttrData: IAttributeData; isCursorInViewport: boolean; markers: IMarker[]; diff --git a/src/common/data/Charsets.ts b/src/common/data/Charsets.ts index 01087d8b1..c72d5a237 100644 --- a/src/common/data/Charsets.ts +++ b/src/common/data/Charsets.ts @@ -10,12 +10,12 @@ import { ICharset } from 'common/Types'; * to be represented within the terminal with only 8-bit encoding. See ISO 2022 * for a discussion on character sets. Only VT100 character sets are supported. */ -export const CHARSETS: { [key: string]: ICharset | null } = {}; +export const CHARSETS: { [key: string]: ICharset | undefined } = {}; /** * The default character set, US. */ -export const DEFAULT_CHARSET: ICharset | null = CHARSETS['B']; +export const DEFAULT_CHARSET: ICharset | undefined = CHARSETS['B']; /** * DEC Special Character and Line Drawing Set. @@ -74,7 +74,7 @@ CHARSETS['A'] = { * United States character set * ESC (B */ -CHARSETS['B'] = null; +CHARSETS['B'] = undefined; /** * Dutch character set diff --git a/src/common/services/CharsetService.ts b/src/common/services/CharsetService.ts index 47a015f6f..c5381065a 100644 --- a/src/common/services/CharsetService.ts +++ b/src/common/services/CharsetService.ts @@ -10,22 +10,23 @@ export class CharsetService implements ICharsetService { public serviceBrand: any; public charset: ICharset | undefined; - public charsets: ICharset[] = []; public glevel: number = 0; + private _charsets: (ICharset | undefined)[] = []; + public reset(): void { this.charset = undefined; - this.charsets = []; + this._charsets = []; this.glevel = 0; } public setgLevel(g: number): void { this.glevel = g; - this.charset = this.charsets[g]; + this.charset = this._charsets[g]; } - public setgCharset(g: number, charset: ICharset): void { - this.charsets[g] = charset; + public setgCharset(g: number, charset: ICharset | undefined): void { + this._charsets[g] = charset; if (this.glevel === g) { this.charset = charset; } diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index 8fa3f57b3..6829d7b96 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -98,7 +98,6 @@ export interface ICharsetService { charset: ICharset | undefined; readonly glevel: number; - readonly charsets: ReadonlyArray; reset(): void; @@ -113,7 +112,7 @@ export interface ICharsetService { * @param g * @param charset */ - setgCharset(g: number, charset: ICharset): void; + setgCharset(g: number, charset: ICharset | undefined): void; } export const IDirtyRowService = createDecorator('DirtyRowService');