mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Merge pull request #2874 from Tyriar/layers2
Move InputHandler into common
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { ITerminalOptions } from '../../../src/Types';
|
||||
import { ITerminalOptions } from '../../../src/common/Types';
|
||||
import { ITheme } from 'xterm';
|
||||
import { assert } from 'chai';
|
||||
import { openTerminal, pollFor, writeSync, getBrowserType } from '../../../out-test/api/TestUtils';
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+88
-6
@@ -121,7 +121,7 @@ describe('Terminal', () => {
|
||||
assert.equal(e, 'title');
|
||||
done();
|
||||
});
|
||||
term.handleTitle('title');
|
||||
term.write('\x1b]2;title\x07');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -140,7 +140,6 @@ describe('Terminal', () => {
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
term.showCursor = () => { };
|
||||
term.clearSelection = () => { };
|
||||
});
|
||||
|
||||
@@ -531,7 +530,6 @@ describe('Terminal', () => {
|
||||
let evKeyPress: any;
|
||||
|
||||
beforeEach(() => {
|
||||
term.showCursor = () => { };
|
||||
term.clearSelection = () => { };
|
||||
// term.compositionHelper = {
|
||||
// isComposing: false,
|
||||
@@ -991,7 +989,7 @@ describe('Terminal', () => {
|
||||
term.writeSync(Array(9).join('0123456789').slice(-80));
|
||||
term.buffer.x = 10;
|
||||
term.buffer.y = 0;
|
||||
term.insertMode = true;
|
||||
term.write('\x1b[4h');
|
||||
term.writeSync('abcde');
|
||||
expect(term.buffer.lines.get(0).length).eql(term.cols);
|
||||
expect(term.buffer.lines.get(0).loadCell(10, cell).getChars()).eql('a');
|
||||
@@ -1003,7 +1001,7 @@ describe('Terminal', () => {
|
||||
term.writeSync(Array(9).join('0123456789').slice(-80));
|
||||
term.buffer.x = 10;
|
||||
term.buffer.y = 0;
|
||||
term.insertMode = true;
|
||||
term.write('\x1b[4h');
|
||||
term.writeSync('¥¥¥');
|
||||
expect(term.buffer.lines.get(0).length).eql(term.cols);
|
||||
expect(term.buffer.lines.get(0).loadCell(10, cell).getChars()).eql('¥');
|
||||
@@ -1016,7 +1014,7 @@ describe('Terminal', () => {
|
||||
term.writeSync(Array(41).join('¥'));
|
||||
term.buffer.x = 10;
|
||||
term.buffer.y = 0;
|
||||
term.insertMode = true;
|
||||
term.write('\x1b[4h');
|
||||
term.writeSync('a');
|
||||
expect(term.buffer.lines.get(0).length).eql(term.cols);
|
||||
expect(term.buffer.lines.get(0).loadCell(10, cell).getChars()).eql('a');
|
||||
@@ -1403,6 +1401,90 @@ describe('Terminal', () => {
|
||||
assert.equal(windowsModeTerminal.buffer.lines.get(2).isWrapped, false);
|
||||
});
|
||||
});
|
||||
it('convertEol setting', function(): void {
|
||||
// not converting
|
||||
const termNotConverting = new TestTerminal({cols: 15, rows: 10});
|
||||
termNotConverting.writeSync('Hello\nWorld');
|
||||
expect(termNotConverting.buffer.lines.get(0).translateToString(false)).equals('Hello ');
|
||||
expect(termNotConverting.buffer.lines.get(1).translateToString(false)).equals(' World ');
|
||||
expect(termNotConverting.buffer.lines.get(0).translateToString(true)).equals('Hello');
|
||||
expect(termNotConverting.buffer.lines.get(1).translateToString(true)).equals(' World');
|
||||
|
||||
// converting
|
||||
const termConverting = new TestTerminal({cols: 15, rows: 10, convertEol: true});
|
||||
termConverting.writeSync('Hello\nWorld');
|
||||
expect(termConverting.buffer.lines.get(0).translateToString(false)).equals('Hello ');
|
||||
expect(termConverting.buffer.lines.get(1).translateToString(false)).equals('World ');
|
||||
expect(termConverting.buffer.lines.get(0).translateToString(true)).equals('Hello');
|
||||
expect(termConverting.buffer.lines.get(1).translateToString(true)).equals('World');
|
||||
});
|
||||
describe('Terminal InputHandler integration', () => {
|
||||
function getLines(term: TestTerminal, limit: number = term.rows): string[] {
|
||||
const res: string[] = [];
|
||||
for (let i = 0; i < limit; ++i) {
|
||||
res.push(term.buffer.lines.get(i).translateToString(true));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// This suite cannot live in InputHandler unless Terminal.scroll moved into IBufferService
|
||||
describe('SL/SR/DECIC/DECDC', () => {
|
||||
let term: TestTerminal;
|
||||
beforeEach(() => {
|
||||
term = new TestTerminal({cols: 5, rows: 5, scrollback: 1});
|
||||
});
|
||||
it('SL (scrollLeft)', () => {
|
||||
term.writeSync('12345'.repeat(6));
|
||||
term.writeSync('\x1b[ @');
|
||||
assert.deepEqual(getLines(term, term.rows + 1), ['12345', '2345', '2345', '2345', '2345', '2345']);
|
||||
term.writeSync('\x1b[0 @');
|
||||
assert.deepEqual(getLines(term, term.rows + 1), ['12345', '345', '345', '345', '345', '345']);
|
||||
term.writeSync('\x1b[2 @');
|
||||
assert.deepEqual(getLines(term, term.rows + 1), ['12345', '5', '5', '5', '5', '5']);
|
||||
});
|
||||
it('SR (scrollRight)', () => {
|
||||
term.writeSync('12345'.repeat(6));
|
||||
term.writeSync('\x1b[ A');
|
||||
assert.deepEqual(getLines(term, term.rows + 1), ['12345', ' 1234', ' 1234', ' 1234', ' 1234', ' 1234']);
|
||||
term.writeSync('\x1b[0 A');
|
||||
assert.deepEqual(getLines(term, term.rows + 1), ['12345', ' 123', ' 123', ' 123', ' 123', ' 123']);
|
||||
term.writeSync('\x1b[2 A');
|
||||
assert.deepEqual(getLines(term, term.rows + 1), ['12345', ' 1', ' 1', ' 1', ' 1', ' 1']);
|
||||
});
|
||||
it('insertColumns (DECIC)', () => {
|
||||
term.writeSync('12345'.repeat(6));
|
||||
term.writeSync('\x1b[3;3H');
|
||||
term.writeSync('\x1b[\'}');
|
||||
assert.deepEqual(getLines(term, term.rows + 1), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']);
|
||||
term.reset();
|
||||
term.writeSync('12345'.repeat(6));
|
||||
term.writeSync('\x1b[3;3H');
|
||||
term.writeSync('\x1b[1\'}');
|
||||
assert.deepEqual(getLines(term, term.rows + 1), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']);
|
||||
term.reset();
|
||||
term.writeSync('12345'.repeat(6));
|
||||
term.writeSync('\x1b[3;3H');
|
||||
term.writeSync('\x1b[2\'}');
|
||||
assert.deepEqual(getLines(term, term.rows + 1), ['12345', '12 3', '12 3', '12 3', '12 3', '12 3']);
|
||||
});
|
||||
it('deleteColumns (DECDC)', () => {
|
||||
term.writeSync('12345'.repeat(6));
|
||||
term.writeSync('\x1b[3;3H');
|
||||
term.writeSync('\x1b[\'~');
|
||||
assert.deepEqual(getLines(term, term.rows + 1), ['12345', '1245', '1245', '1245', '1245', '1245']);
|
||||
term.reset();
|
||||
term.writeSync('12345'.repeat(6));
|
||||
term.writeSync('\x1b[3;3H');
|
||||
term.writeSync('\x1b[1\'~');
|
||||
assert.deepEqual(getLines(term, term.rows + 1), ['12345', '1245', '1245', '1245', '1245', '1245']);
|
||||
term.reset();
|
||||
term.writeSync('12345'.repeat(6));
|
||||
term.writeSync('\x1b[3;3H');
|
||||
term.writeSync('\x1b[2\'~');
|
||||
assert.deepEqual(getLines(term, term.rows + 1), ['12345', '125', '125', '125', '125', '125']);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
class TestLinkifier extends Linkifier {
|
||||
|
||||
+118
-242
File diff suppressed because it is too large
Load Diff
+2
-35
@@ -4,9 +4,9 @@
|
||||
*/
|
||||
|
||||
import { IRenderer, IRenderDimensions, CharacterJoinerHandler, IRequestRedrawEvent } from 'browser/renderer/Types';
|
||||
import { IInputHandlingTerminal, ICompositionHelper, ITerminal, IBrowser, ITerminalOptions } from './Types';
|
||||
import { ICompositionHelper, ITerminal, IBrowser } from './Types';
|
||||
import { IBuffer, IBufferStringIterator, IBufferSet } from 'common/buffer/Types';
|
||||
import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, ICharset } from 'common/Types';
|
||||
import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, ICharset, ITerminalOptions } from 'common/Types';
|
||||
import { Buffer } from 'common/buffer/Buffer';
|
||||
import * as Browser from 'common/Platform';
|
||||
import { IDisposable, IMarker, IEvent, ISelectionPosition, ILinkProvider } from 'xterm';
|
||||
@@ -14,7 +14,6 @@ import { Terminal } from './Terminal';
|
||||
import { AttributeData } from 'common/buffer/AttributeData';
|
||||
import { IColorManager, IColorSet, ILinkMatcherOptions, ILinkifier, IViewport, ILinkifier2 } from 'browser/Types';
|
||||
import { IOptionsService, IUnicodeService } from 'common/services/Services';
|
||||
import { EventEmitter } from 'common/EventEmitter';
|
||||
import { IParams, IFunctionIdentifier } from 'common/parser/Types';
|
||||
import { ISelectionService } from 'browser/services/Services';
|
||||
|
||||
@@ -190,9 +189,6 @@ export class MockTerminal implements ITerminal {
|
||||
public reset(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
public showCursor(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
public refresh(start: number, end: number): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
@@ -200,35 +196,6 @@ export class MockTerminal implements ITerminal {
|
||||
public deregisterCharacterJoiner(joinerId: number): void { }
|
||||
}
|
||||
|
||||
export class MockInputHandlingTerminal implements IInputHandlingTerminal {
|
||||
public onA11yCharEmitter: EventEmitter<string>;
|
||||
public onA11yTabEmitter: EventEmitter<number>;
|
||||
public insertMode: boolean;
|
||||
public bracketedPasteMode: boolean;
|
||||
public sendFocus: boolean;
|
||||
public buffers: IBufferSet;
|
||||
public buffer: IBuffer = new MockBuffer();
|
||||
public viewport: IViewport;
|
||||
public scroll(eraseAttr: IAttributeData, isWrapped?: boolean): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
public is(term: string): boolean {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
public resize(x: number, y: number): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
public showCursor(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
public handler(data: string): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
public handleTitle(title: string): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
|
||||
export class MockBuffer implements IBuffer {
|
||||
public markers: IMarker[];
|
||||
public addMarker(y: number): IMarker {
|
||||
|
||||
Vendored
+4
-120
@@ -3,10 +3,10 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { ITerminalOptions as IPublicTerminalOptions, IDisposable, IMarker, ISelectionPosition, ILinkProvider } from 'xterm';
|
||||
import { ICharset, IAttributeData, CharData, CoreMouseEventType } from 'common/Types';
|
||||
import { IEvent, IEventEmitter } from 'common/EventEmitter';
|
||||
import { IColorSet, ILinkifier, ILinkMatcherOptions, IViewport, ILinkifier2 } from 'browser/Types';
|
||||
import { IDisposable, IMarker, ISelectionPosition, ILinkProvider } from 'xterm';
|
||||
import { IAttributeData, CharData, ITerminalOptions } from 'common/Types';
|
||||
import { IEvent } from 'common/EventEmitter';
|
||||
import { ILinkifier, ILinkMatcherOptions, IViewport, ILinkifier2 } from 'browser/Types';
|
||||
import { IOptionsService, IUnicodeService } from 'common/services/Services';
|
||||
import { IBuffer, IBufferSet } from 'common/buffer/Types';
|
||||
import { IParams, IFunctionIdentifier } from 'common/parser/Types';
|
||||
@@ -15,30 +15,6 @@ export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean;
|
||||
|
||||
export type LineData = CharData[];
|
||||
|
||||
/**
|
||||
* This interface encapsulates everything needed from the Terminal by the
|
||||
* InputHandler. This cleanly separates the large amount of methods needed by
|
||||
* InputHandler cleanly from the ITerminal interface.
|
||||
*/
|
||||
export interface IInputHandlingTerminal {
|
||||
insertMode: boolean;
|
||||
bracketedPasteMode: boolean;
|
||||
sendFocus: boolean;
|
||||
|
||||
buffers: IBufferSet;
|
||||
buffer: IBuffer;
|
||||
viewport: IViewport;
|
||||
|
||||
onA11yCharEmitter: IEventEmitter<string>;
|
||||
onA11yTabEmitter: IEventEmitter<number>;
|
||||
|
||||
scroll(eraseAttr: IAttributeData, isWrapped?: boolean): void;
|
||||
is(term: string): boolean;
|
||||
resize(x: number, y: number): void;
|
||||
showCursor(): void;
|
||||
handleTitle(title: string): void;
|
||||
}
|
||||
|
||||
export interface ICompositionHelper {
|
||||
compositionstart(): void;
|
||||
compositionupdate(ev: CompositionEvent): void;
|
||||
@@ -47,95 +23,12 @@ export interface ICompositionHelper {
|
||||
keydown(ev: KeyboardEvent): boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the parser and handles actions generated by the parser.
|
||||
*/
|
||||
export interface IInputHandler {
|
||||
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;
|
||||
buffer: IBuffer;
|
||||
buffers: IBufferSet;
|
||||
viewport: IViewport;
|
||||
bracketedPasteMode: boolean;
|
||||
optionsService: IOptionsService;
|
||||
// TODO: We should remove options once components adopt optionsService
|
||||
options: ITerminalOptions;
|
||||
@@ -148,7 +41,6 @@ export interface ITerminal extends IPublicTerminal, IElementAccessor, IBufferAcc
|
||||
|
||||
scrollLines(disp: number, suppressScrollEvent?: boolean): void;
|
||||
cancel(ev: Event, force?: boolean): boolean | void;
|
||||
showCursor(): void;
|
||||
}
|
||||
|
||||
// Portions of the public API that are required by the internal Terminal
|
||||
@@ -216,14 +108,6 @@ export interface ILinkifierAccessor {
|
||||
linkifier2: ILinkifier2;
|
||||
}
|
||||
|
||||
// TODO: The options that are not in the public API should be reviewed
|
||||
export interface ITerminalOptions extends IPublicTerminalOptions {
|
||||
[key: string]: any;
|
||||
cancelEvents?: boolean;
|
||||
convertEol?: boolean;
|
||||
termName?: string;
|
||||
}
|
||||
|
||||
export interface IBrowser {
|
||||
isNode: boolean;
|
||||
userAgent: string;
|
||||
|
||||
@@ -42,17 +42,17 @@ export function copyHandler(ev: ClipboardEvent, selectionService: ISelectionServ
|
||||
* @param ev The original paste event to be handled
|
||||
* @param term The terminal on which to apply the handled paste event
|
||||
*/
|
||||
export function handlePasteEvent(ev: ClipboardEvent, textarea: HTMLTextAreaElement, bracketedPasteMode: boolean, coreService: ICoreService): void {
|
||||
export function handlePasteEvent(ev: ClipboardEvent, textarea: HTMLTextAreaElement, coreService: ICoreService): void {
|
||||
ev.stopPropagation();
|
||||
if (ev.clipboardData) {
|
||||
const text = ev.clipboardData.getData('text/plain');
|
||||
paste(text, textarea, bracketedPasteMode, coreService);
|
||||
paste(text, textarea, coreService);
|
||||
}
|
||||
}
|
||||
|
||||
export function paste(text: string, textarea: HTMLTextAreaElement, bracketedPasteMode: boolean, coreService: ICoreService): void {
|
||||
export function paste(text: string, textarea: HTMLTextAreaElement, coreService: ICoreService): void {
|
||||
text = prepareTextForTerminal(text);
|
||||
text = bracketTextForPaste(text, bracketedPasteMode);
|
||||
text = bracketTextForPaste(text, coreService.decPrivateModes.bracketedPasteMode);
|
||||
coreService.triggerDataEvent(text, true);
|
||||
textarea.value = '';
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { IRenderDimensions, IRenderer, CharacterJoinerHandler } from 'browser/re
|
||||
import { IColorSet } from 'browser/Types';
|
||||
|
||||
export class MockCharSizeService implements ICharSizeService {
|
||||
public serviceBrand: any;
|
||||
public serviceBrand: undefined;
|
||||
public get hasValidSize(): boolean { return this.width > 0 && this.height > 0; }
|
||||
public onCharSizeChange: IEvent<void> = new EventEmitter<void>().event;
|
||||
constructor(public width: number, public height: number) {}
|
||||
@@ -17,7 +17,7 @@ export class MockCharSizeService implements ICharSizeService {
|
||||
}
|
||||
|
||||
export class MockMouseService implements IMouseService {
|
||||
public serviceBrand: any;
|
||||
public serviceBrand: undefined;
|
||||
public getCoords(event: {clientX: number, clientY: number}, element: HTMLElement, colCount: number, rowCount: number, isSelection?: boolean): [number, number] | undefined {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
@@ -28,7 +28,7 @@ export class MockMouseService implements IMouseService {
|
||||
}
|
||||
|
||||
export class MockRenderService implements IRenderService {
|
||||
public serviceBrand: any;
|
||||
public serviceBrand: undefined;
|
||||
public onDimensionsChange: IEvent<IRenderDimensions> = new EventEmitter<IRenderDimensions>().event;
|
||||
public onRenderedBufferChange: IEvent<{ start: number, end: number }, void> = new EventEmitter<{ start: number, end: number }>().event;
|
||||
public onRefreshRequest: IEvent<{ start: number, end: number}, void> = new EventEmitter<{ start: number, end: number }>().event;
|
||||
|
||||
@@ -8,7 +8,7 @@ import { IEvent, EventEmitter } from 'common/EventEmitter';
|
||||
import { ICharSizeService } from 'browser/services/Services';
|
||||
|
||||
export class CharSizeService implements ICharSizeService {
|
||||
public serviceBrand: any;
|
||||
public serviceBrand: undefined;
|
||||
|
||||
public width: number = 0;
|
||||
public height: number = 0;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { ICoreBrowserService } from './Services';
|
||||
|
||||
export class CoreBrowserService implements ICoreBrowserService {
|
||||
public serviceBrand: any;
|
||||
public serviceBrand: undefined;
|
||||
|
||||
constructor(
|
||||
private _textarea: HTMLTextAreaElement
|
||||
|
||||
@@ -7,7 +7,7 @@ import { ICharSizeService, IRenderService, IMouseService } from './Services';
|
||||
import { getCoords, getRawByteCoords } from 'browser/input/Mouse';
|
||||
|
||||
export class MouseService implements IMouseService {
|
||||
public serviceBrand: any;
|
||||
public serviceBrand: undefined;
|
||||
|
||||
constructor(
|
||||
@IRenderService private readonly _renderService: IRenderService,
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Disposable } from 'common/Lifecycle';
|
||||
import { ScreenDprMonitor } from 'browser/ScreenDprMonitor';
|
||||
import { addDisposableDomListener } from 'browser/Lifecycle';
|
||||
import { IColorSet } from 'browser/Types';
|
||||
import { IOptionsService } from 'common/services/Services';
|
||||
import { IOptionsService, IBufferService, ICoreService } from 'common/services/Services';
|
||||
import { ICharSizeService, IRenderService } from 'browser/services/Services';
|
||||
|
||||
interface ISelectionState {
|
||||
@@ -20,7 +20,7 @@ interface ISelectionState {
|
||||
}
|
||||
|
||||
export class RenderService extends Disposable implements IRenderService {
|
||||
public serviceBrand: any;
|
||||
public serviceBrand: undefined;
|
||||
|
||||
private _renderDebouncer: RenderDebouncer;
|
||||
private _screenDprMonitor: ScreenDprMonitor;
|
||||
@@ -51,7 +51,8 @@ export class RenderService extends Disposable implements IRenderService {
|
||||
private _rowCount: number,
|
||||
screenElement: HTMLElement,
|
||||
@IOptionsService optionsService: IOptionsService,
|
||||
@ICharSizeService charSizeService: ICharSizeService
|
||||
@ICharSizeService charSizeService: ICharSizeService,
|
||||
@IBufferService private readonly _bufferService: IBufferService
|
||||
) {
|
||||
super();
|
||||
this._renderDebouncer = new RenderDebouncer((start, end) => this._renderRows(start, end));
|
||||
@@ -61,6 +62,7 @@ export class RenderService extends Disposable implements IRenderService {
|
||||
this._screenDprMonitor.setListener(() => this.onDevicePixelRatioChange());
|
||||
this.register(this._screenDprMonitor);
|
||||
|
||||
this.register(this._bufferService.onResize(e => this._fullRefresh()));
|
||||
this.register(optionsService.onOptionChange(() => this._renderer.onOptionsChanged()));
|
||||
this.register(charSizeService.onCharSizeChange(() => this.onCharSizeChanged()));
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ export const enum SelectionMode {
|
||||
* when the selection is ready to be redrawn (on an animation frame).
|
||||
*/
|
||||
export class SelectionService implements ISelectionService {
|
||||
public serviceBrand: any;
|
||||
public serviceBrand: undefined;
|
||||
|
||||
protected _model: SelectionModel;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import { IDisposable } from 'common/Types';
|
||||
|
||||
export const ICharSizeService = createDecorator<ICharSizeService>('CharSizeService');
|
||||
export interface ICharSizeService {
|
||||
serviceBrand: any;
|
||||
serviceBrand: undefined;
|
||||
|
||||
readonly width: number;
|
||||
readonly height: number;
|
||||
@@ -25,14 +25,14 @@ export interface ICharSizeService {
|
||||
|
||||
export const ICoreBrowserService = createDecorator<ICoreBrowserService>('CoreBrowserService');
|
||||
export interface ICoreBrowserService {
|
||||
serviceBrand: any;
|
||||
serviceBrand: undefined;
|
||||
|
||||
readonly isFocused: boolean;
|
||||
}
|
||||
|
||||
export const IMouseService = createDecorator<IMouseService>('MouseService');
|
||||
export interface IMouseService {
|
||||
serviceBrand: any;
|
||||
serviceBrand: undefined;
|
||||
|
||||
getCoords(event: {clientX: number, clientY: number}, element: HTMLElement, colCount: number, rowCount: number, isSelection?: boolean): [number, number] | undefined;
|
||||
getRawByteCoords(event: MouseEvent, element: HTMLElement, colCount: number, rowCount: number): { x: number, y: number } | undefined;
|
||||
@@ -40,7 +40,7 @@ export interface IMouseService {
|
||||
|
||||
export const IRenderService = createDecorator<IRenderService>('RenderService');
|
||||
export interface IRenderService extends IDisposable {
|
||||
serviceBrand: any;
|
||||
serviceBrand: undefined;
|
||||
|
||||
onDimensionsChange: IEvent<IRenderDimensions>;
|
||||
/**
|
||||
@@ -72,7 +72,7 @@ export interface IRenderService extends IDisposable {
|
||||
|
||||
export const ISelectionService = createDecorator<ISelectionService>('SelectionService');
|
||||
export interface ISelectionService {
|
||||
serviceBrand: any;
|
||||
serviceBrand: undefined;
|
||||
|
||||
readonly selectionText: string;
|
||||
readonly hasSelection: boolean;
|
||||
@@ -100,7 +100,7 @@ export interface ISelectionService {
|
||||
|
||||
export const ISoundService = createDecorator<ISoundService>('SoundService');
|
||||
export interface ISoundService {
|
||||
serviceBrand: any;
|
||||
serviceBrand: undefined;
|
||||
|
||||
playBellSound(): void;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { IOptionsService } from 'common/services/Services';
|
||||
import { ISoundService } from 'browser/services/Services';
|
||||
|
||||
export class SoundService implements ISoundService {
|
||||
public serviceBrand: any;
|
||||
public serviceBrand: undefined;
|
||||
|
||||
private static _audioContext: AudioContext;
|
||||
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
"common/*": [ "./common/*" ]
|
||||
}
|
||||
},
|
||||
"include": [ "./**/*" ],
|
||||
"include": [
|
||||
"./**/*",
|
||||
"../../typings/xterm.d.ts"
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../common" }
|
||||
]
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
/**
|
||||
* Copyright (c) 2014-2020 The xterm.js authors. All rights reserved.
|
||||
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
||||
* @license MIT
|
||||
*
|
||||
* Originally forked from (with the author's permission):
|
||||
* Fabrice Bellard's javascript vt100 for jslinux:
|
||||
* http://bellard.org/jslinux/
|
||||
* Copyright (c) 2011 Fabrice Bellard
|
||||
* The original design remains. The terminal itself
|
||||
* has been extended to include xterm CSI codes, among
|
||||
* other features.
|
||||
*
|
||||
* Terminal Emulation References:
|
||||
* http://vt100.net/
|
||||
* http://invisible-island.net/xterm/ctlseqs/ctlseqs.txt
|
||||
* http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
||||
* http://invisible-island.net/vttest/
|
||||
* http://www.inwap.com/pdp10/ansicode.txt
|
||||
* http://linux.die.net/man/4/console_codes
|
||||
* http://linux.die.net/man/7/urxvt
|
||||
*/
|
||||
|
||||
import { Disposable } from 'common/Lifecycle';
|
||||
import { IInstantiationService, IOptionsService, IBufferService, ILogService, ICharsetService, ICoreService, ICoreMouseService, IUnicodeService, IDirtyRowService } from 'common/services/Services';
|
||||
import { InstantiationService } from 'common/services/InstantiationService';
|
||||
import { LogService } from 'common/services/LogService';
|
||||
import { BufferService, MINIMUM_COLS, MINIMUM_ROWS } from 'common/services/BufferService';
|
||||
import { OptionsService } from 'common/services/OptionsService';
|
||||
import { ITerminalOptions, IDisposable } from './Types';
|
||||
import { CoreService } from 'common/services/CoreService';
|
||||
import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter';
|
||||
import { CoreMouseService } from 'common/services/CoreMouseService';
|
||||
import { DirtyRowService } from 'common/services/DirtyRowService';
|
||||
import { UnicodeService } from 'common/services/UnicodeService';
|
||||
import { CharsetService } from 'common/services/CharsetService';
|
||||
import { updateWindowsModeWrappedState } from 'common/WindowsMode';
|
||||
import { IFunctionIdentifier, IParams } from 'common/parser/Types';
|
||||
import { IBufferSet } from 'common/buffer/Types';
|
||||
|
||||
export abstract class CoreTerminal extends Disposable {
|
||||
protected readonly _instantiationService: IInstantiationService;
|
||||
protected readonly _bufferService: IBufferService;
|
||||
protected readonly _logService: ILogService;
|
||||
protected readonly _coreService: ICoreService;
|
||||
protected readonly _charsetService: ICharsetService;
|
||||
protected readonly _coreMouseService: ICoreMouseService;
|
||||
protected readonly _dirtyRowService: IDirtyRowService;
|
||||
|
||||
public readonly unicodeService: IUnicodeService;
|
||||
public readonly optionsService: IOptionsService;
|
||||
|
||||
private _windowsMode: IDisposable | undefined;
|
||||
|
||||
private _onBinary = new EventEmitter<string>();
|
||||
public get onBinary(): IEvent<string> { return this._onBinary.event; }
|
||||
private _onData = new EventEmitter<string>();
|
||||
public get onData(): IEvent<string> { return this._onData.event; }
|
||||
protected _onLineFeed = new EventEmitter<void>();
|
||||
public get onLineFeed(): IEvent<void> { return this._onLineFeed.event; }
|
||||
private _onResize = new EventEmitter<{ cols: number, rows: number }>();
|
||||
public get onResize(): IEvent<{ cols: number, rows: number }> { return this._onResize.event; }
|
||||
|
||||
public get cols(): number { return this._bufferService.cols; }
|
||||
public get rows(): number { return this._bufferService.rows; }
|
||||
public get buffers(): IBufferSet { return this._bufferService.buffers; }
|
||||
|
||||
constructor(
|
||||
options: ITerminalOptions
|
||||
) {
|
||||
super();
|
||||
|
||||
// Setup and initialize services
|
||||
this._instantiationService = new InstantiationService();
|
||||
this.optionsService = new OptionsService(options);
|
||||
this._instantiationService.setService(IOptionsService, this.optionsService);
|
||||
this._bufferService = this._instantiationService.createInstance(BufferService);
|
||||
this._instantiationService.setService(IBufferService, this._bufferService);
|
||||
this._logService = this._instantiationService.createInstance(LogService);
|
||||
this._instantiationService.setService(ILogService, this._logService);
|
||||
this._coreService = this._instantiationService.createInstance(CoreService, () => this.scrollToBottom());
|
||||
this._instantiationService.setService(ICoreService, this._coreService);
|
||||
this._coreMouseService = this._instantiationService.createInstance(CoreMouseService);
|
||||
this._instantiationService.setService(ICoreMouseService, this._coreMouseService);
|
||||
this._dirtyRowService = this._instantiationService.createInstance(DirtyRowService);
|
||||
this._instantiationService.setService(IDirtyRowService, this._dirtyRowService);
|
||||
this.unicodeService = this._instantiationService.createInstance(UnicodeService);
|
||||
this._instantiationService.setService(IUnicodeService, this.unicodeService);
|
||||
this._charsetService = this._instantiationService.createInstance(CharsetService);
|
||||
this._instantiationService.setService(ICharsetService, this._charsetService);
|
||||
|
||||
// Setup listeners
|
||||
this.register(forwardEvent(this._bufferService.onResize, this._onResize));
|
||||
this.register(forwardEvent(this._coreService.onData, this._onData));
|
||||
this.register(forwardEvent(this._coreService.onBinary, this._onBinary));
|
||||
this.register(this.optionsService.onOptionChange(key => this._updateOptions(key)));
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
if (this._isDisposed) {
|
||||
return;
|
||||
}
|
||||
super.dispose();
|
||||
this._windowsMode?.dispose();
|
||||
this._windowsMode = undefined;
|
||||
}
|
||||
|
||||
public resize(x: number, y: number): void {
|
||||
if (isNaN(x) || isNaN(y)) {
|
||||
return;
|
||||
}
|
||||
|
||||
x = Math.max(x, MINIMUM_COLS);
|
||||
y = Math.max(y, MINIMUM_ROWS);
|
||||
|
||||
this._bufferService.resize(x, y);
|
||||
}
|
||||
|
||||
protected _setup(): void {
|
||||
if (this.optionsService.options.windowsMode) {
|
||||
this._enableWindowsMode();
|
||||
}
|
||||
}
|
||||
|
||||
protected _updateOptions(key: string): void {
|
||||
// TODO: These listeners should be owned by individual components
|
||||
switch (key) {
|
||||
case 'scrollback':
|
||||
this.buffers.resize(this.cols, this.rows);
|
||||
break;
|
||||
case 'windowsMode':
|
||||
if (this.optionsService.options.windowsMode) {
|
||||
this._enableWindowsMode();
|
||||
} else {
|
||||
this._windowsMode?.dispose();
|
||||
this._windowsMode = undefined;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected _enableWindowsMode(): void {
|
||||
if (!this._windowsMode) {
|
||||
const disposables: IDisposable[] = [];
|
||||
disposables.push(this.onLineFeed(updateWindowsModeWrappedState.bind(null, this._bufferService)));
|
||||
disposables.push(this.addCsiHandler({ final: 'H' }, () => {
|
||||
updateWindowsModeWrappedState(this._bufferService);
|
||||
return false;
|
||||
}));
|
||||
this._windowsMode = {
|
||||
dispose: () => {
|
||||
disposables.forEach(d => d.dispose());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public abstract scrollToBottom(): void;
|
||||
public abstract addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable;
|
||||
}
|
||||
@@ -63,3 +63,7 @@ export class EventEmitter<T, U = void> implements IEventEmitter<T, U> {
|
||||
this._disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
export function forwardEvent<T>(from: IEvent<T>, to: IEventEmitter<T>): IDisposable {
|
||||
return from(e => to.fire(e));
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IInputHandler, IInputHandlingTerminal } 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,11 +17,9 @@ 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, IInstantiationService } from 'common/services/Services';
|
||||
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';
|
||||
import { IRenderService } from 'browser/services/Services';
|
||||
|
||||
/**
|
||||
* Map collect to glevel. Used in `selectCharset`.
|
||||
@@ -94,7 +92,10 @@ function paramToWindowOption(n: number, opts: IWindowOptions): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
export enum WindowsOptionsReportType {
|
||||
GET_WIN_SIZE_PIXELS = 0,
|
||||
GET_CELL_SIZE_PIXELS = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* DCS subparser implementations
|
||||
@@ -218,27 +219,39 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
private _workCell: CellData = new CellData();
|
||||
private _windowTitle = '';
|
||||
private _iconName = '';
|
||||
private _windowTitleStack: string[] = [];
|
||||
private _iconNameStack: string[] = [];
|
||||
protected _windowTitleStack: string[] = [];
|
||||
protected _iconNameStack: string[] = [];
|
||||
|
||||
private _curAttrData: IAttributeData = DEFAULT_ATTR_DATA.clone();
|
||||
private _eraseAttrDataInternal: IAttributeData = DEFAULT_ATTR_DATA.clone();
|
||||
|
||||
private _onRequestBell = new EventEmitter<void>();
|
||||
public get onRequestBell(): IEvent<void> { return this._onRequestBell.event; }
|
||||
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 _onRequestScroll = new EventEmitter<IAttributeData, boolean | void>();
|
||||
public get onRequestScroll(): IEvent<IAttributeData, boolean | void> { return this._onRequestScroll.event; }
|
||||
private _onRequestSyncScrollBar = new EventEmitter<void>();
|
||||
public get onRequestSyncScrollBar(): IEvent<void> { return this._onRequestSyncScrollBar.event; }
|
||||
private _onRequestWindowsOptionsReport = new EventEmitter<WindowsOptionsReportType>();
|
||||
public get onRequestWindowsOptionsReport(): IEvent<WindowsOptionsReportType> { return this._onRequestWindowsOptionsReport.event; }
|
||||
|
||||
private _onA11yChar = new EventEmitter<string>();
|
||||
public get onA11yChar(): IEvent<string> { return this._onA11yChar.event; }
|
||||
private _onA11yTab = new EventEmitter<number>();
|
||||
public get onA11yTab(): IEvent<number> { return this._onA11yTab.event; }
|
||||
private _onCursorMove = new EventEmitter<void>();
|
||||
public get onCursorMove(): IEvent<void> { return this._onCursorMove.event; }
|
||||
private _onLineFeed = new EventEmitter<void>();
|
||||
public get onLineFeed(): IEvent<void> { return this._onLineFeed.event; }
|
||||
private _onScroll = new EventEmitter<number>();
|
||||
public get onScroll(): IEvent<number> { return this._onScroll.event; }
|
||||
private _onTitleChange = new EventEmitter<string>();
|
||||
public get onTitleChange(): IEvent<string> { return this._onTitleChange.event; }
|
||||
|
||||
constructor(
|
||||
private _terminal: IInputHandlingTerminal,
|
||||
private readonly _bufferService: IBufferService,
|
||||
private readonly _charsetService: ICharsetService,
|
||||
private readonly _coreService: ICoreService,
|
||||
@@ -247,9 +260,8 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
private readonly _optionsService: IOptionsService,
|
||||
private readonly _coreMouseService: ICoreMouseService,
|
||||
private readonly _unicodeService: IUnicodeService,
|
||||
private readonly _instantiationService: IInstantiationService,
|
||||
private readonly _parser: IEscapeSequenceParser = new EscapeSequenceParser())
|
||||
{
|
||||
private readonly _parser: IEscapeSequenceParser = new EscapeSequenceParser()
|
||||
) {
|
||||
super();
|
||||
this.register(this._parser);
|
||||
|
||||
@@ -489,9 +501,9 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
const screenReaderMode = this._optionsService.options.screenReaderMode;
|
||||
const cols = this._bufferService.cols;
|
||||
const wraparoundMode = this._coreService.decPrivateModes.wraparound;
|
||||
const insertMode = this._terminal.insertMode;
|
||||
const insertMode = this._coreService.modes.insertMode;
|
||||
const curAttr = this._curAttrData;
|
||||
let bufferRow = buffer.lines.get(buffer.ybase + buffer.y);
|
||||
let bufferRow = buffer.lines.get(buffer.ybase + buffer.y)!;
|
||||
|
||||
this._dirtyRowService.markDirty(buffer.y);
|
||||
|
||||
@@ -518,7 +530,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
}
|
||||
|
||||
if (screenReaderMode) {
|
||||
this._terminal.onA11yCharEmitter.fire(stringFromCodePoint(code));
|
||||
this._onA11yChar.fire(stringFromCodePoint(code));
|
||||
}
|
||||
|
||||
// insert combining char at last cursor position
|
||||
@@ -548,17 +560,17 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
buffer.y++;
|
||||
if (buffer.y === buffer.scrollBottom + 1) {
|
||||
buffer.y--;
|
||||
this._terminal.scroll(this._eraseAttrData(), true);
|
||||
this._onRequestScroll.fire(this._eraseAttrData(), true);
|
||||
} else {
|
||||
if (buffer.y >= this._bufferService.rows) {
|
||||
buffer.y = this._bufferService.rows - 1;
|
||||
}
|
||||
// The line already exists (eg. the initial viewport), mark it as a
|
||||
// wrapped line
|
||||
buffer.lines.get(buffer.ybase + buffer.y).isWrapped = true;
|
||||
buffer.lines.get(buffer.ybase + buffer.y)!.isWrapped = true;
|
||||
}
|
||||
// row changed, get it again
|
||||
bufferRow = buffer.lines.get(buffer.ybase + buffer.y);
|
||||
bufferRow = buffer.lines.get(buffer.ybase + buffer.y)!;
|
||||
} else {
|
||||
buffer.x = cols - 1;
|
||||
if (chWidth === 2) {
|
||||
@@ -687,7 +699,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
buffer.y++;
|
||||
if (buffer.y === buffer.scrollBottom + 1) {
|
||||
buffer.y--;
|
||||
this._terminal.scroll(this._eraseAttrData());
|
||||
this._onRequestScroll.fire(this._eraseAttrData());
|
||||
} else if (buffer.y >= this._bufferService.rows) {
|
||||
buffer.y = this._bufferService.rows - 1;
|
||||
}
|
||||
@@ -736,7 +748,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
const originalX = this._bufferService.buffer.x;
|
||||
this._bufferService.buffer.x = this._bufferService.buffer.nextStop();
|
||||
if (this._optionsService.options.screenReaderMode) {
|
||||
this._terminal.onA11yTabEmitter.fire(this._bufferService.buffer.x - originalX);
|
||||
this._onA11yTab.fire(this._bufferService.buffer.x - originalX);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1024,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,
|
||||
@@ -1042,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;
|
||||
}
|
||||
@@ -1091,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);
|
||||
@@ -1343,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;
|
||||
}
|
||||
@@ -1376,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;
|
||||
}
|
||||
@@ -1399,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;
|
||||
}
|
||||
@@ -1422,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;
|
||||
}
|
||||
@@ -1520,9 +1532,9 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
if (params.params[0] > 0) {
|
||||
return;
|
||||
}
|
||||
if (this._terminal.is('xterm') || this._terminal.is('rxvt-unicode') || this._terminal.is('screen')) {
|
||||
if (this._is('xterm') || this._is('rxvt-unicode') || this._is('screen')) {
|
||||
this._coreService.triggerDataEvent(C0.ESC + '[?1;2c');
|
||||
} else if (this._terminal.is('linux')) {
|
||||
} else if (this._is('linux')) {
|
||||
this._coreService.triggerDataEvent(C0.ESC + '[?6c');
|
||||
}
|
||||
}
|
||||
@@ -1558,19 +1570,27 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
// xterm and urxvt
|
||||
// seem to spit this
|
||||
// out around ~370 times (?).
|
||||
if (this._terminal.is('xterm')) {
|
||||
if (this._is('xterm')) {
|
||||
this._coreService.triggerDataEvent(C0.ESC + '[>0;276;0c');
|
||||
} else if (this._terminal.is('rxvt-unicode')) {
|
||||
} else if (this._is('rxvt-unicode')) {
|
||||
this._coreService.triggerDataEvent(C0.ESC + '[>85;95;0c');
|
||||
} else if (this._terminal.is('linux')) {
|
||||
} else if (this._is('linux')) {
|
||||
// not supported by linux console.
|
||||
// linux console echoes parameters.
|
||||
this._coreService.triggerDataEvent(params.params[0] + 'c');
|
||||
} else if (this._terminal.is('screen')) {
|
||||
} else if (this._is('screen')) {
|
||||
this._coreService.triggerDataEvent(C0.ESC + '[>83;40003;0c');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate if the current terminal is the given argument.
|
||||
* @param term The terminal name to evaluate
|
||||
*/
|
||||
private _is(term: string): boolean {
|
||||
return (this._optionsService.options.termName + '').indexOf(term) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* CSI Pm h Set Mode (SM).
|
||||
* Ps = 2 -> Keyboard Action Mode (AM).
|
||||
@@ -1587,15 +1607,12 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
* | 4 | Insert Mode (IRM). | #Y |
|
||||
* | 12 | Send/receive (SRM). Always off. | #N |
|
||||
* | 20 | Automatic Newline (LNM). Always off. | #N |
|
||||
*
|
||||
*
|
||||
* FIXME: why is LNM commented out?
|
||||
*/
|
||||
public setMode(params: IParams): void {
|
||||
for (let i = 0; i < params.length; i++) {
|
||||
switch (params.params[i]) {
|
||||
case 4:
|
||||
this._terminal.insertMode = true;
|
||||
this._coreService.modes.insertMode = true;
|
||||
break;
|
||||
case 20:
|
||||
// this._t.convertEol = true;
|
||||
@@ -1736,7 +1753,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
* through `options.windowsOptions`.
|
||||
*/
|
||||
if (this._optionsService.options.windowOptions.setWinLines) {
|
||||
this._terminal.resize(132, this._bufferService.rows);
|
||||
this._bufferService.resize(132, this._bufferService.rows);
|
||||
this._onRequestReset.fire();
|
||||
}
|
||||
break;
|
||||
@@ -1753,7 +1770,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
case 66:
|
||||
this._logService.debug('Serial port requested application keypad.');
|
||||
this._coreService.decPrivateModes.applicationKeypad = true;
|
||||
this._terminal.viewport?.syncScrollArea();
|
||||
this._onRequestSyncScrollBar.fire();
|
||||
break;
|
||||
case 9: // X10 Mouse
|
||||
// no release, no motion, no wheel, no modifiers.
|
||||
@@ -1774,7 +1791,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
case 1004: // send focusin/focusout events
|
||||
// focusin: ^[[I
|
||||
// focusout: ^[[O
|
||||
this._terminal.sendFocus = true;
|
||||
this._coreService.decPrivateModes.sendFocus = true;
|
||||
break;
|
||||
case 1005: // utf8 ext mode mouse - removed in #2507
|
||||
this._logService.debug('DECSET 1005 not supported (see #2507)');
|
||||
@@ -1797,12 +1814,12 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
case 47: // alt screen buffer
|
||||
case 1047: // alt screen buffer
|
||||
this._bufferService.buffers.activateAltBuffer(this._eraseAttrData());
|
||||
this._coreService.isCursorInitialized = true;
|
||||
this._onRequestRefreshRows.fire(0, this._bufferService.rows - 1);
|
||||
this._terminal.viewport?.syncScrollArea();
|
||||
this._terminal.showCursor();
|
||||
this._onRequestSyncScrollBar.fire();
|
||||
break;
|
||||
case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste)
|
||||
this._terminal.bracketedPasteMode = true;
|
||||
this._coreService.decPrivateModes.bracketedPasteMode = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1833,7 +1850,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
for (let i = 0; i < params.length; i++) {
|
||||
switch (params.params[i]) {
|
||||
case 4:
|
||||
this._terminal.insertMode = false;
|
||||
this._coreService.modes.insertMode = false;
|
||||
break;
|
||||
case 20:
|
||||
// this._t.convertEol = false;
|
||||
@@ -1963,7 +1980,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
* through `options.windowsOptions`.
|
||||
*/
|
||||
if (this._optionsService.options.windowOptions.setWinLines) {
|
||||
this._terminal.resize(80, this._bufferService.rows);
|
||||
this._bufferService.resize(80, this._bufferService.rows);
|
||||
this._onRequestReset.fire();
|
||||
}
|
||||
break;
|
||||
@@ -1980,7 +1997,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
case 66:
|
||||
this._logService.debug('Switching back to normal keypad.');
|
||||
this._coreService.decPrivateModes.applicationKeypad = false;
|
||||
this._terminal.viewport?.syncScrollArea();
|
||||
this._onRequestSyncScrollBar.fire();
|
||||
break;
|
||||
case 9: // X10 Mouse
|
||||
case 1000: // vt200 mouse
|
||||
@@ -1989,7 +2006,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
this._coreMouseService.activeProtocol = 'NONE';
|
||||
break;
|
||||
case 1004: // send focusin/focusout events
|
||||
this._terminal.sendFocus = false;
|
||||
this._coreService.decPrivateModes.sendFocus = false;
|
||||
break;
|
||||
case 1005: // utf8 ext mode mouse - removed in #2507
|
||||
this._logService.debug('DECRST 1005 not supported (see #2507)');
|
||||
@@ -2015,12 +2032,12 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
if (params.params[i] === 1049) {
|
||||
this.restoreCursor();
|
||||
}
|
||||
this._coreService.isCursorInitialized = true;
|
||||
this._onRequestRefreshRows.fire(0, this._bufferService.rows - 1);
|
||||
this._terminal.viewport?.syncScrollArea();
|
||||
this._terminal.showCursor();
|
||||
this._onRequestSyncScrollBar.fire();
|
||||
break;
|
||||
case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste)
|
||||
this._terminal.bracketedPasteMode = false;
|
||||
this._coreService.decPrivateModes.bracketedPasteMode = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2046,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) {
|
||||
@@ -2356,8 +2373,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
*/
|
||||
public softReset(params: IParams): void {
|
||||
this._coreService.isCursorHidden = false;
|
||||
this._terminal.insertMode = false;
|
||||
this._terminal.viewport?.syncScrollArea();
|
||||
this._onRequestSyncScrollBar.fire();
|
||||
this._bufferService.buffer.scrollTop = 0;
|
||||
this._bufferService.buffer.scrollBottom = this._bufferService.rows - 1;
|
||||
this._curAttrData = DEFAULT_ATTR_DATA.clone();
|
||||
@@ -2471,22 +2487,14 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
return;
|
||||
}
|
||||
const second = (params.length > 1) ? params.params[1] : 0;
|
||||
const rs = this._instantiationService.getService(IRenderService);
|
||||
switch (params.params[0]) {
|
||||
case 14: // GetWinSizePixels, returns CSI 4 ; height ; width t
|
||||
if (rs && second !== 2) {
|
||||
console.log(rs.dimensions);
|
||||
const w = rs.dimensions.scaledCanvasWidth.toFixed(0);
|
||||
const h = rs.dimensions.scaledCanvasHeight.toFixed(0);
|
||||
this._coreService.triggerDataEvent(`${C0.ESC}[4;${h};${w}t`);
|
||||
if (second !== 2) {
|
||||
this._onRequestWindowsOptionsReport.fire(WindowsOptionsReportType.GET_WIN_SIZE_PIXELS);
|
||||
}
|
||||
break;
|
||||
case 16: // GetCellSizePixels, returns CSI 6 ; height ; width t
|
||||
if (rs) {
|
||||
const w = rs.dimensions.scaledCellWidth.toFixed(0);
|
||||
const h = rs.dimensions.scaledCellHeight.toFixed(0);
|
||||
this._coreService.triggerDataEvent(`${C0.ESC}[6;${h};${w}t`);
|
||||
}
|
||||
this._onRequestWindowsOptionsReport.fire(WindowsOptionsReportType.GET_CELL_SIZE_PIXELS);
|
||||
break;
|
||||
case 18: // GetWinSizeChars, returns CSI 8 ; height ; width t
|
||||
if (this._bufferService) {
|
||||
@@ -2510,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;
|
||||
@@ -2573,7 +2581,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
*/
|
||||
public setTitle(data: string): void {
|
||||
this._windowTitle = data;
|
||||
this._terminal.handleTitle(data);
|
||||
this._onTitleChange.fire(data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2606,7 +2614,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
public keypadApplicationMode(): void {
|
||||
this._logService.debug('Serial port requested application keypad.');
|
||||
this._coreService.decPrivateModes.applicationKeypad = true;
|
||||
this._terminal.viewport?.syncScrollArea();
|
||||
this._onRequestSyncScrollBar.fire();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2617,7 +2625,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
public keypadNumericMode(): void {
|
||||
this._logService.debug('Switching back to normal keypad.');
|
||||
this._coreService.decPrivateModes.applicationKeypad = false;
|
||||
this._terminal.viewport?.syncScrollArea();
|
||||
this._onRequestSyncScrollBar.fire();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2674,7 +2682,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
this._bufferService.buffer.y++;
|
||||
if (buffer.y === buffer.scrollBottom + 1) {
|
||||
buffer.y--;
|
||||
this._terminal.scroll(this._eraseAttrData());
|
||||
this._onRequestScroll.fire(this._eraseAttrData());
|
||||
} else if (buffer.y >= this._bufferService.rows) {
|
||||
buffer.y = this._bufferService.rows - 1;
|
||||
}
|
||||
@@ -2779,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.ybase + buffer.y + 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);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user