aboutsummaryrefslogtreecommitdiffstats
path: root/node_modules/xterm/src/common/services
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/xterm/src/common/services')
-rw-r--r--node_modules/xterm/src/common/services/BufferService.ts185
-rw-r--r--node_modules/xterm/src/common/services/CharsetService.ts34
-rw-r--r--node_modules/xterm/src/common/services/CoreMouseService.ts309
-rw-r--r--node_modules/xterm/src/common/services/CoreService.ts92
-rw-r--r--node_modules/xterm/src/common/services/DirtyRowService.ts53
-rw-r--r--node_modules/xterm/src/common/services/InstantiationService.ts83
-rw-r--r--node_modules/xterm/src/common/services/LogService.ts88
-rw-r--r--node_modules/xterm/src/common/services/OptionsService.ts177
-rw-r--r--node_modules/xterm/src/common/services/ServiceRegistry.ts49
-rw-r--r--node_modules/xterm/src/common/services/Services.ts300
-rw-r--r--node_modules/xterm/src/common/services/UnicodeService.ts82
11 files changed, 1452 insertions, 0 deletions
diff --git a/node_modules/xterm/src/common/services/BufferService.ts b/node_modules/xterm/src/common/services/BufferService.ts
new file mode 100644
index 0000000..bba60dd
--- /dev/null
+++ b/node_modules/xterm/src/common/services/BufferService.ts
@@ -0,0 +1,185 @@
+/**
+ * Copyright (c) 2019 The xterm.js authors. All rights reserved.
+ * @license MIT
+ */
+
+import { IBufferService, IOptionsService } from 'common/services/Services';
+import { BufferSet } from 'common/buffer/BufferSet';
+import { IBufferSet, IBuffer } from 'common/buffer/Types';
+import { EventEmitter, IEvent } from 'common/EventEmitter';
+import { Disposable } from 'common/Lifecycle';
+import { IAttributeData, IBufferLine, ScrollSource } from 'common/Types';
+
+export const MINIMUM_COLS = 2; // Less than 2 can mess with wide chars
+export const MINIMUM_ROWS = 1;
+
+export class BufferService extends Disposable implements IBufferService {
+ public serviceBrand: any;
+
+ public cols: number;
+ public rows: number;
+ public buffers: IBufferSet;
+ /** Whether the user is scrolling (locks the scroll position) */
+ public isUserScrolling: boolean = false;
+
+ private _onResize = new EventEmitter<{ cols: number, rows: number }>();
+ public get onResize(): IEvent<{ cols: number, rows: number }> { return this._onResize.event; }
+ private _onScroll = new EventEmitter<number>();
+ public get onScroll(): IEvent<number> { return this._onScroll.event; }
+
+ public get buffer(): IBuffer { return this.buffers.active; }
+
+ /** An IBufferline to clone/copy from for new blank lines */
+ private _cachedBlankLine: IBufferLine | undefined;
+
+ constructor(
+ @IOptionsService private _optionsService: IOptionsService
+ ) {
+ super();
+ this.cols = Math.max(_optionsService.rawOptions.cols || 0, MINIMUM_COLS);
+ this.rows = Math.max(_optionsService.rawOptions.rows || 0, MINIMUM_ROWS);
+ this.buffers = new BufferSet(_optionsService, this);
+ }
+
+ public dispose(): void {
+ super.dispose();
+ this.buffers.dispose();
+ }
+
+ public resize(cols: number, rows: number): void {
+ this.cols = cols;
+ this.rows = rows;
+ this.buffers.resize(cols, rows);
+ this.buffers.setupTabStops(this.cols);
+ this._onResize.fire({ cols, rows });
+ }
+
+ public reset(): void {
+ this.buffers.reset();
+ this.isUserScrolling = false;
+ }
+
+ /**
+ * Scroll the terminal down 1 row, creating a blank line.
+ * @param isWrapped Whether the new line is wrapped from the previous line.
+ */
+ public scroll(eraseAttr: IAttributeData, isWrapped: boolean = false): void {
+ const buffer = this.buffer;
+
+ let newLine: IBufferLine | undefined;
+ newLine = this._cachedBlankLine;
+ if (!newLine || newLine.length !== this.cols || newLine.getFg(0) !== eraseAttr.fg || newLine.getBg(0) !== eraseAttr.bg) {
+ newLine = buffer.getBlankLine(eraseAttr, isWrapped);
+ this._cachedBlankLine = newLine;
+ }
+ newLine.isWrapped = isWrapped;
+
+ const topRow = buffer.ybase + buffer.scrollTop;
+ const bottomRow = buffer.ybase + buffer.scrollBottom;
+
+ if (buffer.scrollTop === 0) {
+ // Determine whether the buffer is going to be trimmed after insertion.
+ const willBufferBeTrimmed = buffer.lines.isFull;
+
+ // Insert the line using the fastest method
+ if (bottomRow === buffer.lines.length - 1) {
+ if (willBufferBeTrimmed) {
+ buffer.lines.recycle().copyFrom(newLine);
+ } else {
+ buffer.lines.push(newLine.clone());
+ }
+ } else {
+ buffer.lines.splice(bottomRow + 1, 0, newLine.clone());
+ }
+
+ // Only adjust ybase and ydisp when the buffer is not trimmed
+ if (!willBufferBeTrimmed) {
+ buffer.ybase++;
+ // Only scroll the ydisp with ybase if the user has not scrolled up
+ if (!this.isUserScrolling) {
+ buffer.ydisp++;
+ }
+ } else {
+ // When the buffer is full and the user has scrolled up, keep the text
+ // stable unless ydisp is right at the top
+ if (this.isUserScrolling) {
+ buffer.ydisp = Math.max(buffer.ydisp - 1, 0);
+ }
+ }
+ } else {
+ // scrollTop is non-zero which means no line will be going to the
+ // scrollback, instead we can just shift them in-place.
+ const scrollRegionHeight = bottomRow - topRow + 1 /* as it's zero-based */;
+ buffer.lines.shiftElements(topRow + 1, scrollRegionHeight - 1, -1);
+ buffer.lines.set(bottomRow, newLine.clone());
+ }
+
+ // Move the viewport to the bottom of the buffer unless the user is
+ // scrolling.
+ if (!this.isUserScrolling) {
+ buffer.ydisp = buffer.ybase;
+ }
+
+ this._onScroll.fire(buffer.ydisp);
+ }
+
+ /**
+ * Scroll the display of the terminal
+ * @param disp The number of lines to scroll down (negative scroll up).
+ * @param suppressScrollEvent Don't emit the scroll event as scrollLines. This is used
+ * to avoid unwanted events being handled by the viewport when the event was triggered from the
+ * viewport originally.
+ */
+ public scrollLines(disp: number, suppressScrollEvent?: boolean, source?: ScrollSource): void {
+ const buffer = this.buffer;
+ if (disp < 0) {
+ if (buffer.ydisp === 0) {
+ return;
+ }
+ this.isUserScrolling = true;
+ } else if (disp + buffer.ydisp >= buffer.ybase) {
+ this.isUserScrolling = false;
+ }
+
+ const oldYdisp = buffer.ydisp;
+ buffer.ydisp = Math.max(Math.min(buffer.ydisp + disp, buffer.ybase), 0);
+
+ // No change occurred, don't trigger scroll/refresh
+ if (oldYdisp === buffer.ydisp) {
+ return;
+ }
+
+ if (!suppressScrollEvent) {
+ this._onScroll.fire(buffer.ydisp);
+ }
+ }
+
+ /**
+ * Scroll the display of the terminal by a number of pages.
+ * @param pageCount The number of pages to scroll (negative scrolls up).
+ */
+ public scrollPages(pageCount: number): void {
+ this.scrollLines(pageCount * (this.rows - 1));
+ }
+
+ /**
+ * Scrolls the display of the terminal to the top.
+ */
+ public scrollToTop(): void {
+ this.scrollLines(-this.buffer.ydisp);
+ }
+
+ /**
+ * Scrolls the display of the terminal to the bottom.
+ */
+ public scrollToBottom(): void {
+ this.scrollLines(this.buffer.ybase - this.buffer.ydisp);
+ }
+
+ public scrollToLine(line: number): void {
+ const scrollAmount = line - this.buffer.ydisp;
+ if (scrollAmount !== 0) {
+ this.scrollLines(scrollAmount);
+ }
+ }
+}
diff --git a/node_modules/xterm/src/common/services/CharsetService.ts b/node_modules/xterm/src/common/services/CharsetService.ts
new file mode 100644
index 0000000..c538106
--- /dev/null
+++ b/node_modules/xterm/src/common/services/CharsetService.ts
@@ -0,0 +1,34 @@
+/**
+ * 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 {
+ public serviceBrand: any;
+
+ public charset: ICharset | undefined;
+ public glevel: number = 0;
+
+ private _charsets: (ICharset | undefined)[] = [];
+
+ 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 | undefined): void {
+ this._charsets[g] = charset;
+ if (this.glevel === g) {
+ this.charset = charset;
+ }
+ }
+}
diff --git a/node_modules/xterm/src/common/services/CoreMouseService.ts b/node_modules/xterm/src/common/services/CoreMouseService.ts
new file mode 100644
index 0000000..0b0dc36
--- /dev/null
+++ b/node_modules/xterm/src/common/services/CoreMouseService.ts
@@ -0,0 +1,309 @@
+/**
+ * Copyright (c) 2019 The xterm.js authors. All rights reserved.
+ * @license MIT
+ */
+import { IBufferService, ICoreService, ICoreMouseService } from 'common/services/Services';
+import { EventEmitter, IEvent } from 'common/EventEmitter';
+import { ICoreMouseProtocol, ICoreMouseEvent, CoreMouseEncoding, CoreMouseEventType, CoreMouseButton, CoreMouseAction } from 'common/Types';
+
+/**
+ * Supported default protocols.
+ */
+const DEFAULT_PROTOCOLS: {[key: string]: ICoreMouseProtocol} = {
+ /**
+ * NONE
+ * Events: none
+ * Modifiers: none
+ */
+ NONE: {
+ events: CoreMouseEventType.NONE,
+ restrict: () => false
+ },
+ /**
+ * X10
+ * Events: mousedown
+ * Modifiers: none
+ */
+ X10: {
+ events: CoreMouseEventType.DOWN,
+ restrict: (e: ICoreMouseEvent) => {
+ // no wheel, no move, no up
+ if (e.button === CoreMouseButton.WHEEL || e.action !== CoreMouseAction.DOWN) {
+ return false;
+ }
+ // no modifiers
+ e.ctrl = false;
+ e.alt = false;
+ e.shift = false;
+ return true;
+ }
+ },
+ /**
+ * VT200
+ * Events: mousedown / mouseup / wheel
+ * Modifiers: all
+ */
+ VT200: {
+ events: CoreMouseEventType.DOWN | CoreMouseEventType.UP | CoreMouseEventType.WHEEL,
+ restrict: (e: ICoreMouseEvent) => {
+ // no move
+ if (e.action === CoreMouseAction.MOVE) {
+ return false;
+ }
+ return true;
+ }
+ },
+ /**
+ * DRAG
+ * Events: mousedown / mouseup / wheel / mousedrag
+ * Modifiers: all
+ */
+ DRAG: {
+ events: CoreMouseEventType.DOWN | CoreMouseEventType.UP | CoreMouseEventType.WHEEL | CoreMouseEventType.DRAG,
+ restrict: (e: ICoreMouseEvent) => {
+ // no move without button
+ if (e.action === CoreMouseAction.MOVE && e.button === CoreMouseButton.NONE) {
+ return false;
+ }
+ return true;
+ }
+ },
+ /**
+ * ANY
+ * Events: all mouse related events
+ * Modifiers: all
+ */
+ ANY: {
+ events:
+ CoreMouseEventType.DOWN | CoreMouseEventType.UP | CoreMouseEventType.WHEEL
+ | CoreMouseEventType.DRAG | CoreMouseEventType.MOVE,
+ restrict: (e: ICoreMouseEvent) => true
+ }
+};
+
+const enum Modifiers {
+ SHIFT = 4,
+ ALT = 8,
+ CTRL = 16
+}
+
+// helper for default encoders to generate the event code.
+function eventCode(e: ICoreMouseEvent, isSGR: boolean): number {
+ let code = (e.ctrl ? Modifiers.CTRL : 0) | (e.shift ? Modifiers.SHIFT : 0) | (e.alt ? Modifiers.ALT : 0);
+ if (e.button === CoreMouseButton.WHEEL) {
+ code |= 64;
+ code |= e.action;
+ } else {
+ code |= e.button & 3;
+ if (e.button & 4) {
+ code |= 64;
+ }
+ if (e.button & 8) {
+ code |= 128;
+ }
+ if (e.action === CoreMouseAction.MOVE) {
+ code |= CoreMouseAction.MOVE;
+ } else if (e.action === CoreMouseAction.UP && !isSGR) {
+ // special case - only SGR can report button on release
+ // all others have to go with NONE
+ code |= CoreMouseButton.NONE;
+ }
+ }
+ return code;
+}
+
+const S = String.fromCharCode;
+
+/**
+ * Supported default encodings.
+ */
+const DEFAULT_ENCODINGS: {[key: string]: CoreMouseEncoding} = {
+ /**
+ * DEFAULT - CSI M Pb Px Py
+ * Single byte encoding for coords and event code.
+ * Can encode values up to 223 (1-based).
+ */
+ DEFAULT: (e: ICoreMouseEvent) => {
+ const params = [eventCode(e, false) + 32, e.col + 32, e.row + 32];
+ // supress mouse report if we exceed addressible range
+ // Note this is handled differently by emulators
+ // - xterm: sends 0;0 coords instead
+ // - vte, konsole: no report
+ if (params[0] > 255 || params[1] > 255 || params[2] > 255) {
+ return '';
+ }
+ return `\x1b[M${S(params[0])}${S(params[1])}${S(params[2])}`;
+ },
+ /**
+ * SGR - CSI < Pb ; Px ; Py M|m
+ * No encoding limitation.
+ * Can report button on release and works with a well formed sequence.
+ */
+ SGR: (e: ICoreMouseEvent) => {
+ const final = (e.action === CoreMouseAction.UP && e.button !== CoreMouseButton.WHEEL) ? 'm' : 'M';
+ return `\x1b[<${eventCode(e, true)};${e.col};${e.row}${final}`;
+ }
+};
+
+/**
+ * CoreMouseService
+ *
+ * Provides mouse tracking reports with different protocols and encodings.
+ * - protocols: NONE (default), X10, VT200, DRAG, ANY
+ * - encodings: DEFAULT, SGR (UTF8, URXVT removed in #2507)
+ *
+ * Custom protocols/encodings can be added by `addProtocol` / `addEncoding`.
+ * To activate a protocol/encoding, set `activeProtocol` / `activeEncoding`.
+ * Switching a protocol will send a notification event `onProtocolChange`
+ * with a list of needed events to track.
+ *
+ * The service handles the mouse tracking state and decides whether to send
+ * a tracking report to the backend based on protocol and encoding limitations.
+ * To send a mouse event call `triggerMouseEvent`.
+ */
+export class CoreMouseService implements ICoreMouseService {
+ private _protocols: {[name: string]: ICoreMouseProtocol} = {};
+ private _encodings: {[name: string]: CoreMouseEncoding} = {};
+ private _activeProtocol: string = '';
+ private _activeEncoding: string = '';
+ private _onProtocolChange = new EventEmitter<CoreMouseEventType>();
+ private _lastEvent: ICoreMouseEvent | null = null;
+
+ constructor(
+ @IBufferService private readonly _bufferService: IBufferService,
+ @ICoreService private readonly _coreService: ICoreService
+ ) {
+ // register default protocols and encodings
+ for (const name of Object.keys(DEFAULT_PROTOCOLS)) this.addProtocol(name, DEFAULT_PROTOCOLS[name]);
+ for (const name of Object.keys(DEFAULT_ENCODINGS)) this.addEncoding(name, DEFAULT_ENCODINGS[name]);
+ // call reset to set defaults
+ this.reset();
+ }
+
+ public addProtocol(name: string, protocol: ICoreMouseProtocol): void {
+ this._protocols[name] = protocol;
+ }
+
+ public addEncoding(name: string, encoding: CoreMouseEncoding): void {
+ this._encodings[name] = encoding;
+ }
+
+ public get activeProtocol(): string {
+ return this._activeProtocol;
+ }
+
+ public get areMouseEventsActive(): boolean {
+ return this._protocols[this._activeProtocol].events !== 0;
+ }
+
+ public set activeProtocol(name: string) {
+ if (!this._protocols[name]) {
+ throw new Error(`unknown protocol "${name}"`);
+ }
+ this._activeProtocol = name;
+ this._onProtocolChange.fire(this._protocols[name].events);
+ }
+
+ public get activeEncoding(): string {
+ return this._activeEncoding;
+ }
+
+ public set activeEncoding(name: string) {
+ if (!this._encodings[name]) {
+ throw new Error(`unknown encoding "${name}"`);
+ }
+ this._activeEncoding = name;
+ }
+
+ public reset(): void {
+ this.activeProtocol = 'NONE';
+ this.activeEncoding = 'DEFAULT';
+ this._lastEvent = null;
+ }
+
+ /**
+ * Event to announce changes in mouse tracking.
+ */
+ public get onProtocolChange(): IEvent<CoreMouseEventType> {
+ return this._onProtocolChange.event;
+ }
+
+ /**
+ * Triggers a mouse event to be sent.
+ *
+ * Returns true if the event passed all protocol restrictions and a report
+ * was sent, otherwise false. The return value may be used to decide whether
+ * the default event action in the bowser component should be omitted.
+ *
+ * Note: The method will change values of the given event object
+ * to fullfill protocol and encoding restrictions.
+ */
+ public triggerMouseEvent(e: ICoreMouseEvent): boolean {
+ // range check for col/row
+ if (e.col < 0 || e.col >= this._bufferService.cols
+ || e.row < 0 || e.row >= this._bufferService.rows) {
+ return false;
+ }
+
+ // filter nonsense combinations of button + action
+ if (e.button === CoreMouseButton.WHEEL && e.action === CoreMouseAction.MOVE) {
+ return false;
+ }
+ if (e.button === CoreMouseButton.NONE && e.action !== CoreMouseAction.MOVE) {
+ return false;
+ }
+ if (e.button !== CoreMouseButton.WHEEL && (e.action === CoreMouseAction.LEFT || e.action === CoreMouseAction.RIGHT)) {
+ return false;
+ }
+
+ // report 1-based coords
+ e.col++;
+ e.row++;
+
+ // debounce move at grid level
+ if (e.action === CoreMouseAction.MOVE && this._lastEvent && this._compareEvents(this._lastEvent, e)) {
+ return false;
+ }
+
+ // apply protocol restrictions
+ if (!this._protocols[this._activeProtocol].restrict(e)) {
+ return false;
+ }
+
+ // encode report and send
+ const report = this._encodings[this._activeEncoding](e);
+ if (report) {
+ // always send DEFAULT as binary data
+ if (this._activeEncoding === 'DEFAULT') {
+ this._coreService.triggerBinaryEvent(report);
+ } else {
+ this._coreService.triggerDataEvent(report, true);
+ }
+ }
+
+ this._lastEvent = e;
+
+ return true;
+ }
+
+ public explainEvents(events: CoreMouseEventType): {[event: string]: boolean} {
+ return {
+ down: !!(events & CoreMouseEventType.DOWN),
+ up: !!(events & CoreMouseEventType.UP),
+ drag: !!(events & CoreMouseEventType.DRAG),
+ move: !!(events & CoreMouseEventType.MOVE),
+ wheel: !!(events & CoreMouseEventType.WHEEL)
+ };
+ }
+
+ private _compareEvents(e1: ICoreMouseEvent, e2: ICoreMouseEvent): boolean {
+ if (e1.col !== e2.col) return false;
+ if (e1.row !== e2.row) return false;
+ if (e1.button !== e2.button) return false;
+ if (e1.action !== e2.action) return false;
+ if (e1.ctrl !== e2.ctrl) return false;
+ if (e1.alt !== e2.alt) return false;
+ if (e1.shift !== e2.shift) return false;
+ return true;
+ }
+}
diff --git a/node_modules/xterm/src/common/services/CoreService.ts b/node_modules/xterm/src/common/services/CoreService.ts
new file mode 100644
index 0000000..20a3460
--- /dev/null
+++ b/node_modules/xterm/src/common/services/CoreService.ts
@@ -0,0 +1,92 @@
+/**
+ * Copyright (c) 2019 The xterm.js authors. All rights reserved.
+ * @license MIT
+ */
+
+import { ICoreService, ILogService, IOptionsService, IBufferService } from 'common/services/Services';
+import { EventEmitter, IEvent } from 'common/EventEmitter';
+import { IDecPrivateModes, IModes } from 'common/Types';
+import { clone } from 'common/Clone';
+import { Disposable } from 'common/Lifecycle';
+
+const DEFAULT_MODES: IModes = Object.freeze({
+ insertMode: false
+});
+
+const DEFAULT_DEC_PRIVATE_MODES: IDecPrivateModes = Object.freeze({
+ applicationCursorKeys: false,
+ applicationKeypad: false,
+ bracketedPasteMode: false,
+ origin: false,
+ reverseWraparound: false,
+ sendFocus: false,
+ wraparound: true // defaults: xterm - true, vt100 - false
+});
+
+export class CoreService extends Disposable implements ICoreService {
+ public serviceBrand: any;
+
+ public isCursorInitialized: boolean = false;
+ public isCursorHidden: boolean = false;
+ public modes: IModes;
+ public decPrivateModes: IDecPrivateModes;
+
+ // Circular dependency, this must be unset or memory will leak after Terminal.dispose
+ private _scrollToBottom: (() => void) | undefined;
+
+ private _onData = this.register(new EventEmitter<string>());
+ public get onData(): IEvent<string> { return this._onData.event; }
+ private _onUserInput = this.register(new EventEmitter<void>());
+ public get onUserInput(): IEvent<void> { return this._onUserInput.event; }
+ private _onBinary = this.register(new EventEmitter<string>());
+ public get onBinary(): IEvent<string> { return this._onBinary.event; }
+
+ constructor(
+ // TODO: Move this into a service
+ scrollToBottom: () => void,
+ @IBufferService private readonly _bufferService: IBufferService,
+ @ILogService private readonly _logService: ILogService,
+ @IOptionsService private readonly _optionsService: IOptionsService
+ ) {
+ super();
+ this._scrollToBottom = scrollToBottom;
+ this.register({ dispose: () => this._scrollToBottom = undefined });
+ this.modes = clone(DEFAULT_MODES);
+ this.decPrivateModes = clone(DEFAULT_DEC_PRIVATE_MODES);
+ }
+
+ public reset(): void {
+ this.modes = clone(DEFAULT_MODES);
+ this.decPrivateModes = clone(DEFAULT_DEC_PRIVATE_MODES);
+ }
+
+ public triggerDataEvent(data: string, wasUserInput: boolean = false): void {
+ // Prevents all events to pty process if stdin is disabled
+ if (this._optionsService.rawOptions.disableStdin) {
+ return;
+ }
+
+ // Input is being sent to the terminal, the terminal should focus the prompt.
+ const buffer = this._bufferService.buffer;
+ if (buffer.ybase !== buffer.ydisp) {
+ this._scrollToBottom!();
+ }
+
+ // Fire onUserInput so listeners can react as well (eg. clear selection)
+ if (wasUserInput) {
+ this._onUserInput.fire();
+ }
+
+ // Fire onData API
+ this._logService.debug(`sending data "${data}"`, () => data.split('').map(e => e.charCodeAt(0)));
+ this._onData.fire(data);
+ }
+
+ public triggerBinaryEvent(data: string): void {
+ if (this._optionsService.rawOptions.disableStdin) {
+ return;
+ }
+ this._logService.debug(`sending binary "${data}"`, () => data.split('').map(e => e.charCodeAt(0)));
+ this._onBinary.fire(data);
+ }
+}
diff --git a/node_modules/xterm/src/common/services/DirtyRowService.ts b/node_modules/xterm/src/common/services/DirtyRowService.ts
new file mode 100644
index 0000000..1c43b67
--- /dev/null
+++ b/node_modules/xterm/src/common/services/DirtyRowService.ts
@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) 2019 The xterm.js authors. All rights reserved.
+ * @license MIT
+ */
+
+import { IBufferService, IDirtyRowService } from 'common/services/Services';
+
+export class DirtyRowService implements IDirtyRowService {
+ public serviceBrand: any;
+
+ private _start!: number;
+ private _end!: number;
+
+ public get start(): number { return this._start; }
+ public get end(): number { return this._end; }
+
+ constructor(
+ @IBufferService private readonly _bufferService: IBufferService
+ ) {
+ this.clearRange();
+ }
+
+ public clearRange(): void {
+ this._start = this._bufferService.buffer.y;
+ this._end = this._bufferService.buffer.y;
+ }
+
+ public markDirty(y: number): void {
+ if (y < this._start) {
+ this._start = y;
+ } else if (y > this._end) {
+ this._end = y;
+ }
+ }
+
+ public markRangeDirty(y1: number, y2: number): void {
+ if (y1 > y2) {
+ const temp = y1;
+ y1 = y2;
+ y2 = temp;
+ }
+ if (y1 < this._start) {
+ this._start = y1;
+ }
+ if (y2 > this._end) {
+ this._end = y2;
+ }
+ }
+
+ public markAllDirty(): void {
+ this.markRangeDirty(0, this._bufferService.rows - 1);
+ }
+}
diff --git a/node_modules/xterm/src/common/services/InstantiationService.ts b/node_modules/xterm/src/common/services/InstantiationService.ts
new file mode 100644
index 0000000..8280948
--- /dev/null
+++ b/node_modules/xterm/src/common/services/InstantiationService.ts
@@ -0,0 +1,83 @@
+/**
+ * Copyright (c) 2019 The xterm.js authors. All rights reserved.
+ * @license MIT
+ *
+ * This was heavily inspired from microsoft/vscode's dependency injection system (MIT).
+ */
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import { IInstantiationService, IServiceIdentifier } from 'common/services/Services';
+import { getServiceDependencies } from 'common/services/ServiceRegistry';
+
+export class ServiceCollection {
+
+ private _entries = new Map<IServiceIdentifier<any>, any>();
+
+ constructor(...entries: [IServiceIdentifier<any>, any][]) {
+ for (const [id, service] of entries) {
+ this.set(id, service);
+ }
+ }
+
+ public set<T>(id: IServiceIdentifier<T>, instance: T): T {
+ const result = this._entries.get(id);
+ this._entries.set(id, instance);
+ return result;
+ }
+
+ public forEach(callback: (id: IServiceIdentifier<any>, instance: any) => any): void {
+ this._entries.forEach((value, key) => callback(key, value));
+ }
+
+ public has(id: IServiceIdentifier<any>): boolean {
+ return this._entries.has(id);
+ }
+
+ public get<T>(id: IServiceIdentifier<T>): T | undefined {
+ return this._entries.get(id);
+ }
+}
+
+export class InstantiationService implements IInstantiationService {
+ public serviceBrand: undefined;
+
+ private readonly _services: ServiceCollection = new ServiceCollection();
+
+ constructor() {
+ this._services.set(IInstantiationService, this);
+ }
+
+ public setService<T>(id: IServiceIdentifier<T>, instance: T): void {
+ this._services.set(id, instance);
+ }
+
+ public getService<T>(id: IServiceIdentifier<T>): T | undefined {
+ return this._services.get(id);
+ }
+
+ public createInstance<T>(ctor: any, ...args: any[]): T {
+ const serviceDependencies = getServiceDependencies(ctor).sort((a, b) => a.index - b.index);
+
+ const serviceArgs: any[] = [];
+ for (const dependency of serviceDependencies) {
+ const service = this._services.get(dependency.id);
+ if (!service) {
+ throw new Error(`[createInstance] ${ctor.name} depends on UNKNOWN service ${dependency.id}.`);
+ }
+ serviceArgs.push(service);
+ }
+
+ const firstServiceArgPos = serviceDependencies.length > 0 ? serviceDependencies[0].index : args.length;
+
+ // check for argument mismatches, adjust static args if needed
+ if (args.length !== firstServiceArgPos) {
+ throw new Error(`[createInstance] First service dependency of ${ctor.name} at position ${firstServiceArgPos + 1} conflicts with ${args.length} static arguments`);
+ }
+
+ // now create the instance
+ return new ctor(...[...args, ...serviceArgs]);
+ }
+}
diff --git a/node_modules/xterm/src/common/services/LogService.ts b/node_modules/xterm/src/common/services/LogService.ts
new file mode 100644
index 0000000..d356656
--- /dev/null
+++ b/node_modules/xterm/src/common/services/LogService.ts
@@ -0,0 +1,88 @@
+/**
+ * Copyright (c) 2019 The xterm.js authors. All rights reserved.
+ * @license MIT
+ */
+
+import { ILogService, IOptionsService, LogLevelEnum } from 'common/services/Services';
+
+type LogType = (message?: any, ...optionalParams: any[]) => void;
+
+interface IConsole {
+ log: LogType;
+ error: LogType;
+ info: LogType;
+ trace: LogType;
+ warn: LogType;
+}
+
+// console is available on both node.js and browser contexts but the common
+// module doesn't depend on them so we need to explicitly declare it.
+declare const console: IConsole;
+
+const optionsKeyToLogLevel: { [key: string]: LogLevelEnum } = {
+ debug: LogLevelEnum.DEBUG,
+ info: LogLevelEnum.INFO,
+ warn: LogLevelEnum.WARN,
+ error: LogLevelEnum.ERROR,
+ off: LogLevelEnum.OFF
+};
+
+const LOG_PREFIX = 'xterm.js: ';
+
+export class LogService implements ILogService {
+ public serviceBrand: any;
+
+ public logLevel: LogLevelEnum = LogLevelEnum.OFF;
+
+ constructor(
+ @IOptionsService private readonly _optionsService: IOptionsService
+ ) {
+ this._updateLogLevel();
+ this._optionsService.onOptionChange(key => {
+ if (key === 'logLevel') {
+ this._updateLogLevel();
+ }
+ });
+ }
+
+ private _updateLogLevel(): void {
+ this.logLevel = optionsKeyToLogLevel[this._optionsService.rawOptions.logLevel];
+ }
+
+ private _evalLazyOptionalParams(optionalParams: any[]): void {
+ for (let i = 0; i < optionalParams.length; i++) {
+ if (typeof optionalParams[i] === 'function') {
+ optionalParams[i] = optionalParams[i]();
+ }
+ }
+ }
+
+ private _log(type: LogType, message: string, optionalParams: any[]): void {
+ this._evalLazyOptionalParams(optionalParams);
+ type.call(console, LOG_PREFIX + message, ...optionalParams);
+ }
+
+ public debug(message: string, ...optionalParams: any[]): void {
+ if (this.logLevel <= LogLevelEnum.DEBUG) {
+ this._log(console.log, message, optionalParams);
+ }
+ }
+
+ public info(message: string, ...optionalParams: any[]): void {
+ if (this.logLevel <= LogLevelEnum.INFO) {
+ this._log(console.info, message, optionalParams);
+ }
+ }
+
+ public warn(message: string, ...optionalParams: any[]): void {
+ if (this.logLevel <= LogLevelEnum.WARN) {
+ this._log(console.warn, message, optionalParams);
+ }
+ }
+
+ public error(message: string, ...optionalParams: any[]): void {
+ if (this.logLevel <= LogLevelEnum.ERROR) {
+ this._log(console.error, message, optionalParams);
+ }
+ }
+}
diff --git a/node_modules/xterm/src/common/services/OptionsService.ts b/node_modules/xterm/src/common/services/OptionsService.ts
new file mode 100644
index 0000000..43fe998
--- /dev/null
+++ b/node_modules/xterm/src/common/services/OptionsService.ts
@@ -0,0 +1,177 @@
+/**
+ * Copyright (c) 2019 The xterm.js authors. All rights reserved.
+ * @license MIT
+ */
+
+import { IOptionsService, ITerminalOptions, FontWeight } from 'common/services/Services';
+import { EventEmitter, IEvent } from 'common/EventEmitter';
+import { isMac } from 'common/Platform';
+
+// Source: https://freesound.org/people/altemark/sounds/45759/
+// This sound is released under the Creative Commons Attribution 3.0 Unported
+// (CC BY 3.0) license. It was created by 'altemark'. No modifications have been
+// made, apart from the conversion to base64.
+export const DEFAULT_BELL_SOUND = 'data:audio/mp3;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4LjMyLjEwNAAAAAAAAAAAAAAA//tQxAADB8AhSmxhIIEVCSiJrDCQBTcu3UrAIwUdkRgQbFAZC1CQEwTJ9mjRvBA4UOLD8nKVOWfh+UlK3z/177OXrfOdKl7pyn3Xf//WreyTRUoAWgBgkOAGbZHBgG1OF6zM82DWbZaUmMBptgQhGjsyYqc9ae9XFz280948NMBWInljyzsNRFLPWdnZGWrddDsjK1unuSrVN9jJsK8KuQtQCtMBjCEtImISdNKJOopIpBFpNSMbIHCSRpRR5iakjTiyzLhchUUBwCgyKiweBv/7UsQbg8isVNoMPMjAAAA0gAAABEVFGmgqK////9bP/6XCykxBTUUzLjEwMKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq';
+
+export const DEFAULT_OPTIONS: Readonly<ITerminalOptions> = {
+ cols: 80,
+ rows: 24,
+ cursorBlink: false,
+ cursorStyle: 'block',
+ cursorWidth: 1,
+ customGlyphs: true,
+ bellSound: DEFAULT_BELL_SOUND,
+ bellStyle: 'none',
+ drawBoldTextInBrightColors: true,
+ fastScrollModifier: 'alt',
+ fastScrollSensitivity: 5,
+ fontFamily: 'courier-new, courier, monospace',
+ fontSize: 15,
+ fontWeight: 'normal',
+ fontWeightBold: 'bold',
+ lineHeight: 1.0,
+ linkTooltipHoverDuration: 500,
+ letterSpacing: 0,
+ logLevel: 'info',
+ scrollback: 1000,
+ scrollSensitivity: 1,
+ screenReaderMode: false,
+ macOptionIsMeta: false,
+ macOptionClickForcesSelection: false,
+ minimumContrastRatio: 1,
+ disableStdin: false,
+ allowProposedApi: true,
+ allowTransparency: false,
+ tabStopWidth: 8,
+ theme: {},
+ rightClickSelectsWord: isMac,
+ rendererType: 'canvas',
+ windowOptions: {},
+ windowsMode: false,
+ wordSeparator: ' ()[]{}\',"`',
+ altClickMovesCursor: true,
+ convertEol: false,
+ termName: 'xterm',
+ cancelEvents: false
+};
+
+const FONT_WEIGHT_OPTIONS: Extract<FontWeight, string>[] = ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'];
+
+export class OptionsService implements IOptionsService {
+ public serviceBrand: any;
+
+ public readonly rawOptions: ITerminalOptions;
+ public options: ITerminalOptions;
+
+ private _onOptionChange = new EventEmitter<string>();
+ public get onOptionChange(): IEvent<string> { return this._onOptionChange.event; }
+
+ constructor(options: Partial<ITerminalOptions>) {
+ // set the default value of each option
+ const defaultOptions = { ...DEFAULT_OPTIONS };
+ for (const key in options) {
+ if (key in defaultOptions) {
+ try {
+ const newValue = options[key];
+ defaultOptions[key] = this._sanitizeAndValidateOption(key, newValue);
+ } catch (e) {
+ console.error(e);
+ }
+ }
+ }
+
+ // set up getters and setters for each option
+ this.rawOptions = defaultOptions;
+ this.options = { ... defaultOptions };
+ this._setupOptions();
+ }
+
+ private _setupOptions(): void {
+ const getter = (propName: string): any => {
+ if (!(propName in DEFAULT_OPTIONS)) {
+ throw new Error(`No option with key "${propName}"`);
+ }
+ return this.rawOptions[propName];
+ };
+
+ const setter = (propName: string, value: any): void => {
+ if (!(propName in DEFAULT_OPTIONS)) {
+ throw new Error(`No option with key "${propName}"`);
+ }
+
+ value = this._sanitizeAndValidateOption(propName, value);
+ // Don't fire an option change event if they didn't change
+ if (this.rawOptions[propName] !== value) {
+ this.rawOptions[propName] = value;
+ this._onOptionChange.fire(propName);
+ }
+ };
+
+ for (const propName in this.rawOptions) {
+ const desc = {
+ get: getter.bind(this, propName),
+ set: setter.bind(this, propName)
+ };
+ Object.defineProperty(this.options, propName, desc);
+ }
+ }
+
+ public setOption(key: string, value: any): void {
+ this.options[key] = value;
+ }
+
+ private _sanitizeAndValidateOption(key: string, value: any): any {
+ switch (key) {
+ case 'bellStyle':
+ case 'cursorStyle':
+ case 'rendererType':
+ case 'wordSeparator':
+ if (!value) {
+ value = DEFAULT_OPTIONS[key];
+ }
+ break;
+ case 'fontWeight':
+ case 'fontWeightBold':
+ if (typeof value === 'number' && 1 <= value && value <= 1000) {
+ // already valid numeric value
+ break;
+ }
+ value = FONT_WEIGHT_OPTIONS.includes(value) ? value : DEFAULT_OPTIONS[key];
+ break;
+ case 'cursorWidth':
+ value = Math.floor(value);
+ // Fall through for bounds check
+ case 'lineHeight':
+ case 'tabStopWidth':
+ if (value < 1) {
+ throw new Error(`${key} cannot be less than 1, value: ${value}`);
+ }
+ break;
+ case 'minimumContrastRatio':
+ value = Math.max(1, Math.min(21, Math.round(value * 10) / 10));
+ break;
+ case 'scrollback':
+ value = Math.min(value, 4294967295);
+ if (value < 0) {
+ throw new Error(`${key} cannot be less than 0, value: ${value}`);
+ }
+ break;
+ case 'fastScrollSensitivity':
+ case 'scrollSensitivity':
+ if (value <= 0) {
+ throw new Error(`${key} cannot be less than or equal to 0, value: ${value}`);
+ }
+ case 'rows':
+ case 'cols':
+ if (!value && value !== 0) {
+ throw new Error(`${key} must be numeric, value: ${value}`);
+ }
+ break;
+ }
+ return value;
+ }
+
+ public getOption(key: string): any {
+ return this.options[key];
+ }
+}
diff --git a/node_modules/xterm/src/common/services/ServiceRegistry.ts b/node_modules/xterm/src/common/services/ServiceRegistry.ts
new file mode 100644
index 0000000..6510fb8
--- /dev/null
+++ b/node_modules/xterm/src/common/services/ServiceRegistry.ts
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2019 The xterm.js authors. All rights reserved.
+ * @license MIT
+ *
+ * This was heavily inspired from microsoft/vscode's dependency injection system (MIT).
+ */
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import { IServiceIdentifier } from 'common/services/Services';
+
+const DI_TARGET = 'di$target';
+const DI_DEPENDENCIES = 'di$dependencies';
+
+export const serviceRegistry: Map<string, IServiceIdentifier<any>> = new Map();
+
+export function getServiceDependencies(ctor: any): { id: IServiceIdentifier<any>, index: number, optional: boolean }[] {
+ return ctor[DI_DEPENDENCIES] || [];
+}
+
+export function createDecorator<T>(id: string): IServiceIdentifier<T> {
+ if (serviceRegistry.has(id)) {
+ return serviceRegistry.get(id)!;
+ }
+
+ const decorator: any = function (target: Function, key: string, index: number): any {
+ if (arguments.length !== 3) {
+ throw new Error('@IServiceName-decorator can only be used to decorate a parameter');
+ }
+
+ storeServiceDependency(decorator, target, index);
+ };
+
+ decorator.toString = () => id;
+
+ serviceRegistry.set(id, decorator);
+ return decorator;
+}
+
+function storeServiceDependency(id: Function, target: Function, index: number): void {
+ if ((target as any)[DI_TARGET] === target) {
+ (target as any)[DI_DEPENDENCIES].push({ id, index });
+ } else {
+ (target as any)[DI_DEPENDENCIES] = [{ id, index }];
+ (target as any)[DI_TARGET] = target;
+ }
+}
diff --git a/node_modules/xterm/src/common/services/Services.ts b/node_modules/xterm/src/common/services/Services.ts
new file mode 100644
index 0000000..90dca98
--- /dev/null
+++ b/node_modules/xterm/src/common/services/Services.ts
@@ -0,0 +1,300 @@
+/**
+ * Copyright (c) 2019 The xterm.js authors. All rights reserved.
+ * @license MIT
+ */
+
+import { IEvent } from 'common/EventEmitter';
+import { IBuffer, IBufferSet } from 'common/buffer/Types';
+import { IDecPrivateModes, ICoreMouseEvent, CoreMouseEncoding, ICoreMouseProtocol, CoreMouseEventType, ICharset, IWindowOptions, IModes, IAttributeData, ScrollSource } from 'common/Types';
+import { createDecorator } from 'common/services/ServiceRegistry';
+
+export const IBufferService = createDecorator<IBufferService>('BufferService');
+export interface IBufferService {
+ serviceBrand: undefined;
+
+ readonly cols: number;
+ readonly rows: number;
+ readonly buffer: IBuffer;
+ readonly buffers: IBufferSet;
+ isUserScrolling: boolean;
+ onResize: IEvent<{ cols: number, rows: number }>;
+ onScroll: IEvent<number>;
+ scroll(eraseAttr: IAttributeData, isWrapped?: boolean): void;
+ scrollToBottom(): void;
+ scrollToTop(): void;
+ scrollToLine(line: number): void;
+ scrollLines(disp: number, suppressScrollEvent?: boolean, source?: ScrollSource): void;
+ scrollPages(pageCount: number): void;
+ resize(cols: number, rows: number): void;
+ reset(): void;
+}
+
+export const ICoreMouseService = createDecorator<ICoreMouseService>('CoreMouseService');
+export interface ICoreMouseService {
+ activeProtocol: string;
+ activeEncoding: string;
+ areMouseEventsActive: boolean;
+ addProtocol(name: string, protocol: ICoreMouseProtocol): void;
+ addEncoding(name: string, encoding: CoreMouseEncoding): void;
+ reset(): void;
+
+ /**
+ * Triggers a mouse event to be sent.
+ *
+ * Returns true if the event passed all protocol restrictions and a report
+ * was sent, otherwise false. The return value may be used to decide whether
+ * the default event action in the bowser component should be omitted.
+ *
+ * Note: The method will change values of the given event object
+ * to fullfill protocol and encoding restrictions.
+ */
+ triggerMouseEvent(event: ICoreMouseEvent): boolean;
+
+ /**
+ * Event to announce changes in mouse tracking.
+ */
+ onProtocolChange: IEvent<CoreMouseEventType>;
+
+ /**
+ * Human readable version of mouse events.
+ */
+ explainEvents(events: CoreMouseEventType): { [event: string]: boolean };
+}
+
+export const ICoreService = createDecorator<ICoreService>('CoreService');
+export interface ICoreService {
+ serviceBrand: undefined;
+
+ /**
+ * Initially the cursor will not be visible until the first time the terminal
+ * is focused.
+ */
+ isCursorInitialized: boolean;
+ isCursorHidden: boolean;
+
+ readonly modes: IModes;
+ readonly decPrivateModes: IDecPrivateModes;
+
+ readonly onData: IEvent<string>;
+ readonly onUserInput: IEvent<void>;
+ readonly onBinary: IEvent<string>;
+
+ reset(): void;
+
+ /**
+ * Triggers the onData event in the public API.
+ * @param data The data that is being emitted.
+ * @param wasFromUser Whether the data originated from the user (as opposed to
+ * resulting from parsing incoming data). When true this will also:
+ * - Scroll to the bottom of the buffer.s
+ * - Fire the `onUserInput` event (so selection can be cleared).
+ */
+ triggerDataEvent(data: string, wasUserInput?: boolean): void;
+
+ /**
+ * Triggers the onBinary event in the public API.
+ * @param data The data that is being emitted.
+ */
+ triggerBinaryEvent(data: string): void;
+}
+
+export const ICharsetService = createDecorator<ICharsetService>('CharsetService');
+export interface ICharsetService {
+ serviceBrand: undefined;
+
+ charset: ICharset | undefined;
+ readonly glevel: number;
+
+ 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 | undefined): void;
+}
+
+export const IDirtyRowService = createDecorator<IDirtyRowService>('DirtyRowService');
+export interface IDirtyRowService {
+ serviceBrand: undefined;
+
+ readonly start: number;
+ readonly end: number;
+
+ clearRange(): void;
+ markDirty(y: number): void;
+ markRangeDirty(y1: number, y2: number): void;
+ markAllDirty(): void;
+}
+
+export interface IServiceIdentifier<T> {
+ (...args: any[]): void;
+ type: T;
+}
+
+export interface IBrandedService {
+ serviceBrand: undefined;
+}
+
+type GetLeadingNonServiceArgs<Args> =
+ Args extends [...IBrandedService[]] ? []
+ : Args extends [infer A1, ...IBrandedService[]] ? [A1]
+ : Args extends [infer A1, infer A2, ...IBrandedService[]] ? [A1, A2]
+ : Args extends [infer A1, infer A2, infer A3, ...IBrandedService[]] ? [A1, A2, A3]
+ : Args extends [infer A1, infer A2, infer A3, infer A4, ...IBrandedService[]] ? [A1, A2, A3, A4]
+ : Args extends [infer A1, infer A2, infer A3, infer A4, infer A5, ...IBrandedService[]] ? [A1, A2, A3, A4, A5]
+ : Args extends [infer A1, infer A2, infer A3, infer A4, infer A5, infer A6, ...IBrandedService[]] ? [A1, A2, A3, A4, A5, A6]
+ : Args extends [infer A1, infer A2, infer A3, infer A4, infer A5, infer A6, infer A7, ...IBrandedService[]] ? [A1, A2, A3, A4, A5, A6, A7]
+ : Args extends [infer A1, infer A2, infer A3, infer A4, infer A5, infer A6, infer A7, infer A8, ...IBrandedService[]] ? [A1, A2, A3, A4, A5, A6, A7, A8]
+ : never;
+
+export const IInstantiationService = createDecorator<IInstantiationService>('InstantiationService');
+export interface IInstantiationService {
+ serviceBrand: undefined;
+
+ setService<T>(id: IServiceIdentifier<T>, instance: T): void;
+ getService<T>(id: IServiceIdentifier<T>): T | undefined;
+ createInstance<Ctor extends new (...args: any[]) => any, R extends InstanceType<Ctor>>(t: Ctor, ...args: GetLeadingNonServiceArgs<ConstructorParameters<Ctor>>): R;
+}
+
+export enum LogLevelEnum {
+ DEBUG = 0,
+ INFO = 1,
+ WARN = 2,
+ ERROR = 3,
+ OFF = 4
+}
+
+export const ILogService = createDecorator<ILogService>('LogService');
+export interface ILogService {
+ serviceBrand: undefined;
+
+ logLevel: LogLevelEnum;
+
+ debug(message: any, ...optionalParams: any[]): void;
+ info(message: any, ...optionalParams: any[]): void;
+ warn(message: any, ...optionalParams: any[]): void;
+ error(message: any, ...optionalParams: any[]): void;
+}
+
+export const IOptionsService = createDecorator<IOptionsService>('OptionsService');
+export interface IOptionsService {
+ serviceBrand: undefined;
+
+ /**
+ * Read only access to the raw options object, this is an internal-only fast path for accessing
+ * single options without any validation as we trust TypeScript to enforce correct usage
+ * internally.
+ */
+ readonly rawOptions: Readonly<ITerminalOptions>;
+ readonly options: ITerminalOptions;
+
+ readonly onOptionChange: IEvent<string>;
+
+ setOption<T>(key: string, value: T): void;
+ getOption<T>(key: string): T | undefined;
+}
+
+export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900' | number;
+export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'off';
+
+export type RendererType = 'dom' | 'canvas';
+
+export interface ITerminalOptions {
+ allowProposedApi: boolean;
+ allowTransparency: boolean;
+ altClickMovesCursor: boolean;
+ bellSound: string;
+ bellStyle: 'none' | 'sound' /* | 'visual' | 'both' */;
+ cols: number;
+ convertEol: boolean;
+ cursorBlink: boolean;
+ cursorStyle: 'block' | 'underline' | 'bar';
+ cursorWidth: number;
+ customGlyphs: boolean;
+ disableStdin: boolean;
+ drawBoldTextInBrightColors: boolean;
+ fastScrollModifier: 'alt' | 'ctrl' | 'shift' | undefined;
+ fastScrollSensitivity: number;
+ fontSize: number;
+ fontFamily: string;
+ fontWeight: FontWeight;
+ fontWeightBold: FontWeight;
+ letterSpacing: number;
+ lineHeight: number;
+ linkTooltipHoverDuration: number;
+ logLevel: LogLevel;
+ macOptionIsMeta: boolean;
+ macOptionClickForcesSelection: boolean;
+ minimumContrastRatio: number;
+ rendererType: RendererType;
+ rightClickSelectsWord: boolean;
+ rows: number;
+ screenReaderMode: boolean;
+ scrollback: number;
+ scrollSensitivity: number;
+ tabStopWidth: number;
+ theme: ITheme;
+ windowsMode: boolean;
+ windowOptions: IWindowOptions;
+ wordSeparator: string;
+
+ [key: string]: any;
+ cancelEvents: boolean;
+ termName: string;
+}
+
+export interface ITheme {
+ foreground?: string;
+ background?: string;
+ cursor?: string;
+ cursorAccent?: string;
+ selection?: string;
+ black?: string;
+ red?: string;
+ green?: string;
+ yellow?: string;
+ blue?: string;
+ magenta?: string;
+ cyan?: string;
+ white?: string;
+ brightBlack?: string;
+ brightRed?: string;
+ brightGreen?: string;
+ brightYellow?: string;
+ brightBlue?: string;
+ brightMagenta?: string;
+ brightCyan?: string;
+ brightWhite?: string;
+}
+
+export const IUnicodeService = createDecorator<IUnicodeService>('UnicodeService');
+export interface IUnicodeService {
+ serviceBrand: undefined;
+ /** Register an Unicode version provider. */
+ register(provider: IUnicodeVersionProvider): void;
+ /** Registered Unicode versions. */
+ readonly versions: string[];
+ /** Currently active version. */
+ activeVersion: string;
+ /** Event triggered, when activate version changed. */
+ readonly onChange: IEvent<string>;
+
+ /**
+ * Unicode version dependent
+ */
+ wcwidth(codepoint: number): number;
+ getStringCellWidth(s: string): number;
+}
+
+export interface IUnicodeVersionProvider {
+ readonly version: string;
+ wcwidth(ucs: number): 0 | 1 | 2;
+}
diff --git a/node_modules/xterm/src/common/services/UnicodeService.ts b/node_modules/xterm/src/common/services/UnicodeService.ts
new file mode 100644
index 0000000..e96b757
--- /dev/null
+++ b/node_modules/xterm/src/common/services/UnicodeService.ts
@@ -0,0 +1,82 @@
+/**
+ * Copyright (c) 2019 The xterm.js authors. All rights reserved.
+ * @license MIT
+ */
+import { IUnicodeService, IUnicodeVersionProvider } from 'common/services/Services';
+import { EventEmitter, IEvent } from 'common/EventEmitter';
+import { UnicodeV6 } from 'common/input/UnicodeV6';
+
+
+export class UnicodeService implements IUnicodeService {
+ public serviceBrand: any;
+
+ private _providers: {[key: string]: IUnicodeVersionProvider} = Object.create(null);
+ private _active: string = '';
+ private _activeProvider: IUnicodeVersionProvider;
+ private _onChange = new EventEmitter<string>();
+ public get onChange(): IEvent<string> { return this._onChange.event; }
+
+ constructor() {
+ const defaultProvider = new UnicodeV6();
+ this.register(defaultProvider);
+ this._active = defaultProvider.version;
+ this._activeProvider = defaultProvider;
+ }
+
+ public get versions(): string[] {
+ return Object.keys(this._providers);
+ }
+
+ public get activeVersion(): string {
+ return this._active;
+ }
+
+ public set activeVersion(version: string) {
+ if (!this._providers[version]) {
+ throw new Error(`unknown Unicode version "${version}"`);
+ }
+ this._active = version;
+ this._activeProvider = this._providers[version];
+ this._onChange.fire(version);
+ }
+
+ public register(provider: IUnicodeVersionProvider): void {
+ this._providers[provider.version] = provider;
+ }
+
+ /**
+ * Unicode version dependent interface.
+ */
+ public wcwidth(num: number): number {
+ return this._activeProvider.wcwidth(num);
+ }
+
+ public getStringCellWidth(s: string): number {
+ let result = 0;
+ const length = s.length;
+ for (let i = 0; i < length; ++i) {
+ let code = s.charCodeAt(i);
+ // surrogate pair first
+ if (0xD800 <= code && code <= 0xDBFF) {
+ if (++i >= length) {
+ // this should not happen with strings retrieved from
+ // Buffer.translateToString as it converts from UTF-32
+ // and therefore always should contain the second part
+ // for any other string we still have to handle it somehow:
+ // simply treat the lonely surrogate first as a single char (UCS-2 behavior)
+ return result + this.wcwidth(code);
+ }
+ const second = s.charCodeAt(i);
+ // convert surrogate pair to high codepoint only for valid second part (UTF-16)
+ // otherwise treat them independently (UCS-2 behavior)
+ if (0xDC00 <= second && second <= 0xDFFF) {
+ code = (code - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
+ } else {
+ result += this.wcwidth(second);
+ }
+ }
+ result += this.wcwidth(code);
+ }
+ return result;
+ }
+}