mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Merge pull request #2637 from Tyriar/input_handler
Remove a large portion of InputHandler's dependency on Terminal
This commit is contained in:
+19
-15
@@ -7,13 +7,13 @@ import { assert, expect } from 'chai';
|
||||
import { InputHandler } from './InputHandler';
|
||||
import { MockInputHandlingTerminal, TestTerminal } from './TestUtils.test';
|
||||
import { Terminal } from './Terminal';
|
||||
import { IBufferLine } from 'common/Types';
|
||||
import { IBufferLine, IAttributeData } from 'common/Types';
|
||||
import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
|
||||
import { CellData } from 'common/buffer/CellData';
|
||||
import { Attributes } from 'common/buffer/Constants';
|
||||
import { AttributeData } from 'common/buffer/AttributeData';
|
||||
import { Params } from 'common/parser/Params';
|
||||
import { MockCoreService, MockBufferService, MockDirtyRowService, MockOptionsService, MockLogService, MockCoreMouseService } from 'common/TestUtils.test';
|
||||
import { MockCoreService, MockBufferService, MockDirtyRowService, MockOptionsService, MockLogService, MockCoreMouseService, MockCharsetService } from 'common/TestUtils.test';
|
||||
import { IBufferService } from 'common/services/Services';
|
||||
import { DEFAULT_OPTIONS } from 'common/services/OptionsService';
|
||||
import { clone } from 'common/Clone';
|
||||
@@ -33,34 +33,38 @@ function getLines(term: TestTerminal, limit: number = term.rows): string[] {
|
||||
return res;
|
||||
}
|
||||
|
||||
class TestInputHandler extends InputHandler {
|
||||
get curAttrData(): IAttributeData { return (this as any)._curAttrData; }
|
||||
}
|
||||
|
||||
describe('InputHandler', () => {
|
||||
describe('save and restore cursor', () => {
|
||||
const terminal = new MockInputHandlingTerminal();
|
||||
terminal.curAttrData.fg = 3;
|
||||
const bufferService = new MockBufferService(80, 30);
|
||||
bufferService.buffer.x = 1;
|
||||
bufferService.buffer.y = 2;
|
||||
bufferService.buffer.ybase = 0;
|
||||
const inputHandler = new InputHandler(terminal, bufferService, new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService());
|
||||
const inputHandler = new TestInputHandler(terminal, bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService());
|
||||
inputHandler.curAttrData.fg = 3;
|
||||
// Save cursor position
|
||||
inputHandler.saveCursor();
|
||||
assert.equal(bufferService.buffer.x, 1);
|
||||
assert.equal(bufferService.buffer.y, 2);
|
||||
assert.equal(terminal.curAttrData.fg, 3);
|
||||
assert.equal(inputHandler.curAttrData.fg, 3);
|
||||
// Change cursor position
|
||||
bufferService.buffer.x = 10;
|
||||
bufferService.buffer.y = 20;
|
||||
terminal.curAttrData.fg = 30;
|
||||
inputHandler.curAttrData.fg = 30;
|
||||
// Restore cursor position
|
||||
inputHandler.restoreCursor();
|
||||
assert.equal(bufferService.buffer.x, 1);
|
||||
assert.equal(bufferService.buffer.y, 2);
|
||||
assert.equal(terminal.curAttrData.fg, 3);
|
||||
assert.equal(inputHandler.curAttrData.fg, 3);
|
||||
});
|
||||
describe('setCursorStyle', () => {
|
||||
it('should call Terminal.setOption with correct params', () => {
|
||||
const optionsService = new MockOptionsService();
|
||||
const inputHandler = new InputHandler(new MockInputHandlingTerminal(), new MockBufferService(80, 30), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), optionsService, new MockCoreMouseService());
|
||||
const inputHandler = new InputHandler(new MockInputHandlingTerminal(), new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), optionsService, new MockCoreMouseService());
|
||||
|
||||
inputHandler.setCursorStyle(Params.fromArray([0]));
|
||||
assert.equal(optionsService.options['cursorStyle'], 'block');
|
||||
@@ -101,7 +105,7 @@ describe('InputHandler', () => {
|
||||
it('should toggle Terminal.bracketedPasteMode', () => {
|
||||
const terminal = new MockInputHandlingTerminal();
|
||||
terminal.bracketedPasteMode = false;
|
||||
const inputHandler = new InputHandler(terminal, new MockBufferService(80, 30), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService());
|
||||
const inputHandler = new InputHandler(terminal, new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService());
|
||||
// Set bracketed paste mode
|
||||
inputHandler.setModePrivate(Params.fromArray([2004]));
|
||||
assert.equal(terminal.bracketedPasteMode, true);
|
||||
@@ -120,7 +124,7 @@ describe('InputHandler', () => {
|
||||
it('insertChars', function(): void {
|
||||
const term = new Terminal();
|
||||
const bufferService = new MockBufferService(80, 30);
|
||||
const inputHandler = new InputHandler(term, bufferService, new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService());
|
||||
const inputHandler = new InputHandler(term, bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService());
|
||||
|
||||
// insert some data in first and second line
|
||||
inputHandler.parse(Array(bufferService.cols - 9).join('a'));
|
||||
@@ -158,7 +162,7 @@ describe('InputHandler', () => {
|
||||
it('deleteChars', function(): void {
|
||||
const term = new Terminal();
|
||||
const bufferService = new MockBufferService(80, 30);
|
||||
const inputHandler = new InputHandler(term, bufferService, new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService());
|
||||
const inputHandler = new InputHandler(term, bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService());
|
||||
|
||||
// insert some data in first and second line
|
||||
inputHandler.parse(Array(bufferService.cols - 9).join('a'));
|
||||
@@ -199,7 +203,7 @@ describe('InputHandler', () => {
|
||||
it('eraseInLine', function(): void {
|
||||
const term = new Terminal();
|
||||
const bufferService = new MockBufferService(80, 30);
|
||||
const inputHandler = new InputHandler(term, bufferService, new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService());
|
||||
const inputHandler = new InputHandler(term, bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService());
|
||||
|
||||
// fill 6 lines to test 3 different states
|
||||
inputHandler.parse(Array(bufferService.cols + 1).join('a'));
|
||||
@@ -228,7 +232,7 @@ describe('InputHandler', () => {
|
||||
it('eraseInDisplay', function(): void {
|
||||
const term = new Terminal({cols: 80, rows: 7});
|
||||
const bufferService = new MockBufferService(80, 7);
|
||||
const inputHandler = new InputHandler(term, bufferService, new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService());
|
||||
const inputHandler = new InputHandler(term, bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService());
|
||||
|
||||
// fill display with a's
|
||||
for (let i = 0; i < bufferService.rows; ++i) inputHandler.parse(Array(bufferService.cols + 1).join('a'));
|
||||
@@ -363,7 +367,7 @@ describe('InputHandler', () => {
|
||||
describe('print', () => {
|
||||
it('should not cause an infinite loop (regression test)', () => {
|
||||
const term = new Terminal();
|
||||
const inputHandler = new InputHandler(term, new MockBufferService(80, 30), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService());
|
||||
const inputHandler = new InputHandler(term, new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService());
|
||||
const container = new Uint32Array(10);
|
||||
container[0] = 0x200B;
|
||||
inputHandler.print(container, 0, 1);
|
||||
@@ -378,7 +382,7 @@ describe('InputHandler', () => {
|
||||
beforeEach(() => {
|
||||
term = new Terminal();
|
||||
bufferService = new MockBufferService(80, 30);
|
||||
handler = new InputHandler(term, bufferService, new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService());
|
||||
handler = new InputHandler(term, bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService());
|
||||
});
|
||||
it('should handle DECSET/DECRST 47 (alt screen buffer)', () => {
|
||||
handler.parse('\x1b[?47h\r\n\x1b[31mJUNK\x1b[?47lTEST');
|
||||
|
||||
+96
-91
@@ -19,7 +19,7 @@ import { NULL_CELL_CODE, NULL_CELL_WIDTH, Attributes, FgFlags, BgFlags, Content
|
||||
import { CellData } from 'common/buffer/CellData';
|
||||
import { AttributeData } from 'common/buffer/AttributeData';
|
||||
import { IAttributeData, IDisposable } from 'common/Types';
|
||||
import { ICoreService, IBufferService, IOptionsService, ILogService, IDirtyRowService, ICoreMouseService } from 'common/services/Services';
|
||||
import { ICoreService, IBufferService, IOptionsService, ILogService, IDirtyRowService, ICoreMouseService, ICharsetService } from 'common/services/Services';
|
||||
import { OscHandler } from 'common/parser/OscParser';
|
||||
import { DcsHandler } from 'common/parser/DcsParser';
|
||||
|
||||
@@ -128,6 +128,15 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
private _utf8Decoder: Utf8ToUtf32 = new Utf8ToUtf32();
|
||||
private _workCell: CellData = new CellData();
|
||||
|
||||
private _curAttrData: IAttributeData = DEFAULT_ATTR_DATA.clone();
|
||||
private _eraseAttrDataInternal: IAttributeData = DEFAULT_ATTR_DATA.clone();
|
||||
|
||||
private _onRequestRefreshRows = new EventEmitter<number, number>();
|
||||
public get onRequestRefreshRows(): IEvent<number, number> { return this._onRequestRefreshRows.event; }
|
||||
private _onRequestReset = new EventEmitter<void>();
|
||||
public get onRequestReset(): IEvent<void> { return this._onRequestReset.event; }
|
||||
private _onRequestBell = new EventEmitter<void>();
|
||||
public get onRequestBell(): IEvent<void> { return this._onRequestBell.event; }
|
||||
private _onCursorMove = new EventEmitter<void>();
|
||||
public get onCursorMove(): IEvent<void> { return this._onCursorMove.event; }
|
||||
private _onLineFeed = new EventEmitter<void>();
|
||||
@@ -136,8 +145,9 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
public get onScroll(): IEvent<number> { return this._onScroll.event; }
|
||||
|
||||
constructor(
|
||||
protected _terminal: IInputHandlingTerminal,
|
||||
private _terminal: IInputHandlingTerminal,
|
||||
private readonly _bufferService: IBufferService,
|
||||
private readonly _charsetService: ICharsetService,
|
||||
private readonly _coreService: ICoreService,
|
||||
private readonly _dirtyRowService: IDirtyRowService,
|
||||
private readonly _logService: ILogService,
|
||||
@@ -296,7 +306,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
this._parser.setEscHandler({final: 'M'}, () => this.reverseIndex());
|
||||
this._parser.setEscHandler({final: '='}, () => this.keypadApplicationMode());
|
||||
this._parser.setEscHandler({final: '>'}, () => this.keypadNumericMode());
|
||||
this._parser.setEscHandler({final: 'c'}, () => this.reset());
|
||||
this._parser.setEscHandler({final: 'c'}, () => this.fullReset());
|
||||
this._parser.setEscHandler({final: 'n'}, () => this.setgLevel(2));
|
||||
this._parser.setEscHandler({final: 'o'}, () => this.setgLevel(3));
|
||||
this._parser.setEscHandler({final: '|'}, () => this.setgLevel(3));
|
||||
@@ -372,19 +382,19 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
}
|
||||
|
||||
// Refresh any dirty rows accumulated as part of parsing
|
||||
this._terminal.refresh(this._dirtyRowService.start, this._dirtyRowService.end);
|
||||
this._onRequestRefreshRows.fire(this._dirtyRowService.start, this._dirtyRowService.end);
|
||||
}
|
||||
|
||||
public print(data: Uint32Array, start: number, end: number): void {
|
||||
let code: number;
|
||||
let chWidth: number;
|
||||
const buffer = this._bufferService.buffer;
|
||||
const charset = this._terminal.charset;
|
||||
const charset = this._charsetService.charset;
|
||||
const screenReaderMode = this._optionsService.options.screenReaderMode;
|
||||
const cols = this._bufferService.cols;
|
||||
const wraparoundMode = this._terminal.wraparoundMode;
|
||||
const wraparoundMode = this._coreService.decPrivateModes.wraparound;
|
||||
const insertMode = this._terminal.insertMode;
|
||||
const curAttr = this._terminal.curAttrData;
|
||||
const curAttr = this._curAttrData;
|
||||
let bufferRow = buffer.lines.get(buffer.y + buffer.ybase);
|
||||
|
||||
this._dirtyRowService.markDirty(buffer.y);
|
||||
@@ -439,7 +449,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
buffer.y++;
|
||||
if (buffer.y === buffer.scrollBottom + 1) {
|
||||
buffer.y--;
|
||||
this._terminal.scroll(true);
|
||||
this._terminal.scroll(this._eraseAttrData(), true);
|
||||
} else {
|
||||
if (buffer.y >= this._bufferService.rows) {
|
||||
buffer.y = this._bufferService.rows - 1;
|
||||
@@ -535,7 +545,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
* Bell (Ctrl-G).
|
||||
*/
|
||||
public bell(): void {
|
||||
this._terminal.bell();
|
||||
this._onRequestBell.fire();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -553,7 +563,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
buffer.y++;
|
||||
if (buffer.y === buffer.scrollBottom + 1) {
|
||||
buffer.y--;
|
||||
this._terminal.scroll();
|
||||
this._terminal.scroll(this._eraseAttrData());
|
||||
} else if (buffer.y >= this._bufferService.rows) {
|
||||
buffer.y = this._bufferService.rows - 1;
|
||||
}
|
||||
@@ -606,7 +616,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
* G1 character set.
|
||||
*/
|
||||
public shiftOut(): void {
|
||||
this._terminal.setgLevel(1);
|
||||
this._charsetService.setgLevel(1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -615,7 +625,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
* character set (the default).
|
||||
*/
|
||||
public shiftIn(): void {
|
||||
this._terminal.setgLevel(0);
|
||||
this._charsetService.setgLevel(0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -623,7 +633,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
*/
|
||||
private _restrictCursor(): void {
|
||||
this._bufferService.buffer.x = Math.min(this._bufferService.cols - 1, Math.max(0, this._bufferService.buffer.x));
|
||||
this._bufferService.buffer.y = this._terminal.originMode
|
||||
this._bufferService.buffer.y = this._coreService.decPrivateModes.origin
|
||||
? Math.min(this._bufferService.buffer.scrollBottom, Math.max(this._bufferService.buffer.scrollTop, this._bufferService.buffer.y))
|
||||
: Math.min(this._bufferService.rows - 1, Math.max(0, this._bufferService.buffer.y));
|
||||
this._dirtyRowService.markDirty(this._bufferService.buffer.y);
|
||||
@@ -634,7 +644,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
*/
|
||||
private _setCursor(x: number, y: number): void {
|
||||
this._dirtyRowService.markDirty(this._bufferService.buffer.y);
|
||||
if (this._terminal.originMode) {
|
||||
if (this._coreService.decPrivateModes.origin) {
|
||||
this._bufferService.buffer.x = x;
|
||||
this._bufferService.buffer.y = this._bufferService.buffer.scrollTop + y;
|
||||
} else {
|
||||
@@ -845,7 +855,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
line.replaceCells(
|
||||
start,
|
||||
end,
|
||||
this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData())
|
||||
this._bufferService.buffer.getNullCell(this._eraseAttrData())
|
||||
);
|
||||
if (clearWrap) {
|
||||
line.isWrapped = false;
|
||||
@@ -859,7 +869,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
*/
|
||||
private _resetBufferLine(y: number): void {
|
||||
const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y);
|
||||
line.fill(this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData()));
|
||||
line.fill(this._bufferService.buffer.getNullCell(this._eraseAttrData()));
|
||||
line.isWrapped = false;
|
||||
}
|
||||
|
||||
@@ -974,7 +984,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
// test: echo -e '\e[44m\e[1L\e[0m'
|
||||
// blankLine(true) - xterm/linux behavior
|
||||
buffer.lines.splice(scrollBottomAbsolute - 1, 1);
|
||||
buffer.lines.splice(row, 0, buffer.getBlankLine(this._terminal.eraseAttrData()));
|
||||
buffer.lines.splice(row, 0, buffer.getBlankLine(this._eraseAttrData()));
|
||||
}
|
||||
|
||||
this._dirtyRowService.markRangeDirty(buffer.y, buffer.scrollBottom);
|
||||
@@ -1005,7 +1015,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
// test: echo -e '\e[44m\e[1M\e[0m'
|
||||
// blankLine(true) - xterm/linux behavior
|
||||
buffer.lines.splice(row, 1);
|
||||
buffer.lines.splice(j, 0, buffer.getBlankLine(this._terminal.eraseAttrData()));
|
||||
buffer.lines.splice(j, 0, buffer.getBlankLine(this._eraseAttrData()));
|
||||
}
|
||||
|
||||
this._dirtyRowService.markRangeDirty(buffer.y, buffer.scrollBottom);
|
||||
@@ -1023,7 +1033,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
line.insertCells(
|
||||
this._bufferService.buffer.x,
|
||||
params.params[0] || 1,
|
||||
this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData())
|
||||
this._bufferService.buffer.getNullCell(this._eraseAttrData())
|
||||
);
|
||||
this._dirtyRowService.markDirty(this._bufferService.buffer.y);
|
||||
}
|
||||
@@ -1040,7 +1050,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
line.deleteCells(
|
||||
this._bufferService.buffer.x,
|
||||
params.params[0] || 1,
|
||||
this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData())
|
||||
this._bufferService.buffer.getNullCell(this._eraseAttrData())
|
||||
);
|
||||
this._dirtyRowService.markDirty(this._bufferService.buffer.y);
|
||||
}
|
||||
@@ -1057,7 +1067,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
|
||||
while (param--) {
|
||||
buffer.lines.splice(buffer.ybase + buffer.scrollTop, 1);
|
||||
buffer.lines.splice(buffer.ybase + buffer.scrollBottom, 0, buffer.getBlankLine(this._terminal.eraseAttrData()));
|
||||
buffer.lines.splice(buffer.ybase + buffer.scrollBottom, 0, buffer.getBlankLine(this._eraseAttrData()));
|
||||
}
|
||||
this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom);
|
||||
}
|
||||
@@ -1100,7 +1110,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);
|
||||
line.deleteCells(0, param, buffer.getNullCell(this._terminal.eraseAttrData()));
|
||||
line.deleteCells(0, param, buffer.getNullCell(this._eraseAttrData()));
|
||||
line.isWrapped = false;
|
||||
}
|
||||
this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom);
|
||||
@@ -1128,7 +1138,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);
|
||||
line.insertCells(0, param, buffer.getNullCell(this._terminal.eraseAttrData()));
|
||||
line.insertCells(0, param, buffer.getNullCell(this._eraseAttrData()));
|
||||
line.isWrapped = false;
|
||||
}
|
||||
this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom);
|
||||
@@ -1146,7 +1156,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);
|
||||
line.insertCells(buffer.x, param, buffer.getNullCell(this._terminal.eraseAttrData()));
|
||||
line.insertCells(buffer.x, param, buffer.getNullCell(this._eraseAttrData()));
|
||||
line.isWrapped = false;
|
||||
}
|
||||
this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom);
|
||||
@@ -1164,7 +1174,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);
|
||||
line.deleteCells(buffer.x, param, buffer.getNullCell(this._terminal.eraseAttrData()));
|
||||
line.deleteCells(buffer.x, param, buffer.getNullCell(this._eraseAttrData()));
|
||||
line.isWrapped = false;
|
||||
}
|
||||
this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom);
|
||||
@@ -1181,7 +1191,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
line.replaceCells(
|
||||
this._bufferService.buffer.x,
|
||||
this._bufferService.buffer.x + (params.params[0] || 1),
|
||||
this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData())
|
||||
this._bufferService.buffer.getNullCell(this._eraseAttrData())
|
||||
);
|
||||
this._dirtyRowService.markDirty(this._bufferService.buffer.y);
|
||||
}
|
||||
@@ -1394,34 +1404,32 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
this._coreService.decPrivateModes.applicationCursorKeys = true;
|
||||
break;
|
||||
case 2:
|
||||
this._terminal.setgCharset(0, DEFAULT_CHARSET);
|
||||
this._terminal.setgCharset(1, DEFAULT_CHARSET);
|
||||
this._terminal.setgCharset(2, DEFAULT_CHARSET);
|
||||
this._terminal.setgCharset(3, DEFAULT_CHARSET);
|
||||
this._charsetService.setgCharset(0, DEFAULT_CHARSET);
|
||||
this._charsetService.setgCharset(1, DEFAULT_CHARSET);
|
||||
this._charsetService.setgCharset(2, DEFAULT_CHARSET);
|
||||
this._charsetService.setgCharset(3, DEFAULT_CHARSET);
|
||||
// set VT100 mode here
|
||||
break;
|
||||
case 3: // 132 col mode
|
||||
// TODO: move DECCOLM into compat addon
|
||||
this._terminal.savedCols = this._bufferService.cols;
|
||||
this._terminal.resize(132, this._bufferService.rows);
|
||||
this._terminal.reset();
|
||||
this._onRequestReset.fire();
|
||||
break;
|
||||
case 6:
|
||||
this._terminal.originMode = true;
|
||||
this._coreService.decPrivateModes.origin = true;
|
||||
this._setCursor(0, 0);
|
||||
break;
|
||||
case 7:
|
||||
this._terminal.wraparoundMode = true;
|
||||
this._coreService.decPrivateModes.wraparound = true;
|
||||
break;
|
||||
case 12:
|
||||
// this.cursorBlink = true;
|
||||
break;
|
||||
case 66:
|
||||
this._logService.debug('Serial port requested application keypad.');
|
||||
this._terminal.applicationKeypad = true;
|
||||
if (this._terminal.viewport) {
|
||||
this._terminal.viewport.syncScrollArea();
|
||||
}
|
||||
this._coreService.decPrivateModes.applicationKeypad = true;
|
||||
this._terminal.viewport?.syncScrollArea();
|
||||
break;
|
||||
case 9: // X10 Mouse
|
||||
// no release, no motion, no wheel, no modifiers.
|
||||
@@ -1464,11 +1472,9 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
// FALL-THROUGH
|
||||
case 47: // alt screen buffer
|
||||
case 1047: // alt screen buffer
|
||||
this._bufferService.buffers.activateAltBuffer(this._terminal.eraseAttrData());
|
||||
this._terminal.refresh(0, this._bufferService.rows - 1);
|
||||
if (this._terminal.viewport) {
|
||||
this._terminal.viewport.syncScrollArea();
|
||||
}
|
||||
this._bufferService.buffers.activateAltBuffer(this._eraseAttrData());
|
||||
this._onRequestRefreshRows.fire(0, this._bufferService.rows - 1);
|
||||
this._terminal.viewport?.syncScrollArea();
|
||||
this._terminal.showCursor();
|
||||
break;
|
||||
case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste)
|
||||
@@ -1587,24 +1593,22 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
this._terminal.resize(this._terminal.savedCols, this._bufferService.rows);
|
||||
}
|
||||
delete this._terminal.savedCols;
|
||||
this._terminal.reset();
|
||||
this._onRequestReset.fire();
|
||||
break;
|
||||
case 6:
|
||||
this._terminal.originMode = false;
|
||||
this._coreService.decPrivateModes.origin = false;
|
||||
this._setCursor(0, 0);
|
||||
break;
|
||||
case 7:
|
||||
this._terminal.wraparoundMode = false;
|
||||
this._coreService.decPrivateModes.wraparound = false;
|
||||
break;
|
||||
case 12:
|
||||
// this.cursorBlink = false;
|
||||
break;
|
||||
case 66:
|
||||
this._logService.debug('Switching back to normal keypad.');
|
||||
this._terminal.applicationKeypad = false;
|
||||
if (this._terminal.viewport) {
|
||||
this._terminal.viewport.syncScrollArea();
|
||||
}
|
||||
this._coreService.decPrivateModes.applicationKeypad = false;
|
||||
this._terminal.viewport?.syncScrollArea();
|
||||
break;
|
||||
case 9: // X10 Mouse
|
||||
case 1000: // vt200 mouse
|
||||
@@ -1639,10 +1643,8 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
if (params.params[i] === 1049) {
|
||||
this.restoreCursor();
|
||||
}
|
||||
this._terminal.refresh(0, this._bufferService.rows - 1);
|
||||
if (this._terminal.viewport) {
|
||||
this._terminal.viewport.syncScrollArea();
|
||||
}
|
||||
this._onRequestRefreshRows.fire(0, this._bufferService.rows - 1);
|
||||
this._terminal.viewport?.syncScrollArea();
|
||||
this._terminal.showCursor();
|
||||
break;
|
||||
case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste)
|
||||
@@ -1792,14 +1794,14 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
public charAttributes(params: IParams): void {
|
||||
// Optimize a single SGR0.
|
||||
if (params.length === 1 && params.params[0] === 0) {
|
||||
this._terminal.curAttrData.fg = DEFAULT_ATTR_DATA.fg;
|
||||
this._terminal.curAttrData.bg = DEFAULT_ATTR_DATA.bg;
|
||||
this._curAttrData.fg = DEFAULT_ATTR_DATA.fg;
|
||||
this._curAttrData.bg = DEFAULT_ATTR_DATA.bg;
|
||||
return;
|
||||
}
|
||||
|
||||
const l = params.length;
|
||||
let p;
|
||||
const attr = this._terminal.curAttrData;
|
||||
const attr = this._curAttrData;
|
||||
|
||||
for (let i = 0; i < l; i++) {
|
||||
p = params.params[i];
|
||||
@@ -1961,20 +1963,13 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
public softReset(params: IParams): void {
|
||||
this._coreService.isCursorHidden = false;
|
||||
this._terminal.insertMode = false;
|
||||
this._terminal.originMode = false;
|
||||
this._terminal.wraparoundMode = true; // defaults: xterm - true, vt100 - false
|
||||
this._terminal.applicationKeypad = false; // ?
|
||||
if (this._terminal.viewport) {
|
||||
this._terminal.viewport.syncScrollArea();
|
||||
}
|
||||
this._coreService.decPrivateModes.applicationCursorKeys = false;
|
||||
this._terminal.viewport?.syncScrollArea();
|
||||
this._bufferService.buffer.scrollTop = 0;
|
||||
this._bufferService.buffer.scrollBottom = this._bufferService.rows - 1;
|
||||
this._terminal.curAttrData = DEFAULT_ATTR_DATA.clone();
|
||||
this._curAttrData = DEFAULT_ATTR_DATA.clone();
|
||||
this._bufferService.buffer.x = this._bufferService.buffer.y = 0; // ?
|
||||
this._terminal.charset = null;
|
||||
this._terminal.glevel = 0; // ??
|
||||
this._terminal.charsets = [null]; // ??
|
||||
this._coreService.reset();
|
||||
this._charsetService.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2036,9 +2031,9 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
public saveCursor(params?: IParams): void {
|
||||
this._bufferService.buffer.savedX = this._bufferService.buffer.x;
|
||||
this._bufferService.buffer.savedY = this._bufferService.buffer.ybase + this._bufferService.buffer.y;
|
||||
this._bufferService.buffer.savedCurAttrData.fg = this._terminal.curAttrData.fg;
|
||||
this._bufferService.buffer.savedCurAttrData.bg = this._terminal.curAttrData.bg;
|
||||
this._bufferService.buffer.savedCharset = this._terminal.charset;
|
||||
this._bufferService.buffer.savedCurAttrData.fg = this._curAttrData.fg;
|
||||
this._bufferService.buffer.savedCurAttrData.bg = this._curAttrData.bg;
|
||||
this._bufferService.buffer.savedCharset = this._charsetService.charset;
|
||||
}
|
||||
|
||||
|
||||
@@ -2050,11 +2045,11 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
public restoreCursor(params?: IParams): void {
|
||||
this._bufferService.buffer.x = this._bufferService.buffer.savedX || 0;
|
||||
this._bufferService.buffer.y = Math.max(this._bufferService.buffer.savedY - this._bufferService.buffer.ybase, 0);
|
||||
this._terminal.curAttrData.fg = this._bufferService.buffer.savedCurAttrData.fg;
|
||||
this._terminal.curAttrData.bg = this._bufferService.buffer.savedCurAttrData.bg;
|
||||
this._terminal.charset = (this as any)._savedCharset;
|
||||
this._curAttrData.fg = this._bufferService.buffer.savedCurAttrData.fg;
|
||||
this._curAttrData.bg = this._bufferService.buffer.savedCurAttrData.bg;
|
||||
this._charsetService.charset = (this as any)._savedCharset;
|
||||
if (this._bufferService.buffer.savedCharset) {
|
||||
this._terminal.charset = this._bufferService.buffer.savedCharset;
|
||||
this._charsetService.charset = this._bufferService.buffer.savedCharset;
|
||||
}
|
||||
this._restrictCursor();
|
||||
}
|
||||
@@ -2087,10 +2082,8 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
*/
|
||||
public keypadApplicationMode(): void {
|
||||
this._logService.debug('Serial port requested application keypad.');
|
||||
this._terminal.applicationKeypad = true;
|
||||
if (this._terminal.viewport) {
|
||||
this._terminal.viewport.syncScrollArea();
|
||||
}
|
||||
this._coreService.decPrivateModes.applicationKeypad = true;
|
||||
this._terminal.viewport?.syncScrollArea();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2100,10 +2093,8 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
*/
|
||||
public keypadNumericMode(): void {
|
||||
this._logService.debug('Switching back to normal keypad.');
|
||||
this._terminal.applicationKeypad = false;
|
||||
if (this._terminal.viewport) {
|
||||
this._terminal.viewport.syncScrollArea();
|
||||
}
|
||||
this._coreService.decPrivateModes.applicationKeypad = false;
|
||||
this._terminal.viewport?.syncScrollArea();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2113,8 +2104,8 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
* therefore ESC % G does the same.
|
||||
*/
|
||||
public selectDefaultCharset(): void {
|
||||
this._terminal.setgLevel(0);
|
||||
this._terminal.setgCharset(0, DEFAULT_CHARSET); // US (default)
|
||||
this._charsetService.setgLevel(0);
|
||||
this._charsetService.setgCharset(0, DEFAULT_CHARSET); // US (default)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2141,7 +2132,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
if (collectAndFlag[0] === '/') {
|
||||
return; // TODO: Is this supported?
|
||||
}
|
||||
this._terminal.setgCharset(GLEVEL[collectAndFlag[0]], CHARSETS[collectAndFlag[1]] || DEFAULT_CHARSET);
|
||||
this._charsetService.setgCharset(GLEVEL[collectAndFlag[0]], CHARSETS[collectAndFlag[1]] || DEFAULT_CHARSET);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2157,7 +2148,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
this._bufferService.buffer.y++;
|
||||
if (buffer.y === buffer.scrollBottom + 1) {
|
||||
buffer.y--;
|
||||
this._terminal.scroll();
|
||||
this._terminal.scroll(this._eraseAttrData());
|
||||
} else if (buffer.y >= this._bufferService.rows) {
|
||||
buffer.y = this._bufferService.rows - 1;
|
||||
}
|
||||
@@ -2191,7 +2182,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
// blankLine(true) is xterm/linux behavior
|
||||
const scrollRegionHeight = buffer.scrollBottom - buffer.scrollTop;
|
||||
buffer.lines.shiftElements(buffer.y + buffer.ybase, scrollRegionHeight, 1);
|
||||
buffer.lines.set(buffer.y + buffer.ybase, buffer.getBlankLine(this._terminal.eraseAttrData()));
|
||||
buffer.lines.set(buffer.y + buffer.ybase, buffer.getBlankLine(this._eraseAttrData()));
|
||||
this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom);
|
||||
} else {
|
||||
buffer.y--;
|
||||
@@ -2204,9 +2195,23 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
* DEC mnemonic: RIS (https://vt100.net/docs/vt510-rm/RIS.html)
|
||||
* Reset to initial state.
|
||||
*/
|
||||
public fullReset(): void {
|
||||
this._onRequestReset.fire();
|
||||
}
|
||||
|
||||
public reset(): void {
|
||||
this._parser.reset();
|
||||
this._terminal.reset(); // TODO: save to move from terminal?
|
||||
this._curAttrData = DEFAULT_ATTR_DATA.clone();
|
||||
this._eraseAttrDataInternal = DEFAULT_ATTR_DATA.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* back_color_erase feature for xterm.
|
||||
*/
|
||||
private _eraseAttrData(): IAttributeData {
|
||||
this._eraseAttrDataInternal.bg &= ~(Attributes.CM_MASK | 0xFFFFFF);
|
||||
this._eraseAttrDataInternal.bg |= this._curAttrData.bg & ~0xFC000000;
|
||||
return this._eraseAttrDataInternal;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2220,7 +2225,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
* you use another locking shift. (partly supported)
|
||||
*/
|
||||
public setgLevel(level: number): void {
|
||||
this._terminal.setgLevel(level); // TODO: save to move from terminal?
|
||||
this._charsetService.setgLevel(level);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2235,8 +2240,8 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
// prepare cell data
|
||||
const cell = new CellData();
|
||||
cell.content = 1 << Content.WIDTH_SHIFT | 'E'.charCodeAt(0);
|
||||
cell.fg = this._terminal.curAttrData.fg;
|
||||
cell.bg = this._terminal.curAttrData.bg;
|
||||
cell.fg = this._curAttrData.fg;
|
||||
cell.bg = this._curAttrData.bg;
|
||||
|
||||
const buffer = this._bufferService.buffer;
|
||||
|
||||
|
||||
+11
-19
@@ -112,7 +112,7 @@ describe('Terminal', () => {
|
||||
assert.equal(typeof e, 'number');
|
||||
done();
|
||||
});
|
||||
term.scroll();
|
||||
term.scroll(DEFAULT_ATTR_DATA.clone());
|
||||
});
|
||||
it('should fire the onTitleChange event', (done) => {
|
||||
term.onTitleChange(e => {
|
||||
@@ -397,7 +397,7 @@ describe('Terminal', () => {
|
||||
term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)]));
|
||||
term.buffer.lines.get(INIT_ROWS - 1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)]));
|
||||
term.buffer.y = INIT_ROWS - 1; // Move cursor to last line
|
||||
term.scroll();
|
||||
term.scroll(DEFAULT_ATTR_DATA.clone());
|
||||
assert.equal(term.buffer.lines.length, INIT_ROWS + 1);
|
||||
assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a');
|
||||
assert.equal(term.buffer.lines.get(INIT_ROWS - 1).loadCell(0, new CellData()).getChars(), 'b');
|
||||
@@ -410,7 +410,7 @@ describe('Terminal', () => {
|
||||
term.buffer.lines.get(2).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)]));
|
||||
term.buffer.y = INIT_ROWS - 1; // Move cursor to last line
|
||||
term.buffer.scrollTop = 1;
|
||||
term.scroll();
|
||||
term.scroll(DEFAULT_ATTR_DATA.clone());
|
||||
assert.equal(term.buffer.lines.length, INIT_ROWS);
|
||||
assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a');
|
||||
assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'c');
|
||||
@@ -424,7 +424,7 @@ describe('Terminal', () => {
|
||||
term.buffer.lines.get(4).setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)]));
|
||||
term.buffer.y = 3;
|
||||
term.buffer.scrollBottom = 3;
|
||||
term.scroll();
|
||||
term.scroll(DEFAULT_ATTR_DATA.clone());
|
||||
assert.equal(term.buffer.lines.length, INIT_ROWS + 1);
|
||||
assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a', '\'a\' should be pushed to the scrollback');
|
||||
assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'b');
|
||||
@@ -443,7 +443,7 @@ describe('Terminal', () => {
|
||||
term.buffer.y = INIT_ROWS - 1; // Move cursor to last line
|
||||
term.buffer.scrollTop = 1;
|
||||
term.buffer.scrollBottom = 3;
|
||||
term.scroll();
|
||||
term.scroll(DEFAULT_ATTR_DATA.clone());
|
||||
assert.equal(term.buffer.lines.length, INIT_ROWS);
|
||||
assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a');
|
||||
assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'c', '\'b\' should be removed from the buffer');
|
||||
@@ -465,7 +465,7 @@ describe('Terminal', () => {
|
||||
term.buffer.lines.get(INIT_ROWS - 1).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)]));
|
||||
term.buffer.y = INIT_ROWS - 1; // Move cursor to last line
|
||||
assert.equal(term.buffer.lines.length, INIT_ROWS);
|
||||
term.scroll();
|
||||
term.scroll(DEFAULT_ATTR_DATA.clone());
|
||||
assert.equal(term.buffer.lines.length, INIT_ROWS);
|
||||
// 'a' gets pushed out of buffer
|
||||
assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'b');
|
||||
@@ -480,7 +480,7 @@ describe('Terminal', () => {
|
||||
term.buffer.lines.get(2).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)]));
|
||||
term.buffer.y = INIT_ROWS - 1; // Move cursor to last line
|
||||
term.buffer.scrollTop = 1;
|
||||
term.scroll();
|
||||
term.scroll(DEFAULT_ATTR_DATA.clone());
|
||||
assert.equal(term.buffer.lines.length, INIT_ROWS);
|
||||
assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a');
|
||||
assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'c');
|
||||
@@ -494,7 +494,7 @@ describe('Terminal', () => {
|
||||
term.buffer.lines.get(4).setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)]));
|
||||
term.buffer.y = 3;
|
||||
term.buffer.scrollBottom = 3;
|
||||
term.scroll();
|
||||
term.scroll(DEFAULT_ATTR_DATA.clone());
|
||||
assert.equal(term.buffer.lines.length, INIT_ROWS);
|
||||
assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'b');
|
||||
assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'c');
|
||||
@@ -512,7 +512,7 @@ describe('Terminal', () => {
|
||||
term.buffer.y = INIT_ROWS - 1; // Move cursor to last line
|
||||
term.buffer.scrollTop = 1;
|
||||
term.buffer.scrollBottom = 3;
|
||||
term.scroll();
|
||||
term.scroll(DEFAULT_ATTR_DATA.clone());
|
||||
assert.equal(term.buffer.lines.length, INIT_ROWS);
|
||||
assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a');
|
||||
assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'c', '\'b\' should be removed from the buffer');
|
||||
@@ -747,7 +747,7 @@ describe('Terminal', () => {
|
||||
const cell = new CellData();
|
||||
for (let i = 0xDC00; i <= 0xDCFF; ++i) {
|
||||
term.buffer.x = term.cols - 1;
|
||||
term.wraparoundMode = true;
|
||||
|
||||
term.writeSync('a' + high + String.fromCharCode(i));
|
||||
expect(term.buffer.lines.get(0).loadCell(term.cols - 1, cell).getChars()).eql('a');
|
||||
expect(term.buffer.lines.get(1).loadCell(0, cell).getChars()).eql(high + String.fromCharCode(i));
|
||||
@@ -761,7 +761,7 @@ describe('Terminal', () => {
|
||||
const cell = new CellData();
|
||||
for (let i = 0xDC00; i <= 0xDCFF; ++i) {
|
||||
term.buffer.x = term.cols - 1;
|
||||
term.wraparoundMode = false;
|
||||
term.writeSync('\x1b[?7l'); // Disable wraparound mode
|
||||
const width = wcwidth((0xD800 - 0xD800) * 0x400 + i - 0xDC00 + 0x10000);
|
||||
if (width !== 1) {
|
||||
continue;
|
||||
@@ -812,7 +812,6 @@ describe('Terminal', () => {
|
||||
expect(cell.getWidth()).eql(1);
|
||||
});
|
||||
it('multiple combined é', () => {
|
||||
term.wraparoundMode = true;
|
||||
term.writeSync(Array(100).join('e\u0301'));
|
||||
for (let i = 0; i < term.cols; ++i) {
|
||||
term.buffer.lines.get(0).loadCell(i, cell);
|
||||
@@ -826,7 +825,6 @@ describe('Terminal', () => {
|
||||
expect(cell.getWidth()).eql(1);
|
||||
});
|
||||
it('multiple surrogate with combined', () => {
|
||||
term.wraparoundMode = true;
|
||||
term.writeSync(Array(100).join('\uD800\uDC00\u0301'));
|
||||
for (let i = 0; i < term.cols; ++i) {
|
||||
term.buffer.lines.get(0).loadCell(i, cell);
|
||||
@@ -855,7 +853,6 @@ describe('Terminal', () => {
|
||||
expect(term.buffer.x).eql(3);
|
||||
});
|
||||
it('line of ¥ even', () => {
|
||||
term.wraparoundMode = true;
|
||||
term.writeSync(Array(50).join('¥'));
|
||||
for (let i = 0; i < term.cols; ++i) {
|
||||
term.buffer.lines.get(0).loadCell(i, cell);
|
||||
@@ -875,7 +872,6 @@ describe('Terminal', () => {
|
||||
expect(cell.getWidth()).eql(2);
|
||||
});
|
||||
it('line of ¥ odd', () => {
|
||||
term.wraparoundMode = true;
|
||||
term.buffer.x = 1;
|
||||
term.writeSync(Array(50).join('¥'));
|
||||
for (let i = 1; i < term.cols - 1; ++i) {
|
||||
@@ -900,7 +896,6 @@ describe('Terminal', () => {
|
||||
expect(cell.getWidth()).eql(2);
|
||||
});
|
||||
it('line of ¥ with combining odd', () => {
|
||||
term.wraparoundMode = true;
|
||||
term.buffer.x = 1;
|
||||
term.writeSync(Array(50).join('¥\u0301'));
|
||||
for (let i = 1; i < term.cols - 1; ++i) {
|
||||
@@ -925,7 +920,6 @@ describe('Terminal', () => {
|
||||
expect(cell.getWidth()).eql(2);
|
||||
});
|
||||
it('line of ¥ with combining even', () => {
|
||||
term.wraparoundMode = true;
|
||||
term.writeSync(Array(50).join('¥\u0301'));
|
||||
for (let i = 0; i < term.cols; ++i) {
|
||||
term.buffer.lines.get(0).loadCell(i, cell);
|
||||
@@ -945,7 +939,6 @@ describe('Terminal', () => {
|
||||
expect(cell.getWidth()).eql(2);
|
||||
});
|
||||
it('line of surrogate fullwidth with combining odd', () => {
|
||||
term.wraparoundMode = true;
|
||||
term.buffer.x = 1;
|
||||
term.writeSync(Array(50).join('\ud843\ude6d\u0301'));
|
||||
for (let i = 1; i < term.cols - 1; ++i) {
|
||||
@@ -970,7 +963,6 @@ describe('Terminal', () => {
|
||||
expect(cell.getWidth()).eql(2);
|
||||
});
|
||||
it('line of surrogate fullwidth with combining even', () => {
|
||||
term.wraparoundMode = true;
|
||||
term.writeSync(Array(50).join('\ud843\ude6d\u0301'));
|
||||
for (let i = 0; i < term.cols; ++i) {
|
||||
term.buffer.lines.get(0).loadCell(i, cell);
|
||||
|
||||
+26
-86
@@ -39,21 +39,20 @@ import { MouseZoneManager } from 'browser/MouseZoneManager';
|
||||
import { AccessibilityManager } from './AccessibilityManager';
|
||||
import { ITheme, IMarker, IDisposable, ISelectionPosition } from 'xterm';
|
||||
import { DomRenderer } from 'browser/renderer/dom/DomRenderer';
|
||||
import { IKeyboardEvent, KeyboardResultType, ICharset, IBufferLine, IAttributeData, CoreMouseEventType, CoreMouseButton, CoreMouseAction } from 'common/Types';
|
||||
import { IKeyboardEvent, KeyboardResultType, IBufferLine, IAttributeData, CoreMouseEventType, CoreMouseButton, CoreMouseAction } from 'common/Types';
|
||||
import { evaluateKeyboardEvent } from 'common/input/Keyboard';
|
||||
import { EventEmitter, IEvent } from 'common/EventEmitter';
|
||||
import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
|
||||
import { handleWindowsModeLineFeed } from 'common/WindowsMode';
|
||||
import { ColorManager } from 'browser/ColorManager';
|
||||
import { RenderService } from 'browser/services/RenderService';
|
||||
import { IOptionsService, IBufferService, ICoreMouseService, ICoreService, ILogService, IDirtyRowService, IInstantiationService } from 'common/services/Services';
|
||||
import { IOptionsService, IBufferService, ICoreMouseService, ICoreService, ILogService, IDirtyRowService, IInstantiationService, ICharsetService } from 'common/services/Services';
|
||||
import { OptionsService } from 'common/services/OptionsService';
|
||||
import { ICharSizeService, IRenderService, IMouseService, ISelectionService, ISoundService, ICoreBrowserService } from 'browser/services/Services';
|
||||
import { CharSizeService } from 'browser/services/CharSizeService';
|
||||
import { BufferService, MINIMUM_COLS, MINIMUM_ROWS } from 'common/services/BufferService';
|
||||
import { Disposable } from 'common/Lifecycle';
|
||||
import { IBufferSet, IBuffer } from 'common/buffer/Types';
|
||||
import { Attributes } from 'common/buffer/Constants';
|
||||
import { MouseService } from 'browser/services/MouseService';
|
||||
import { IParams, IFunctionIdentifier } from 'common/parser/Types';
|
||||
import { CoreService } from 'common/services/CoreService';
|
||||
@@ -64,6 +63,7 @@ import { InstantiationService } from 'common/services/InstantiationService';
|
||||
import { CoreMouseService } from 'common/services/CoreMouseService';
|
||||
import { WriteBuffer } from 'common/input/WriteBuffer';
|
||||
import { CoreBrowserService } from 'browser/services/CoreBrowserService';
|
||||
import { CharsetService } from 'common/services/CharsetService';
|
||||
|
||||
// Let it work inside Node.js for automated testing purposes.
|
||||
const document = (typeof window !== 'undefined') ? window.document : null;
|
||||
@@ -74,10 +74,6 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
public element: HTMLElement;
|
||||
public screenElement: HTMLElement;
|
||||
|
||||
/**
|
||||
* The HTMLElement that the terminal is created in, set by Terminal.open.
|
||||
*/
|
||||
private _parent: HTMLElement | null;
|
||||
private _document: Document;
|
||||
private _viewportScrollArea: HTMLElement;
|
||||
private _viewportElement: HTMLElement;
|
||||
@@ -96,6 +92,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
// common services
|
||||
private _bufferService: IBufferService;
|
||||
private _coreService: ICoreService;
|
||||
private _charsetService: ICharsetService;
|
||||
private _coreMouseService: ICoreMouseService;
|
||||
private _dirtyRowService: IDirtyRowService;
|
||||
private _instantiationService: IInstantiationService;
|
||||
@@ -110,19 +107,9 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
private _soundService: ISoundService;
|
||||
|
||||
// modes
|
||||
public applicationKeypad: boolean;
|
||||
public originMode: boolean;
|
||||
public insertMode: boolean;
|
||||
public wraparoundMode: boolean; // defaults: xterm - true, vt100 - false
|
||||
public bracketedPasteMode: boolean;
|
||||
|
||||
// charset
|
||||
// The current charset
|
||||
public charset: ICharset;
|
||||
public gcharset: number;
|
||||
public glevel: number;
|
||||
public charsets: ICharset[];
|
||||
|
||||
// mouse properties
|
||||
public mouseEvents: CoreMouseEventType = CoreMouseEventType.NONE;
|
||||
public sendFocus: boolean;
|
||||
@@ -130,12 +117,6 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
// misc
|
||||
public savedCols: number;
|
||||
|
||||
public curAttrData: IAttributeData;
|
||||
private _eraseAttrData: IAttributeData;
|
||||
|
||||
public params: (string | number)[];
|
||||
public currentParam: string | number;
|
||||
|
||||
// write buffer
|
||||
private _writeBuffer: WriteBuffer;
|
||||
|
||||
@@ -228,6 +209,8 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
this._instantiationService.setService(ICoreMouseService, this._coreMouseService);
|
||||
this._dirtyRowService = this._instantiationService.createInstance(DirtyRowService);
|
||||
this._instantiationService.setService(IDirtyRowService, this._dirtyRowService);
|
||||
this._charsetService = this._instantiationService.createInstance(CharsetService);
|
||||
this._instantiationService.setService(ICharsetService, this._charsetService);
|
||||
|
||||
this._setupOptionsListeners();
|
||||
this._setup();
|
||||
@@ -249,39 +232,30 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
}
|
||||
|
||||
private _setup(): void {
|
||||
this._parent = document ? document.body : null;
|
||||
|
||||
this._customKeyEventHandler = null;
|
||||
|
||||
// modes
|
||||
this.applicationKeypad = false;
|
||||
this.originMode = false;
|
||||
this.insertMode = false;
|
||||
this.wraparoundMode = true; // defaults: xterm - true, vt100 - false
|
||||
this.bracketedPasteMode = false;
|
||||
|
||||
// charset
|
||||
this.charset = null;
|
||||
this.gcharset = null;
|
||||
this.glevel = 0;
|
||||
// TODO: Can this be just []?
|
||||
this.charsets = [null];
|
||||
|
||||
this.curAttrData = DEFAULT_ATTR_DATA.clone();
|
||||
this._eraseAttrData = DEFAULT_ATTR_DATA.clone();
|
||||
|
||||
this.params = [];
|
||||
this.currentParam = 0;
|
||||
|
||||
this._userScrolling = false;
|
||||
|
||||
// Register input handler and refire/handle events
|
||||
this._inputHandler = new InputHandler(this, this._bufferService, this._coreService, this._dirtyRowService, this._logService, this.optionsService, this._coreMouseService);
|
||||
this._inputHandler.onCursorMove(() => this._onCursorMove.fire());
|
||||
this._inputHandler.onLineFeed(() => this._onLineFeed.fire());
|
||||
this.register(this._inputHandler);
|
||||
if (this._inputHandler) {
|
||||
this._inputHandler.reset();
|
||||
} else {
|
||||
// Register input handler and refire/handle events
|
||||
this._inputHandler = new InputHandler(this, this._bufferService, this._charsetService, this._coreService, this._dirtyRowService, this._logService, this.optionsService, this._coreMouseService);
|
||||
this._inputHandler.onRequestBell(() => this.bell());
|
||||
this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end));
|
||||
this._inputHandler.onRequestReset(() => this.reset());
|
||||
this._inputHandler.onCursorMove(() => this._onCursorMove.fire());
|
||||
this._inputHandler.onLineFeed(() => this._onLineFeed.fire());
|
||||
this.register(this._inputHandler);
|
||||
}
|
||||
|
||||
this.linkifier = this.linkifier || new Linkifier(this._bufferService, this._logService);
|
||||
if (!this.linkifier) {
|
||||
this.linkifier = new Linkifier(this._bufferService, this._logService);
|
||||
}
|
||||
|
||||
if (this.options.windowsMode) {
|
||||
this._enableWindowsMode();
|
||||
@@ -305,15 +279,6 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
return this._bufferService.buffers;
|
||||
}
|
||||
|
||||
/**
|
||||
* back_color_erase feature for xterm.
|
||||
*/
|
||||
public eraseAttrData(): IAttributeData {
|
||||
this._eraseAttrData.bg &= ~(Attributes.CM_MASK | 0xFFFFFF);
|
||||
this._eraseAttrData.bg |= this.curAttrData.bg & ~0xFC000000;
|
||||
return this._eraseAttrData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus the terminal. Delegates focus handling to the terminal's DOM element.
|
||||
*/
|
||||
@@ -485,9 +450,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
* @param parent The element to create the terminal within.
|
||||
*/
|
||||
public open(parent: HTMLElement): void {
|
||||
this._parent = parent || this._parent;
|
||||
|
||||
if (!this._parent) {
|
||||
if (!parent) {
|
||||
throw new Error('Terminal requires a parent element.');
|
||||
}
|
||||
|
||||
@@ -495,7 +458,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
this._logService.warn('Terminal.open was called on an element that was not attached to the DOM');
|
||||
}
|
||||
|
||||
this._document = this._parent.ownerDocument;
|
||||
this._document = parent.ownerDocument;
|
||||
|
||||
// Create main element container
|
||||
this.element = this._document.createElement('div');
|
||||
@@ -503,7 +466,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
this.element.classList.add('terminal');
|
||||
this.element.classList.add('xterm');
|
||||
this.element.setAttribute('tabindex', '0');
|
||||
this._parent.appendChild(this.element);
|
||||
parent.appendChild(this.element);
|
||||
|
||||
// Performance: Use a document fragment to build the terminal
|
||||
// viewport and helper elements detached from the DOM
|
||||
@@ -958,10 +921,9 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
* Scroll the terminal down 1 row, creating a blank line.
|
||||
* @param isWrapped Whether the new line is wrapped from the previous line.
|
||||
*/
|
||||
public scroll(isWrapped: boolean = false): void {
|
||||
public scroll(eraseAttr: IAttributeData, isWrapped: boolean = false): void {
|
||||
let newLine: IBufferLine;
|
||||
newLine = this._blankLine;
|
||||
const eraseAttr = this.eraseAttrData();
|
||||
if (!newLine || newLine.length !== this.cols || newLine.getFg(0) !== eraseAttr.fg || newLine.getBg(0) !== eraseAttr.bg) {
|
||||
newLine = this.buffer.getBlankLine(eraseAttr, isWrapped);
|
||||
this._blankLine = newLine;
|
||||
@@ -1306,27 +1268,6 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
return thirdLevelKey && (!ev.keyCode || ev.keyCode > 47);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the G level of the terminal
|
||||
* @param g
|
||||
*/
|
||||
public setgLevel(g: number): void {
|
||||
this.glevel = g;
|
||||
this.charset = this.charsets[g];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the charset for the given G level of the terminal
|
||||
* @param g
|
||||
* @param charset
|
||||
*/
|
||||
public setgCharset(g: number, charset: ICharset): void {
|
||||
this.charsets[g] = charset;
|
||||
if (this.glevel === g) {
|
||||
this.charset = charset;
|
||||
}
|
||||
}
|
||||
|
||||
protected _keyUp(ev: KeyboardEvent): void {
|
||||
if (this._customKeyEventHandler && this._customKeyEventHandler(ev) === false) {
|
||||
return;
|
||||
@@ -1512,18 +1453,17 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
this.options.rows = this.rows;
|
||||
this.options.cols = this.cols;
|
||||
const customKeyEventHandler = this._customKeyEventHandler;
|
||||
const inputHandler = this._inputHandler;
|
||||
const userScrolling = this._userScrolling;
|
||||
|
||||
this._setup();
|
||||
this._bufferService.reset();
|
||||
this._charsetService.reset();
|
||||
this._coreService.reset();
|
||||
this._coreMouseService.reset();
|
||||
this._selectionService?.reset();
|
||||
|
||||
// reattach
|
||||
this._customKeyEventHandler = customKeyEventHandler;
|
||||
this._inputHandler = inputHandler;
|
||||
this._userScrolling = userScrolling;
|
||||
|
||||
// do a full screen refresh
|
||||
|
||||
+3
-89
@@ -6,7 +6,7 @@
|
||||
import { IRenderer, IRenderDimensions, CharacterJoinerHandler, IRequestRefreshRowsEvent } from 'browser/renderer/Types';
|
||||
import { IInputHandlingTerminal, ICompositionHelper, ITerminal, IBrowser, ITerminalOptions } from './Types';
|
||||
import { IBuffer, IBufferStringIterator, IBufferSet } from 'common/buffer/Types';
|
||||
import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, ICharset, CoreMouseEventType } from 'common/Types';
|
||||
import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, ICharset } from 'common/Types';
|
||||
import { Buffer } from 'common/buffer/Buffer';
|
||||
import * as Browser from 'common/Platform';
|
||||
import { IDisposable, IMarker, IEvent, ISelectionPosition } from 'xterm';
|
||||
@@ -19,6 +19,7 @@ import { IParams, IFunctionIdentifier } from 'common/parser/Types';
|
||||
import { ISelectionService } from 'browser/services/Services';
|
||||
|
||||
export class TestTerminal extends Terminal {
|
||||
get curAttrData(): IAttributeData { return (this as any)._inputHandler._curAttrData; }
|
||||
keyDown(ev: any): boolean { return this._keyDown(ev); }
|
||||
keyPress(ev: any): boolean { return this._keyPress(ev); }
|
||||
}
|
||||
@@ -197,112 +198,25 @@ export class MockTerminal implements ITerminal {
|
||||
export class MockInputHandlingTerminal implements IInputHandlingTerminal {
|
||||
onA11yCharEmitter: EventEmitter<string>;
|
||||
onA11yTabEmitter: EventEmitter<number>;
|
||||
element: HTMLElement;
|
||||
options: ITerminalOptions = {};
|
||||
cols: number;
|
||||
rows: number;
|
||||
charset: { [key: string]: string; };
|
||||
gcharset: number;
|
||||
glevel: number;
|
||||
charsets: { [key: string]: string; }[];
|
||||
applicationKeypad: boolean;
|
||||
applicationCursor: boolean;
|
||||
originMode: boolean;
|
||||
insertMode: boolean;
|
||||
wraparoundMode: boolean;
|
||||
bracketedPasteMode: boolean;
|
||||
curAttrData = new AttributeData();
|
||||
savedCols: number;
|
||||
x10Mouse: boolean;
|
||||
vt200Mouse: boolean;
|
||||
normalMouse: boolean;
|
||||
mouseEvents: CoreMouseEventType;
|
||||
sendFocus: boolean;
|
||||
utfMouse: boolean;
|
||||
sgrMouse: boolean;
|
||||
urxvtMouse: boolean;
|
||||
cursorHidden: boolean;
|
||||
buffers: IBufferSet;
|
||||
buffer: IBuffer = new MockBuffer();
|
||||
viewport: IViewport;
|
||||
selectionService: ISelectionService;
|
||||
focus(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
convertEol: boolean;
|
||||
bell(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
updateRange(y: number): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
scroll(isWrapped?: boolean): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
nextStop(x?: number): number {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
setgLevel(g: number): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
eraseAttrData(): IAttributeData {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
eraseRight(x: number, y: number): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
eraseLine(y: number): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
eraseLeft(x: number, y: number): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
prevStop(x?: number): number {
|
||||
scroll(eraseAttr: IAttributeData, isWrapped?: boolean): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
is(term: string): boolean {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
setgCharset(g: number, charset: { [key: string]: string; }): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
resize(x: number, y: number): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
log(text: string, data?: any): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
reset(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
showCursor(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
refresh(start: number, end: number): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
matchColor(r1: number, g1: number, b1: number): number {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
error(text: string, data?: any): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
setOption(key: string, value: any): void {
|
||||
(<any>this.options)[key] = value;
|
||||
}
|
||||
on(type: string, listener: XtermListener): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
off(type: string, listener: XtermListener): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
emit(type: string, data?: any): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
addDisposableListener(type: string, handler: XtermListener): IDisposable {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
handler(data: string): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
Vendored
+2
-22
@@ -21,22 +21,9 @@ export type LineData = CharData[];
|
||||
* InputHandler cleanly from the ITerminal interface.
|
||||
*/
|
||||
export interface IInputHandlingTerminal {
|
||||
element: HTMLElement;
|
||||
options: ITerminalOptions;
|
||||
cols: number;
|
||||
rows: number;
|
||||
charset: ICharset;
|
||||
gcharset: number;
|
||||
glevel: number;
|
||||
charsets: ICharset[];
|
||||
applicationKeypad: boolean;
|
||||
originMode: boolean;
|
||||
insertMode: boolean;
|
||||
wraparoundMode: boolean;
|
||||
bracketedPasteMode: boolean;
|
||||
curAttrData: IAttributeData;
|
||||
savedCols: number;
|
||||
mouseEvents: CoreMouseEventType;
|
||||
sendFocus: boolean;
|
||||
|
||||
buffers: IBufferSet;
|
||||
@@ -46,17 +33,10 @@ export interface IInputHandlingTerminal {
|
||||
onA11yCharEmitter: IEventEmitter<string>;
|
||||
onA11yTabEmitter: IEventEmitter<number>;
|
||||
|
||||
bell(): void;
|
||||
focus(): void;
|
||||
scroll(isWrapped?: boolean): void;
|
||||
setgLevel(g: number): void;
|
||||
eraseAttrData(): IAttributeData;
|
||||
scroll(eraseAttr: IAttributeData, isWrapped?: boolean): void;
|
||||
is(term: string): boolean;
|
||||
setgCharset(g: number, charset: ICharset): void;
|
||||
resize(x: number, y: number): void;
|
||||
reset(): void;
|
||||
showCursor(): void;
|
||||
refresh(start: number, end: number): void;
|
||||
handleTitle(title: string): void;
|
||||
}
|
||||
|
||||
@@ -141,7 +121,7 @@ export interface IInputHandler {
|
||||
/** ESC D */ index(): void;
|
||||
/** ESC H */ tabSet(): void;
|
||||
/** ESC M */ reverseIndex(): void;
|
||||
/** ESC c */ reset(): void;
|
||||
/** ESC c */ fullReset(): void;
|
||||
/** ESC n
|
||||
ESC o
|
||||
ESC |
|
||||
|
||||
+15
-15
@@ -5,28 +5,28 @@
|
||||
|
||||
import { IDisposable } from 'common/Types';
|
||||
|
||||
interface IListener<T> {
|
||||
(e: T): void;
|
||||
interface IListener<T, U = void> {
|
||||
(arg1: T, arg2: U): void;
|
||||
}
|
||||
|
||||
export interface IEvent<T> {
|
||||
(listener: (e: T) => any): IDisposable;
|
||||
export interface IEvent<T, U = void> {
|
||||
(listener: (arg1: T, arg2: U) => any): IDisposable;
|
||||
}
|
||||
|
||||
export interface IEventEmitter<T> {
|
||||
event: IEvent<T>;
|
||||
fire(data: T): void;
|
||||
export interface IEventEmitter<T, U = void> {
|
||||
event: IEvent<T, U>;
|
||||
fire(arg1: T, arg2: U): void;
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
export class EventEmitter<T> implements IEventEmitter<T> {
|
||||
private _listeners: IListener<T>[] = [];
|
||||
private _event?: IEvent<T>;
|
||||
export class EventEmitter<T, U = void> implements IEventEmitter<T, U> {
|
||||
private _listeners: IListener<T, U>[] = [];
|
||||
private _event?: IEvent<T, U>;
|
||||
private _disposed: boolean = false;
|
||||
|
||||
public get event(): IEvent<T> {
|
||||
public get event(): IEvent<T, U> {
|
||||
if (!this._event) {
|
||||
this._event = (listener: (e: T) => any) => {
|
||||
this._event = (listener: (arg1: T, arg2: U) => any) => {
|
||||
this._listeners.push(listener);
|
||||
const disposable = {
|
||||
dispose: () => {
|
||||
@@ -46,13 +46,13 @@ export class EventEmitter<T> implements IEventEmitter<T> {
|
||||
return this._event;
|
||||
}
|
||||
|
||||
public fire(data: T): void {
|
||||
const queue: IListener<T>[] = [];
|
||||
public fire(arg1: T, arg2: U): void {
|
||||
const queue: IListener<T, U>[] = [];
|
||||
for (let i = 0; i < this._listeners.length; i++) {
|
||||
queue.push(this._listeners[i]);
|
||||
}
|
||||
for (let i = 0; i < queue.length; i++) {
|
||||
queue[i].call(undefined, data);
|
||||
queue[i].call(undefined, arg1, arg2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IBufferService, ICoreService, ILogService, IOptionsService, ITerminalOptions, IPartialTerminalOptions, IDirtyRowService, ICoreMouseService } from 'common/services/Services';
|
||||
import { IBufferService, ICoreService, ILogService, IOptionsService, ITerminalOptions, IPartialTerminalOptions, IDirtyRowService, ICoreMouseService, ICharsetService } from 'common/services/Services';
|
||||
import { IEvent, EventEmitter } from 'common/EventEmitter';
|
||||
import { clone } from 'common/Clone';
|
||||
import { DEFAULT_OPTIONS } from 'common/services/OptionsService';
|
||||
import { IBufferSet, IBuffer } from 'common/buffer/Types';
|
||||
import { BufferSet } from 'common/buffer/BufferSet';
|
||||
import { IDecPrivateModes, ICoreMouseEvent, CoreMouseEventType } from 'common/Types';
|
||||
import { IDecPrivateModes, ICoreMouseEvent, CoreMouseEventType, ICharset } from 'common/Types';
|
||||
|
||||
export class MockBufferService implements IBufferService {
|
||||
serviceBrand: any;
|
||||
@@ -42,12 +42,27 @@ export class MockCoreMouseService implements ICoreMouseService {
|
||||
}
|
||||
}
|
||||
|
||||
export class MockCharsetService implements ICharsetService {
|
||||
serviceBrand: any;
|
||||
charset: ICharset | undefined;
|
||||
glevel: number = 0;
|
||||
charsets: readonly ICharset[] = [];
|
||||
reset(): void {}
|
||||
setgLevel(g: number): void {}
|
||||
setgCharset(g: number, charset: ICharset): void {}
|
||||
}
|
||||
|
||||
export class MockCoreService implements ICoreService {
|
||||
serviceBrand: any;
|
||||
isCursorInitialized: boolean = false;
|
||||
isCursorHidden: boolean = false;
|
||||
isFocused: boolean = false;
|
||||
serviceBrand: any;
|
||||
decPrivateModes: IDecPrivateModes = {} as any;
|
||||
decPrivateModes: IDecPrivateModes = {
|
||||
applicationCursorKeys: false,
|
||||
applicationKeypad: false,
|
||||
origin: false,
|
||||
wraparound: true
|
||||
};
|
||||
onData: IEvent<string> = new EventEmitter<string>().event;
|
||||
onUserInput: IEvent<void> = new EventEmitter<void>().event;
|
||||
onBinary: IEvent<string> = new EventEmitter<string>().event;
|
||||
|
||||
Vendored
+4
-1
@@ -62,7 +62,7 @@ export interface IKeyboardResult {
|
||||
}
|
||||
|
||||
export interface ICharset {
|
||||
[key: string]: string;
|
||||
[key: string]: string | undefined;
|
||||
}
|
||||
|
||||
export type CharData = [number, string, number, number];
|
||||
@@ -152,6 +152,9 @@ export interface IMarker extends IDisposable {
|
||||
|
||||
export interface IDecPrivateModes {
|
||||
applicationCursorKeys: boolean;
|
||||
applicationKeypad: boolean;
|
||||
origin: boolean;
|
||||
wraparound: boolean; // defaults: xterm - true, vt100 - false
|
||||
}
|
||||
|
||||
export interface IRowRange {
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { ICharsetService } from 'common/services/Services';
|
||||
import { ICharset } from 'common/Types';
|
||||
|
||||
export class CharsetService implements ICharsetService {
|
||||
serviceBrand: any;
|
||||
|
||||
public charset: ICharset | undefined;
|
||||
public charsets: ICharset[] = [];
|
||||
public glevel: number = 0;
|
||||
|
||||
public reset(): void {
|
||||
this.charset = undefined;
|
||||
this.charsets = [];
|
||||
this.glevel = 0;
|
||||
}
|
||||
|
||||
public setgLevel(g: number): void {
|
||||
this.glevel = g;
|
||||
this.charset = this.charsets[g];
|
||||
}
|
||||
|
||||
public setgCharset(g: number, charset: ICharset): void {
|
||||
this.charsets[g] = charset;
|
||||
if (this.glevel === g) {
|
||||
this.charset = charset;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,14 @@
|
||||
|
||||
import { ICoreService, ILogService, IOptionsService, IBufferService } from 'common/services/Services';
|
||||
import { EventEmitter, IEvent } from 'common/EventEmitter';
|
||||
import { IDecPrivateModes } from 'common/Types';
|
||||
import { IDecPrivateModes, ICharset } from 'common/Types';
|
||||
import { clone } from 'common/Clone';
|
||||
|
||||
const DEFAULT_DEC_PRIVATE_MODES: IDecPrivateModes = Object.freeze({
|
||||
applicationCursorKeys: false
|
||||
applicationCursorKeys: false,
|
||||
applicationKeypad: false,
|
||||
origin: false,
|
||||
wraparound: true // defaults: xterm - true, vt100 - false
|
||||
});
|
||||
|
||||
export class CoreService implements ICoreService {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { IEvent } from 'common/EventEmitter';
|
||||
import { IBuffer, IBufferSet } from 'common/buffer/Types';
|
||||
import { IDecPrivateModes, ICoreMouseEvent, CoreMouseEncoding, ICoreMouseProtocol, CoreMouseEventType } from 'common/Types';
|
||||
import { IDecPrivateModes, ICoreMouseEvent, CoreMouseEncoding, ICoreMouseProtocol, CoreMouseEventType, ICharset } from 'common/Types';
|
||||
import { createDecorator } from 'common/services/ServiceRegistry';
|
||||
|
||||
export const IBufferService = createDecorator<IBufferService>('BufferService');
|
||||
@@ -64,6 +64,7 @@ export interface ICoreService {
|
||||
*/
|
||||
isCursorInitialized: boolean;
|
||||
isCursorHidden: boolean;
|
||||
|
||||
readonly decPrivateModes: IDecPrivateModes;
|
||||
|
||||
readonly onData: IEvent<string>;
|
||||
@@ -89,6 +90,30 @@ export interface ICoreService {
|
||||
triggerBinaryEvent(data: string): void;
|
||||
}
|
||||
|
||||
export const ICharsetService = createDecorator<ICharsetService>('CharsetService');
|
||||
export interface ICharsetService {
|
||||
serviceBrand: any;
|
||||
|
||||
charset: ICharset | undefined;
|
||||
readonly glevel: number;
|
||||
readonly charsets: ReadonlyArray<ICharset>;
|
||||
|
||||
reset(): void;
|
||||
|
||||
/**
|
||||
* Set the G level of the terminal.
|
||||
* @param g
|
||||
*/
|
||||
setgLevel(g: number): void;
|
||||
|
||||
/**
|
||||
* Set the charset for the given G level of the terminal.
|
||||
* @param g
|
||||
* @param charset
|
||||
*/
|
||||
setgCharset(g: number, charset: ICharset): void;
|
||||
}
|
||||
|
||||
export const IDirtyRowService = createDecorator<IDirtyRowService>('DirtyRowService');
|
||||
export interface IDirtyRowService {
|
||||
serviceBrand: any;
|
||||
|
||||
Vendored
+3
-3
@@ -336,8 +336,8 @@ declare module 'xterm' {
|
||||
* An event that can be listened to.
|
||||
* @returns an `IDisposable` to stop listening.
|
||||
*/
|
||||
export interface IEvent<T> {
|
||||
(listener: (e: T) => any): IDisposable;
|
||||
export interface IEvent<T, U = void> {
|
||||
(listener: (arg1: T, arg2: U) => any): IDisposable;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -444,7 +444,7 @@ declare module 'xterm' {
|
||||
* Currently this is only used for a certain type of mouse reports that
|
||||
* happen to be not UTF-8 compatible.
|
||||
* The event value is a JS string, pass it to the underlying pty as
|
||||
* binary data, e.g. `pty.write(Buffer.from(data, 'binary'))`.
|
||||
* binary data, e.g. `pty.write(Buffer.from(data, 'binary'))`.
|
||||
* @returns an `IDisposable` to stop listening.
|
||||
*/
|
||||
onBinary: IEvent<string>;
|
||||
|
||||
Reference in New Issue
Block a user