diff --git a/.gitignore b/.gitignore
index c8ff90c23..68b295540 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,7 +8,6 @@ __pycache__/
# Distribution / packaging
.Python
-build/
develop-eggs/
dist/
downloads/
diff --git a/route/static/build/addons/attach/attach.js b/route/static/build/addons/attach/attach.js
new file mode 100755
index 000000000..847cb62e8
--- /dev/null
+++ b/route/static/build/addons/attach/attach.js
@@ -0,0 +1,141 @@
+/**
+ * Copyright (c) 2014 The xterm.js authors. All rights reserved.
+ * @license MIT
+ *
+ * Implements the attach method, that attaches the terminal to a WebSocket stream.
+ */
+
+(function (attach) {
+ if (typeof exports === 'object' && typeof module === 'object') {
+ /*
+ * CommonJS environment
+ */
+ module.exports = attach(require('../../Terminal').Terminal);
+ } else if (typeof define == 'function') {
+ /*
+ * Require.js is available
+ */
+ define(['../../xterm'], attach);
+ } else {
+ /*
+ * Plain browser environment
+ */
+ attach(window.Terminal);
+ }
+})(function (Terminal) {
+ 'use strict';
+
+ var exports = {};
+
+ /**
+ * Attaches the given terminal to the given socket.
+ *
+ * @param {Terminal} term - The terminal to be attached to the given socket.
+ * @param {WebSocket} socket - The socket to attach the current terminal.
+ * @param {boolean} bidirectional - Whether the terminal should send data
+ * to the socket as well.
+ * @param {boolean} buffered - Whether the rendering of incoming data
+ * should happen instantly or at a maximum
+ * frequency of 1 rendering per 10ms.
+ */
+ exports.attach = function (term, socket, bidirectional, buffered) {
+ bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional;
+ term.socket = socket;
+
+ term._flushBuffer = function () {
+ term.write(term._attachSocketBuffer);
+ term._attachSocketBuffer = null;
+ };
+
+ term._pushToBuffer = function (data) {
+ if (term._attachSocketBuffer) {
+ term._attachSocketBuffer += data;
+ } else {
+ term._attachSocketBuffer = data;
+ setTimeout(term._flushBuffer, 10);
+ }
+ };
+
+ var myTextDecoder;
+
+ term._getMessage = function (ev) {
+ var str;
+ if (typeof ev.data === "object") {
+ if (ev.data instanceof ArrayBuffer) {
+ if (!myTextDecoder) {
+ myTextDecoder = new TextDecoder();
+ }
+
+ str = myTextDecoder.decode( ev.data );
+ }
+ else {
+ throw "TODO: handle Blob?";
+ }
+ }
+
+ if (buffered) {
+ term._pushToBuffer(str || ev.data);
+ } else {
+ term.write(str || ev.data);
+ }
+ };
+
+ term._sendData = function (data) {
+ socket.send(data);
+ };
+
+ socket.addEventListener('message', term._getMessage);
+
+ if (bidirectional) {
+ term.on('data', term._sendData);
+ }
+
+ socket.addEventListener('close', term.detach.bind(term, socket));
+ socket.addEventListener('error', term.detach.bind(term, socket));
+ };
+
+ /**
+ * Detaches the given terminal from the given socket
+ *
+ * @param {Terminal} term - The terminal to be detached from the given socket.
+ * @param {WebSocket} socket - The socket from which to detach the current
+ * terminal.
+ */
+ exports.detach = function (term, socket) {
+ term.off('data', term._sendData);
+
+ socket = (typeof socket == 'undefined') ? term.socket : socket;
+
+ if (socket) {
+ socket.removeEventListener('message', term._getMessage);
+ }
+
+ delete term.socket;
+ };
+
+ /**
+ * Attaches the current terminal to the given socket
+ *
+ * @param {WebSocket} socket - The socket to attach the current terminal.
+ * @param {boolean} bidirectional - Whether the terminal should send data
+ * to the socket as well.
+ * @param {boolean} buffered - Whether the rendering of incoming data
+ * should happen instantly or at a maximum
+ * frequency of 1 rendering per 10ms.
+ */
+ Terminal.prototype.attach = function (socket, bidirectional, buffered) {
+ return exports.attach(this, socket, bidirectional, buffered);
+ };
+
+ /**
+ * Detaches the current terminal from the given socket.
+ *
+ * @param {WebSocket} socket - The socket from which to detach the current
+ * terminal.
+ */
+ Terminal.prototype.detach = function (socket) {
+ return exports.detach(this, socket);
+ };
+
+ return exports;
+});
diff --git a/route/static/build/addons/attach/index.html b/route/static/build/addons/attach/index.html
new file mode 100755
index 000000000..4a41fbde2
--- /dev/null
+++ b/route/static/build/addons/attach/index.html
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ xterm.js: socket attach
+
+
+ Attach the terminal to a WebSocket terminal stream with ease. Perfect for attaching to your
+ Docker containers.
+
+
+ Socket information
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/route/static/build/addons/attach/package.json b/route/static/build/addons/attach/package.json
new file mode 100755
index 000000000..e8f6b2ca2
--- /dev/null
+++ b/route/static/build/addons/attach/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "xterm.attach",
+ "main": "attach.js",
+ "private": true
+}
diff --git a/route/static/build/addons/fit/fit.js b/route/static/build/addons/fit/fit.js
new file mode 100755
index 000000000..01e0c2f21
--- /dev/null
+++ b/route/static/build/addons/fit/fit.js
@@ -0,0 +1,81 @@
+/**
+ * Copyright (c) 2014 The xterm.js authors. All rights reserved.
+ * @license MIT
+ *
+ * Fit terminal columns and rows to the dimensions of its DOM element.
+ *
+ * ## Approach
+ *
+ * Rows: Truncate the division of the terminal parent element height by the
+ * terminal row height.
+ * Columns: Truncate the division of the terminal parent element width by the
+ * terminal character width (apply display: inline at the terminal
+ * row and truncate its width with the current number of columns).
+ */
+
+(function (fit) {
+ if (typeof exports === 'object' && typeof module === 'object') {
+ /*
+ * CommonJS environment
+ */
+ module.exports = fit(require('../../Terminal').Terminal);
+ } else if (typeof define == 'function') {
+ /*
+ * Require.js is available
+ */
+ define(['../../xterm'], fit);
+ } else {
+ /*
+ * Plain browser environment
+ */
+ fit(window.Terminal);
+ }
+})(function (Terminal) {
+ var exports = {};
+
+ exports.proposeGeometry = function (term) {
+ if (!term.element.parentElement) {
+ return null;
+ }
+ var parentElementStyle = window.getComputedStyle(term.element.parentElement);
+ var parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height'));
+ var parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')) - 17);
+ var elementStyle = window.getComputedStyle(term.element);
+ var elementPaddingVer = parseInt(elementStyle.getPropertyValue('padding-top')) + parseInt(elementStyle.getPropertyValue('padding-bottom'));
+ var elementPaddingHor = parseInt(elementStyle.getPropertyValue('padding-right')) + parseInt(elementStyle.getPropertyValue('padding-left'));
+ var availableHeight = parentElementHeight - elementPaddingVer;
+ var availableWidth = parentElementWidth - elementPaddingHor;
+ var geometry = {
+ cols: Math.floor(availableWidth / term.charMeasure.width),
+ rows: Math.floor(availableHeight / Math.floor(term.charMeasure.height * term.getOption('lineHeight')))
+ };
+
+ return geometry;
+ };
+
+ exports.fit = function (term) {
+ // Wrap fit in a setTimeout as charMeasure needs time to get initialized
+ // after calling Terminal.open
+ setTimeout(function () {
+ var geometry = exports.proposeGeometry(term);
+
+ if (geometry) {
+ // Force a full render
+ if (term.rows !== geometry.rows || term.cols !== geometry.cols) {
+ term.renderer.clear();
+ term.resize(geometry.cols, geometry.rows);
+ }
+ }
+ }, 0);
+ };
+
+ Terminal.prototype.proposeGeometry = function () {
+ return exports.proposeGeometry(this);
+ };
+
+ Terminal.prototype.fit = function () {
+ return exports.fit(this);
+ };
+
+ return exports;
+});
diff --git a/route/static/build/addons/fit/package.json b/route/static/build/addons/fit/package.json
new file mode 100755
index 000000000..aec1bbd6d
--- /dev/null
+++ b/route/static/build/addons/fit/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "xterm.fit",
+ "main": "fit.js",
+ "private": true
+}
diff --git a/route/static/build/addons/fullscreen/fullscreen.css b/route/static/build/addons/fullscreen/fullscreen.css
new file mode 100755
index 000000000..37229932f
--- /dev/null
+++ b/route/static/build/addons/fullscreen/fullscreen.css
@@ -0,0 +1,10 @@
+.xterm.fullscreen {
+ position: fixed;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ width: auto;
+ height: auto;
+ z-index: 255;
+}
diff --git a/route/static/build/addons/fullscreen/fullscreen.js b/route/static/build/addons/fullscreen/fullscreen.js
new file mode 100755
index 000000000..f1dc56a26
--- /dev/null
+++ b/route/static/build/addons/fullscreen/fullscreen.js
@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) 2014 The xterm.js authors. All rights reserved.
+ * @license MIT
+ */
+
+(function (fullscreen) {
+ if (typeof exports === 'object' && typeof module === 'object') {
+ /*
+ * CommonJS environment
+ */
+ module.exports = fullscreen(require('../../Terminal').Terminal);
+ } else if (typeof define == 'function') {
+ /*
+ * Require.js is available
+ */
+ define(['../../xterm'], fullscreen);
+ } else {
+ /*
+ * Plain browser environment
+ */
+ fullscreen(window.Terminal);
+ }
+})(function (Terminal) {
+ var exports = {};
+
+ /**
+ * Toggle the given terminal's fullscreen mode.
+ * @param {Terminal} term - The terminal to toggle full screen mode
+ * @param {boolean} fullscreen - Toggle fullscreen on (true) or off (false)
+ */
+ exports.toggleFullScreen = function (term, fullscreen) {
+ var fn;
+
+ if (typeof fullscreen == 'undefined') {
+ fn = (term.element.classList.contains('fullscreen')) ? 'remove' : 'add';
+ } else if (!fullscreen) {
+ fn = 'remove';
+ } else {
+ fn = 'add';
+ }
+
+ term.element.classList[fn]('fullscreen');
+ };
+
+ Terminal.prototype.toggleFullscreen = function (fullscreen) {
+ exports.toggleFullScreen(this, fullscreen);
+ };
+
+ return exports;
+});
diff --git a/route/static/build/addons/fullscreen/package.json b/route/static/build/addons/fullscreen/package.json
new file mode 100755
index 000000000..9c359a052
--- /dev/null
+++ b/route/static/build/addons/fullscreen/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "xterm.fullscreen",
+ "main": "fullscreen.js",
+ "private": true
+}
diff --git a/route/static/build/addons/search/search.js b/route/static/build/addons/search/search.js
new file mode 100755
index 000000000..088e28347
--- /dev/null
+++ b/route/static/build/addons/search/search.js
@@ -0,0 +1,116 @@
+(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 0; y--) {
+ result = this._findInLine(term, y);
+ if (result) {
+ break;
+ }
+ }
+ if (!result) {
+ for (var y = this._terminal.buffer.ybase + this._terminal.rows - 1; y > startRow; y--) {
+ result = this._findInLine(term, y);
+ if (result) {
+ break;
+ }
+ }
+ }
+ return this._selectResult(result);
+ };
+ SearchHelper.prototype._findInLine = function (term, y) {
+ var lowerStringLine = this._terminal.buffer.translateBufferLineToString(y, true).toLowerCase();
+ var lowerTerm = term.toLowerCase();
+ var searchIndex = lowerStringLine.indexOf(lowerTerm);
+ if (searchIndex >= 0) {
+ return {
+ term: term,
+ col: searchIndex,
+ row: y
+ };
+ }
+ };
+ SearchHelper.prototype._selectResult = function (result) {
+ if (!result) {
+ return false;
+ }
+ this._terminal.selectionManager.setSelection(result.col, result.row, result.term.length);
+ this._terminal.scrollLines(result.row - this._terminal.buffer.ydisp, false);
+ return true;
+ };
+ return SearchHelper;
+}());
+exports.SearchHelper = SearchHelper;
+
+
+
+},{}],2:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var SearchHelper_1 = require("./SearchHelper");
+(function (addon) {
+ if (typeof window !== 'undefined' && 'Terminal' in window) {
+ addon(window.Terminal);
+ }
+ else if (typeof exports === 'object' && typeof module === 'object') {
+ module.exports = addon(require('../../Terminal').Terminal);
+ }
+ else if (typeof define === 'function') {
+ define(['../../xterm'], addon);
+ }
+})(function (Terminal) {
+ Terminal.prototype.findNext = function (term) {
+ if (!this._searchHelper) {
+ this.searchHelper = new SearchHelper_1.SearchHelper(this);
+ }
+ return this.searchHelper.findNext(term);
+ };
+ Terminal.prototype.findPrevious = function (term) {
+ if (!this._searchHelper) {
+ this.searchHelper = new SearchHelper_1.SearchHelper(this);
+ }
+ return this.searchHelper.findPrevious(term);
+ };
+});
+
+
+
+},{"../../Terminal":undefined,"./SearchHelper":1}]},{},[2])
+//# sourceMappingURL=search.js.map
diff --git a/route/static/build/addons/search/search.js.map b/route/static/build/addons/search/search.js.map
new file mode 100755
index 000000000..baa06e886
--- /dev/null
+++ b/route/static/build/addons/search/search.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"search.js","sources":["../../../src/addons/search/search.ts","../../../src/addons/search/SearchHelper.ts","../../../node_modules/browser-pack/_prelude.js"],"sourcesContent":["/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { SearchHelper } from './SearchHelper';\n\ndeclare var exports: any;\ndeclare var module: any;\ndeclare var define: any;\ndeclare var require: any;\ndeclare var window: any;\n\n(function (addon) {\n if (typeof window !== 'undefined' && 'Terminal' in window) {\n /**\n * Plain browser environment\n */\n addon(window.Terminal);\n } else if (typeof exports === 'object' && typeof module === 'object') {\n /**\n * CommonJS environment\n */\n module.exports = addon(require('../../Terminal').Terminal);\n } else if (typeof define === 'function') {\n /**\n * Require.js is available\n */\n define(['../../xterm'], addon);\n }\n})((Terminal: any) => {\n /**\n * Find the next instance of the term, then scroll to and select it. If it\n * doesn't exist, do nothing.\n * @param term Tne search term.\n * @return Whether a result was found.\n */\n Terminal.prototype.findNext = function(term: string): boolean {\n if (!this._searchHelper) {\n this.searchHelper = new SearchHelper(this);\n }\n return (this.searchHelper).findNext(term);\n };\n\n /**\n * Find the previous instance of the term, then scroll to and select it. If it\n * doesn't exist, do nothing.\n * @param term Tne search term.\n * @return Whether a result was found.\n */\n Terminal.prototype.findPrevious = function(term: string): boolean {\n if (!this._searchHelper) {\n this.searchHelper = new SearchHelper(this);\n }\n return (this.searchHelper).findPrevious(term);\n };\n});\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\n// import { ITerminal } from '../../Interfaces';\n// import { translateBufferLineToString } from '../../utils/BufferLine';\n\ninterface ISearchResult {\n term: string;\n col: number;\n row: number;\n}\n\n/**\n * A class that knows how to search the terminal and how to display the results.\n */\nexport class SearchHelper {\n constructor(private _terminal: any) {\n // TODO: Search for multiple instances on 1 line\n // TODO: Don't use the actual selection, instead use a \"find selection\" so multiple instances can be highlighted\n // TODO: Highlight other instances in the viewport\n // TODO: Support regex, case sensitivity, etc.\n }\n\n /**\n * Find the next instance of the term, then scroll to and select it. If it\n * doesn't exist, do nothing.\n * @param term Tne search term.\n * @return Whether a result was found.\n */\n public findNext(term: string): boolean {\n if (!term || term.length === 0) {\n return false;\n }\n\n let result: ISearchResult;\n\n let startRow = this._terminal.buffer.ydisp;\n if (this._terminal.selectionManager.selectionEnd) {\n // Start from the selection end if there is a selection\n startRow = this._terminal.selectionManager.selectionEnd[1];\n }\n\n // Search from ydisp + 1 to end\n for (let y = startRow + 1; y < this._terminal.buffer.ybase + this._terminal.rows; y++) {\n result = this._findInLine(term, y);\n if (result) {\n break;\n }\n }\n\n // Search from the top to the current ydisp\n if (!result) {\n for (let y = 0; y < startRow; y++) {\n result = this._findInLine(term, y);\n if (result) {\n break;\n }\n }\n }\n\n // Set selection and scroll if a result was found\n return this._selectResult(result);\n }\n\n /**\n * Find the previous instance of the term, then scroll to and select it. If it\n * doesn't exist, do nothing.\n * @param term Tne search term.\n * @return Whether a result was found.\n */\n public findPrevious(term: string): boolean {\n if (!term || term.length === 0) {\n return false;\n }\n\n let result: ISearchResult;\n\n let startRow = this._terminal.buffer.ydisp;\n if (this._terminal.selectionManager.selectionStart) {\n // Start from the selection end if there is a selection\n startRow = this._terminal.selectionManager.selectionStart[1];\n }\n\n // Search from ydisp + 1 to end\n for (let y = startRow - 1; y >= 0; y--) {\n result = this._findInLine(term, y);\n if (result) {\n break;\n }\n }\n\n // Search from the top to the current ydisp\n if (!result) {\n for (let y = this._terminal.buffer.ybase + this._terminal.rows - 1; y > startRow; y--) {\n result = this._findInLine(term, y);\n if (result) {\n break;\n }\n }\n }\n\n // Set selection and scroll if a result was found\n return this._selectResult(result);\n }\n\n /**\n * Searches a line for a search term.\n * @param term Tne search term.\n * @param y The line to search.\n * @return The search result if it was found.\n */\n private _findInLine(term: string, y: number): ISearchResult {\n const lowerStringLine = this._terminal.buffer.translateBufferLineToString(y, true).toLowerCase();\n const lowerTerm = term.toLowerCase();\n const searchIndex = lowerStringLine.indexOf(lowerTerm);\n if (searchIndex >= 0) {\n return {\n term,\n col: searchIndex,\n row: y\n };\n }\n }\n\n /**\n * Selects and scrolls to a result.\n * @param result The result to select.\n * @return Whethera result was selected.\n */\n private _selectResult(result: ISearchResult): boolean {\n if (!result) {\n return false;\n }\n this._terminal.selectionManager.setSelection(result.col, result.row, result.term.length);\n this._terminal.scrollLines(result.row - this._terminal.buffer.ydisp, false);\n return true;\n }\n}\n",null],"names":[],"mappings":"AEAA;;;ADiBA;AACA;AAAA;AAKA;AAQA;AACA;AACA;AACA;AAEA;AAEA;AACA;AAEA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AAQA;AACA;AACA;AACA;AAEA;AAEA;AACA;AAEA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AA1Ha;;;;;;;ADZb;AAQA;AACA;AAIA;AACA;AAAA;AAIA;AACA;AAAA;AAIA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;;;"}
\ No newline at end of file
diff --git a/route/static/build/addons/terminado/package.json b/route/static/build/addons/terminado/package.json
new file mode 100755
index 000000000..9af1851bc
--- /dev/null
+++ b/route/static/build/addons/terminado/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "xterm.terminado",
+ "main": "terminado.js",
+ "private": true
+}
diff --git a/route/static/build/addons/terminado/terminado.js b/route/static/build/addons/terminado/terminado.js
new file mode 100755
index 000000000..702351b9c
--- /dev/null
+++ b/route/static/build/addons/terminado/terminado.js
@@ -0,0 +1,134 @@
+/**
+ * Copyright (c) 2016 The xterm.js authors. All rights reserved.
+ * @license MIT
+ *
+ * This module provides methods for attaching a terminal to a terminado
+ * WebSocket stream.
+ */
+
+(function (attach) {
+ if (typeof exports === 'object' && typeof module === 'object') {
+ /*
+ * CommonJS environment
+ */
+ module.exports = attach(require('../../Terminal').Terminal);
+ } else if (typeof define == 'function') {
+ /*
+ * Require.js is available
+ */
+ define(['../../xterm'], attach);
+ } else {
+ /*
+ * Plain browser environment
+ */
+ attach(window.Terminal);
+ }
+})(function (Terminal) {
+ 'use strict';
+
+ var exports = {};
+
+ /**
+ * Attaches the given terminal to the given socket.
+ *
+ * @param {Terminal} term - The terminal to be attached to the given socket.
+ * @param {WebSocket} socket - The socket to attach the current terminal.
+ * @param {boolean} bidirectional - Whether the terminal should send data
+ * to the socket as well.
+ * @param {boolean} buffered - Whether the rendering of incoming data
+ * should happen instantly or at a maximum
+ * frequency of 1 rendering per 10ms.
+ */
+ exports.terminadoAttach = function (term, socket, bidirectional, buffered) {
+ bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional;
+ term.socket = socket;
+
+ term._flushBuffer = function () {
+ term.write(term._attachSocketBuffer);
+ term._attachSocketBuffer = null;
+ };
+
+ term._pushToBuffer = function (data) {
+ if (term._attachSocketBuffer) {
+ term._attachSocketBuffer += data;
+ } else {
+ term._attachSocketBuffer = data;
+ setTimeout(term._flushBuffer, 10);
+ }
+ };
+
+ term._getMessage = function (ev) {
+ var data = JSON.parse(ev.data)
+ if( data[0] == "stdout" ) {
+ if (buffered) {
+ term._pushToBuffer(data[1]);
+ } else {
+ term.write(data[1]);
+ }
+ }
+ };
+
+ term._sendData = function (data) {
+ socket.send(JSON.stringify(['stdin', data]));
+ };
+
+ term._setSize = function (size) {
+ socket.send(JSON.stringify(['set_size', size.rows, size.cols]));
+ };
+
+ socket.addEventListener('message', term._getMessage);
+
+ if (bidirectional) {
+ term.on('data', term._sendData);
+ }
+ term.on('resize', term._setSize);
+
+ socket.addEventListener('close', term.terminadoDetach.bind(term, socket));
+ socket.addEventListener('error', term.terminadoDetach.bind(term, socket));
+ };
+
+ /**
+ * Detaches the given terminal from the given socket
+ *
+ * @param {Xterm} term - The terminal to be detached from the given socket.
+ * @param {WebSocket} socket - The socket from which to detach the current
+ * terminal.
+ */
+ exports.terminadoDetach = function (term, socket) {
+ term.off('data', term._sendData);
+
+ socket = (typeof socket == 'undefined') ? term.socket : socket;
+
+ if (socket) {
+ socket.removeEventListener('message', term._getMessage);
+ }
+
+ delete term.socket;
+ };
+
+ /**
+ * Attaches the current terminal to the given socket
+ *
+ * @param {WebSocket} socket - The socket to attach the current terminal.
+ * @param {boolean} bidirectional - Whether the terminal should send data
+ * to the socket as well.
+ * @param {boolean} buffered - Whether the rendering of incoming data
+ * should happen instantly or at a maximum
+ * frequency of 1 rendering per 10ms.
+ */
+ Terminal.prototype.terminadoAttach = function (socket, bidirectional, buffered) {
+ return exports.terminadoAttach(this, socket, bidirectional, buffered);
+ };
+
+ /**
+ * Detaches the current terminal from the given socket.
+ *
+ * @param {WebSocket} socket - The socket from which to detach the current
+ * terminal.
+ */
+ Terminal.prototype.terminadoDetach = function (socket) {
+ return exports.terminadoDetach(this, socket);
+ };
+
+ return exports;
+});
diff --git a/route/static/build/addons/winptyCompat/winptyCompat.js b/route/static/build/addons/winptyCompat/winptyCompat.js
new file mode 100755
index 000000000..89c0d8795
--- /dev/null
+++ b/route/static/build/addons/winptyCompat/winptyCompat.js
@@ -0,0 +1,29 @@
+(function (addon) {
+ if (typeof window !== 'undefined' && 'Terminal' in window) {
+ addon(window.Terminal);
+ }
+ else if (typeof exports === 'object' && typeof module === 'object') {
+ module.exports = addon(require('../../Terminal').Terminal);
+ }
+ else if (typeof define === 'function') {
+ define(['../../xterm'], addon);
+ }
+})(function (Terminal) {
+ Terminal.prototype.winptyCompatInit = function () {
+ var _this = this;
+ var isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].indexOf(navigator.platform) >= 0;
+ if (!isWindows) {
+ return;
+ }
+ this.on('lineFeed', function () {
+ var line = _this.buffer.lines.get(_this.buffer.ybase + _this.buffer.y - 1);
+ var lastChar = line[_this.cols - 1];
+ if (lastChar[3] !== 32) {
+ var nextLine = _this.buffer.lines.get(_this.buffer.ybase + _this.buffer.y);
+ nextLine.isWrapped = true;
+ }
+ });
+ };
+});
+
+//# sourceMappingURL=winptyCompat.js.map
diff --git a/route/static/build/addons/winptyCompat/winptyCompat.js.map b/route/static/build/addons/winptyCompat/winptyCompat.js.map
new file mode 100755
index 000000000..826e69714
--- /dev/null
+++ b/route/static/build/addons/winptyCompat/winptyCompat.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../../../src/addons/winptyCompat/winptyCompat.ts"],"names":[],"mappings":"AAQA,CAAC,UAAU,KAAK;IACd,EAAE,CAAC,CAAC,OAAO,MAAM,KAAK,WAAW,IAAI,UAAU,IAAI,MAAM,CAAC,CAAC,CAAC;QAI1D,KAAK,CAAO,MAAO,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;IAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC;QAIrE,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC7D,CAAC;IAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC;QAIxC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC;AACH,CAAC,CAAC,CAAC,UAAC,QAAa;IACf,QAAQ,CAAC,SAAS,CAAC,gBAAgB,GAAG;QAAA,iBAyBrC;QAvBC,IAAM,SAAS,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC1F,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;YACf,MAAM,CAAC;QACT,CAAC;QAYD,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE;YAClB,IAAM,IAAI,GAAG,KAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,KAAI,CAAC,MAAM,CAAC,KAAK,GAAG,KAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC1E,IAAM,QAAQ,GAAG,IAAI,CAAC,KAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;YACrC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,EAAY,CAAC,CAAC,CAAC;gBACjC,IAAM,QAAQ,GAAG,KAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,KAAI,CAAC,MAAM,CAAC,KAAK,GAAG,KAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;gBACpE,QAAS,CAAC,SAAS,GAAG,IAAI,CAAC;YACnC,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC","file":"winptyCompat.js","sourceRoot":"."}
\ No newline at end of file
diff --git a/route/static/build/addons/zmodem/demo/app.js b/route/static/build/addons/zmodem/demo/app.js
new file mode 100755
index 000000000..13a40a6d2
--- /dev/null
+++ b/route/static/build/addons/zmodem/demo/app.js
@@ -0,0 +1,87 @@
+var express = require('express');
+var app = express();
+var expressWs = require('express-ws')(app);
+var os = require('os');
+var pty = require('node-pty');
+
+var terminals = {},
+ logs = {};
+
+app.use('/build', express.static(__dirname + '/../../../../build'));
+app.use('/demo', express.static(__dirname + '/../../../../demo'));
+app.use('/zmodemjs', express.static(__dirname + '/../../../../node_modules/zmodem.js/dist'));
+
+app.get('/', function(req, res){
+ res.sendFile(__dirname + '/index.html');
+});
+
+app.get('/style.css', function(req, res){
+ res.sendFile(__dirname + '/style.css');
+});
+
+app.get('/main.js', function(req, res){
+ res.sendFile(__dirname + '/main.js');
+});
+
+app.post('/terminals', function (req, res) {
+ var cols = parseInt(req.query.cols),
+ rows = parseInt(req.query.rows),
+ term = pty.spawn(process.platform === 'win32' ? 'cmd.exe' : 'bash', [], {
+ encoding: null,
+ name: 'xterm-color',
+ cols: cols || 80,
+ rows: rows || 24,
+ cwd: process.env.PWD,
+ env: process.env
+ });
+
+ console.log('Created terminal with PID: ' + term.pid);
+ terminals[term.pid] = term;
+ logs[term.pid] = '';
+ term.on('data', function(data) {
+ logs[term.pid] += data;
+ });
+ res.send(term.pid.toString());
+ res.end();
+});
+
+app.post('/terminals/:pid/size', function (req, res) {
+ var pid = parseInt(req.params.pid),
+ cols = parseInt(req.query.cols),
+ rows = parseInt(req.query.rows),
+ term = terminals[pid];
+
+ term.resize(cols, rows);
+ console.log('Resized terminal ' + pid + ' to ' + cols + ' cols and ' + rows + ' rows.');
+ res.end();
+});
+
+app.ws('/terminals/:pid', function (ws, req) {
+ var term = terminals[parseInt(req.params.pid)];
+ console.log('Connected to terminal ' + term.pid);
+ ws.send(logs[term.pid]);
+
+ term.on('data', function(data) {
+ try {
+ ws.send(data);
+ } catch (ex) {
+ // The WebSocket is not open, ignore
+ }
+ });
+ ws.on('message', function(msg) {
+ term.write(msg);
+ });
+ ws.on('close', function () {
+ term.kill();
+ console.log('Closed terminal ' + term.pid);
+ // Clean things up
+ delete terminals[term.pid];
+ delete logs[term.pid];
+ });
+});
+
+var port = process.env.PORT || 3000,
+ host = os.platform() === 'win32' ? '127.0.0.1' : '0.0.0.0';
+
+console.log('App listening to http://' + host + ':' + port);
+app.listen(port, host);
diff --git a/route/static/build/addons/zmodem/demo/index.html b/route/static/build/addons/zmodem/demo/index.html
new file mode 100755
index 000000000..0b38cf4f1
--- /dev/null
+++ b/route/static/build/addons/zmodem/demo/index.html
@@ -0,0 +1,128 @@
+
+
+
+ xterm.js demo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ xterm.js: xterm, in the browser
+
+
+
+
+
+
+
+
+
+
Name:
+
Size:
+
Last modified:
+
Mode:
+
+
Conversion:
+
Management:
+
Transport:
+
Sparse?
+
+
Files remaining in batch:
+
Bytes remaining in batch:
+
+
+
+
+
+
+
+
+
+
Options
+
+ cursorBlink
+
+
+ Accept all ZMODEM prompts*
+
+
+
+ cursorStyle
+
+ block
+ underline
+ bar
+
+
+
+
+
+ bellStyle
+
+ none
+ sound
+ visual
+ both
+
+
+
+
+ scrollback
+
+
+ tabStopWidth
+
+
+
+ Attention: The demo is a barebones implementation and is designed for xterm.js evaluation purposes only. Exposing the demo to the public as is would introduce security risks for the host.
+ * ZMODEM file transfers are supported via an addon. To try it out, install lrzsz
onto the remote peer, then run rz
to send from your browser or sz <file>
to send from the remote peer.
+
+
+
diff --git a/route/static/build/addons/zmodem/demo/main.js b/route/static/build/addons/zmodem/demo/main.js
new file mode 100755
index 000000000..aca441355
--- /dev/null
+++ b/route/static/build/addons/zmodem/demo/main.js
@@ -0,0 +1,383 @@
+"use strict";
+
+var term,
+ protocol,
+ socketURL,
+ socket,
+ pid;
+
+var terminalContainer = document.getElementById('terminal-container'),
+ actionElements = {
+ findNext: document.querySelector('#find-next'),
+ findPrevious: document.querySelector('#find-previous')
+ },
+ optionElements = {
+ cursorBlink: document.querySelector('#option-cursor-blink'),
+ cursorStyle: document.querySelector('#option-cursor-style'),
+ scrollback: document.querySelector('#option-scrollback'),
+ tabstopwidth: document.querySelector('#option-tabstopwidth'),
+ bellStyle: document.querySelector('#option-bell-style')
+ },
+ colsElement = document.getElementById('cols'),
+ rowsElement = document.getElementById('rows');
+
+function setTerminalSize() {
+ var cols = parseInt(colsElement.value, 10);
+ var rows = parseInt(rowsElement.value, 10);
+ var viewportElement = document.querySelector('.xterm-viewport');
+ var scrollBarWidth = viewportElement.offsetWidth - viewportElement.clientWidth;
+ var width = (cols * term.charMeasure.width + 20 /*room for scrollbar*/).toString() + 'px';
+ var height = (rows * term.charMeasure.height).toString() + 'px';
+
+ terminalContainer.style.width = width;
+ terminalContainer.style.height = height;
+ term.resize(cols, rows);
+}
+
+colsElement.addEventListener('change', setTerminalSize);
+rowsElement.addEventListener('change', setTerminalSize);
+
+actionElements.findNext.addEventListener('keypress', function (e) {
+ if (e.key === "Enter") {
+ e.preventDefault();
+ term.findNext(actionElements.findNext.value);
+ }
+});
+actionElements.findPrevious.addEventListener('keypress', function (e) {
+ if (e.key === "Enter") {
+ e.preventDefault();
+ term.findPrevious(actionElements.findPrevious.value);
+ }
+});
+
+optionElements.cursorBlink.addEventListener('change', function () {
+ term.setOption('cursorBlink', optionElements.cursorBlink.checked);
+});
+optionElements.cursorStyle.addEventListener('change', function () {
+ term.setOption('cursorStyle', optionElements.cursorStyle.value);
+});
+optionElements.bellStyle.addEventListener('change', function () {
+ term.setOption('bellStyle', optionElements.bellStyle.value);
+});
+optionElements.scrollback.addEventListener('change', function () {
+ term.setOption('scrollback', parseInt(optionElements.scrollback.value, 10));
+});
+optionElements.tabstopwidth.addEventListener('change', function () {
+ term.setOption('tabStopWidth', parseInt(optionElements.tabstopwidth.value, 10));
+});
+
+createTerminal();
+
+function createTerminal() {
+ // Clean terminal
+ while (terminalContainer.children.length) {
+ terminalContainer.removeChild(terminalContainer.children[0]);
+ }
+ term = new Terminal({
+ cursorBlink: optionElements.cursorBlink.checked,
+ scrollback: parseInt(optionElements.scrollback.value, 10),
+ tabStopWidth: parseInt(optionElements.tabstopwidth.value, 10)
+ });
+ term.on('resize', function (size) {
+ if (!pid) {
+ return;
+ }
+ var cols = size.cols,
+ rows = size.rows,
+ url = '/terminals/' + pid + '/size?cols=' + cols + '&rows=' + rows;
+
+ fetch(url, {method: 'POST'});
+ });
+ protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://';
+ socketURL = protocol + location.hostname + ((location.port) ? (':' + location.port) : '') + '/terminals/';
+
+ term.open(terminalContainer);
+ term.fit();
+
+ // fit is called within a setTimeout, cols and rows need this.
+ setTimeout(function () {
+ colsElement.value = term.cols;
+ rowsElement.value = term.rows;
+
+ // Set terminal size again to set the specific dimensions on the demo
+ setTerminalSize();
+
+ fetch('/terminals?cols=' + term.cols + '&rows=' + term.rows, {method: 'POST'}).then(function (res) {
+
+ res.text().then(function (pid) {
+ window.pid = pid;
+ socketURL += pid;
+ socket = new WebSocket(socketURL);
+ socket.onopen = runRealTerminal;
+ socket.onclose = runFakeTerminal;
+ socket.onerror = runFakeTerminal;
+
+ term.zmodemAttach(socket, {
+ noTerminalWriteOutsideSession: true,
+ } );
+
+ term.on("zmodemRetract", () => {
+ start_form.style.display = "none";
+ start_form.onsubmit = null;
+ });
+
+ term.on("zmodemDetect", (detection) => {
+ function do_zmodem() {
+ term.detach();
+ let zsession = detection.confirm();
+
+ var promise;
+
+ if (zsession.type === "receive") {
+ promise = _handle_receive_session(zsession);
+ }
+ else {
+ promise = _handle_send_session(zsession);
+ }
+
+ promise.catch( console.error.bind(console) ).then( () => {
+ term.attach(socket);
+ } );
+ }
+
+ if (_auto_zmodem()) {
+ do_zmodem();
+ }
+ else {
+ start_form.style.display = "";
+ start_form.onsubmit = function(e) {
+ start_form.style.display = "none";
+
+ if (document.getElementById("zmstart_yes").checked) {
+ do_zmodem();
+ }
+ else {
+ detection.deny();
+ }
+ };
+ }
+ });
+ });
+ });
+ }, 0);
+}
+
+//----------------------------------------------------------------------
+// UI STUFF
+
+function _show_file_info(xfer) {
+ var file_info = xfer.get_details();
+
+ document.getElementById("name").textContent = file_info.name;
+ document.getElementById("size").textContent = file_info.size;
+ document.getElementById("mtime").textContent = file_info.mtime;
+ document.getElementById("files_remaining").textContent = file_info.files_remaining;
+ document.getElementById("bytes_remaining").textContent = file_info.bytes_remaining;
+
+ document.getElementById("mode").textContent = "0" + file_info.mode.toString(8);
+
+ var xfer_opts = xfer.get_options();
+ ["conversion", "management", "transport", "sparse"].forEach( (lbl) => {
+ document.getElementById(`zfile_${lbl}`).textContent = xfer_opts[lbl];
+ } );
+
+ document.getElementById("zm_file").style.display = "";
+}
+function _hide_file_info() {
+ document.getElementById("zm_file").style.display = "none";
+}
+
+function _save_to_disk(xfer, buffer) {
+ return Zmodem.Browser.save_to_disk(buffer, xfer.get_details().name);
+}
+
+var skipper_button = document.getElementById("zm_progress_skipper");
+var skipper_button_orig_text = skipper_button.textContent;
+
+function _show_progress() {
+ skipper_button.disabled = false;
+ skipper_button.textContent = skipper_button_orig_text;
+
+ document.getElementById("bytes_received").textContent = 0;
+ document.getElementById("percent_received").textContent = 0;
+
+ document.getElementById("zm_progress").style.display = "";
+}
+
+function _update_progress(xfer) {
+ var total_in = xfer.get_offset();
+
+ document.getElementById("bytes_received").textContent = total_in;
+
+ var percent_received = 100 * total_in / xfer.get_details().size;
+ document.getElementById("percent_received").textContent = percent_received.toFixed(2);
+}
+
+function _hide_progress() {
+ document.getElementById("zm_progress").style.display = "none";
+}
+
+var start_form = document.getElementById("zm_start");
+
+function _auto_zmodem() {
+ return document.getElementById("zmodem-auto").checked;
+}
+
+// END UI STUFF
+//----------------------------------------------------------------------
+
+function _handle_receive_session(zsession) {
+ zsession.on("offer", function(xfer) {
+ current_receive_xfer = xfer;
+
+ _show_file_info(xfer);
+
+ var offer_form = document.getElementById("zm_offer");
+
+ function on_form_submit() {
+ offer_form.style.display = "none";
+
+ //START
+ //if (offer_form.zmaccept.value) {
+ if (_auto_zmodem() || document.getElementById("zmaccept_yes").checked) {
+ _show_progress();
+
+ var FILE_BUFFER = [];
+ xfer.on("input", (payload) => {
+ _update_progress(xfer);
+ FILE_BUFFER.push( new Uint8Array(payload) );
+ });
+ xfer.accept().then(
+ () => {
+ _save_to_disk(xfer, FILE_BUFFER);
+ },
+ console.error.bind(console)
+ );
+ }
+ else {
+ xfer.skip();
+ }
+ //END
+ }
+
+ if (_auto_zmodem()) {
+ on_form_submit();
+ }
+ else {
+ offer_form.onsubmit = on_form_submit;
+ offer_form.style.display = "";
+ }
+ } );
+
+ var promise = new Promise( (res) => {
+ zsession.on("session_end", () => {
+ _hide_file_info();
+ _hide_progress();
+ res();
+ } );
+ } );
+
+ zsession.start();
+
+ return promise;
+}
+
+function _handle_send_session(zsession) {
+ var choose_form = document.getElementById("zm_choose");
+ choose_form.style.display = "";
+
+ var file_el = document.getElementById("zm_files");
+
+ var promise = new Promise( (res) => {
+ file_el.onchange = function(e) {
+ choose_form.style.display = "none";
+
+ var files_obj = file_el.files;
+
+ Zmodem.Browser.send_files(
+ zsession,
+ files_obj,
+ {
+ on_offer_response(obj, xfer) {
+ if (xfer) _show_progress();
+ //console.log("offer", xfer ? "accepted" : "skipped");
+ },
+ on_progress(obj, xfer) {
+ _update_progress(xfer);
+ },
+ on_file_complete(obj) {
+ //console.log("COMPLETE", obj);
+ _hide_progress();
+ },
+ }
+ ).then(_hide_progress).then(
+ zsession.close.bind(zsession),
+ console.error.bind(console)
+ ).then( () => {
+ _hide_file_info();
+ _hide_progress();
+ res();
+ } );
+ };
+ } );
+
+ return promise;
+}
+
+//This is here to allow canceling of an in-progress ZMODEM transfer.
+var current_receive_xfer;
+
+//Called from HTML directly.
+function skip_current_file() {
+ current_receive_xfer.skip();
+
+ skipper_button.disabled = true;
+ skipper_button.textContent = "Waiting for server to acknowledge skip …";
+}
+
+function runRealTerminal() {
+ term.attach(socket);
+
+ term._initialized = true;
+}
+
+function runFakeTerminal() {
+ if (term._initialized) {
+ return;
+ }
+
+ term._initialized = true;
+
+ var shellprompt = '$ ';
+
+ term.prompt = function () {
+ term.write('\r\n' + shellprompt);
+ };
+
+ term.writeln('Welcome to xterm.js');
+ term.writeln('This is a local terminal emulation, without a real terminal in the back-end.');
+ term.writeln('Type some keys and commands to play around.');
+ term.writeln('');
+ term.prompt();
+
+ term.on('key', function (key, ev) {
+ var printable = (
+ !ev.altKey && !ev.altGraphKey && !ev.ctrlKey && !ev.metaKey
+ );
+
+ if (ev.keyCode == 13) {
+ term.prompt();
+ } else if (ev.keyCode == 8) {
+ // Do not delete the prompt
+ if (term.x > 2) {
+ term.write('\b \b');
+ }
+ } else if (printable) {
+ term.write(key);
+ }
+ });
+
+ term.on('paste', function (data, ev) {
+ term.write(data);
+ });
+}
diff --git a/route/static/build/addons/zmodem/zmodem.js b/route/static/build/addons/zmodem/zmodem.js
new file mode 100755
index 000000000..aeb2fd5f0
--- /dev/null
+++ b/route/static/build/addons/zmodem/zmodem.js
@@ -0,0 +1,108 @@
+/**
+ *
+ * Allow xterm.js to handle ZMODEM uploads and downloads.
+ *
+ * This addon is a wrapper around zmodem.js. It adds the following to the
+ * Terminal class:
+ *
+ * - function `zmodemAttach(, )` - creates a Zmodem.Sentry
+ * on the passed WebSocket object. The Object passed is optional and
+ * can contain:
+ * - noTerminalWriteOutsideSession: Suppress writes from the Sentry
+ * object to the Terminal while there is no active Session. This
+ * is necessary for compatibility with, for example, the
+ * `attach.js` addon.
+ *
+ * - event `zmodemDetect` - fired on Zmodem.Sentry’s `on_detect` callback.
+ * Passes the zmodem.js Detection object.
+ *
+ * - event `zmodemRetract` - fired on Zmodem.Sentry’s `on_retract` callback.
+ *
+ * You’ll need to provide logic to handle uploads and downloads.
+ * See zmodem.js’s documentation for more details.
+ *
+ * **IMPORTANT:** After you confirm() a zmodem.js Detection, if you have
+ * used the `attach` or `terminado` addons, you’ll need to suspend their
+ * operation for the duration of the ZMODEM session. (The demo does this
+ * via `detach()` and a re-`attach()`.)
+ */
+(function (addon) {
+ if (typeof exports === 'object' && typeof module === 'object') {
+ /*
+ * CommonJS environment
+ */
+ module.exports = addon(require('../../Terminal').Terminal);
+ } else if (typeof define == 'function') {
+ /*
+ * Require.js is available
+ */
+ define(['../../xterm'], addon);
+ } else {
+ /*
+ * Plain browser environment
+ */
+ addon(window.Terminal);
+ }
+})(function _zmodemAddon(Terminal) {
+ Object.assign(
+ Terminal.prototype,
+ {
+ zmodemAttach: function zmodemAttach(ws, opts) {
+ var term = this;
+
+ if (!opts) opts = {};
+
+ var senderFunc = function _ws_sender_func(octets) {
+ ws.send( new Uint8Array(octets) );
+ };
+
+ var zsentry;
+
+ function _shouldWrite() {
+ return !!zsentry.get_confirmed_session() || !opts.noTerminalWriteOutsideSession;
+ }
+
+ zsentry = new Zmodem.Sentry( {
+ to_terminal: function _to_terminal(octets) {
+ if (_shouldWrite()) {
+ term.write(
+ String.fromCharCode.apply(String, octets)
+ );
+ }
+ },
+
+ sender: senderFunc,
+
+ on_retract: function _on_retract() {
+ term.emit("zmodemRetract");
+ },
+
+ on_detect: function _on_detect(detection) {
+ term.emit("zmodemDetect", detection);
+ },
+ } );
+
+ function handleWSMessage(evt) {
+
+ //In testing with xterm.js’s demo the first message was
+ //always text even if the rest were binary. While that
+ //may be specific to xterm.js’s demo, ultimately we
+ //should reject anything that isn’t binary.
+ if (typeof evt.data === "string") {
+ if (_shouldWrite()) {
+ term.write(evt.data);
+ }
+ }
+ else {
+ zsentry.consume(evt.data);
+ }
+ }
+
+ ws.binaryType = "arraybuffer";
+ ws.addEventListener("message", handleWSMessage);
+ },
+
+ zmodemBrowser: Zmodem.Browser,
+ }
+ );
+});
diff --git a/route/static/build/xterm.css b/route/static/build/xterm.css
new file mode 100755
index 000000000..c668af403
--- /dev/null
+++ b/route/static/build/xterm.css
@@ -0,0 +1,124 @@
+/**
+ * Copyright (c) 2014 The xterm.js authors. All rights reserved.
+ * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
+ * https://github.com/chjj/term.js
+ * @license MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * 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.
+ */
+
+/**
+ * Default styles for xterm.js
+ */
+
+.xterm {
+ font-family: courier-new, courier, monospace;
+ font-feature-settings: "liga" 0;
+ position: relative;
+ user-select: none;
+ -ms-user-select: none;
+ -webkit-user-select: none;
+}
+
+.xterm.focus,
+.xterm:focus {
+ outline: none;
+}
+
+.xterm .xterm-helpers {
+ position: absolute;
+ top: 0;
+ /**
+ * The z-index of the helpers must be higher than the canvases in order for
+ * IMEs to appear on top.
+ */
+ z-index: 10;
+}
+
+.xterm .xterm-helper-textarea {
+ /*
+ * HACK: to fix IE's blinking cursor
+ * Move textarea out of the screen to the far left, so that the cursor is not visible.
+ */
+ position: absolute;
+ opacity: 0;
+ left: -9999em;
+ top: 0;
+ width: 0;
+ height: 0;
+ z-index: -10;
+ /** Prevent wrapping so the IME appears against the textarea at the correct position */
+ white-space: nowrap;
+ overflow: hidden;
+ resize: none;
+}
+
+.xterm .composition-view {
+ /* TODO: Composition position got messed up somewhere */
+ background: #333;
+ color: #FFF;
+ display: none;
+ position: absolute;
+ white-space: nowrap;
+ z-index: 1;
+}
+
+.xterm .composition-view.active {
+ display: block;
+}
+
+.xterm .xterm-viewport {
+ /* On OS X this is required in order for the scroll bar to appear fully opaque */
+ background-color: #333;
+ overflow-y: scroll;
+}
+
+.xterm canvas {
+ position: absolute;
+ left: 0;
+ top: 0;
+}
+
+.xterm .xterm-scroll-area {
+ visibility: hidden;
+}
+
+.xterm .xterm-char-measure-element {
+ display: inline-block;
+ visibility: hidden;
+ position: absolute;
+ left: -9999em;
+}
+
+.xterm.enable-mouse-events {
+ /* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */
+ cursor: default;
+}
+
+.xterm:not(.enable-mouse-events) {
+ cursor: text;
+}
diff --git a/route/static/build/xterm.js b/route/static/build/xterm.js
new file mode 100755
index 000000000..80b0ba5d3
--- /dev/null
+++ b/route/static/build/xterm.js
@@ -0,0 +1,6241 @@
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Terminal = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o this._terminal.rows;
+ },
+ enumerable: true,
+ configurable: true
+ });
+ Object.defineProperty(Buffer.prototype, "isCursorInViewport", {
+ get: function () {
+ var absoluteY = this.ybase + this.y;
+ var relativeY = absoluteY - this.ydisp;
+ return (relativeY >= 0 && relativeY < this._terminal.rows);
+ },
+ enumerable: true,
+ configurable: true
+ });
+ Buffer.prototype._getCorrectBufferLength = function (rows) {
+ if (!this._hasScrollback) {
+ return rows;
+ }
+ var correctBufferLength = rows + this._terminal.options.scrollback;
+ return correctBufferLength > exports.MAX_BUFFER_SIZE ? exports.MAX_BUFFER_SIZE : correctBufferLength;
+ };
+ Buffer.prototype.fillViewportRows = function () {
+ if (this._lines.length === 0) {
+ var i = this._terminal.rows;
+ while (i--) {
+ this.lines.push(this._terminal.blankLine());
+ }
+ }
+ };
+ Buffer.prototype.clear = function () {
+ this.ydisp = 0;
+ this.ybase = 0;
+ this.y = 0;
+ this.x = 0;
+ this._lines = new CircularList_1.CircularList(this._getCorrectBufferLength(this._terminal.rows));
+ this.scrollTop = 0;
+ this.scrollBottom = this._terminal.rows - 1;
+ this.setupTabStops();
+ };
+ Buffer.prototype.resize = function (newCols, newRows) {
+ var newMaxLength = this._getCorrectBufferLength(newRows);
+ if (newMaxLength > this._lines.maxLength) {
+ this._lines.maxLength = newMaxLength;
+ }
+ if (this._lines.length > 0) {
+ if (this._terminal.cols < newCols) {
+ var ch = [this._terminal.defAttr, ' ', 1, 32];
+ for (var i = 0; i < this._lines.length; i++) {
+ if (this._lines.get(i) === undefined) {
+ this._lines.set(i, this._terminal.blankLine(undefined, undefined, newCols));
+ }
+ while (this._lines.get(i).length < newCols) {
+ this._lines.get(i).push(ch);
+ }
+ }
+ }
+ var addToY = 0;
+ if (this._terminal.rows < newRows) {
+ for (var y = this._terminal.rows; y < newRows; y++) {
+ if (this._lines.length < newRows + this.ybase) {
+ if (this.ybase > 0 && this._lines.length <= this.ybase + this.y + addToY + 1) {
+ this.ybase--;
+ addToY++;
+ if (this.ydisp > 0) {
+ this.ydisp--;
+ }
+ }
+ else {
+ this._lines.push(this._terminal.blankLine(undefined, undefined, newCols));
+ }
+ }
+ }
+ }
+ else {
+ for (var y = this._terminal.rows; y > newRows; y--) {
+ if (this._lines.length > newRows + this.ybase) {
+ if (this._lines.length > this.ybase + this.y + 1) {
+ this._lines.pop();
+ }
+ else {
+ this.ybase++;
+ this.ydisp++;
+ }
+ }
+ }
+ }
+ if (newMaxLength < this._lines.maxLength) {
+ var amountToTrim = this._lines.length - newMaxLength;
+ if (amountToTrim > 0) {
+ this._lines.trimStart(amountToTrim);
+ this.ybase = Math.max(this.ybase - amountToTrim, 0);
+ this.ydisp = Math.max(this.ydisp - amountToTrim, 0);
+ }
+ this._lines.maxLength = newMaxLength;
+ }
+ if (this.y >= newRows) {
+ this.y = newRows - 1;
+ }
+ if (addToY) {
+ this.y += addToY;
+ }
+ if (this.x >= newCols) {
+ this.x = newCols - 1;
+ }
+ this.scrollTop = 0;
+ }
+ this.scrollBottom = newRows - 1;
+ };
+ Buffer.prototype.translateBufferLineToString = function (lineIndex, trimRight, startCol, endCol) {
+ if (startCol === void 0) { startCol = 0; }
+ if (endCol === void 0) { endCol = null; }
+ var lineString = '';
+ var line = this.lines.get(lineIndex);
+ if (!line) {
+ return '';
+ }
+ var startIndex = startCol;
+ endCol = endCol || line.length;
+ var endIndex = endCol;
+ for (var i = 0; i < line.length; i++) {
+ var char = line[i];
+ lineString += char[exports.CHAR_DATA_CHAR_INDEX];
+ if (char[exports.CHAR_DATA_WIDTH_INDEX] === 0) {
+ if (startCol >= i) {
+ startIndex--;
+ }
+ if (endCol >= i) {
+ endIndex--;
+ }
+ }
+ else {
+ if (char[exports.CHAR_DATA_CHAR_INDEX].length > 1) {
+ if (startCol > i) {
+ startIndex += char[exports.CHAR_DATA_CHAR_INDEX].length - 1;
+ }
+ if (endCol > i) {
+ endIndex += char[exports.CHAR_DATA_CHAR_INDEX].length - 1;
+ }
+ }
+ }
+ }
+ if (trimRight) {
+ var rightWhitespaceIndex = lineString.search(/\s+$/);
+ if (rightWhitespaceIndex !== -1) {
+ endIndex = Math.min(endIndex, rightWhitespaceIndex);
+ }
+ if (endIndex <= startIndex) {
+ return '';
+ }
+ }
+ return lineString.substring(startIndex, endIndex);
+ };
+ Buffer.prototype.setupTabStops = function (i) {
+ if (i != null) {
+ if (!this.tabs[i]) {
+ i = this.prevStop(i);
+ }
+ }
+ else {
+ this.tabs = {};
+ i = 0;
+ }
+ for (; i < this._terminal.cols; i += this._terminal.options.tabStopWidth) {
+ this.tabs[i] = true;
+ }
+ };
+ Buffer.prototype.prevStop = function (x) {
+ if (x == null) {
+ x = this.x;
+ }
+ while (!this.tabs[--x] && x > 0)
+ ;
+ return x >= this._terminal.cols ? this._terminal.cols - 1 : x < 0 ? 0 : x;
+ };
+ Buffer.prototype.nextStop = function (x) {
+ if (x == null) {
+ x = this.x;
+ }
+ while (!this.tabs[++x] && x < this._terminal.cols)
+ ;
+ return x >= this._terminal.cols ? this._terminal.cols - 1 : x < 0 ? 0 : x;
+ };
+ return Buffer;
+}());
+exports.Buffer = Buffer;
+
+
+
+},{"./utils/CircularList":30}],2:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+ var extendStatics = Object.setPrototypeOf ||
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+ function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+ return function (d, b) {
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Buffer_1 = require("./Buffer");
+var EventEmitter_1 = require("./EventEmitter");
+var BufferSet = (function (_super) {
+ __extends(BufferSet, _super);
+ function BufferSet(_terminal) {
+ var _this = _super.call(this) || this;
+ _this._terminal = _terminal;
+ _this._normal = new Buffer_1.Buffer(_this._terminal, true);
+ _this._normal.fillViewportRows();
+ _this._alt = new Buffer_1.Buffer(_this._terminal, false);
+ _this._activeBuffer = _this._normal;
+ _this.setupTabStops();
+ return _this;
+ }
+ Object.defineProperty(BufferSet.prototype, "alt", {
+ get: function () {
+ return this._alt;
+ },
+ enumerable: true,
+ configurable: true
+ });
+ Object.defineProperty(BufferSet.prototype, "active", {
+ get: function () {
+ return this._activeBuffer;
+ },
+ enumerable: true,
+ configurable: true
+ });
+ Object.defineProperty(BufferSet.prototype, "normal", {
+ get: function () {
+ return this._normal;
+ },
+ enumerable: true,
+ configurable: true
+ });
+ BufferSet.prototype.activateNormalBuffer = function () {
+ this._alt.clear();
+ this._activeBuffer = this._normal;
+ this.emit('activate', this._normal);
+ };
+ BufferSet.prototype.activateAltBuffer = function () {
+ this._alt.fillViewportRows();
+ this._activeBuffer = this._alt;
+ this.emit('activate', this._alt);
+ };
+ BufferSet.prototype.resize = function (newCols, newRows) {
+ this._normal.resize(newCols, newRows);
+ this._alt.resize(newCols, newRows);
+ };
+ BufferSet.prototype.setupTabStops = function (i) {
+ this._normal.setupTabStops(i);
+ this._alt.setupTabStops(i);
+ };
+ return BufferSet;
+}(EventEmitter_1.EventEmitter));
+exports.BufferSet = BufferSet;
+
+
+
+},{"./Buffer":1,"./EventEmitter":7}],3:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.wcwidth = (function (opts) {
+ var COMBINING_BMP = [
+ [0x0300, 0x036F], [0x0483, 0x0486], [0x0488, 0x0489],
+ [0x0591, 0x05BD], [0x05BF, 0x05BF], [0x05C1, 0x05C2],
+ [0x05C4, 0x05C5], [0x05C7, 0x05C7], [0x0600, 0x0603],
+ [0x0610, 0x0615], [0x064B, 0x065E], [0x0670, 0x0670],
+ [0x06D6, 0x06E4], [0x06E7, 0x06E8], [0x06EA, 0x06ED],
+ [0x070F, 0x070F], [0x0711, 0x0711], [0x0730, 0x074A],
+ [0x07A6, 0x07B0], [0x07EB, 0x07F3], [0x0901, 0x0902],
+ [0x093C, 0x093C], [0x0941, 0x0948], [0x094D, 0x094D],
+ [0x0951, 0x0954], [0x0962, 0x0963], [0x0981, 0x0981],
+ [0x09BC, 0x09BC], [0x09C1, 0x09C4], [0x09CD, 0x09CD],
+ [0x09E2, 0x09E3], [0x0A01, 0x0A02], [0x0A3C, 0x0A3C],
+ [0x0A41, 0x0A42], [0x0A47, 0x0A48], [0x0A4B, 0x0A4D],
+ [0x0A70, 0x0A71], [0x0A81, 0x0A82], [0x0ABC, 0x0ABC],
+ [0x0AC1, 0x0AC5], [0x0AC7, 0x0AC8], [0x0ACD, 0x0ACD],
+ [0x0AE2, 0x0AE3], [0x0B01, 0x0B01], [0x0B3C, 0x0B3C],
+ [0x0B3F, 0x0B3F], [0x0B41, 0x0B43], [0x0B4D, 0x0B4D],
+ [0x0B56, 0x0B56], [0x0B82, 0x0B82], [0x0BC0, 0x0BC0],
+ [0x0BCD, 0x0BCD], [0x0C3E, 0x0C40], [0x0C46, 0x0C48],
+ [0x0C4A, 0x0C4D], [0x0C55, 0x0C56], [0x0CBC, 0x0CBC],
+ [0x0CBF, 0x0CBF], [0x0CC6, 0x0CC6], [0x0CCC, 0x0CCD],
+ [0x0CE2, 0x0CE3], [0x0D41, 0x0D43], [0x0D4D, 0x0D4D],
+ [0x0DCA, 0x0DCA], [0x0DD2, 0x0DD4], [0x0DD6, 0x0DD6],
+ [0x0E31, 0x0E31], [0x0E34, 0x0E3A], [0x0E47, 0x0E4E],
+ [0x0EB1, 0x0EB1], [0x0EB4, 0x0EB9], [0x0EBB, 0x0EBC],
+ [0x0EC8, 0x0ECD], [0x0F18, 0x0F19], [0x0F35, 0x0F35],
+ [0x0F37, 0x0F37], [0x0F39, 0x0F39], [0x0F71, 0x0F7E],
+ [0x0F80, 0x0F84], [0x0F86, 0x0F87], [0x0F90, 0x0F97],
+ [0x0F99, 0x0FBC], [0x0FC6, 0x0FC6], [0x102D, 0x1030],
+ [0x1032, 0x1032], [0x1036, 0x1037], [0x1039, 0x1039],
+ [0x1058, 0x1059], [0x1160, 0x11FF], [0x135F, 0x135F],
+ [0x1712, 0x1714], [0x1732, 0x1734], [0x1752, 0x1753],
+ [0x1772, 0x1773], [0x17B4, 0x17B5], [0x17B7, 0x17BD],
+ [0x17C6, 0x17C6], [0x17C9, 0x17D3], [0x17DD, 0x17DD],
+ [0x180B, 0x180D], [0x18A9, 0x18A9], [0x1920, 0x1922],
+ [0x1927, 0x1928], [0x1932, 0x1932], [0x1939, 0x193B],
+ [0x1A17, 0x1A18], [0x1B00, 0x1B03], [0x1B34, 0x1B34],
+ [0x1B36, 0x1B3A], [0x1B3C, 0x1B3C], [0x1B42, 0x1B42],
+ [0x1B6B, 0x1B73], [0x1DC0, 0x1DCA], [0x1DFE, 0x1DFF],
+ [0x200B, 0x200F], [0x202A, 0x202E], [0x2060, 0x2063],
+ [0x206A, 0x206F], [0x20D0, 0x20EF], [0x302A, 0x302F],
+ [0x3099, 0x309A], [0xA806, 0xA806], [0xA80B, 0xA80B],
+ [0xA825, 0xA826], [0xFB1E, 0xFB1E], [0xFE00, 0xFE0F],
+ [0xFE20, 0xFE23], [0xFEFF, 0xFEFF], [0xFFF9, 0xFFFB],
+ ];
+ var COMBINING_HIGH = [
+ [0x10A01, 0x10A03], [0x10A05, 0x10A06], [0x10A0C, 0x10A0F],
+ [0x10A38, 0x10A3A], [0x10A3F, 0x10A3F], [0x1D167, 0x1D169],
+ [0x1D173, 0x1D182], [0x1D185, 0x1D18B], [0x1D1AA, 0x1D1AD],
+ [0x1D242, 0x1D244], [0xE0001, 0xE0001], [0xE0020, 0xE007F],
+ [0xE0100, 0xE01EF]
+ ];
+ function bisearch(ucs, data) {
+ var min = 0;
+ var max = data.length - 1;
+ var mid;
+ if (ucs < data[0][0] || ucs > data[max][1])
+ return false;
+ while (max >= min) {
+ mid = (min + max) >> 1;
+ if (ucs > data[mid][1])
+ min = mid + 1;
+ else if (ucs < data[mid][0])
+ max = mid - 1;
+ else
+ return true;
+ }
+ return false;
+ }
+ function wcwidthBMP(ucs) {
+ if (ucs === 0)
+ return opts.nul;
+ if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
+ return opts.control;
+ if (bisearch(ucs, COMBINING_BMP))
+ return 0;
+ if (isWideBMP(ucs)) {
+ return 2;
+ }
+ return 1;
+ }
+ function isWideBMP(ucs) {
+ return (ucs >= 0x1100 && (ucs <= 0x115f ||
+ ucs === 0x2329 ||
+ ucs === 0x232a ||
+ (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs !== 0x303f) ||
+ (ucs >= 0xac00 && ucs <= 0xd7a3) ||
+ (ucs >= 0xf900 && ucs <= 0xfaff) ||
+ (ucs >= 0xfe10 && ucs <= 0xfe19) ||
+ (ucs >= 0xfe30 && ucs <= 0xfe6f) ||
+ (ucs >= 0xff00 && ucs <= 0xff60) ||
+ (ucs >= 0xffe0 && ucs <= 0xffe6)));
+ }
+ function wcwidthHigh(ucs) {
+ if (bisearch(ucs, COMBINING_HIGH))
+ return 0;
+ if ((ucs >= 0x20000 && ucs <= 0x2fffd) || (ucs >= 0x30000 && ucs <= 0x3fffd)) {
+ return 2;
+ }
+ return 1;
+ }
+ var control = opts.control | 0;
+ var table = null;
+ function init_table() {
+ var CODEPOINTS = 65536;
+ var BITWIDTH = 2;
+ var ITEMSIZE = 32;
+ var CONTAINERSIZE = CODEPOINTS * BITWIDTH / ITEMSIZE;
+ var CODEPOINTS_PER_ITEM = ITEMSIZE / BITWIDTH;
+ table = (typeof Uint32Array === 'undefined')
+ ? new Array(CONTAINERSIZE)
+ : new Uint32Array(CONTAINERSIZE);
+ for (var i = 0; i < CONTAINERSIZE; ++i) {
+ var num = 0;
+ var pos = CODEPOINTS_PER_ITEM;
+ while (pos--)
+ num = (num << 2) | wcwidthBMP(CODEPOINTS_PER_ITEM * i + pos);
+ table[i] = num;
+ }
+ return table;
+ }
+ return function (num) {
+ num = num | 0;
+ if (num < 32)
+ return control | 0;
+ if (num < 127)
+ return 1;
+ var t = table || init_table();
+ if (num < 65536)
+ return t[num >> 4] >> ((num & 15) << 1) & 3;
+ return wcwidthHigh(num);
+ };
+})({ nul: 0, control: 0 });
+
+
+
+},{}],4:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.CHARSETS = {};
+exports.DEFAULT_CHARSET = exports.CHARSETS['B'];
+exports.CHARSETS['0'] = {
+ '`': '\u25c6',
+ 'a': '\u2592',
+ 'b': '\u0009',
+ 'c': '\u000c',
+ 'd': '\u000d',
+ 'e': '\u000a',
+ 'f': '\u00b0',
+ 'g': '\u00b1',
+ 'h': '\u2424',
+ 'i': '\u000b',
+ 'j': '\u2518',
+ 'k': '\u2510',
+ 'l': '\u250c',
+ 'm': '\u2514',
+ 'n': '\u253c',
+ 'o': '\u23ba',
+ 'p': '\u23bb',
+ 'q': '\u2500',
+ 'r': '\u23bc',
+ 's': '\u23bd',
+ 't': '\u251c',
+ 'u': '\u2524',
+ 'v': '\u2534',
+ 'w': '\u252c',
+ 'x': '\u2502',
+ 'y': '\u2264',
+ 'z': '\u2265',
+ '{': '\u03c0',
+ '|': '\u2260',
+ '}': '\u00a3',
+ '~': '\u00b7'
+};
+exports.CHARSETS['A'] = {
+ '#': '£'
+};
+exports.CHARSETS['B'] = null;
+exports.CHARSETS['4'] = {
+ '#': '£',
+ '@': '¾',
+ '[': 'ij',
+ '\\': '½',
+ ']': '|',
+ '{': '¨',
+ '|': 'f',
+ '}': '¼',
+ '~': '´'
+};
+exports.CHARSETS['C'] =
+ exports.CHARSETS['5'] = {
+ '[': 'Ä',
+ '\\': 'Ö',
+ ']': 'Å',
+ '^': 'Ü',
+ '`': 'é',
+ '{': 'ä',
+ '|': 'ö',
+ '}': 'å',
+ '~': 'ü'
+ };
+exports.CHARSETS['R'] = {
+ '#': '£',
+ '@': 'à',
+ '[': '°',
+ '\\': 'ç',
+ ']': '§',
+ '{': 'é',
+ '|': 'ù',
+ '}': 'è',
+ '~': '¨'
+};
+exports.CHARSETS['Q'] = {
+ '@': 'à',
+ '[': 'â',
+ '\\': 'ç',
+ ']': 'ê',
+ '^': 'î',
+ '`': 'ô',
+ '{': 'é',
+ '|': 'ù',
+ '}': 'è',
+ '~': 'û'
+};
+exports.CHARSETS['K'] = {
+ '@': '§',
+ '[': 'Ä',
+ '\\': 'Ö',
+ ']': 'Ü',
+ '{': 'ä',
+ '|': 'ö',
+ '}': 'ü',
+ '~': 'ß'
+};
+exports.CHARSETS['Y'] = {
+ '#': '£',
+ '@': '§',
+ '[': '°',
+ '\\': 'ç',
+ ']': 'é',
+ '`': 'ù',
+ '{': 'à',
+ '|': 'ò',
+ '}': 'è',
+ '~': 'ì'
+};
+exports.CHARSETS['E'] =
+ exports.CHARSETS['6'] = {
+ '@': 'Ä',
+ '[': 'Æ',
+ '\\': 'Ø',
+ ']': 'Å',
+ '^': 'Ü',
+ '`': 'ä',
+ '{': 'æ',
+ '|': 'ø',
+ '}': 'å',
+ '~': 'ü'
+ };
+exports.CHARSETS['Z'] = {
+ '#': '£',
+ '@': '§',
+ '[': '¡',
+ '\\': 'Ñ',
+ ']': '¿',
+ '{': '°',
+ '|': 'ñ',
+ '}': 'ç'
+};
+exports.CHARSETS['H'] =
+ exports.CHARSETS['7'] = {
+ '@': 'É',
+ '[': 'Ä',
+ '\\': 'Ö',
+ ']': 'Å',
+ '^': 'Ü',
+ '`': 'é',
+ '{': 'ä',
+ '|': 'ö',
+ '}': 'å',
+ '~': 'ü'
+ };
+exports.CHARSETS['='] = {
+ '#': 'ù',
+ '@': 'à',
+ '[': 'é',
+ '\\': 'ç',
+ ']': 'ê',
+ '^': 'î',
+ '_': 'è',
+ '`': 'ô',
+ '{': 'ä',
+ '|': 'ö',
+ '}': 'ü',
+ '~': 'û'
+};
+
+
+
+},{}],5:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var CompositionHelper = (function () {
+ function CompositionHelper(textarea, compositionView, terminal) {
+ this.textarea = textarea;
+ this.compositionView = compositionView;
+ this.terminal = terminal;
+ this.isComposing = false;
+ this.isSendingComposition = false;
+ this.compositionPosition = { start: null, end: null };
+ }
+ CompositionHelper.prototype.compositionstart = function () {
+ this.isComposing = true;
+ this.compositionPosition.start = this.textarea.value.length;
+ this.compositionView.textContent = '';
+ this.compositionView.classList.add('active');
+ };
+ CompositionHelper.prototype.compositionupdate = function (ev) {
+ var _this = this;
+ this.compositionView.textContent = ev.data;
+ this.updateCompositionElements();
+ setTimeout(function () {
+ _this.compositionPosition.end = _this.textarea.value.length;
+ }, 0);
+ };
+ CompositionHelper.prototype.compositionend = function () {
+ this.finalizeComposition(true);
+ };
+ CompositionHelper.prototype.keydown = function (ev) {
+ if (this.isComposing || this.isSendingComposition) {
+ if (ev.keyCode === 229) {
+ return false;
+ }
+ else if (ev.keyCode === 16 || ev.keyCode === 17 || ev.keyCode === 18) {
+ return false;
+ }
+ else {
+ this.finalizeComposition(false);
+ }
+ }
+ if (ev.keyCode === 229) {
+ this.handleAnyTextareaChanges();
+ return false;
+ }
+ return true;
+ };
+ CompositionHelper.prototype.finalizeComposition = function (waitForPropogation) {
+ var _this = this;
+ this.compositionView.classList.remove('active');
+ this.isComposing = false;
+ this.clearTextareaPosition();
+ if (!waitForPropogation) {
+ this.isSendingComposition = false;
+ var input = this.textarea.value.substring(this.compositionPosition.start, this.compositionPosition.end);
+ this.terminal.handler(input);
+ }
+ else {
+ var currentCompositionPosition_1 = {
+ start: this.compositionPosition.start,
+ end: this.compositionPosition.end,
+ };
+ this.isSendingComposition = true;
+ setTimeout(function () {
+ if (_this.isSendingComposition) {
+ _this.isSendingComposition = false;
+ var input = void 0;
+ if (_this.isComposing) {
+ input = _this.textarea.value.substring(currentCompositionPosition_1.start, currentCompositionPosition_1.end);
+ }
+ else {
+ input = _this.textarea.value.substring(currentCompositionPosition_1.start);
+ }
+ _this.terminal.handler(input);
+ }
+ }, 0);
+ }
+ };
+ CompositionHelper.prototype.handleAnyTextareaChanges = function () {
+ var _this = this;
+ var oldValue = this.textarea.value;
+ setTimeout(function () {
+ if (!_this.isComposing) {
+ var newValue = _this.textarea.value;
+ var diff = newValue.replace(oldValue, '');
+ if (diff.length > 0) {
+ _this.terminal.handler(diff);
+ }
+ }
+ }, 0);
+ };
+ CompositionHelper.prototype.updateCompositionElements = function (dontRecurse) {
+ var _this = this;
+ if (!this.isComposing) {
+ return;
+ }
+ if (this.terminal.buffer.isCursorInViewport) {
+ var cellHeight = Math.ceil(this.terminal.charMeasure.height * this.terminal.options.lineHeight);
+ var cursorTop = this.terminal.buffer.y * cellHeight;
+ var cursorLeft = this.terminal.buffer.x * this.terminal.charMeasure.width;
+ this.compositionView.style.left = cursorLeft + 'px';
+ this.compositionView.style.top = cursorTop + 'px';
+ this.compositionView.style.height = cellHeight + 'px';
+ this.compositionView.style.lineHeight = cellHeight + 'px';
+ var compositionViewBounds = this.compositionView.getBoundingClientRect();
+ this.textarea.style.left = cursorLeft + 'px';
+ this.textarea.style.top = cursorTop + 'px';
+ this.textarea.style.width = compositionViewBounds.width + 'px';
+ this.textarea.style.height = compositionViewBounds.height + 'px';
+ this.textarea.style.lineHeight = compositionViewBounds.height + 'px';
+ }
+ if (!dontRecurse) {
+ setTimeout(function () { return _this.updateCompositionElements(true); }, 0);
+ }
+ };
+ ;
+ CompositionHelper.prototype.clearTextareaPosition = function () {
+ this.textarea.style.left = '';
+ this.textarea.style.top = '';
+ };
+ ;
+ return CompositionHelper;
+}());
+exports.CompositionHelper = CompositionHelper;
+
+
+
+},{}],6:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var C0;
+(function (C0) {
+ C0.NUL = '\x00';
+ C0.SOH = '\x01';
+ C0.STX = '\x02';
+ C0.ETX = '\x03';
+ C0.EOT = '\x04';
+ C0.ENQ = '\x05';
+ C0.ACK = '\x06';
+ C0.BEL = '\x07';
+ C0.BS = '\x08';
+ C0.HT = '\x09';
+ C0.LF = '\x0a';
+ C0.VT = '\x0b';
+ C0.FF = '\x0c';
+ C0.CR = '\x0d';
+ C0.SO = '\x0e';
+ C0.SI = '\x0f';
+ C0.DLE = '\x10';
+ C0.DC1 = '\x11';
+ C0.DC2 = '\x12';
+ C0.DC3 = '\x13';
+ C0.DC4 = '\x14';
+ C0.NAK = '\x15';
+ C0.SYN = '\x16';
+ C0.ETB = '\x17';
+ C0.CAN = '\x18';
+ C0.EM = '\x19';
+ C0.SUB = '\x1a';
+ C0.ESC = '\x1b';
+ C0.FS = '\x1c';
+ C0.GS = '\x1d';
+ C0.RS = '\x1e';
+ C0.US = '\x1f';
+ C0.SP = '\x20';
+ C0.DEL = '\x7f';
+})(C0 = exports.C0 || (exports.C0 = {}));
+;
+
+
+
+},{}],7:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var EventEmitter = (function () {
+ function EventEmitter() {
+ this._events = this._events || {};
+ }
+ EventEmitter.prototype.on = function (type, listener) {
+ this._events[type] = this._events[type] || [];
+ this._events[type].push(listener);
+ };
+ EventEmitter.prototype.off = function (type, listener) {
+ if (!this._events[type]) {
+ return;
+ }
+ var obj = this._events[type];
+ var i = obj.length;
+ while (i--) {
+ if (obj[i] === listener || obj[i].listener === listener) {
+ obj.splice(i, 1);
+ return;
+ }
+ }
+ };
+ EventEmitter.prototype.removeAllListeners = function (type) {
+ if (this._events[type]) {
+ delete this._events[type];
+ }
+ };
+ EventEmitter.prototype.once = function (type, listener) {
+ function on() {
+ var args = Array.prototype.slice.call(arguments);
+ this.off(type, on);
+ listener.apply(this, args);
+ }
+ on.listener = listener;
+ this.on(type, on);
+ };
+ EventEmitter.prototype.emit = function (type) {
+ var args = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ args[_i - 1] = arguments[_i];
+ }
+ if (!this._events[type]) {
+ return;
+ }
+ var obj = this._events[type];
+ for (var i = 0; i < obj.length; i++) {
+ obj[i].apply(this, args);
+ }
+ };
+ EventEmitter.prototype.listeners = function (type) {
+ return this._events[type] || [];
+ };
+ EventEmitter.prototype.destroy = function () {
+ this._events = {};
+ };
+ return EventEmitter;
+}());
+exports.EventEmitter = EventEmitter;
+
+
+
+},{}],8:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var EscapeSequences_1 = require("./EscapeSequences");
+var Charsets_1 = require("./Charsets");
+var Buffer_1 = require("./Buffer");
+var Types_1 = require("./renderer/Types");
+var CharWidth_1 = require("./CharWidth");
+var InputHandler = (function () {
+ function InputHandler(_terminal) {
+ this._terminal = _terminal;
+ }
+ InputHandler.prototype.addChar = function (char, code) {
+ if (char >= ' ') {
+ var ch_width = CharWidth_1.wcwidth(code);
+ if (this._terminal.charset && this._terminal.charset[char]) {
+ char = this._terminal.charset[char];
+ }
+ var row = this._terminal.buffer.y + this._terminal.buffer.ybase;
+ if (!ch_width && this._terminal.buffer.x) {
+ if (this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1]) {
+ if (!this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][Buffer_1.CHAR_DATA_WIDTH_INDEX]) {
+ if (this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2]) {
+ this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2][Buffer_1.CHAR_DATA_CHAR_INDEX] += char;
+ this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2][3] = char.charCodeAt(0);
+ }
+ }
+ else {
+ this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][Buffer_1.CHAR_DATA_CHAR_INDEX] += char;
+ this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][3] = char.charCodeAt(0);
+ }
+ this._terminal.updateRange(this._terminal.buffer.y);
+ }
+ return;
+ }
+ if (this._terminal.buffer.x + ch_width - 1 >= this._terminal.cols) {
+ if (this._terminal.wraparoundMode) {
+ this._terminal.buffer.x = 0;
+ this._terminal.buffer.y++;
+ if (this._terminal.buffer.y > this._terminal.buffer.scrollBottom) {
+ this._terminal.buffer.y--;
+ this._terminal.scroll(true);
+ }
+ else {
+ this._terminal.buffer.lines.get(this._terminal.buffer.y).isWrapped = true;
+ }
+ }
+ else {
+ if (ch_width === 2)
+ return;
+ }
+ }
+ row = this._terminal.buffer.y + this._terminal.buffer.ybase;
+ if (this._terminal.insertMode) {
+ for (var moves = 0; moves < ch_width; ++moves) {
+ var removed = this._terminal.buffer.lines.get(this._terminal.buffer.y + this._terminal.buffer.ybase).pop();
+ if (removed[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0
+ && this._terminal.buffer.lines.get(row)[this._terminal.cols - 2]
+ && this._terminal.buffer.lines.get(row)[this._terminal.cols - 2][Buffer_1.CHAR_DATA_WIDTH_INDEX] === 2) {
+ this._terminal.buffer.lines.get(row)[this._terminal.cols - 2] = [this._terminal.curAttr, ' ', 1, ' '.charCodeAt(0)];
+ }
+ this._terminal.buffer.lines.get(row).splice(this._terminal.buffer.x, 0, [this._terminal.curAttr, ' ', 1, ' '.charCodeAt(0)]);
+ }
+ }
+ this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, char, ch_width, char.charCodeAt(0)];
+ this._terminal.buffer.x++;
+ this._terminal.updateRange(this._terminal.buffer.y);
+ if (ch_width === 2) {
+ this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, '', 0, undefined];
+ this._terminal.buffer.x++;
+ }
+ }
+ };
+ InputHandler.prototype.bell = function () {
+ this._terminal.bell();
+ };
+ InputHandler.prototype.lineFeed = function () {
+ if (this._terminal.convertEol) {
+ this._terminal.buffer.x = 0;
+ }
+ this._terminal.buffer.y++;
+ if (this._terminal.buffer.y > this._terminal.buffer.scrollBottom) {
+ this._terminal.buffer.y--;
+ this._terminal.scroll();
+ }
+ if (this._terminal.buffer.x >= this._terminal.cols) {
+ this._terminal.buffer.x--;
+ }
+ this._terminal.emit('lineFeed');
+ };
+ InputHandler.prototype.carriageReturn = function () {
+ this._terminal.buffer.x = 0;
+ };
+ InputHandler.prototype.backspace = function () {
+ if (this._terminal.buffer.x > 0) {
+ this._terminal.buffer.x--;
+ }
+ };
+ InputHandler.prototype.tab = function () {
+ this._terminal.buffer.x = this._terminal.buffer.nextStop();
+ };
+ InputHandler.prototype.shiftOut = function () {
+ this._terminal.setgLevel(1);
+ };
+ InputHandler.prototype.shiftIn = function () {
+ this._terminal.setgLevel(0);
+ };
+ InputHandler.prototype.insertChars = function (params) {
+ var param = params[0];
+ if (param < 1)
+ param = 1;
+ var row = this._terminal.buffer.y + this._terminal.buffer.ybase;
+ var j = this._terminal.buffer.x;
+ var ch = [this._terminal.eraseAttr(), ' ', 1, 32];
+ while (param-- && j < this._terminal.cols) {
+ this._terminal.buffer.lines.get(row).splice(j++, 0, ch);
+ this._terminal.buffer.lines.get(row).pop();
+ }
+ };
+ InputHandler.prototype.cursorUp = function (params) {
+ var param = params[0];
+ if (param < 1) {
+ param = 1;
+ }
+ this._terminal.buffer.y -= param;
+ if (this._terminal.buffer.y < 0) {
+ this._terminal.buffer.y = 0;
+ }
+ };
+ InputHandler.prototype.cursorDown = function (params) {
+ var param = params[0];
+ if (param < 1) {
+ param = 1;
+ }
+ this._terminal.buffer.y += param;
+ if (this._terminal.buffer.y >= this._terminal.rows) {
+ this._terminal.buffer.y = this._terminal.rows - 1;
+ }
+ if (this._terminal.buffer.x >= this._terminal.cols) {
+ this._terminal.buffer.x--;
+ }
+ };
+ InputHandler.prototype.cursorForward = function (params) {
+ var param = params[0];
+ if (param < 1) {
+ param = 1;
+ }
+ this._terminal.buffer.x += param;
+ if (this._terminal.buffer.x >= this._terminal.cols) {
+ this._terminal.buffer.x = this._terminal.cols - 1;
+ }
+ };
+ InputHandler.prototype.cursorBackward = function (params) {
+ var param = params[0];
+ if (param < 1) {
+ param = 1;
+ }
+ if (this._terminal.buffer.x >= this._terminal.cols) {
+ this._terminal.buffer.x--;
+ }
+ this._terminal.buffer.x -= param;
+ if (this._terminal.buffer.x < 0) {
+ this._terminal.buffer.x = 0;
+ }
+ };
+ InputHandler.prototype.cursorNextLine = function (params) {
+ var param = params[0];
+ if (param < 1) {
+ param = 1;
+ }
+ this._terminal.buffer.y += param;
+ if (this._terminal.buffer.y >= this._terminal.rows) {
+ this._terminal.buffer.y = this._terminal.rows - 1;
+ }
+ this._terminal.buffer.x = 0;
+ };
+ InputHandler.prototype.cursorPrecedingLine = function (params) {
+ var param = params[0];
+ if (param < 1) {
+ param = 1;
+ }
+ this._terminal.buffer.y -= param;
+ if (this._terminal.buffer.y < 0) {
+ this._terminal.buffer.y = 0;
+ }
+ this._terminal.buffer.x = 0;
+ };
+ InputHandler.prototype.cursorCharAbsolute = function (params) {
+ var param = params[0];
+ if (param < 1) {
+ param = 1;
+ }
+ this._terminal.buffer.x = param - 1;
+ };
+ InputHandler.prototype.cursorPosition = function (params) {
+ var col;
+ var row = params[0] - 1;
+ if (params.length >= 2) {
+ col = params[1] - 1;
+ }
+ else {
+ col = 0;
+ }
+ if (row < 0) {
+ row = 0;
+ }
+ else if (row >= this._terminal.rows) {
+ row = this._terminal.rows - 1;
+ }
+ if (col < 0) {
+ col = 0;
+ }
+ else if (col >= this._terminal.cols) {
+ col = this._terminal.cols - 1;
+ }
+ this._terminal.buffer.x = col;
+ this._terminal.buffer.y = row;
+ };
+ InputHandler.prototype.cursorForwardTab = function (params) {
+ var param = params[0] || 1;
+ while (param--) {
+ this._terminal.buffer.x = this._terminal.buffer.nextStop();
+ }
+ };
+ InputHandler.prototype.eraseInDisplay = function (params) {
+ var j;
+ switch (params[0]) {
+ case 0:
+ this._terminal.eraseRight(this._terminal.buffer.x, this._terminal.buffer.y);
+ j = this._terminal.buffer.y + 1;
+ for (; j < this._terminal.rows; j++) {
+ this._terminal.eraseLine(j);
+ }
+ break;
+ case 1:
+ this._terminal.eraseLeft(this._terminal.buffer.x, this._terminal.buffer.y);
+ j = this._terminal.buffer.y;
+ while (j--) {
+ this._terminal.eraseLine(j);
+ }
+ break;
+ case 2:
+ j = this._terminal.rows;
+ while (j--)
+ this._terminal.eraseLine(j);
+ break;
+ case 3:
+ var scrollBackSize = this._terminal.buffer.lines.length - this._terminal.rows;
+ if (scrollBackSize > 0) {
+ this._terminal.buffer.lines.trimStart(scrollBackSize);
+ this._terminal.buffer.ybase = Math.max(this._terminal.buffer.ybase - scrollBackSize, 0);
+ this._terminal.buffer.ydisp = Math.max(this._terminal.buffer.ydisp - scrollBackSize, 0);
+ this._terminal.emit('scroll', 0);
+ }
+ break;
+ }
+ };
+ InputHandler.prototype.eraseInLine = function (params) {
+ switch (params[0]) {
+ case 0:
+ this._terminal.eraseRight(this._terminal.buffer.x, this._terminal.buffer.y);
+ break;
+ case 1:
+ this._terminal.eraseLeft(this._terminal.buffer.x, this._terminal.buffer.y);
+ break;
+ case 2:
+ this._terminal.eraseLine(this._terminal.buffer.y);
+ break;
+ }
+ };
+ InputHandler.prototype.insertLines = function (params) {
+ var param = params[0];
+ if (param < 1) {
+ param = 1;
+ }
+ var row = this._terminal.buffer.y + this._terminal.buffer.ybase;
+ var scrollBottomRowsOffset = this._terminal.rows - 1 - this._terminal.buffer.scrollBottom;
+ var scrollBottomAbsolute = this._terminal.rows - 1 + this._terminal.buffer.ybase - scrollBottomRowsOffset + 1;
+ while (param--) {
+ this._terminal.buffer.lines.splice(scrollBottomAbsolute - 1, 1);
+ this._terminal.buffer.lines.splice(row, 0, this._terminal.blankLine(true));
+ }
+ this._terminal.updateRange(this._terminal.buffer.y);
+ this._terminal.updateRange(this._terminal.buffer.scrollBottom);
+ };
+ InputHandler.prototype.deleteLines = function (params) {
+ var param = params[0];
+ if (param < 1) {
+ param = 1;
+ }
+ var row = this._terminal.buffer.y + this._terminal.buffer.ybase;
+ var j;
+ j = this._terminal.rows - 1 - this._terminal.buffer.scrollBottom;
+ j = this._terminal.rows - 1 + this._terminal.buffer.ybase - j;
+ while (param--) {
+ this._terminal.buffer.lines.splice(row, 1);
+ this._terminal.buffer.lines.splice(j, 0, this._terminal.blankLine(true));
+ }
+ this._terminal.updateRange(this._terminal.buffer.y);
+ this._terminal.updateRange(this._terminal.buffer.scrollBottom);
+ };
+ InputHandler.prototype.deleteChars = function (params) {
+ var param = params[0];
+ if (param < 1) {
+ param = 1;
+ }
+ var row = this._terminal.buffer.y + this._terminal.buffer.ybase;
+ var ch = [this._terminal.eraseAttr(), ' ', 1, 32];
+ while (param--) {
+ this._terminal.buffer.lines.get(row).splice(this._terminal.buffer.x, 1);
+ this._terminal.buffer.lines.get(row).push(ch);
+ }
+ this._terminal.updateRange(this._terminal.buffer.y);
+ };
+ InputHandler.prototype.scrollUp = function (params) {
+ var param = params[0] || 1;
+ while (param--) {
+ this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollTop, 1);
+ this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollBottom, 0, this._terminal.blankLine());
+ }
+ this._terminal.updateRange(this._terminal.buffer.scrollTop);
+ this._terminal.updateRange(this._terminal.buffer.scrollBottom);
+ };
+ InputHandler.prototype.scrollDown = function (params) {
+ var param = params[0] || 1;
+ while (param--) {
+ this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollBottom, 1);
+ this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollTop, 0, this._terminal.blankLine());
+ }
+ this._terminal.updateRange(this._terminal.buffer.scrollTop);
+ this._terminal.updateRange(this._terminal.buffer.scrollBottom);
+ };
+ InputHandler.prototype.eraseChars = function (params) {
+ var param = params[0];
+ if (param < 1) {
+ param = 1;
+ }
+ var row = this._terminal.buffer.y + this._terminal.buffer.ybase;
+ var j = this._terminal.buffer.x;
+ var ch = [this._terminal.eraseAttr(), ' ', 1, 32];
+ while (param-- && j < this._terminal.cols) {
+ this._terminal.buffer.lines.get(row)[j++] = ch;
+ }
+ };
+ InputHandler.prototype.cursorBackwardTab = function (params) {
+ var param = params[0] || 1;
+ while (param--) {
+ this._terminal.buffer.x = this._terminal.buffer.prevStop();
+ }
+ };
+ InputHandler.prototype.charPosAbsolute = function (params) {
+ var param = params[0];
+ if (param < 1) {
+ param = 1;
+ }
+ this._terminal.buffer.x = param - 1;
+ if (this._terminal.buffer.x >= this._terminal.cols) {
+ this._terminal.buffer.x = this._terminal.cols - 1;
+ }
+ };
+ InputHandler.prototype.HPositionRelative = function (params) {
+ var param = params[0];
+ if (param < 1) {
+ param = 1;
+ }
+ this._terminal.buffer.x += param;
+ if (this._terminal.buffer.x >= this._terminal.cols) {
+ this._terminal.buffer.x = this._terminal.cols - 1;
+ }
+ };
+ InputHandler.prototype.repeatPrecedingCharacter = function (params) {
+ var param = params[0] || 1;
+ var line = this._terminal.buffer.lines.get(this._terminal.buffer.ybase + this._terminal.buffer.y);
+ var ch = line[this._terminal.buffer.x - 1] || [this._terminal.defAttr, ' ', 1, 32];
+ while (param--) {
+ line[this._terminal.buffer.x++] = ch;
+ }
+ };
+ InputHandler.prototype.sendDeviceAttributes = function (params) {
+ if (params[0] > 0) {
+ return;
+ }
+ if (!this._terminal.prefix) {
+ if (this._terminal.is('xterm') || this._terminal.is('rxvt-unicode') || this._terminal.is('screen')) {
+ this._terminal.send(EscapeSequences_1.C0.ESC + '[?1;2c');
+ }
+ else if (this._terminal.is('linux')) {
+ this._terminal.send(EscapeSequences_1.C0.ESC + '[?6c');
+ }
+ }
+ else if (this._terminal.prefix === '>') {
+ if (this._terminal.is('xterm')) {
+ this._terminal.send(EscapeSequences_1.C0.ESC + '[>0;276;0c');
+ }
+ else if (this._terminal.is('rxvt-unicode')) {
+ this._terminal.send(EscapeSequences_1.C0.ESC + '[>85;95;0c');
+ }
+ else if (this._terminal.is('linux')) {
+ this._terminal.send(params[0] + 'c');
+ }
+ else if (this._terminal.is('screen')) {
+ this._terminal.send(EscapeSequences_1.C0.ESC + '[>83;40003;0c');
+ }
+ }
+ };
+ InputHandler.prototype.linePosAbsolute = function (params) {
+ var param = params[0];
+ if (param < 1) {
+ param = 1;
+ }
+ this._terminal.buffer.y = param - 1;
+ if (this._terminal.buffer.y >= this._terminal.rows) {
+ this._terminal.buffer.y = this._terminal.rows - 1;
+ }
+ };
+ InputHandler.prototype.VPositionRelative = function (params) {
+ var param = params[0];
+ if (param < 1) {
+ param = 1;
+ }
+ this._terminal.buffer.y += param;
+ if (this._terminal.buffer.y >= this._terminal.rows) {
+ this._terminal.buffer.y = this._terminal.rows - 1;
+ }
+ if (this._terminal.buffer.x >= this._terminal.cols) {
+ this._terminal.buffer.x--;
+ }
+ };
+ InputHandler.prototype.HVPosition = function (params) {
+ if (params[0] < 1)
+ params[0] = 1;
+ if (params[1] < 1)
+ params[1] = 1;
+ this._terminal.buffer.y = params[0] - 1;
+ if (this._terminal.buffer.y >= this._terminal.rows) {
+ this._terminal.buffer.y = this._terminal.rows - 1;
+ }
+ this._terminal.buffer.x = params[1] - 1;
+ if (this._terminal.buffer.x >= this._terminal.cols) {
+ this._terminal.buffer.x = this._terminal.cols - 1;
+ }
+ };
+ InputHandler.prototype.tabClear = function (params) {
+ var param = params[0];
+ if (param <= 0) {
+ delete this._terminal.buffer.tabs[this._terminal.buffer.x];
+ }
+ else if (param === 3) {
+ this._terminal.buffer.tabs = {};
+ }
+ };
+ InputHandler.prototype.setMode = function (params) {
+ if (params.length > 1) {
+ for (var i = 0; i < params.length; i++) {
+ this.setMode([params[i]]);
+ }
+ return;
+ }
+ if (!this._terminal.prefix) {
+ switch (params[0]) {
+ case 4:
+ this._terminal.insertMode = true;
+ break;
+ case 20:
+ break;
+ }
+ }
+ else if (this._terminal.prefix === '?') {
+ switch (params[0]) {
+ case 1:
+ this._terminal.applicationCursor = true;
+ break;
+ case 2:
+ this._terminal.setgCharset(0, Charsets_1.DEFAULT_CHARSET);
+ this._terminal.setgCharset(1, Charsets_1.DEFAULT_CHARSET);
+ this._terminal.setgCharset(2, Charsets_1.DEFAULT_CHARSET);
+ this._terminal.setgCharset(3, Charsets_1.DEFAULT_CHARSET);
+ break;
+ case 3:
+ this._terminal.savedCols = this._terminal.cols;
+ this._terminal.resize(132, this._terminal.rows);
+ break;
+ case 6:
+ this._terminal.originMode = true;
+ break;
+ case 7:
+ this._terminal.wraparoundMode = true;
+ break;
+ case 12:
+ break;
+ case 66:
+ this._terminal.log('Serial port requested application keypad.');
+ this._terminal.applicationKeypad = true;
+ this._terminal.viewport.syncScrollArea();
+ break;
+ case 9:
+ case 1000:
+ case 1002:
+ case 1003:
+ this._terminal.x10Mouse = params[0] === 9;
+ this._terminal.vt200Mouse = params[0] === 1000;
+ this._terminal.normalMouse = params[0] > 1000;
+ this._terminal.mouseEvents = true;
+ this._terminal.element.classList.add('enable-mouse-events');
+ this._terminal.selectionManager.disable();
+ this._terminal.log('Binding to mouse events.');
+ break;
+ case 1004:
+ this._terminal.sendFocus = true;
+ break;
+ case 1005:
+ this._terminal.utfMouse = true;
+ break;
+ case 1006:
+ this._terminal.sgrMouse = true;
+ break;
+ case 1015:
+ this._terminal.urxvtMouse = true;
+ break;
+ case 25:
+ this._terminal.cursorHidden = false;
+ break;
+ case 1049:
+ case 47:
+ case 1047:
+ this._terminal.buffers.activateAltBuffer();
+ this._terminal.selectionManager.setBuffer(this._terminal.buffer);
+ this._terminal.viewport.syncScrollArea();
+ this._terminal.showCursor();
+ break;
+ case 2004:
+ this._terminal.bracketedPasteMode = true;
+ break;
+ }
+ }
+ };
+ InputHandler.prototype.resetMode = function (params) {
+ if (params.length > 1) {
+ for (var i = 0; i < params.length; i++) {
+ this.resetMode([params[i]]);
+ }
+ return;
+ }
+ if (!this._terminal.prefix) {
+ switch (params[0]) {
+ case 4:
+ this._terminal.insertMode = false;
+ break;
+ case 20:
+ break;
+ }
+ }
+ else if (this._terminal.prefix === '?') {
+ switch (params[0]) {
+ case 1:
+ this._terminal.applicationCursor = false;
+ break;
+ case 3:
+ if (this._terminal.cols === 132 && this._terminal.savedCols) {
+ this._terminal.resize(this._terminal.savedCols, this._terminal.rows);
+ }
+ delete this._terminal.savedCols;
+ break;
+ case 6:
+ this._terminal.originMode = false;
+ break;
+ case 7:
+ this._terminal.wraparoundMode = false;
+ break;
+ case 12:
+ break;
+ case 66:
+ this._terminal.log('Switching back to normal keypad.');
+ this._terminal.applicationKeypad = false;
+ this._terminal.viewport.syncScrollArea();
+ break;
+ case 9:
+ case 1000:
+ case 1002:
+ case 1003:
+ this._terminal.x10Mouse = false;
+ this._terminal.vt200Mouse = false;
+ this._terminal.normalMouse = false;
+ this._terminal.mouseEvents = false;
+ this._terminal.element.classList.remove('enable-mouse-events');
+ this._terminal.selectionManager.enable();
+ break;
+ case 1004:
+ this._terminal.sendFocus = false;
+ break;
+ case 1005:
+ this._terminal.utfMouse = false;
+ break;
+ case 1006:
+ this._terminal.sgrMouse = false;
+ break;
+ case 1015:
+ this._terminal.urxvtMouse = false;
+ break;
+ case 25:
+ this._terminal.cursorHidden = true;
+ break;
+ case 1049:
+ case 47:
+ case 1047:
+ this._terminal.buffers.activateNormalBuffer();
+ this._terminal.selectionManager.setBuffer(this._terminal.buffer);
+ this._terminal.refresh(0, this._terminal.rows - 1);
+ this._terminal.viewport.syncScrollArea();
+ this._terminal.showCursor();
+ break;
+ case 2004:
+ this._terminal.bracketedPasteMode = false;
+ break;
+ }
+ }
+ };
+ InputHandler.prototype.charAttributes = function (params) {
+ if (params.length === 1 && params[0] === 0) {
+ this._terminal.curAttr = this._terminal.defAttr;
+ return;
+ }
+ var l = params.length;
+ var flags = this._terminal.curAttr >> 18;
+ var fg = (this._terminal.curAttr >> 9) & 0x1ff;
+ var bg = this._terminal.curAttr & 0x1ff;
+ var p;
+ for (var i = 0; i < l; i++) {
+ p = params[i];
+ if (p >= 30 && p <= 37) {
+ fg = p - 30;
+ }
+ else if (p >= 40 && p <= 47) {
+ bg = p - 40;
+ }
+ else if (p >= 90 && p <= 97) {
+ p += 8;
+ fg = p - 90;
+ }
+ else if (p >= 100 && p <= 107) {
+ p += 8;
+ bg = p - 100;
+ }
+ else if (p === 0) {
+ flags = this._terminal.defAttr >> 18;
+ fg = (this._terminal.defAttr >> 9) & 0x1ff;
+ bg = this._terminal.defAttr & 0x1ff;
+ }
+ else if (p === 1) {
+ flags |= Types_1.FLAGS.BOLD;
+ }
+ else if (p === 4) {
+ flags |= Types_1.FLAGS.UNDERLINE;
+ }
+ else if (p === 5) {
+ flags |= Types_1.FLAGS.BLINK;
+ }
+ else if (p === 7) {
+ flags |= Types_1.FLAGS.INVERSE;
+ }
+ else if (p === 8) {
+ flags |= Types_1.FLAGS.INVISIBLE;
+ }
+ else if (p === 2) {
+ flags |= Types_1.FLAGS.DIM;
+ }
+ else if (p === 22) {
+ flags &= ~Types_1.FLAGS.BOLD;
+ flags &= ~Types_1.FLAGS.DIM;
+ }
+ else if (p === 24) {
+ flags &= ~Types_1.FLAGS.UNDERLINE;
+ }
+ else if (p === 25) {
+ flags &= ~Types_1.FLAGS.BLINK;
+ }
+ else if (p === 27) {
+ flags &= ~Types_1.FLAGS.INVERSE;
+ }
+ else if (p === 28) {
+ flags &= ~Types_1.FLAGS.INVISIBLE;
+ }
+ else if (p === 39) {
+ fg = (this._terminal.defAttr >> 9) & 0x1ff;
+ }
+ else if (p === 49) {
+ bg = this._terminal.defAttr & 0x1ff;
+ }
+ else if (p === 38) {
+ if (params[i + 1] === 2) {
+ i += 2;
+ fg = this._terminal.matchColor(params[i] & 0xff, params[i + 1] & 0xff, params[i + 2] & 0xff);
+ if (fg === -1)
+ fg = 0x1ff;
+ i += 2;
+ }
+ else if (params[i + 1] === 5) {
+ i += 2;
+ p = params[i] & 0xff;
+ fg = p;
+ }
+ }
+ else if (p === 48) {
+ if (params[i + 1] === 2) {
+ i += 2;
+ bg = this._terminal.matchColor(params[i] & 0xff, params[i + 1] & 0xff, params[i + 2] & 0xff);
+ if (bg === -1)
+ bg = 0x1ff;
+ i += 2;
+ }
+ else if (params[i + 1] === 5) {
+ i += 2;
+ p = params[i] & 0xff;
+ bg = p;
+ }
+ }
+ else if (p === 100) {
+ fg = (this._terminal.defAttr >> 9) & 0x1ff;
+ bg = this._terminal.defAttr & 0x1ff;
+ }
+ else {
+ this._terminal.error('Unknown SGR attribute: %d.', p);
+ }
+ }
+ this._terminal.curAttr = (flags << 18) | (fg << 9) | bg;
+ };
+ InputHandler.prototype.deviceStatus = function (params) {
+ if (!this._terminal.prefix) {
+ switch (params[0]) {
+ case 5:
+ this._terminal.send(EscapeSequences_1.C0.ESC + '[0n');
+ break;
+ case 6:
+ this._terminal.send(EscapeSequences_1.C0.ESC + '['
+ + (this._terminal.buffer.y + 1)
+ + ';'
+ + (this._terminal.buffer.x + 1)
+ + 'R');
+ break;
+ }
+ }
+ else if (this._terminal.prefix === '?') {
+ switch (params[0]) {
+ case 6:
+ this._terminal.send(EscapeSequences_1.C0.ESC + '[?'
+ + (this._terminal.buffer.y + 1)
+ + ';'
+ + (this._terminal.buffer.x + 1)
+ + 'R');
+ break;
+ case 15:
+ break;
+ case 25:
+ break;
+ case 26:
+ break;
+ case 53:
+ break;
+ }
+ }
+ };
+ InputHandler.prototype.softReset = function (params) {
+ this._terminal.cursorHidden = false;
+ this._terminal.insertMode = false;
+ this._terminal.originMode = false;
+ this._terminal.wraparoundMode = true;
+ this._terminal.applicationKeypad = false;
+ this._terminal.viewport.syncScrollArea();
+ this._terminal.applicationCursor = false;
+ this._terminal.buffer.scrollTop = 0;
+ this._terminal.buffer.scrollBottom = this._terminal.rows - 1;
+ this._terminal.curAttr = this._terminal.defAttr;
+ this._terminal.buffer.x = this._terminal.buffer.y = 0;
+ this._terminal.charset = null;
+ this._terminal.glevel = 0;
+ this._terminal.charsets = [null];
+ };
+ InputHandler.prototype.setCursorStyle = function (params) {
+ var param = params[0] < 1 ? 1 : params[0];
+ switch (param) {
+ case 1:
+ case 2:
+ this._terminal.setOption('cursorStyle', 'block');
+ break;
+ case 3:
+ case 4:
+ this._terminal.setOption('cursorStyle', 'underline');
+ break;
+ case 5:
+ case 6:
+ this._terminal.setOption('cursorStyle', 'bar');
+ break;
+ }
+ var isBlinking = param % 2 === 1;
+ this._terminal.setOption('cursorBlink', isBlinking);
+ };
+ InputHandler.prototype.setScrollRegion = function (params) {
+ if (this._terminal.prefix)
+ return;
+ this._terminal.buffer.scrollTop = (params[0] || 1) - 1;
+ this._terminal.buffer.scrollBottom = (params[1] && params[1] <= this._terminal.rows ? params[1] : this._terminal.rows) - 1;
+ this._terminal.buffer.x = 0;
+ this._terminal.buffer.y = 0;
+ };
+ InputHandler.prototype.saveCursor = function (params) {
+ this._terminal.buffer.savedX = this._terminal.buffer.x;
+ this._terminal.buffer.savedY = this._terminal.buffer.y;
+ };
+ InputHandler.prototype.restoreCursor = function (params) {
+ this._terminal.buffer.x = this._terminal.buffer.savedX || 0;
+ this._terminal.buffer.y = this._terminal.buffer.savedY || 0;
+ };
+ return InputHandler;
+}());
+exports.InputHandler = InputHandler;
+
+
+
+},{"./Buffer":1,"./CharWidth":3,"./Charsets":4,"./EscapeSequences":6,"./renderer/Types":27}],9:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+ var extendStatics = Object.setPrototypeOf ||
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+ function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+ return function (d, b) {
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Types_1 = require("./Types");
+var MouseZoneManager_1 = require("./input/MouseZoneManager");
+var EventEmitter_1 = require("./EventEmitter");
+var protocolClause = '(https?:\\/\\/)';
+var domainCharacterSet = '[\\da-z\\.-]+';
+var negatedDomainCharacterSet = '[^\\da-z\\.-]+';
+var domainBodyClause = '(' + domainCharacterSet + ')';
+var tldClause = '([a-z\\.]{2,6})';
+var ipClause = '((\\d{1,3}\\.){3}\\d{1,3})';
+var localHostClause = '(localhost)';
+var portClause = '(:\\d{1,5})';
+var hostClause = '((' + domainBodyClause + '\\.' + tldClause + ')|' + ipClause + '|' + localHostClause + ')' + portClause + '?';
+var pathClause = '(\\/[\\/\\w\\.\\-%~]*)*';
+var queryStringHashFragmentCharacterSet = '[0-9\\w\\[\\]\\(\\)\\/\\?\\!#@$%&\'*+,:;~\\=\\.\\-]*';
+var queryStringClause = '(\\?' + queryStringHashFragmentCharacterSet + ')?';
+var hashFragmentClause = '(#' + queryStringHashFragmentCharacterSet + ')?';
+var negatedPathCharacterSet = '[^\\/\\w\\.\\-%]+';
+var bodyClause = hostClause + pathClause + queryStringClause + hashFragmentClause;
+var start = '(?:^|' + negatedDomainCharacterSet + ')(';
+var end = ')($|' + negatedPathCharacterSet + ')';
+var strictUrlRegex = new RegExp(start + protocolClause + bodyClause + end);
+var HYPERTEXT_LINK_MATCHER_ID = 0;
+var Linkifier = (function (_super) {
+ __extends(Linkifier, _super);
+ function Linkifier(_terminal) {
+ var _this = _super.call(this) || this;
+ _this._terminal = _terminal;
+ _this._linkMatchers = [];
+ _this._nextLinkMatcherId = HYPERTEXT_LINK_MATCHER_ID;
+ _this._rowsToLinkify = {
+ start: null,
+ end: null
+ };
+ _this.registerLinkMatcher(strictUrlRegex, null, { matchIndex: 1 });
+ return _this;
+ }
+ Linkifier.prototype.attachToDom = function (mouseZoneManager) {
+ this._mouseZoneManager = mouseZoneManager;
+ };
+ Linkifier.prototype.linkifyRows = function (start, end) {
+ var _this = this;
+ if (!this._mouseZoneManager) {
+ return;
+ }
+ if (!this._rowsToLinkify.start) {
+ this._rowsToLinkify.start = start;
+ this._rowsToLinkify.end = end;
+ }
+ else {
+ this._rowsToLinkify.start = this._rowsToLinkify.start < start ? this._rowsToLinkify.start : start;
+ this._rowsToLinkify.end = this._rowsToLinkify.end > end ? this._rowsToLinkify.end : end;
+ }
+ this._mouseZoneManager.clearAll(start, end);
+ if (this._rowsTimeoutId) {
+ clearTimeout(this._rowsTimeoutId);
+ }
+ this._rowsTimeoutId = setTimeout(function () { return _this._linkifyRows(); }, Linkifier.TIME_BEFORE_LINKIFY);
+ };
+ Linkifier.prototype._linkifyRows = function () {
+ this._rowsTimeoutId = null;
+ for (var i = this._rowsToLinkify.start; i <= this._rowsToLinkify.end; i++) {
+ this._linkifyRow(i);
+ }
+ this._rowsToLinkify.start = null;
+ this._rowsToLinkify.end = null;
+ };
+ Linkifier.prototype.setHypertextLinkHandler = function (handler) {
+ this._linkMatchers[HYPERTEXT_LINK_MATCHER_ID].handler = handler;
+ };
+ Linkifier.prototype.setHypertextValidationCallback = function (callback) {
+ this._linkMatchers[HYPERTEXT_LINK_MATCHER_ID].validationCallback = callback;
+ };
+ Linkifier.prototype.registerLinkMatcher = function (regex, handler, options) {
+ if (options === void 0) { options = {}; }
+ if (this._nextLinkMatcherId !== HYPERTEXT_LINK_MATCHER_ID && !handler) {
+ throw new Error('handler must be defined');
+ }
+ var matcher = {
+ id: this._nextLinkMatcherId++,
+ regex: regex,
+ handler: handler,
+ matchIndex: options.matchIndex,
+ validationCallback: options.validationCallback,
+ hoverTooltipCallback: options.tooltipCallback,
+ hoverLeaveCallback: options.leaveCallback,
+ priority: options.priority || 0
+ };
+ this._addLinkMatcherToList(matcher);
+ return matcher.id;
+ };
+ Linkifier.prototype._addLinkMatcherToList = function (matcher) {
+ if (this._linkMatchers.length === 0) {
+ this._linkMatchers.push(matcher);
+ return;
+ }
+ for (var i = this._linkMatchers.length - 1; i >= 0; i--) {
+ if (matcher.priority <= this._linkMatchers[i].priority) {
+ this._linkMatchers.splice(i + 1, 0, matcher);
+ return;
+ }
+ }
+ this._linkMatchers.splice(0, 0, matcher);
+ };
+ Linkifier.prototype.deregisterLinkMatcher = function (matcherId) {
+ for (var i = 1; i < this._linkMatchers.length; i++) {
+ if (this._linkMatchers[i].id === matcherId) {
+ this._linkMatchers.splice(i, 1);
+ return true;
+ }
+ }
+ return false;
+ };
+ Linkifier.prototype._linkifyRow = function (rowIndex) {
+ var absoluteRowIndex = this._terminal.buffer.ydisp + rowIndex;
+ if (absoluteRowIndex >= this._terminal.buffer.lines.length) {
+ return;
+ }
+ var text = this._terminal.buffer.translateBufferLineToString(absoluteRowIndex, false);
+ for (var i = 0; i < this._linkMatchers.length; i++) {
+ this._doLinkifyRow(rowIndex, text, this._linkMatchers[i]);
+ }
+ };
+ Linkifier.prototype._doLinkifyRow = function (rowIndex, text, matcher, offset) {
+ var _this = this;
+ if (offset === void 0) { offset = 0; }
+ var result = [];
+ var isHttpLinkMatcher = matcher.id === HYPERTEXT_LINK_MATCHER_ID;
+ var match = text.match(matcher.regex);
+ if (!match || match.length === 0) {
+ return;
+ }
+ var uri = match[typeof matcher.matchIndex !== 'number' ? 0 : matcher.matchIndex];
+ var index = text.indexOf(uri);
+ if (matcher.validationCallback) {
+ matcher.validationCallback(uri, function (isValid) {
+ if (_this._rowsTimeoutId) {
+ return;
+ }
+ if (isValid) {
+ _this._addLink(offset + index, rowIndex, uri, matcher);
+ }
+ });
+ }
+ else {
+ this._addLink(offset + index, rowIndex, uri, matcher);
+ }
+ var remainingStartIndex = index + uri.length;
+ var remainingText = text.substr(remainingStartIndex);
+ if (remainingText.length > 0) {
+ this._doLinkifyRow(rowIndex, remainingText, matcher, offset + remainingStartIndex);
+ }
+ };
+ Linkifier.prototype._addLink = function (x, y, uri, matcher) {
+ var _this = this;
+ this._mouseZoneManager.add(new MouseZoneManager_1.MouseZone(x + 1, x + 1 + uri.length, y + 1, function (e) {
+ if (matcher.handler) {
+ return matcher.handler(e, uri);
+ }
+ window.open(uri, '_blank');
+ }, function (e) {
+ _this.emit(Types_1.LinkHoverEventTypes.HOVER, { x: x, y: y, length: uri.length });
+ _this._terminal.element.style.cursor = 'pointer';
+ }, function (e) {
+ _this.emit(Types_1.LinkHoverEventTypes.TOOLTIP, { x: x, y: y, length: uri.length });
+ if (matcher.hoverTooltipCallback) {
+ matcher.hoverTooltipCallback(e, uri);
+ }
+ }, function () {
+ _this.emit(Types_1.LinkHoverEventTypes.LEAVE, { x: x, y: y, length: uri.length });
+ _this._terminal.element.style.cursor = '';
+ if (matcher.hoverLeaveCallback) {
+ matcher.hoverLeaveCallback();
+ }
+ }));
+ };
+ Linkifier.TIME_BEFORE_LINKIFY = 200;
+ return Linkifier;
+}(EventEmitter_1.EventEmitter));
+exports.Linkifier = Linkifier;
+
+
+
+},{"./EventEmitter":7,"./Types":14,"./input/MouseZoneManager":17}],10:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var EscapeSequences_1 = require("./EscapeSequences");
+var Charsets_1 = require("./Charsets");
+var normalStateHandler = {};
+normalStateHandler[EscapeSequences_1.C0.BEL] = function (parser, handler) { return handler.bell(); };
+normalStateHandler[EscapeSequences_1.C0.LF] = function (parser, handler) { return handler.lineFeed(); };
+normalStateHandler[EscapeSequences_1.C0.VT] = normalStateHandler[EscapeSequences_1.C0.LF];
+normalStateHandler[EscapeSequences_1.C0.FF] = normalStateHandler[EscapeSequences_1.C0.LF];
+normalStateHandler[EscapeSequences_1.C0.CR] = function (parser, handler) { return handler.carriageReturn(); };
+normalStateHandler[EscapeSequences_1.C0.BS] = function (parser, handler) { return handler.backspace(); };
+normalStateHandler[EscapeSequences_1.C0.HT] = function (parser, handler) { return handler.tab(); };
+normalStateHandler[EscapeSequences_1.C0.SO] = function (parser, handler) { return handler.shiftOut(); };
+normalStateHandler[EscapeSequences_1.C0.SI] = function (parser, handler) { return handler.shiftIn(); };
+normalStateHandler[EscapeSequences_1.C0.ESC] = function (parser, handler) { return parser.setState(ParserState.ESCAPED); };
+var escapedStateHandler = {};
+escapedStateHandler['['] = function (parser, terminal) {
+ terminal.params = [];
+ terminal.currentParam = 0;
+ parser.setState(ParserState.CSI_PARAM);
+};
+escapedStateHandler[']'] = function (parser, terminal) {
+ terminal.params = [];
+ terminal.currentParam = 0;
+ parser.setState(ParserState.OSC);
+};
+escapedStateHandler['P'] = function (parser, terminal) {
+ terminal.params = [];
+ terminal.currentParam = 0;
+ parser.setState(ParserState.DCS);
+};
+escapedStateHandler['_'] = function (parser, terminal) {
+ parser.setState(ParserState.IGNORE);
+};
+escapedStateHandler['^'] = function (parser, terminal) {
+ parser.setState(ParserState.IGNORE);
+};
+escapedStateHandler['c'] = function (parser, terminal) {
+ terminal.reset();
+};
+escapedStateHandler['E'] = function (parser, terminal) {
+ terminal.buffer.x = 0;
+ terminal.index();
+ parser.setState(ParserState.NORMAL);
+};
+escapedStateHandler['D'] = function (parser, terminal) {
+ terminal.index();
+ parser.setState(ParserState.NORMAL);
+};
+escapedStateHandler['M'] = function (parser, terminal) {
+ terminal.reverseIndex();
+ parser.setState(ParserState.NORMAL);
+};
+escapedStateHandler['%'] = function (parser, terminal) {
+ terminal.setgLevel(0);
+ terminal.setgCharset(0, Charsets_1.DEFAULT_CHARSET);
+ parser.setState(ParserState.NORMAL);
+ parser.skipNextChar();
+};
+escapedStateHandler[EscapeSequences_1.C0.CAN] = function (parser) { return parser.setState(ParserState.NORMAL); };
+var csiParamStateHandler = {};
+csiParamStateHandler['?'] = function (parser) { return parser.setPrefix('?'); };
+csiParamStateHandler['>'] = function (parser) { return parser.setPrefix('>'); };
+csiParamStateHandler['!'] = function (parser) { return parser.setPrefix('!'); };
+csiParamStateHandler['0'] = function (parser) { return parser.setParam(parser.getParam() * 10); };
+csiParamStateHandler['1'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 1); };
+csiParamStateHandler['2'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 2); };
+csiParamStateHandler['3'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 3); };
+csiParamStateHandler['4'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 4); };
+csiParamStateHandler['5'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 5); };
+csiParamStateHandler['6'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 6); };
+csiParamStateHandler['7'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 7); };
+csiParamStateHandler['8'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 8); };
+csiParamStateHandler['9'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 9); };
+csiParamStateHandler['$'] = function (parser) { return parser.setPostfix('$'); };
+csiParamStateHandler['"'] = function (parser) { return parser.setPostfix('"'); };
+csiParamStateHandler[' '] = function (parser) { return parser.setPostfix(' '); };
+csiParamStateHandler['\''] = function (parser) { return parser.setPostfix('\''); };
+csiParamStateHandler[';'] = function (parser) { return parser.finalizeParam(); };
+csiParamStateHandler[EscapeSequences_1.C0.CAN] = function (parser) { return parser.setState(ParserState.NORMAL); };
+var csiStateHandler = {};
+csiStateHandler['@'] = function (handler, params, prefix) { return handler.insertChars(params); };
+csiStateHandler['A'] = function (handler, params, prefix) { return handler.cursorUp(params); };
+csiStateHandler['B'] = function (handler, params, prefix) { return handler.cursorDown(params); };
+csiStateHandler['C'] = function (handler, params, prefix) { return handler.cursorForward(params); };
+csiStateHandler['D'] = function (handler, params, prefix) { return handler.cursorBackward(params); };
+csiStateHandler['E'] = function (handler, params, prefix) { return handler.cursorNextLine(params); };
+csiStateHandler['F'] = function (handler, params, prefix) { return handler.cursorPrecedingLine(params); };
+csiStateHandler['G'] = function (handler, params, prefix) { return handler.cursorCharAbsolute(params); };
+csiStateHandler['H'] = function (handler, params, prefix) { return handler.cursorPosition(params); };
+csiStateHandler['I'] = function (handler, params, prefix) { return handler.cursorForwardTab(params); };
+csiStateHandler['J'] = function (handler, params, prefix) { return handler.eraseInDisplay(params); };
+csiStateHandler['K'] = function (handler, params, prefix) { return handler.eraseInLine(params); };
+csiStateHandler['L'] = function (handler, params, prefix) { return handler.insertLines(params); };
+csiStateHandler['M'] = function (handler, params, prefix) { return handler.deleteLines(params); };
+csiStateHandler['P'] = function (handler, params, prefix) { return handler.deleteChars(params); };
+csiStateHandler['S'] = function (handler, params, prefix) { return handler.scrollUp(params); };
+csiStateHandler['T'] = function (handler, params, prefix) {
+ if (params.length < 2 && !prefix) {
+ handler.scrollDown(params);
+ }
+};
+csiStateHandler['X'] = function (handler, params, prefix) { return handler.eraseChars(params); };
+csiStateHandler['Z'] = function (handler, params, prefix) { return handler.cursorBackwardTab(params); };
+csiStateHandler['`'] = function (handler, params, prefix) { return handler.charPosAbsolute(params); };
+csiStateHandler['a'] = function (handler, params, prefix) { return handler.HPositionRelative(params); };
+csiStateHandler['b'] = function (handler, params, prefix) { return handler.repeatPrecedingCharacter(params); };
+csiStateHandler['c'] = function (handler, params, prefix) { return handler.sendDeviceAttributes(params); };
+csiStateHandler['d'] = function (handler, params, prefix) { return handler.linePosAbsolute(params); };
+csiStateHandler['e'] = function (handler, params, prefix) { return handler.VPositionRelative(params); };
+csiStateHandler['f'] = function (handler, params, prefix) { return handler.HVPosition(params); };
+csiStateHandler['g'] = function (handler, params, prefix) { return handler.tabClear(params); };
+csiStateHandler['h'] = function (handler, params, prefix) { return handler.setMode(params); };
+csiStateHandler['l'] = function (handler, params, prefix) { return handler.resetMode(params); };
+csiStateHandler['m'] = function (handler, params, prefix) { return handler.charAttributes(params); };
+csiStateHandler['n'] = function (handler, params, prefix) { return handler.deviceStatus(params); };
+csiStateHandler['p'] = function (handler, params, prefix) {
+ switch (prefix) {
+ case '!':
+ handler.softReset(params);
+ break;
+ }
+};
+csiStateHandler['q'] = function (handler, params, prefix, postfix) {
+ if (postfix === ' ') {
+ handler.setCursorStyle(params);
+ }
+};
+csiStateHandler['r'] = function (handler, params) { return handler.setScrollRegion(params); };
+csiStateHandler['s'] = function (handler, params) { return handler.saveCursor(params); };
+csiStateHandler['u'] = function (handler, params) { return handler.restoreCursor(params); };
+csiStateHandler[EscapeSequences_1.C0.CAN] = function (handler, params, prefix, postfix, parser) { return parser.setState(ParserState.NORMAL); };
+var ParserState;
+(function (ParserState) {
+ ParserState[ParserState["NORMAL"] = 0] = "NORMAL";
+ ParserState[ParserState["ESCAPED"] = 1] = "ESCAPED";
+ ParserState[ParserState["CSI_PARAM"] = 2] = "CSI_PARAM";
+ ParserState[ParserState["CSI"] = 3] = "CSI";
+ ParserState[ParserState["OSC"] = 4] = "OSC";
+ ParserState[ParserState["CHARSET"] = 5] = "CHARSET";
+ ParserState[ParserState["DCS"] = 6] = "DCS";
+ ParserState[ParserState["IGNORE"] = 7] = "IGNORE";
+})(ParserState = exports.ParserState || (exports.ParserState = {}));
+var Parser = (function () {
+ function Parser(_inputHandler, _terminal) {
+ this._inputHandler = _inputHandler;
+ this._terminal = _terminal;
+ this._state = ParserState.NORMAL;
+ }
+ Parser.prototype.parse = function (data) {
+ var l = data.length;
+ var j;
+ var cs;
+ var ch;
+ var code;
+ var low;
+ var cursorStartX = this._terminal.buffer.x;
+ var cursorStartY = this._terminal.buffer.y;
+ if (this._terminal.debug) {
+ this._terminal.log('data: ' + data);
+ }
+ this._position = 0;
+ if (this._terminal.surrogate_high) {
+ data = this._terminal.surrogate_high + data;
+ this._terminal.surrogate_high = '';
+ }
+ for (; this._position < l; this._position++) {
+ ch = data[this._position];
+ code = data.charCodeAt(this._position);
+ if (0xD800 <= code && code <= 0xDBFF) {
+ low = data.charCodeAt(this._position + 1);
+ if (isNaN(low)) {
+ this._terminal.surrogate_high = ch;
+ continue;
+ }
+ code = ((code - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
+ ch += data.charAt(this._position + 1);
+ }
+ if (0xDC00 <= code && code <= 0xDFFF)
+ continue;
+ switch (this._state) {
+ case ParserState.NORMAL:
+ if (ch in normalStateHandler) {
+ normalStateHandler[ch](this, this._inputHandler);
+ }
+ else {
+ this._inputHandler.addChar(ch, code);
+ }
+ break;
+ case ParserState.ESCAPED:
+ if (ch in escapedStateHandler) {
+ escapedStateHandler[ch](this, this._terminal);
+ break;
+ }
+ switch (ch) {
+ case '(':
+ case ')':
+ case '*':
+ case '+':
+ case '-':
+ case '.':
+ switch (ch) {
+ case '(':
+ this._terminal.gcharset = 0;
+ break;
+ case ')':
+ this._terminal.gcharset = 1;
+ break;
+ case '*':
+ this._terminal.gcharset = 2;
+ break;
+ case '+':
+ this._terminal.gcharset = 3;
+ break;
+ case '-':
+ this._terminal.gcharset = 1;
+ break;
+ case '.':
+ this._terminal.gcharset = 2;
+ break;
+ }
+ this._state = ParserState.CHARSET;
+ break;
+ case '/':
+ this._terminal.gcharset = 3;
+ this._state = ParserState.CHARSET;
+ this._position--;
+ break;
+ case 'N':
+ break;
+ case 'O':
+ break;
+ case 'n':
+ this._terminal.setgLevel(2);
+ break;
+ case 'o':
+ this._terminal.setgLevel(3);
+ break;
+ case '|':
+ this._terminal.setgLevel(3);
+ break;
+ case '}':
+ this._terminal.setgLevel(2);
+ break;
+ case '~':
+ this._terminal.setgLevel(1);
+ break;
+ case '7':
+ this._inputHandler.saveCursor();
+ this._state = ParserState.NORMAL;
+ break;
+ case '8':
+ this._inputHandler.restoreCursor();
+ this._state = ParserState.NORMAL;
+ break;
+ case '#':
+ this._state = ParserState.NORMAL;
+ this._position++;
+ break;
+ case 'H':
+ this._terminal.tabSet();
+ this._state = ParserState.NORMAL;
+ break;
+ case '=':
+ this._terminal.log('Serial port requested application keypad.');
+ this._terminal.applicationKeypad = true;
+ if (this._terminal.viewport) {
+ this._terminal.viewport.syncScrollArea();
+ }
+ this._state = ParserState.NORMAL;
+ break;
+ case '>':
+ this._terminal.log('Switching back to normal keypad.');
+ this._terminal.applicationKeypad = false;
+ if (this._terminal.viewport) {
+ this._terminal.viewport.syncScrollArea();
+ }
+ this._state = ParserState.NORMAL;
+ break;
+ default:
+ this._state = ParserState.NORMAL;
+ this._terminal.error('Unknown ESC control: %s.', ch);
+ break;
+ }
+ break;
+ case ParserState.CHARSET:
+ if (ch in Charsets_1.CHARSETS) {
+ cs = Charsets_1.CHARSETS[ch];
+ if (ch === '/') {
+ this.skipNextChar();
+ }
+ }
+ else {
+ cs = Charsets_1.DEFAULT_CHARSET;
+ }
+ this._terminal.setgCharset(this._terminal.gcharset, cs);
+ this._terminal.gcharset = null;
+ this._state = ParserState.NORMAL;
+ break;
+ case ParserState.OSC:
+ if (ch === EscapeSequences_1.C0.ESC || ch === EscapeSequences_1.C0.BEL) {
+ if (ch === EscapeSequences_1.C0.ESC)
+ this._position++;
+ this._terminal.params.push(this._terminal.currentParam);
+ switch (this._terminal.params[0]) {
+ case 0:
+ case 1:
+ case 2:
+ if (this._terminal.params[1]) {
+ this._terminal.title = this._terminal.params[1];
+ this._terminal.handleTitle(this._terminal.title);
+ }
+ break;
+ case 3:
+ break;
+ case 4:
+ case 5:
+ break;
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18:
+ case 19:
+ break;
+ case 46:
+ break;
+ case 50:
+ break;
+ case 51:
+ break;
+ case 52:
+ break;
+ case 104:
+ case 105:
+ case 110:
+ case 111:
+ case 112:
+ case 113:
+ case 114:
+ case 115:
+ case 116:
+ case 117:
+ case 118:
+ break;
+ }
+ this._terminal.params = [];
+ this._terminal.currentParam = 0;
+ this._state = ParserState.NORMAL;
+ }
+ else {
+ if (!this._terminal.params.length) {
+ if (ch >= '0' && ch <= '9') {
+ this._terminal.currentParam =
+ this._terminal.currentParam * 10 + ch.charCodeAt(0) - 48;
+ }
+ else if (ch === ';') {
+ this._terminal.params.push(this._terminal.currentParam);
+ this._terminal.currentParam = '';
+ }
+ }
+ else {
+ this._terminal.currentParam += ch;
+ }
+ }
+ break;
+ case ParserState.CSI_PARAM:
+ if (ch in csiParamStateHandler) {
+ csiParamStateHandler[ch](this);
+ break;
+ }
+ this.finalizeParam();
+ this._state = ParserState.CSI;
+ case ParserState.CSI:
+ if (ch in csiStateHandler) {
+ if (this._terminal.debug) {
+ this._terminal.log("CSI " + (this._terminal.prefix ? this._terminal.prefix : '') + " " + (this._terminal.params ? this._terminal.params.join(';') : '') + " " + (this._terminal.postfix ? this._terminal.postfix : '') + " " + ch);
+ }
+ csiStateHandler[ch](this._inputHandler, this._terminal.params, this._terminal.prefix, this._terminal.postfix, this);
+ }
+ else {
+ this._terminal.error('Unknown CSI code: %s.', ch);
+ }
+ this._state = ParserState.NORMAL;
+ this._terminal.prefix = '';
+ this._terminal.postfix = '';
+ break;
+ case ParserState.DCS:
+ if (ch === EscapeSequences_1.C0.ESC || ch === EscapeSequences_1.C0.BEL) {
+ if (ch === EscapeSequences_1.C0.ESC)
+ this._position++;
+ var pt = void 0;
+ var valid = void 0;
+ switch (this._terminal.prefix) {
+ case '':
+ break;
+ case '$q':
+ pt = this._terminal.currentParam;
+ valid = false;
+ switch (pt) {
+ case '"q':
+ pt = '0"q';
+ break;
+ case '"p':
+ pt = '61"p';
+ break;
+ case 'r':
+ pt = ''
+ + (this._terminal.buffer.scrollTop + 1)
+ + ';'
+ + (this._terminal.buffer.scrollBottom + 1)
+ + 'r';
+ break;
+ case 'm':
+ pt = '0m';
+ break;
+ default:
+ this._terminal.error('Unknown DCS Pt: %s.', pt);
+ pt = '';
+ break;
+ }
+ this._terminal.send(EscapeSequences_1.C0.ESC + 'P' + +valid + '$r' + pt + EscapeSequences_1.C0.ESC + '\\');
+ break;
+ case '+p':
+ break;
+ case '+q':
+ pt = this._terminal.currentParam;
+ valid = false;
+ this._terminal.send(EscapeSequences_1.C0.ESC + 'P' + +valid + '+r' + pt + EscapeSequences_1.C0.ESC + '\\');
+ break;
+ default:
+ this._terminal.error('Unknown DCS prefix: %s.', this._terminal.prefix);
+ break;
+ }
+ this._terminal.currentParam = 0;
+ this._terminal.prefix = '';
+ this._state = ParserState.NORMAL;
+ }
+ else if (!this._terminal.currentParam) {
+ if (!this._terminal.prefix && ch !== '$' && ch !== '+') {
+ this._terminal.currentParam = ch;
+ }
+ else if (this._terminal.prefix.length === 2) {
+ this._terminal.currentParam = ch;
+ }
+ else {
+ this._terminal.prefix += ch;
+ }
+ }
+ else {
+ this._terminal.currentParam += ch;
+ }
+ break;
+ case ParserState.IGNORE:
+ if (ch === EscapeSequences_1.C0.ESC || ch === EscapeSequences_1.C0.BEL) {
+ if (ch === EscapeSequences_1.C0.ESC)
+ this._position++;
+ this._state = ParserState.NORMAL;
+ }
+ break;
+ }
+ }
+ if (this._terminal.buffer.x !== cursorStartX || this._terminal.buffer.y !== cursorStartY) {
+ this._terminal.emit('cursormove');
+ }
+ return this._state;
+ };
+ Parser.prototype.setState = function (state) {
+ this._state = state;
+ };
+ Parser.prototype.setPrefix = function (prefix) {
+ this._terminal.prefix = prefix;
+ };
+ Parser.prototype.setPostfix = function (postfix) {
+ this._terminal.postfix = postfix;
+ };
+ Parser.prototype.setParam = function (param) {
+ this._terminal.currentParam = param;
+ };
+ Parser.prototype.getParam = function () {
+ return this._terminal.currentParam;
+ };
+ Parser.prototype.finalizeParam = function () {
+ this._terminal.params.push(this._terminal.currentParam);
+ this._terminal.currentParam = 0;
+ };
+ Parser.prototype.skipNextChar = function () {
+ this._position++;
+ };
+ return Parser;
+}());
+exports.Parser = Parser;
+
+
+
+},{"./Charsets":4,"./EscapeSequences":6}],11:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+ var extendStatics = Object.setPrototypeOf ||
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+ function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+ return function (d, b) {
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var MouseHelper_1 = require("./utils/MouseHelper");
+var Browser = require("./utils/Browser");
+var EventEmitter_1 = require("./EventEmitter");
+var SelectionModel_1 = require("./SelectionModel");
+var Buffer_1 = require("./Buffer");
+var DRAG_SCROLL_MAX_THRESHOLD = 50;
+var DRAG_SCROLL_MAX_SPEED = 15;
+var DRAG_SCROLL_INTERVAL = 50;
+var WORD_SEPARATORS = ' ()[]{}\'"';
+var NON_BREAKING_SPACE_CHAR = String.fromCharCode(160);
+var ALL_NON_BREAKING_SPACE_REGEX = new RegExp(NON_BREAKING_SPACE_CHAR, 'g');
+var SelectionMode;
+(function (SelectionMode) {
+ SelectionMode[SelectionMode["NORMAL"] = 0] = "NORMAL";
+ SelectionMode[SelectionMode["WORD"] = 1] = "WORD";
+ SelectionMode[SelectionMode["LINE"] = 2] = "LINE";
+})(SelectionMode || (SelectionMode = {}));
+var SelectionManager = (function (_super) {
+ __extends(SelectionManager, _super);
+ function SelectionManager(_terminal, _buffer, _charMeasure) {
+ var _this = _super.call(this) || this;
+ _this._terminal = _terminal;
+ _this._buffer = _buffer;
+ _this._charMeasure = _charMeasure;
+ _this._enabled = true;
+ _this._initListeners();
+ _this.enable();
+ _this._model = new SelectionModel_1.SelectionModel(_terminal);
+ _this._activeSelectionMode = SelectionMode.NORMAL;
+ return _this;
+ }
+ SelectionManager.prototype._initListeners = function () {
+ var _this = this;
+ this._mouseMoveListener = function (event) { return _this._onMouseMove(event); };
+ this._mouseUpListener = function (event) { return _this._onMouseUp(event); };
+ this._buffer.lines.on('trim', function (amount) { return _this._onTrim(amount); });
+ };
+ SelectionManager.prototype.disable = function () {
+ this.clearSelection();
+ this._enabled = false;
+ };
+ SelectionManager.prototype.enable = function () {
+ this._enabled = true;
+ };
+ SelectionManager.prototype.setBuffer = function (buffer) {
+ this._buffer = buffer;
+ this.clearSelection();
+ };
+ Object.defineProperty(SelectionManager.prototype, "selectionStart", {
+ get: function () { return this._model.finalSelectionStart; },
+ enumerable: true,
+ configurable: true
+ });
+ Object.defineProperty(SelectionManager.prototype, "selectionEnd", {
+ get: function () { return this._model.finalSelectionEnd; },
+ enumerable: true,
+ configurable: true
+ });
+ Object.defineProperty(SelectionManager.prototype, "hasSelection", {
+ get: function () {
+ var start = this._model.finalSelectionStart;
+ var end = this._model.finalSelectionEnd;
+ if (!start || !end) {
+ return false;
+ }
+ return start[0] !== end[0] || start[1] !== end[1];
+ },
+ enumerable: true,
+ configurable: true
+ });
+ Object.defineProperty(SelectionManager.prototype, "selectionText", {
+ get: function () {
+ var start = this._model.finalSelectionStart;
+ var end = this._model.finalSelectionEnd;
+ if (!start || !end) {
+ return '';
+ }
+ var startRowEndCol = start[1] === end[1] ? end[0] : null;
+ var result = [];
+ result.push(this._buffer.translateBufferLineToString(start[1], true, start[0], startRowEndCol));
+ for (var i = start[1] + 1; i <= end[1] - 1; i++) {
+ var bufferLine = this._buffer.lines.get(i);
+ var lineText = this._buffer.translateBufferLineToString(i, true);
+ if (bufferLine.isWrapped) {
+ result[result.length - 1] += lineText;
+ }
+ else {
+ result.push(lineText);
+ }
+ }
+ if (start[1] !== end[1]) {
+ var bufferLine = this._buffer.lines.get(end[1]);
+ var lineText = this._buffer.translateBufferLineToString(end[1], true, 0, end[0]);
+ if (bufferLine.isWrapped) {
+ result[result.length - 1] += lineText;
+ }
+ else {
+ result.push(lineText);
+ }
+ }
+ var formattedResult = result.map(function (line) {
+ return line.replace(ALL_NON_BREAKING_SPACE_REGEX, ' ');
+ }).join(Browser.isMSWindows ? '\r\n' : '\n');
+ return formattedResult;
+ },
+ enumerable: true,
+ configurable: true
+ });
+ SelectionManager.prototype.clearSelection = function () {
+ this._model.clearSelection();
+ this._removeMouseDownListeners();
+ this.refresh();
+ };
+ SelectionManager.prototype.refresh = function (isNewSelection) {
+ var _this = this;
+ if (!this._refreshAnimationFrame) {
+ this._refreshAnimationFrame = window.requestAnimationFrame(function () { return _this._refresh(); });
+ }
+ if (Browser.isLinux && isNewSelection) {
+ var selectionText = this.selectionText;
+ if (selectionText.length) {
+ this.emit('newselection', this.selectionText);
+ }
+ }
+ };
+ SelectionManager.prototype._refresh = function () {
+ this._refreshAnimationFrame = null;
+ this.emit('refresh', { start: this._model.finalSelectionStart, end: this._model.finalSelectionEnd });
+ };
+ SelectionManager.prototype.selectAll = function () {
+ this._model.isSelectAllActive = true;
+ this.refresh();
+ this.emit('selection');
+ };
+ SelectionManager.prototype._onTrim = function (amount) {
+ var needsRefresh = this._model.onTrim(amount);
+ if (needsRefresh) {
+ this.refresh();
+ }
+ };
+ SelectionManager.prototype._getMouseBufferCoords = function (event) {
+ var coords = this._terminal.mouseHelper.getCoords(event, this._terminal.element, this._charMeasure, this._terminal.options.lineHeight, this._terminal.cols, this._terminal.rows, true);
+ if (!coords) {
+ return null;
+ }
+ coords[0]--;
+ coords[1]--;
+ coords[1] += this._terminal.buffer.ydisp;
+ return coords;
+ };
+ SelectionManager.prototype._getMouseEventScrollAmount = function (event) {
+ var offset = MouseHelper_1.MouseHelper.getCoordsRelativeToElement(event, this._terminal.element)[1];
+ var terminalHeight = this._terminal.rows * Math.ceil(this._charMeasure.height * this._terminal.options.lineHeight);
+ if (offset >= 0 && offset <= terminalHeight) {
+ return 0;
+ }
+ if (offset > terminalHeight) {
+ offset -= terminalHeight;
+ }
+ offset = Math.min(Math.max(offset, -DRAG_SCROLL_MAX_THRESHOLD), DRAG_SCROLL_MAX_THRESHOLD);
+ offset /= DRAG_SCROLL_MAX_THRESHOLD;
+ return (offset / Math.abs(offset)) + Math.round(offset * (DRAG_SCROLL_MAX_SPEED - 1));
+ };
+ SelectionManager.prototype.shouldForceSelection = function (event) {
+ return Browser.isMac ? event.altKey : event.shiftKey;
+ };
+ SelectionManager.prototype.onMouseDown = function (event) {
+ if (event.button === 2 && this.hasSelection) {
+ return;
+ }
+ if (event.button !== 0) {
+ return;
+ }
+ if (!this._enabled) {
+ if (!this.shouldForceSelection(event)) {
+ return;
+ }
+ event.stopPropagation();
+ }
+ event.preventDefault();
+ this._dragScrollAmount = 0;
+ if (this._enabled && event.shiftKey) {
+ this._onIncrementalClick(event);
+ }
+ else {
+ if (event.detail === 1) {
+ this._onSingleClick(event);
+ }
+ else if (event.detail === 2) {
+ this._onDoubleClick(event);
+ }
+ else if (event.detail === 3) {
+ this._onTripleClick(event);
+ }
+ }
+ this._addMouseDownListeners();
+ this.refresh(true);
+ };
+ SelectionManager.prototype._addMouseDownListeners = function () {
+ var _this = this;
+ this._terminal.element.ownerDocument.addEventListener('mousemove', this._mouseMoveListener);
+ this._terminal.element.ownerDocument.addEventListener('mouseup', this._mouseUpListener);
+ this._dragScrollIntervalTimer = setInterval(function () { return _this._dragScroll(); }, DRAG_SCROLL_INTERVAL);
+ };
+ SelectionManager.prototype._removeMouseDownListeners = function () {
+ this._terminal.element.ownerDocument.removeEventListener('mousemove', this._mouseMoveListener);
+ this._terminal.element.ownerDocument.removeEventListener('mouseup', this._mouseUpListener);
+ clearInterval(this._dragScrollIntervalTimer);
+ this._dragScrollIntervalTimer = null;
+ };
+ SelectionManager.prototype._onIncrementalClick = function (event) {
+ if (this._model.selectionStart) {
+ this._model.selectionEnd = this._getMouseBufferCoords(event);
+ }
+ };
+ SelectionManager.prototype._onSingleClick = function (event) {
+ this._model.selectionStartLength = 0;
+ this._model.isSelectAllActive = false;
+ this._activeSelectionMode = SelectionMode.NORMAL;
+ this._model.selectionStart = this._getMouseBufferCoords(event);
+ if (!this._model.selectionStart) {
+ return;
+ }
+ this._model.selectionEnd = null;
+ var line = this._buffer.lines.get(this._model.selectionStart[1]);
+ if (!line) {
+ return;
+ }
+ if (line.length >= this._model.selectionStart[0]) {
+ return;
+ }
+ var char = line[this._model.selectionStart[0]];
+ if (char[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0) {
+ this._model.selectionStart[0]++;
+ }
+ };
+ SelectionManager.prototype._onDoubleClick = function (event) {
+ var coords = this._getMouseBufferCoords(event);
+ if (coords) {
+ this._activeSelectionMode = SelectionMode.WORD;
+ this._selectWordAt(coords);
+ }
+ };
+ SelectionManager.prototype._onTripleClick = function (event) {
+ var coords = this._getMouseBufferCoords(event);
+ if (coords) {
+ this._activeSelectionMode = SelectionMode.LINE;
+ this._selectLineAt(coords[1]);
+ }
+ };
+ SelectionManager.prototype._onMouseMove = function (event) {
+ event.stopImmediatePropagation();
+ var previousSelectionEnd = this._model.selectionEnd ? [this._model.selectionEnd[0], this._model.selectionEnd[1]] : null;
+ this._model.selectionEnd = this._getMouseBufferCoords(event);
+ if (!this._model.selectionEnd) {
+ this.refresh(true);
+ return;
+ }
+ if (this._activeSelectionMode === SelectionMode.LINE) {
+ if (this._model.selectionEnd[1] < this._model.selectionStart[1]) {
+ this._model.selectionEnd[0] = 0;
+ }
+ else {
+ this._model.selectionEnd[0] = this._terminal.cols;
+ }
+ }
+ else if (this._activeSelectionMode === SelectionMode.WORD) {
+ this._selectToWordAt(this._model.selectionEnd);
+ }
+ this._dragScrollAmount = this._getMouseEventScrollAmount(event);
+ if (this._dragScrollAmount > 0) {
+ this._model.selectionEnd[0] = this._terminal.cols;
+ }
+ else if (this._dragScrollAmount < 0) {
+ this._model.selectionEnd[0] = 0;
+ }
+ if (this._model.selectionEnd[1] < this._buffer.lines.length) {
+ var char = this._buffer.lines.get(this._model.selectionEnd[1])[this._model.selectionEnd[0]];
+ if (char && char[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0) {
+ this._model.selectionEnd[0]++;
+ }
+ }
+ if (!previousSelectionEnd ||
+ previousSelectionEnd[0] !== this._model.selectionEnd[0] ||
+ previousSelectionEnd[1] !== this._model.selectionEnd[1]) {
+ this.refresh(true);
+ }
+ };
+ SelectionManager.prototype._dragScroll = function () {
+ if (this._dragScrollAmount) {
+ this._terminal.scrollLines(this._dragScrollAmount, false);
+ if (this._dragScrollAmount > 0) {
+ this._model.selectionEnd = [this._terminal.cols - 1, this._terminal.buffer.ydisp + this._terminal.rows];
+ }
+ else {
+ this._model.selectionEnd = [0, this._terminal.buffer.ydisp];
+ }
+ this.refresh();
+ }
+ };
+ SelectionManager.prototype._onMouseUp = function (event) {
+ this._removeMouseDownListeners();
+ if (this.hasSelection)
+ this.emit('selection');
+ };
+ SelectionManager.prototype._convertViewportColToCharacterIndex = function (bufferLine, coords) {
+ var charIndex = coords[0];
+ for (var i = 0; coords[0] >= i; i++) {
+ var char = bufferLine[i];
+ if (char[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0) {
+ charIndex--;
+ }
+ else if (char[Buffer_1.CHAR_DATA_CHAR_INDEX].length > 1 && coords[0] !== i) {
+ charIndex += char[Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1;
+ }
+ }
+ return charIndex;
+ };
+ SelectionManager.prototype.setSelection = function (col, row, length) {
+ this._model.clearSelection();
+ this._removeMouseDownListeners();
+ this._model.selectionStart = [col, row];
+ this._model.selectionStartLength = length;
+ this.refresh();
+ };
+ SelectionManager.prototype._getWordAt = function (coords) {
+ var bufferLine = this._buffer.lines.get(coords[1]);
+ if (!bufferLine) {
+ return null;
+ }
+ var line = this._buffer.translateBufferLineToString(coords[1], false);
+ var startIndex = this._convertViewportColToCharacterIndex(bufferLine, coords);
+ var endIndex = startIndex;
+ var charOffset = coords[0] - startIndex;
+ var leftWideCharCount = 0;
+ var rightWideCharCount = 0;
+ var leftLongCharOffset = 0;
+ var rightLongCharOffset = 0;
+ if (line.charAt(startIndex) === ' ') {
+ while (startIndex > 0 && line.charAt(startIndex - 1) === ' ') {
+ startIndex--;
+ }
+ while (endIndex < line.length && line.charAt(endIndex + 1) === ' ') {
+ endIndex++;
+ }
+ }
+ else {
+ var startCol = coords[0];
+ var endCol = coords[0];
+ if (bufferLine[startCol][Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0) {
+ leftWideCharCount++;
+ startCol--;
+ }
+ if (bufferLine[endCol][Buffer_1.CHAR_DATA_WIDTH_INDEX] === 2) {
+ rightWideCharCount++;
+ endCol++;
+ }
+ if (bufferLine[endCol][Buffer_1.CHAR_DATA_CHAR_INDEX].length > 1) {
+ rightLongCharOffset += bufferLine[endCol][Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1;
+ endIndex += bufferLine[endCol][Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1;
+ }
+ while (startCol > 0 && startIndex > 0 && !this._isCharWordSeparator(bufferLine[startCol - 1])) {
+ var char = bufferLine[startCol - 1];
+ if (char[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0) {
+ leftWideCharCount++;
+ startCol--;
+ }
+ else if (char[Buffer_1.CHAR_DATA_CHAR_INDEX].length > 1) {
+ leftLongCharOffset += char[Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1;
+ startIndex -= char[Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1;
+ }
+ startIndex--;
+ startCol--;
+ }
+ while (endCol < bufferLine.length && endIndex + 1 < line.length && !this._isCharWordSeparator(bufferLine[endCol + 1])) {
+ var char = bufferLine[endCol + 1];
+ if (char[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 2) {
+ rightWideCharCount++;
+ endCol++;
+ }
+ else if (char[Buffer_1.CHAR_DATA_CHAR_INDEX].length > 1) {
+ rightLongCharOffset += char[Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1;
+ endIndex += char[Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1;
+ }
+ endIndex++;
+ endCol++;
+ }
+ }
+ endIndex++;
+ var start = startIndex
+ + charOffset
+ - leftWideCharCount
+ + leftLongCharOffset;
+ var length = Math.min(this._terminal.cols, endIndex
+ - startIndex
+ + leftWideCharCount
+ + rightWideCharCount
+ - leftLongCharOffset
+ - rightLongCharOffset);
+ return { start: start, length: length };
+ };
+ SelectionManager.prototype._selectWordAt = function (coords) {
+ var wordPosition = this._getWordAt(coords);
+ if (wordPosition) {
+ this._model.selectionStart = [wordPosition.start, coords[1]];
+ this._model.selectionStartLength = wordPosition.length;
+ }
+ };
+ SelectionManager.prototype._selectToWordAt = function (coords) {
+ var wordPosition = this._getWordAt(coords);
+ if (wordPosition) {
+ this._model.selectionEnd = [this._model.areSelectionValuesReversed() ? wordPosition.start : (wordPosition.start + wordPosition.length), coords[1]];
+ }
+ };
+ SelectionManager.prototype._isCharWordSeparator = function (charData) {
+ if (charData[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0) {
+ return false;
+ }
+ return WORD_SEPARATORS.indexOf(charData[Buffer_1.CHAR_DATA_CHAR_INDEX]) >= 0;
+ };
+ SelectionManager.prototype._selectLineAt = function (line) {
+ this._model.selectionStart = [0, line];
+ this._model.selectionStartLength = this._terminal.cols;
+ };
+ return SelectionManager;
+}(EventEmitter_1.EventEmitter));
+exports.SelectionManager = SelectionManager;
+
+
+
+},{"./Buffer":1,"./EventEmitter":7,"./SelectionModel":12,"./utils/Browser":28,"./utils/MouseHelper":32}],12:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var SelectionModel = (function () {
+ function SelectionModel(_terminal) {
+ this._terminal = _terminal;
+ this.clearSelection();
+ }
+ SelectionModel.prototype.clearSelection = function () {
+ this.selectionStart = null;
+ this.selectionEnd = null;
+ this.isSelectAllActive = false;
+ this.selectionStartLength = 0;
+ };
+ Object.defineProperty(SelectionModel.prototype, "finalSelectionStart", {
+ get: function () {
+ if (this.isSelectAllActive) {
+ return [0, 0];
+ }
+ if (!this.selectionEnd || !this.selectionStart) {
+ return this.selectionStart;
+ }
+ return this.areSelectionValuesReversed() ? this.selectionEnd : this.selectionStart;
+ },
+ enumerable: true,
+ configurable: true
+ });
+ Object.defineProperty(SelectionModel.prototype, "finalSelectionEnd", {
+ get: function () {
+ if (this.isSelectAllActive) {
+ return [this._terminal.cols, this._terminal.buffer.ybase + this._terminal.rows - 1];
+ }
+ if (!this.selectionStart) {
+ return null;
+ }
+ if (!this.selectionEnd || this.areSelectionValuesReversed()) {
+ return [this.selectionStart[0] + this.selectionStartLength, this.selectionStart[1]];
+ }
+ if (this.selectionStartLength) {
+ if (this.selectionEnd[1] === this.selectionStart[1]) {
+ return [Math.max(this.selectionStart[0] + this.selectionStartLength, this.selectionEnd[0]), this.selectionEnd[1]];
+ }
+ }
+ return this.selectionEnd;
+ },
+ enumerable: true,
+ configurable: true
+ });
+ SelectionModel.prototype.areSelectionValuesReversed = function () {
+ var start = this.selectionStart;
+ var end = this.selectionEnd;
+ if (!start || !end) {
+ return false;
+ }
+ return start[1] > end[1] || (start[1] === end[1] && start[0] > end[0]);
+ };
+ SelectionModel.prototype.onTrim = function (amount) {
+ if (this.selectionStart) {
+ this.selectionStart[1] -= amount;
+ }
+ if (this.selectionEnd) {
+ this.selectionEnd[1] -= amount;
+ }
+ if (this.selectionEnd && this.selectionEnd[1] < 0) {
+ this.clearSelection();
+ return true;
+ }
+ if (this.selectionStart && this.selectionStart[1] < 0) {
+ this.selectionStart[1] = 0;
+ }
+ return false;
+ };
+ return SelectionModel;
+}());
+exports.SelectionModel = SelectionModel;
+
+
+
+},{}],13:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+ var extendStatics = Object.setPrototypeOf ||
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+ function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+ return function (d, b) {
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var BufferSet_1 = require("./BufferSet");
+var Buffer_1 = require("./Buffer");
+var CompositionHelper_1 = require("./CompositionHelper");
+var EventEmitter_1 = require("./EventEmitter");
+var Viewport_1 = require("./Viewport");
+var Clipboard_1 = require("./handlers/Clipboard");
+var EscapeSequences_1 = require("./EscapeSequences");
+var InputHandler_1 = require("./InputHandler");
+var Parser_1 = require("./Parser");
+var Renderer_1 = require("./renderer/Renderer");
+var Linkifier_1 = require("./Linkifier");
+var SelectionManager_1 = require("./SelectionManager");
+var CharMeasure_1 = require("./utils/CharMeasure");
+var Browser = require("./utils/Browser");
+var MouseHelper_1 = require("./utils/MouseHelper");
+var Sounds_1 = require("./utils/Sounds");
+var ColorManager_1 = require("./renderer/ColorManager");
+var MouseZoneManager_1 = require("./input/MouseZoneManager");
+var CharAtlas_1 = require("./renderer/CharAtlas");
+var document = (typeof window !== 'undefined') ? window.document : null;
+var WRITE_BUFFER_PAUSE_THRESHOLD = 5;
+var WRITE_BATCH_SIZE = 300;
+var DEFAULT_OPTIONS = {
+ convertEol: false,
+ termName: 'xterm',
+ geometry: [80, 24],
+ cursorBlink: false,
+ cursorStyle: 'block',
+ bellSound: Sounds_1.BellSound,
+ bellStyle: 'none',
+ enableBold: true,
+ fontFamily: 'courier-new, courier, monospace',
+ fontSize: 15,
+ lineHeight: 1.0,
+ letterSpacing: 0,
+ scrollback: 1000,
+ screenKeys: false,
+ debug: false,
+ cancelEvents: false,
+ disableStdin: false,
+ useFlowControl: false,
+ tabStopWidth: 8,
+ theme: null
+};
+var Terminal = (function (_super) {
+ __extends(Terminal, _super);
+ function Terminal(options) {
+ if (options === void 0) { options = {}; }
+ var _this = _super.call(this) || this;
+ _this.browser = Browser;
+ _this.options = options;
+ _this.setup();
+ return _this;
+ }
+ Terminal.prototype.setup = function () {
+ var _this = this;
+ Object.keys(DEFAULT_OPTIONS).forEach(function (key) {
+ if (_this.options[key] == null) {
+ _this.options[key] = DEFAULT_OPTIONS[key];
+ }
+ _this[key] = _this.options[key];
+ });
+ this.parent = document ? document.body : null;
+ this.cols = this.options.cols || this.options.geometry[0];
+ this.rows = this.options.rows || this.options.geometry[1];
+ this.geometry = [this.cols, this.rows];
+ if (this.options.handler) {
+ this.on('data', this.options.handler);
+ }
+ this.cursorState = 0;
+ this.cursorHidden = false;
+ this.sendDataQueue = '';
+ this.customKeyEventHandler = null;
+ this.applicationKeypad = false;
+ this.applicationCursor = false;
+ this.originMode = false;
+ this.insertMode = false;
+ this.wraparoundMode = true;
+ this.bracketedPasteMode = false;
+ this.charset = null;
+ this.gcharset = null;
+ this.glevel = 0;
+ this.charsets = [null];
+ this.readable = true;
+ this.writable = true;
+ this.defAttr = (0 << 18) | (257 << 9) | (256 << 0);
+ this.curAttr = (0 << 18) | (257 << 9) | (256 << 0);
+ this.params = [];
+ this.currentParam = 0;
+ this.prefix = '';
+ this.postfix = '';
+ this.writeBuffer = [];
+ this.writeInProgress = false;
+ this.xoffSentToCatchUp = false;
+ this.writeStopped = false;
+ this.surrogate_high = '';
+ this.userScrolling = false;
+ this.inputHandler = new InputHandler_1.InputHandler(this);
+ this.parser = new Parser_1.Parser(this.inputHandler, this);
+ this.renderer = this.renderer || null;
+ this.selectionManager = this.selectionManager || null;
+ this.linkifier = this.linkifier || new Linkifier_1.Linkifier(this);
+ this._mouseZoneManager = this._mouseZoneManager || null;
+ this.buffers = new BufferSet_1.BufferSet(this);
+ this.buffer = this.buffers.active;
+ this.buffers.on('activate', function (buffer) {
+ _this.buffer = buffer;
+ });
+ if (this.selectionManager) {
+ this.selectionManager.setBuffer(this.buffer);
+ }
+ };
+ Terminal.prototype.eraseAttr = function () {
+ return (this.defAttr & ~0x1ff) | (this.curAttr & 0x1ff);
+ };
+ Terminal.prototype.focus = function () {
+ this.textarea.focus();
+ };
+ Object.defineProperty(Terminal.prototype, "isFocused", {
+ get: function () {
+ return document.activeElement === this.textarea;
+ },
+ enumerable: true,
+ configurable: true
+ });
+ Terminal.prototype.getOption = function (key) {
+ if (!(key in DEFAULT_OPTIONS)) {
+ throw new Error('No option with key "' + key + '"');
+ }
+ if (typeof this.options[key] !== 'undefined') {
+ return this.options[key];
+ }
+ return this[key];
+ };
+ Terminal.prototype.setOption = function (key, value) {
+ if (!(key in DEFAULT_OPTIONS)) {
+ throw new Error('No option with key "' + key + '"');
+ }
+ switch (key) {
+ case 'bellStyle':
+ if (!value) {
+ value = 'none';
+ }
+ break;
+ case 'cursorStyle':
+ if (!value) {
+ value = 'block';
+ }
+ break;
+ case 'lineHeight':
+ if (value < 1) {
+ console.warn(key + " cannot be less than 1, value: " + value);
+ return;
+ }
+ case 'tabStopWidth':
+ if (value < 1) {
+ console.warn(key + " cannot be less than 1, value: " + value);
+ return;
+ }
+ break;
+ case 'theme':
+ if (this.renderer) {
+ this._setTheme(value);
+ return;
+ }
+ break;
+ case 'scrollback':
+ value = Math.min(value, Buffer_1.MAX_BUFFER_SIZE);
+ if (value < 0) {
+ console.warn(key + " cannot be less than 0, value: " + value);
+ return;
+ }
+ if (this.options[key] !== value) {
+ var newBufferLength = this.rows + value;
+ if (this.buffer.lines.length > newBufferLength) {
+ var amountToTrim = this.buffer.lines.length - newBufferLength;
+ var needsRefresh = (this.buffer.ydisp - amountToTrim < 0);
+ this.buffer.lines.trimStart(amountToTrim);
+ this.buffer.ybase = Math.max(this.buffer.ybase - amountToTrim, 0);
+ this.buffer.ydisp = Math.max(this.buffer.ydisp - amountToTrim, 0);
+ if (needsRefresh) {
+ this.refresh(0, this.rows - 1);
+ }
+ }
+ }
+ break;
+ }
+ this[key] = value;
+ this.options[key] = value;
+ switch (key) {
+ case 'fontFamily':
+ case 'fontSize':
+ this.renderer.clear();
+ this.charMeasure.measure(this.options);
+ break;
+ case 'enableBold':
+ case 'letterSpacing':
+ case 'lineHeight':
+ this.renderer.clear();
+ this.renderer.onResize(this.cols, this.rows, false);
+ this.refresh(0, this.rows - 1);
+ case 'scrollback':
+ this.buffers.resize(this.cols, this.rows);
+ this.viewport.syncScrollArea();
+ break;
+ case 'tabStopWidth':
+ this.buffers.setupTabStops();
+ break;
+ case 'bellSound':
+ case 'bellStyle':
+ this.syncBellSound();
+ break;
+ }
+ if (this.renderer) {
+ this.renderer.onOptionsChanged();
+ }
+ };
+ Terminal.prototype._onTextAreaFocus = function () {
+ if (this.sendFocus) {
+ this.send(EscapeSequences_1.C0.ESC + '[I');
+ }
+ this.element.classList.add('focus');
+ this.showCursor();
+ this.emit('focus');
+ };
+ ;
+ Terminal.prototype.blur = function () {
+ return this.textarea.blur();
+ };
+ Terminal.prototype._onTextAreaBlur = function () {
+ this.refresh(this.buffer.y, this.buffer.y);
+ if (this.sendFocus) {
+ this.send(EscapeSequences_1.C0.ESC + '[O');
+ }
+ this.element.classList.remove('focus');
+ this.emit('blur');
+ };
+ Terminal.prototype.initGlobal = function () {
+ var _this = this;
+ this.bindKeys();
+ on(this.element, 'copy', function (event) {
+ if (!_this.hasSelection()) {
+ return;
+ }
+ Clipboard_1.copyHandler(event, _this, _this.selectionManager);
+ });
+ var pasteHandlerWrapper = function (event) { return Clipboard_1.pasteHandler(event, _this); };
+ on(this.textarea, 'paste', pasteHandlerWrapper);
+ on(this.element, 'paste', pasteHandlerWrapper);
+ if (Browser.isFirefox) {
+ on(this.element, 'mousedown', function (event) {
+ if (event.button === 2) {
+ Clipboard_1.rightClickHandler(event, _this.textarea, _this.selectionManager);
+ }
+ });
+ }
+ else {
+ on(this.element, 'contextmenu', function (event) {
+ Clipboard_1.rightClickHandler(event, _this.textarea, _this.selectionManager);
+ });
+ }
+ if (Browser.isLinux) {
+ on(this.element, 'auxclick', function (event) {
+ if (event.button === 1) {
+ Clipboard_1.moveTextAreaUnderMouseCursor(event, _this.textarea);
+ }
+ });
+ }
+ };
+ Terminal.prototype.bindKeys = function () {
+ var _this = this;
+ var self = this;
+ on(this.element, 'keydown', function (ev) {
+ if (document.activeElement !== this) {
+ return;
+ }
+ self._keyDown(ev);
+ }, true);
+ on(this.element, 'keypress', function (ev) {
+ if (document.activeElement !== this) {
+ return;
+ }
+ self._keyPress(ev);
+ }, true);
+ on(this.element, 'keyup', function (ev) {
+ if (!wasMondifierKeyOnlyEvent(ev)) {
+ _this.focus();
+ }
+ }, true);
+ on(this.textarea, 'keydown', function (ev) {
+ _this._keyDown(ev);
+ }, true);
+ on(this.textarea, 'keypress', function (ev) {
+ _this._keyPress(ev);
+ _this.textarea.value = '';
+ }, true);
+ on(this.textarea, 'compositionstart', function () { return _this.compositionHelper.compositionstart(); });
+ on(this.textarea, 'compositionupdate', function (e) { return _this.compositionHelper.compositionupdate(e); });
+ on(this.textarea, 'compositionend', function () { return _this.compositionHelper.compositionend(); });
+ this.on('refresh', function () { return _this.compositionHelper.updateCompositionElements(); });
+ this.on('refresh', function (data) { return _this.queueLinkification(data.start, data.end); });
+ };
+ Terminal.prototype.open = function (parent) {
+ var _this = this;
+ var i = 0;
+ var div;
+ this.parent = parent || this.parent;
+ if (!this.parent) {
+ throw new Error('Terminal requires a parent element.');
+ }
+ this.context = this.parent.ownerDocument.defaultView;
+ this.document = this.parent.ownerDocument;
+ this.body = this.document.body;
+ CharAtlas_1.initialize(this.document);
+ this.element = this.document.createElement('div');
+ this.element.classList.add('terminal');
+ this.element.classList.add('xterm');
+ this.element.setAttribute('tabindex', '0');
+ this.viewportElement = document.createElement('div');
+ this.viewportElement.classList.add('xterm-viewport');
+ this.element.appendChild(this.viewportElement);
+ this.viewportScrollArea = document.createElement('div');
+ this.viewportScrollArea.classList.add('xterm-scroll-area');
+ this.viewportElement.appendChild(this.viewportScrollArea);
+ this.syncBellSound();
+ this._mouseZoneManager = new MouseZoneManager_1.MouseZoneManager(this);
+ this.on('scroll', function () { return _this._mouseZoneManager.clearAll(); });
+ this.linkifier.attachToDom(this._mouseZoneManager);
+ this.helperContainer = document.createElement('div');
+ this.helperContainer.classList.add('xterm-helpers');
+ this.element.appendChild(this.helperContainer);
+ this.textarea = document.createElement('textarea');
+ this.textarea.classList.add('xterm-helper-textarea');
+ this.textarea.setAttribute('autocorrect', 'off');
+ this.textarea.setAttribute('autocapitalize', 'off');
+ this.textarea.setAttribute('spellcheck', 'false');
+ this.textarea.tabIndex = 0;
+ this.textarea.addEventListener('focus', function () { return _this._onTextAreaFocus(); });
+ this.textarea.addEventListener('blur', function () { return _this._onTextAreaBlur(); });
+ this.helperContainer.appendChild(this.textarea);
+ this.compositionView = document.createElement('div');
+ this.compositionView.classList.add('composition-view');
+ this.compositionHelper = new CompositionHelper_1.CompositionHelper(this.textarea, this.compositionView, this);
+ this.helperContainer.appendChild(this.compositionView);
+ this.charSizeStyleElement = document.createElement('style');
+ this.helperContainer.appendChild(this.charSizeStyleElement);
+ this.parent.appendChild(this.element);
+ this.charMeasure = new CharMeasure_1.CharMeasure(document, this.helperContainer);
+ this.renderer = new Renderer_1.Renderer(this, this.options.theme);
+ this.options.theme = null;
+ this.viewport = new Viewport_1.Viewport(this, this.viewportElement, this.viewportScrollArea, this.charMeasure);
+ this.viewport.onThemeChanged(this.renderer.colorManager.colors);
+ this.on('cursormove', function () { return _this.renderer.onCursorMove(); });
+ this.on('resize', function () { return _this.renderer.onResize(_this.cols, _this.rows, false); });
+ this.on('blur', function () { return _this.renderer.onBlur(); });
+ this.on('focus', function () { return _this.renderer.onFocus(); });
+ window.addEventListener('resize', function () { return _this.renderer.onWindowResize(window.devicePixelRatio); });
+ this.charMeasure.on('charsizechanged', function () { return _this.renderer.onResize(_this.cols, _this.rows, true); });
+ this.renderer.on('resize', function (dimensions) { return _this.viewport.syncScrollArea(); });
+ this.selectionManager = new SelectionManager_1.SelectionManager(this, this.buffer, this.charMeasure);
+ this.element.addEventListener('mousedown', function (e) { return _this.selectionManager.onMouseDown(e); });
+ this.selectionManager.on('refresh', function (data) { return _this.renderer.onSelectionChanged(data.start, data.end); });
+ this.selectionManager.on('newselection', function (text) {
+ _this.textarea.value = text;
+ _this.textarea.focus();
+ _this.textarea.select();
+ });
+ this.on('scroll', function () {
+ _this.viewport.syncScrollArea();
+ _this.selectionManager.refresh();
+ });
+ this.viewportElement.addEventListener('scroll', function () { return _this.selectionManager.refresh(); });
+ this.mouseHelper = new MouseHelper_1.MouseHelper(this.renderer);
+ this.charMeasure.measure(this.options);
+ this.refresh(0, this.rows - 1);
+ this.initGlobal();
+ this.bindMouse();
+ };
+ Terminal.prototype._setTheme = function (theme) {
+ var colors = this.renderer.setTheme(theme);
+ if (this.viewport) {
+ this.viewport.onThemeChanged(colors);
+ }
+ };
+ Terminal.loadAddon = function (addon, callback) {
+ if (typeof exports === 'object' && typeof module === 'object') {
+ return require('./addons/' + addon + '/' + addon);
+ }
+ else if (typeof define === 'function') {
+ return require(['./addons/' + addon + '/' + addon], callback);
+ }
+ else {
+ console.error('Cannot load a module without a CommonJS or RequireJS environment.');
+ return false;
+ }
+ };
+ Terminal.prototype.bindMouse = function () {
+ var _this = this;
+ var el = this.element;
+ var self = this;
+ var pressed = 32;
+ function sendButton(ev) {
+ var button;
+ var pos;
+ button = getButton(ev);
+ pos = self.mouseHelper.getRawByteCoords(ev, self.element, self.charMeasure, self.options.lineHeight, self.cols, self.rows);
+ if (!pos)
+ return;
+ sendEvent(button, pos);
+ switch (ev.overrideType || ev.type) {
+ case 'mousedown':
+ pressed = button;
+ break;
+ case 'mouseup':
+ pressed = 32;
+ break;
+ case 'wheel':
+ break;
+ }
+ }
+ function sendMove(ev) {
+ var button = pressed;
+ var pos = self.mouseHelper.getRawByteCoords(ev, self.element, self.charMeasure, self.options.lineHeight, self.cols, self.rows);
+ if (!pos)
+ return;
+ button += 32;
+ sendEvent(button, pos);
+ }
+ function encode(data, ch) {
+ if (!self.utfMouse) {
+ if (ch === 255) {
+ data.push(0);
+ return;
+ }
+ if (ch > 127)
+ ch = 127;
+ data.push(ch);
+ }
+ else {
+ if (ch === 2047) {
+ data.push(0);
+ return;
+ }
+ if (ch < 127) {
+ data.push(ch);
+ }
+ else {
+ if (ch > 2047)
+ ch = 2047;
+ data.push(0xC0 | (ch >> 6));
+ data.push(0x80 | (ch & 0x3F));
+ }
+ }
+ }
+ function sendEvent(button, pos) {
+ if (self.vt300Mouse) {
+ button &= 3;
+ pos.x -= 32;
+ pos.y -= 32;
+ var data_1 = EscapeSequences_1.C0.ESC + '[24';
+ if (button === 0)
+ data_1 += '1';
+ else if (button === 1)
+ data_1 += '3';
+ else if (button === 2)
+ data_1 += '5';
+ else if (button === 3)
+ return;
+ else
+ data_1 += '0';
+ data_1 += '~[' + pos.x + ',' + pos.y + ']\r';
+ self.send(data_1);
+ return;
+ }
+ if (self.decLocator) {
+ button &= 3;
+ pos.x -= 32;
+ pos.y -= 32;
+ if (button === 0)
+ button = 2;
+ else if (button === 1)
+ button = 4;
+ else if (button === 2)
+ button = 6;
+ else if (button === 3)
+ button = 3;
+ self.send(EscapeSequences_1.C0.ESC + '['
+ + button
+ + ';'
+ + (button === 3 ? 4 : 0)
+ + ';'
+ + pos.y
+ + ';'
+ + pos.x
+ + ';'
+ + pos.page || 0
+ + '&w');
+ return;
+ }
+ if (self.urxvtMouse) {
+ pos.x -= 32;
+ pos.y -= 32;
+ pos.x++;
+ pos.y++;
+ self.send(EscapeSequences_1.C0.ESC + '[' + button + ';' + pos.x + ';' + pos.y + 'M');
+ return;
+ }
+ if (self.sgrMouse) {
+ pos.x -= 32;
+ pos.y -= 32;
+ self.send(EscapeSequences_1.C0.ESC + '[<'
+ + (((button & 3) === 3 ? button & ~3 : button) - 32)
+ + ';'
+ + pos.x
+ + ';'
+ + pos.y
+ + ((button & 3) === 3 ? 'm' : 'M'));
+ return;
+ }
+ var data = [];
+ encode(data, button);
+ encode(data, pos.x);
+ encode(data, pos.y);
+ self.send(EscapeSequences_1.C0.ESC + '[M' + String.fromCharCode.apply(String, data));
+ }
+ function getButton(ev) {
+ var button;
+ var shift;
+ var meta;
+ var ctrl;
+ var mod;
+ switch (ev.overrideType || ev.type) {
+ case 'mousedown':
+ button = ev.button != null
+ ? +ev.button
+ : ev.which != null
+ ? ev.which - 1
+ : null;
+ if (Browser.isMSIE) {
+ button = button === 1 ? 0 : button === 4 ? 1 : button;
+ }
+ break;
+ case 'mouseup':
+ button = 3;
+ break;
+ case 'DOMMouseScroll':
+ button = ev.detail < 0
+ ? 64
+ : 65;
+ break;
+ case 'wheel':
+ button = ev.wheelDeltaY > 0
+ ? 64
+ : 65;
+ break;
+ }
+ shift = ev.shiftKey ? 4 : 0;
+ meta = ev.metaKey ? 8 : 0;
+ ctrl = ev.ctrlKey ? 16 : 0;
+ mod = shift | meta | ctrl;
+ if (self.vt200Mouse) {
+ mod &= ctrl;
+ }
+ else if (!self.normalMouse) {
+ mod = 0;
+ }
+ button = (32 + (mod << 2)) + button;
+ return button;
+ }
+ on(el, 'mousedown', function (ev) {
+ ev.preventDefault();
+ _this.focus();
+ if (!_this.mouseEvents || _this.selectionManager.shouldForceSelection(ev)) {
+ return;
+ }
+ sendButton(ev);
+ if (_this.vt200Mouse) {
+ ev.overrideType = 'mouseup';
+ sendButton(ev);
+ return _this.cancel(ev);
+ }
+ if (_this.normalMouse)
+ on(_this.document, 'mousemove', sendMove);
+ if (!_this.x10Mouse) {
+ var handler_1 = function (ev) {
+ sendButton(ev);
+ if (_this.normalMouse)
+ off(_this.document, 'mousemove', sendMove);
+ off(_this.document, 'mouseup', handler_1);
+ return _this.cancel(ev);
+ };
+ on(_this.document, 'mouseup', handler_1);
+ }
+ return _this.cancel(ev);
+ });
+ on(el, 'wheel', function (ev) {
+ if (!_this.mouseEvents)
+ return;
+ if (_this.x10Mouse || _this.vt300Mouse || _this.decLocator)
+ return;
+ sendButton(ev);
+ ev.preventDefault();
+ });
+ on(el, 'wheel', function (ev) {
+ if (_this.mouseEvents)
+ return;
+ _this.viewport.onWheel(ev);
+ return _this.cancel(ev);
+ });
+ on(el, 'touchstart', function (ev) {
+ if (_this.mouseEvents)
+ return;
+ _this.viewport.onTouchStart(ev);
+ return _this.cancel(ev);
+ });
+ on(el, 'touchmove', function (ev) {
+ if (_this.mouseEvents)
+ return;
+ _this.viewport.onTouchMove(ev);
+ return _this.cancel(ev);
+ });
+ };
+ Terminal.prototype.destroy = function () {
+ _super.prototype.destroy.call(this);
+ this.readable = false;
+ this.writable = false;
+ this.handler = function () { };
+ this.write = function () { };
+ if (this.element && this.element.parentNode) {
+ this.element.parentNode.removeChild(this.element);
+ }
+ };
+ Terminal.prototype.refresh = function (start, end) {
+ if (this.renderer) {
+ this.renderer.queueRefresh(start, end);
+ }
+ };
+ Terminal.prototype.queueLinkification = function (start, end) {
+ if (this.linkifier) {
+ this.linkifier.linkifyRows(start, end);
+ }
+ };
+ Terminal.prototype.showCursor = function () {
+ if (!this.cursorState) {
+ this.cursorState = 1;
+ this.refresh(this.buffer.y, this.buffer.y);
+ }
+ };
+ Terminal.prototype.scroll = function (isWrapped) {
+ var newLine = this.blankLine(undefined, isWrapped);
+ var topRow = this.buffer.ybase + this.buffer.scrollTop;
+ var bottomRow = this.buffer.ybase + this.buffer.scrollBottom;
+ if (this.buffer.scrollTop === 0) {
+ var willBufferBeTrimmed = this.buffer.lines.length === this.buffer.lines.maxLength;
+ if (bottomRow === this.buffer.lines.length - 1) {
+ this.buffer.lines.push(newLine);
+ }
+ else {
+ this.buffer.lines.splice(bottomRow + 1, 0, newLine);
+ }
+ if (!willBufferBeTrimmed) {
+ this.buffer.ybase++;
+ if (!this.userScrolling) {
+ this.buffer.ydisp++;
+ }
+ }
+ else {
+ if (this.userScrolling) {
+ this.buffer.ydisp = Math.max(this.buffer.ydisp - 1, 0);
+ }
+ }
+ }
+ else {
+ var scrollRegionHeight = bottomRow - topRow + 1;
+ this.buffer.lines.shiftElements(topRow + 1, scrollRegionHeight - 1, -1);
+ this.buffer.lines.set(bottomRow, newLine);
+ }
+ if (!this.userScrolling) {
+ this.buffer.ydisp = this.buffer.ybase;
+ }
+ this.updateRange(this.buffer.scrollTop);
+ this.updateRange(this.buffer.scrollBottom);
+ this.emit('scroll', this.buffer.ydisp);
+ };
+ Terminal.prototype.scrollLines = function (disp, suppressScrollEvent) {
+ if (disp < 0) {
+ if (this.buffer.ydisp === 0) {
+ return;
+ }
+ this.userScrolling = true;
+ }
+ else if (disp + this.buffer.ydisp >= this.buffer.ybase) {
+ this.userScrolling = false;
+ }
+ var oldYdisp = this.buffer.ydisp;
+ this.buffer.ydisp = Math.max(Math.min(this.buffer.ydisp + disp, this.buffer.ybase), 0);
+ if (oldYdisp === this.buffer.ydisp) {
+ return;
+ }
+ if (!suppressScrollEvent) {
+ this.emit('scroll', this.buffer.ydisp);
+ }
+ this.refresh(0, this.rows - 1);
+ };
+ Terminal.prototype.scrollPages = function (pageCount) {
+ this.scrollLines(pageCount * (this.rows - 1));
+ };
+ Terminal.prototype.scrollToTop = function () {
+ this.scrollLines(-this.buffer.ydisp);
+ };
+ Terminal.prototype.scrollToBottom = function () {
+ this.scrollLines(this.buffer.ybase - this.buffer.ydisp);
+ };
+ Terminal.prototype.write = function (data) {
+ var _this = this;
+ this.writeBuffer.push(data);
+ if (this.options.useFlowControl && !this.xoffSentToCatchUp && this.writeBuffer.length >= WRITE_BUFFER_PAUSE_THRESHOLD) {
+ this.send(EscapeSequences_1.C0.DC3);
+ this.xoffSentToCatchUp = true;
+ }
+ if (!this.writeInProgress && this.writeBuffer.length > 0) {
+ this.writeInProgress = true;
+ setTimeout(function () {
+ _this.innerWrite();
+ });
+ }
+ };
+ Terminal.prototype.innerWrite = function () {
+ var _this = this;
+ var writeBatch = this.writeBuffer.splice(0, WRITE_BATCH_SIZE);
+ while (writeBatch.length > 0) {
+ var data = writeBatch.shift();
+ if (this.xoffSentToCatchUp && writeBatch.length === 0 && this.writeBuffer.length === 0) {
+ this.send(EscapeSequences_1.C0.DC1);
+ this.xoffSentToCatchUp = false;
+ }
+ this.refreshStart = this.buffer.y;
+ this.refreshEnd = this.buffer.y;
+ var state = this.parser.parse(data);
+ this.parser.setState(state);
+ this.updateRange(this.buffer.y);
+ this.refresh(this.refreshStart, this.refreshEnd);
+ }
+ if (this.writeBuffer.length > 0) {
+ setTimeout(function () { return _this.innerWrite(); }, 0);
+ }
+ else {
+ this.writeInProgress = false;
+ }
+ };
+ Terminal.prototype.writeln = function (data) {
+ this.write(data + '\r\n');
+ };
+ Terminal.prototype.attachCustomKeyEventHandler = function (customKeyEventHandler) {
+ this.customKeyEventHandler = customKeyEventHandler;
+ };
+ Terminal.prototype.setHypertextLinkHandler = function (handler) {
+ if (!this.linkifier) {
+ throw new Error('Cannot attach a hypertext link handler before Terminal.open is called');
+ }
+ this.linkifier.setHypertextLinkHandler(handler);
+ this.refresh(0, this.rows - 1);
+ };
+ Terminal.prototype.setHypertextValidationCallback = function (callback) {
+ if (!this.linkifier) {
+ throw new Error('Cannot attach a hypertext validation callback before Terminal.open is called');
+ }
+ this.linkifier.setHypertextValidationCallback(callback);
+ this.refresh(0, this.rows - 1);
+ };
+ Terminal.prototype.registerLinkMatcher = function (regex, handler, options) {
+ if (this.linkifier) {
+ var matcherId = this.linkifier.registerLinkMatcher(regex, handler, options);
+ this.refresh(0, this.rows - 1);
+ return matcherId;
+ }
+ return 0;
+ };
+ Terminal.prototype.deregisterLinkMatcher = function (matcherId) {
+ if (this.linkifier) {
+ if (this.linkifier.deregisterLinkMatcher(matcherId)) {
+ this.refresh(0, this.rows - 1);
+ }
+ }
+ };
+ Terminal.prototype.hasSelection = function () {
+ return this.selectionManager ? this.selectionManager.hasSelection : false;
+ };
+ Terminal.prototype.getSelection = function () {
+ return this.selectionManager ? this.selectionManager.selectionText : '';
+ };
+ Terminal.prototype.clearSelection = function () {
+ if (this.selectionManager) {
+ this.selectionManager.clearSelection();
+ }
+ };
+ Terminal.prototype.selectAll = function () {
+ if (this.selectionManager) {
+ this.selectionManager.selectAll();
+ }
+ };
+ Terminal.prototype._keyDown = function (ev) {
+ if (this.customKeyEventHandler && this.customKeyEventHandler(ev) === false) {
+ return false;
+ }
+ if (!this.compositionHelper.keydown(ev)) {
+ if (this.buffer.ybase !== this.buffer.ydisp) {
+ this.scrollToBottom();
+ }
+ return false;
+ }
+ var result = this._evaluateKeyEscapeSequence(ev);
+ if (result.key === EscapeSequences_1.C0.DC3) {
+ this.writeStopped = true;
+ }
+ else if (result.key === EscapeSequences_1.C0.DC1) {
+ this.writeStopped = false;
+ }
+ if (result.scrollLines) {
+ this.scrollLines(result.scrollLines);
+ return this.cancel(ev, true);
+ }
+ if (isThirdLevelShift(this.browser, ev)) {
+ return true;
+ }
+ if (result.cancel) {
+ this.cancel(ev, true);
+ }
+ if (!result.key) {
+ return true;
+ }
+ this.emit('keydown', ev);
+ this.emit('key', result.key, ev);
+ this.showCursor();
+ this.handler(result.key);
+ return this.cancel(ev, true);
+ };
+ Terminal.prototype._evaluateKeyEscapeSequence = function (ev) {
+ var result = {
+ cancel: false,
+ key: undefined,
+ scrollLines: undefined
+ };
+ var modifiers = (ev.shiftKey ? 1 : 0) | (ev.altKey ? 2 : 0) | (ev.ctrlKey ? 4 : 0) | (ev.metaKey ? 8 : 0);
+ switch (ev.keyCode) {
+ case 0:
+ if (ev.key === 'UIKeyInputUpArrow') {
+ if (this.applicationCursor) {
+ result.key = EscapeSequences_1.C0.ESC + 'OA';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[A';
+ }
+ }
+ else if (ev.key === 'UIKeyInputLeftArrow') {
+ if (this.applicationCursor) {
+ result.key = EscapeSequences_1.C0.ESC + 'OD';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[D';
+ }
+ }
+ else if (ev.key === 'UIKeyInputRightArrow') {
+ if (this.applicationCursor) {
+ result.key = EscapeSequences_1.C0.ESC + 'OC';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[C';
+ }
+ }
+ else if (ev.key === 'UIKeyInputDownArrow') {
+ if (this.applicationCursor) {
+ result.key = EscapeSequences_1.C0.ESC + 'OB';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[B';
+ }
+ }
+ break;
+ case 8:
+ if (ev.shiftKey) {
+ result.key = EscapeSequences_1.C0.BS;
+ break;
+ }
+ result.key = EscapeSequences_1.C0.DEL;
+ break;
+ case 9:
+ if (ev.shiftKey) {
+ result.key = EscapeSequences_1.C0.ESC + '[Z';
+ break;
+ }
+ result.key = EscapeSequences_1.C0.HT;
+ result.cancel = true;
+ break;
+ case 13:
+ result.key = EscapeSequences_1.C0.CR;
+ result.cancel = true;
+ break;
+ case 27:
+ result.key = EscapeSequences_1.C0.ESC;
+ result.cancel = true;
+ break;
+ case 37:
+ if (modifiers) {
+ result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'D';
+ if (result.key === EscapeSequences_1.C0.ESC + '[1;3D') {
+ result.key = (this.browser.isMac) ? EscapeSequences_1.C0.ESC + 'b' : EscapeSequences_1.C0.ESC + '[1;5D';
+ }
+ }
+ else if (this.applicationCursor) {
+ result.key = EscapeSequences_1.C0.ESC + 'OD';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[D';
+ }
+ break;
+ case 39:
+ if (modifiers) {
+ result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'C';
+ if (result.key === EscapeSequences_1.C0.ESC + '[1;3C') {
+ result.key = (this.browser.isMac) ? EscapeSequences_1.C0.ESC + 'f' : EscapeSequences_1.C0.ESC + '[1;5C';
+ }
+ }
+ else if (this.applicationCursor) {
+ result.key = EscapeSequences_1.C0.ESC + 'OC';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[C';
+ }
+ break;
+ case 38:
+ if (modifiers) {
+ result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'A';
+ if (result.key === EscapeSequences_1.C0.ESC + '[1;3A') {
+ result.key = EscapeSequences_1.C0.ESC + '[1;5A';
+ }
+ }
+ else if (this.applicationCursor) {
+ result.key = EscapeSequences_1.C0.ESC + 'OA';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[A';
+ }
+ break;
+ case 40:
+ if (modifiers) {
+ result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'B';
+ if (result.key === EscapeSequences_1.C0.ESC + '[1;3B') {
+ result.key = EscapeSequences_1.C0.ESC + '[1;5B';
+ }
+ }
+ else if (this.applicationCursor) {
+ result.key = EscapeSequences_1.C0.ESC + 'OB';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[B';
+ }
+ break;
+ case 45:
+ if (!ev.shiftKey && !ev.ctrlKey) {
+ result.key = EscapeSequences_1.C0.ESC + '[2~';
+ }
+ break;
+ case 46:
+ if (modifiers) {
+ result.key = EscapeSequences_1.C0.ESC + '[3;' + (modifiers + 1) + '~';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[3~';
+ }
+ break;
+ case 36:
+ if (modifiers)
+ result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'H';
+ else if (this.applicationCursor)
+ result.key = EscapeSequences_1.C0.ESC + 'OH';
+ else
+ result.key = EscapeSequences_1.C0.ESC + '[H';
+ break;
+ case 35:
+ if (modifiers)
+ result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'F';
+ else if (this.applicationCursor)
+ result.key = EscapeSequences_1.C0.ESC + 'OF';
+ else
+ result.key = EscapeSequences_1.C0.ESC + '[F';
+ break;
+ case 33:
+ if (ev.shiftKey) {
+ result.scrollLines = -(this.rows - 1);
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[5~';
+ }
+ break;
+ case 34:
+ if (ev.shiftKey) {
+ result.scrollLines = this.rows - 1;
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[6~';
+ }
+ break;
+ case 112:
+ if (modifiers) {
+ result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'P';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + 'OP';
+ }
+ break;
+ case 113:
+ if (modifiers) {
+ result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'Q';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + 'OQ';
+ }
+ break;
+ case 114:
+ if (modifiers) {
+ result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'R';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + 'OR';
+ }
+ break;
+ case 115:
+ if (modifiers) {
+ result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'S';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + 'OS';
+ }
+ break;
+ case 116:
+ if (modifiers) {
+ result.key = EscapeSequences_1.C0.ESC + '[15;' + (modifiers + 1) + '~';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[15~';
+ }
+ break;
+ case 117:
+ if (modifiers) {
+ result.key = EscapeSequences_1.C0.ESC + '[17;' + (modifiers + 1) + '~';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[17~';
+ }
+ break;
+ case 118:
+ if (modifiers) {
+ result.key = EscapeSequences_1.C0.ESC + '[18;' + (modifiers + 1) + '~';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[18~';
+ }
+ break;
+ case 119:
+ if (modifiers) {
+ result.key = EscapeSequences_1.C0.ESC + '[19;' + (modifiers + 1) + '~';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[19~';
+ }
+ break;
+ case 120:
+ if (modifiers) {
+ result.key = EscapeSequences_1.C0.ESC + '[20;' + (modifiers + 1) + '~';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[20~';
+ }
+ break;
+ case 121:
+ if (modifiers) {
+ result.key = EscapeSequences_1.C0.ESC + '[21;' + (modifiers + 1) + '~';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[21~';
+ }
+ break;
+ case 122:
+ if (modifiers) {
+ result.key = EscapeSequences_1.C0.ESC + '[23;' + (modifiers + 1) + '~';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[23~';
+ }
+ break;
+ case 123:
+ if (modifiers) {
+ result.key = EscapeSequences_1.C0.ESC + '[24;' + (modifiers + 1) + '~';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[24~';
+ }
+ break;
+ default:
+ if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) {
+ if (ev.keyCode >= 65 && ev.keyCode <= 90) {
+ result.key = String.fromCharCode(ev.keyCode - 64);
+ }
+ else if (ev.keyCode === 32) {
+ result.key = String.fromCharCode(0);
+ }
+ else if (ev.keyCode >= 51 && ev.keyCode <= 55) {
+ result.key = String.fromCharCode(ev.keyCode - 51 + 27);
+ }
+ else if (ev.keyCode === 56) {
+ result.key = String.fromCharCode(127);
+ }
+ else if (ev.keyCode === 219) {
+ result.key = String.fromCharCode(27);
+ }
+ else if (ev.keyCode === 220) {
+ result.key = String.fromCharCode(28);
+ }
+ else if (ev.keyCode === 221) {
+ result.key = String.fromCharCode(29);
+ }
+ }
+ else if (!this.browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) {
+ if (ev.keyCode >= 65 && ev.keyCode <= 90) {
+ result.key = EscapeSequences_1.C0.ESC + String.fromCharCode(ev.keyCode + 32);
+ }
+ else if (ev.keyCode === 192) {
+ result.key = EscapeSequences_1.C0.ESC + '`';
+ }
+ else if (ev.keyCode >= 48 && ev.keyCode <= 57) {
+ result.key = EscapeSequences_1.C0.ESC + (ev.keyCode - 48);
+ }
+ }
+ else if (this.browser.isMac && !ev.altKey && !ev.ctrlKey && ev.metaKey) {
+ if (ev.keyCode === 65) {
+ this.selectAll();
+ }
+ }
+ break;
+ }
+ return result;
+ };
+ Terminal.prototype.setgLevel = function (g) {
+ this.glevel = g;
+ this.charset = this.charsets[g];
+ };
+ Terminal.prototype.setgCharset = function (g, charset) {
+ this.charsets[g] = charset;
+ if (this.glevel === g) {
+ this.charset = charset;
+ }
+ };
+ Terminal.prototype._keyPress = function (ev) {
+ var key;
+ if (this.customKeyEventHandler && this.customKeyEventHandler(ev) === false) {
+ return false;
+ }
+ this.cancel(ev);
+ if (ev.charCode) {
+ key = ev.charCode;
+ }
+ else if (ev.which == null) {
+ key = ev.keyCode;
+ }
+ else if (ev.which !== 0 && ev.charCode !== 0) {
+ key = ev.which;
+ }
+ else {
+ return false;
+ }
+ if (!key || ((ev.altKey || ev.ctrlKey || ev.metaKey) && !isThirdLevelShift(this.browser, ev))) {
+ return false;
+ }
+ key = String.fromCharCode(key);
+ this.emit('keypress', key, ev);
+ this.emit('key', key, ev);
+ this.showCursor();
+ this.handler(key);
+ return true;
+ };
+ Terminal.prototype.send = function (data) {
+ var _this = this;
+ if (!this.sendDataQueue) {
+ setTimeout(function () {
+ _this.handler(_this.sendDataQueue);
+ _this.sendDataQueue = '';
+ }, 1);
+ }
+ this.sendDataQueue += data;
+ };
+ Terminal.prototype.bell = function () {
+ var _this = this;
+ this.emit('bell');
+ if (this.soundBell())
+ this.bellAudioElement.play();
+ if (this.visualBell()) {
+ this.element.classList.add('visual-bell-active');
+ clearTimeout(this.visualBellTimer);
+ this.visualBellTimer = window.setTimeout(function () {
+ _this.element.classList.remove('visual-bell-active');
+ }, 200);
+ }
+ };
+ Terminal.prototype.log = function (text, data) {
+ if (!this.options.debug)
+ return;
+ if (!this.context.console || !this.context.console.log)
+ return;
+ this.context.console.log(text, data);
+ };
+ Terminal.prototype.error = function (text, data) {
+ if (!this.options.debug)
+ return;
+ if (!this.context.console || !this.context.console.error)
+ return;
+ this.context.console.error(text, data);
+ };
+ Terminal.prototype.resize = function (x, y) {
+ if (isNaN(x) || isNaN(y)) {
+ return;
+ }
+ if (x === this.cols && y === this.rows) {
+ if (!this.charMeasure.width || !this.charMeasure.height) {
+ this.charMeasure.measure(this.options);
+ }
+ return;
+ }
+ if (x < 1)
+ x = 1;
+ if (y < 1)
+ y = 1;
+ this.buffers.resize(x, y);
+ this.cols = x;
+ this.rows = y;
+ this.buffers.setupTabStops(this.cols);
+ this.charMeasure.measure(this.options);
+ this.refresh(0, this.rows - 1);
+ this.geometry = [this.cols, this.rows];
+ this.emit('resize', { cols: x, rows: y });
+ };
+ Terminal.prototype.updateRange = function (y) {
+ if (y < this.refreshStart)
+ this.refreshStart = y;
+ if (y > this.refreshEnd)
+ this.refreshEnd = y;
+ };
+ Terminal.prototype.maxRange = function () {
+ this.refreshStart = 0;
+ this.refreshEnd = this.rows - 1;
+ };
+ Terminal.prototype.eraseRight = function (x, y) {
+ var line = this.buffer.lines.get(this.buffer.ybase + y);
+ if (!line) {
+ return;
+ }
+ var ch = [this.eraseAttr(), ' ', 1, 32];
+ for (; x < this.cols; x++) {
+ line[x] = ch;
+ }
+ this.updateRange(y);
+ };
+ Terminal.prototype.eraseLeft = function (x, y) {
+ var line = this.buffer.lines.get(this.buffer.ybase + y);
+ if (!line) {
+ return;
+ }
+ var ch = [this.eraseAttr(), ' ', 1, 32];
+ x++;
+ while (x--) {
+ line[x] = ch;
+ }
+ this.updateRange(y);
+ };
+ Terminal.prototype.clear = function () {
+ if (this.buffer.ybase === 0 && this.buffer.y === 0) {
+ return;
+ }
+ this.buffer.lines.set(0, this.buffer.lines.get(this.buffer.ybase + this.buffer.y));
+ this.buffer.lines.length = 1;
+ this.buffer.ydisp = 0;
+ this.buffer.ybase = 0;
+ this.buffer.y = 0;
+ for (var i = 1; i < this.rows; i++) {
+ this.buffer.lines.push(this.blankLine());
+ }
+ this.refresh(0, this.rows - 1);
+ this.emit('scroll', this.buffer.ydisp);
+ };
+ Terminal.prototype.eraseLine = function (y) {
+ this.eraseRight(0, y);
+ };
+ Terminal.prototype.blankLine = function (cur, isWrapped, cols) {
+ var attr = cur ? this.eraseAttr() : this.defAttr;
+ var ch = [attr, ' ', 1, 32];
+ var line = [];
+ if (isWrapped) {
+ line.isWrapped = isWrapped;
+ }
+ cols = cols || this.cols;
+ for (var i = 0; i < cols; i++) {
+ line[i] = ch;
+ }
+ return line;
+ };
+ Terminal.prototype.ch = function (cur) {
+ if (cur) {
+ return [this.eraseAttr(), ' ', 1, 32];
+ }
+ return [this.defAttr, ' ', 1, 32];
+ };
+ Terminal.prototype.is = function (term) {
+ return (this.options.termName + '').indexOf(term) === 0;
+ };
+ Terminal.prototype.handler = function (data) {
+ if (this.options.disableStdin) {
+ return;
+ }
+ if (this.selectionManager && this.selectionManager.hasSelection) {
+ this.selectionManager.clearSelection();
+ }
+ if (this.buffer.ybase !== this.buffer.ydisp) {
+ this.scrollToBottom();
+ }
+ this.emit('data', data);
+ };
+ Terminal.prototype.handleTitle = function (title) {
+ this.emit('title', title);
+ };
+ Terminal.prototype.index = function () {
+ this.buffer.y++;
+ if (this.buffer.y > this.buffer.scrollBottom) {
+ this.buffer.y--;
+ this.scroll();
+ }
+ if (this.buffer.x >= this.cols) {
+ this.buffer.x--;
+ }
+ };
+ Terminal.prototype.reverseIndex = function () {
+ if (this.buffer.y === this.buffer.scrollTop) {
+ var scrollRegionHeight = this.buffer.scrollBottom - this.buffer.scrollTop;
+ this.buffer.lines.shiftElements(this.buffer.y + this.buffer.ybase, scrollRegionHeight, 1);
+ this.buffer.lines.set(this.buffer.y + this.buffer.ybase, this.blankLine(true));
+ this.updateRange(this.buffer.scrollTop);
+ this.updateRange(this.buffer.scrollBottom);
+ }
+ else {
+ this.buffer.y--;
+ }
+ };
+ Terminal.prototype.reset = function () {
+ this.options.rows = this.rows;
+ this.options.cols = this.cols;
+ var customKeyEventHandler = this.customKeyEventHandler;
+ var inputHandler = this.inputHandler;
+ var buffers = this.buffers;
+ this.setup();
+ this.customKeyEventHandler = customKeyEventHandler;
+ this.inputHandler = inputHandler;
+ this.buffers = buffers;
+ this.refresh(0, this.rows - 1);
+ this.viewport.syncScrollArea();
+ };
+ Terminal.prototype.tabSet = function () {
+ this.buffer.tabs[this.buffer.x] = true;
+ };
+ Terminal.prototype.cancel = function (ev, force) {
+ if (!this.options.cancelEvents && !force) {
+ return;
+ }
+ ev.preventDefault();
+ ev.stopPropagation();
+ return false;
+ };
+ Terminal.prototype.matchColor = function (r1, g1, b1) {
+ return matchColor_(r1, g1, b1);
+ };
+ Terminal.prototype.visualBell = function () {
+ return this.options.bellStyle === 'visual' ||
+ this.options.bellStyle === 'both';
+ };
+ Terminal.prototype.soundBell = function () {
+ return this.options.bellStyle === 'sound' ||
+ this.options.bellStyle === 'both';
+ };
+ Terminal.prototype.syncBellSound = function () {
+ if (this.soundBell() && this.bellAudioElement) {
+ this.bellAudioElement.setAttribute('src', this.options.bellSound);
+ }
+ else if (this.soundBell()) {
+ this.bellAudioElement = document.createElement('audio');
+ this.bellAudioElement.setAttribute('preload', 'auto');
+ this.bellAudioElement.setAttribute('src', this.options.bellSound);
+ this.helperContainer.appendChild(this.bellAudioElement);
+ }
+ else if (this.bellAudioElement) {
+ this.helperContainer.removeChild(this.bellAudioElement);
+ }
+ };
+ return Terminal;
+}(EventEmitter_1.EventEmitter));
+exports.Terminal = Terminal;
+function globalOn(el, type, handler, capture) {
+ if (!Array.isArray(el)) {
+ el = [el];
+ }
+ el.forEach(function (element) {
+ element.addEventListener(type, handler, capture || false);
+ });
+}
+var on = globalOn;
+function off(el, type, handler, capture) {
+ if (capture === void 0) { capture = false; }
+ el.removeEventListener(type, handler, capture);
+}
+function isThirdLevelShift(browser, ev) {
+ var thirdLevelKey = (browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) ||
+ (browser.isMSWindows && ev.altKey && ev.ctrlKey && !ev.metaKey);
+ if (ev.type === 'keypress') {
+ return thirdLevelKey;
+ }
+ return thirdLevelKey && (!ev.keyCode || ev.keyCode > 47);
+}
+function wasMondifierKeyOnlyEvent(ev) {
+ return ev.keyCode === 16 ||
+ ev.keyCode === 17 ||
+ ev.keyCode === 18;
+}
+var vcolors = (function () {
+ var result = ColorManager_1.DEFAULT_ANSI_COLORS.map(function (c) {
+ c = c.substring(1);
+ return [
+ parseInt(c.substring(0, 2), 16),
+ parseInt(c.substring(2, 4), 16),
+ parseInt(c.substring(4, 6), 16)
+ ];
+ });
+ var r = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff];
+ for (var i = 0; i < 216; i++) {
+ result.push([
+ r[(i / 36) % 6 | 0],
+ r[(i / 6) % 6 | 0],
+ r[i % 6]
+ ]);
+ }
+ var c;
+ for (var i = 0; i < 24; i++) {
+ c = 8 + i * 10;
+ result.push([c, c, c]);
+ }
+ return result;
+})();
+var matchColorCache = {};
+function matchColorDistance(r1, g1, b1, r2, g2, b2) {
+ return Math.pow(30 * (r1 - r2), 2)
+ + Math.pow(59 * (g1 - g2), 2)
+ + Math.pow(11 * (b1 - b2), 2);
+}
+;
+function matchColor_(r1, g1, b1) {
+ var hash = (r1 << 16) | (g1 << 8) | b1;
+ if (matchColorCache[hash] != null) {
+ return matchColorCache[hash];
+ }
+ var ldiff = Infinity;
+ var li = -1;
+ var i = 0;
+ var c;
+ var r2;
+ var g2;
+ var b2;
+ var diff;
+ for (; i < vcolors.length; i++) {
+ c = vcolors[i];
+ r2 = c[0];
+ g2 = c[1];
+ b2 = c[2];
+ diff = matchColorDistance(r1, g1, b1, r2, g2, b2);
+ if (diff === 0) {
+ li = i;
+ break;
+ }
+ if (diff < ldiff) {
+ ldiff = diff;
+ li = i;
+ }
+ }
+ return matchColorCache[hash] = li;
+}
+
+
+
+},{"./Buffer":1,"./BufferSet":2,"./CompositionHelper":5,"./EscapeSequences":6,"./EventEmitter":7,"./InputHandler":8,"./Linkifier":9,"./Parser":10,"./SelectionManager":11,"./Viewport":15,"./handlers/Clipboard":16,"./input/MouseZoneManager":17,"./renderer/CharAtlas":19,"./renderer/ColorManager":20,"./renderer/Renderer":24,"./utils/Browser":28,"./utils/CharMeasure":29,"./utils/MouseHelper":32,"./utils/Sounds":33}],14:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var LinkHoverEventTypes;
+(function (LinkHoverEventTypes) {
+ LinkHoverEventTypes["HOVER"] = "linkhover";
+ LinkHoverEventTypes["TOOLTIP"] = "linktooltip";
+ LinkHoverEventTypes["LEAVE"] = "linkleave";
+})(LinkHoverEventTypes = exports.LinkHoverEventTypes || (exports.LinkHoverEventTypes = {}));
+;
+
+
+
+},{}],15:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Viewport = (function () {
+ function Viewport(terminal, viewportElement, scrollArea, charMeasure) {
+ var _this = this;
+ this.terminal = terminal;
+ this.viewportElement = viewportElement;
+ this.scrollArea = scrollArea;
+ this.charMeasure = charMeasure;
+ this.currentRowHeight = 0;
+ this.lastRecordedBufferLength = 0;
+ this.lastRecordedViewportHeight = 0;
+ this.lastRecordedBufferHeight = 0;
+ this.viewportElement.addEventListener('scroll', this.onScroll.bind(this));
+ setTimeout(function () { return _this.syncScrollArea(); }, 0);
+ }
+ Viewport.prototype.onThemeChanged = function (colors) {
+ this.viewportElement.style.backgroundColor = colors.background;
+ };
+ Viewport.prototype.refresh = function () {
+ if (this.charMeasure.height > 0) {
+ this.currentRowHeight = this.terminal.renderer.dimensions.scaledCellHeight / window.devicePixelRatio;
+ if (this.lastRecordedViewportHeight !== this.terminal.renderer.dimensions.canvasHeight) {
+ this.lastRecordedViewportHeight = this.terminal.renderer.dimensions.canvasHeight;
+ this.viewportElement.style.height = this.lastRecordedViewportHeight + 'px';
+ }
+ var newBufferHeight = Math.round(this.currentRowHeight * this.lastRecordedBufferLength);
+ if (this.lastRecordedBufferHeight !== newBufferHeight) {
+ this.lastRecordedBufferHeight = newBufferHeight;
+ this.scrollArea.style.height = this.lastRecordedBufferHeight + 'px';
+ }
+ }
+ };
+ Viewport.prototype.syncScrollArea = function () {
+ if (this.lastRecordedBufferLength !== this.terminal.buffer.lines.length) {
+ this.lastRecordedBufferLength = this.terminal.buffer.lines.length;
+ this.refresh();
+ }
+ else if (this.lastRecordedViewportHeight !== this.terminal.renderer.dimensions.canvasHeight) {
+ this.refresh();
+ }
+ else {
+ if (this.terminal.renderer.dimensions.scaledCellHeight / window.devicePixelRatio !== this.currentRowHeight) {
+ this.refresh();
+ }
+ }
+ var scrollTop = this.terminal.buffer.ydisp * this.currentRowHeight;
+ if (this.viewportElement.scrollTop !== scrollTop) {
+ this.viewportElement.scrollTop = scrollTop;
+ }
+ };
+ Viewport.prototype.onScroll = function (ev) {
+ var newRow = Math.round(this.viewportElement.scrollTop / this.currentRowHeight);
+ var diff = newRow - this.terminal.buffer.ydisp;
+ this.terminal.scrollLines(diff, true);
+ };
+ Viewport.prototype.onWheel = function (ev) {
+ if (ev.deltaY === 0) {
+ return;
+ }
+ var multiplier = 1;
+ if (ev.deltaMode === WheelEvent.DOM_DELTA_LINE) {
+ multiplier = this.currentRowHeight;
+ }
+ else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) {
+ multiplier = this.currentRowHeight * this.terminal.rows;
+ }
+ this.viewportElement.scrollTop += ev.deltaY * multiplier;
+ ev.preventDefault();
+ };
+ ;
+ Viewport.prototype.onTouchStart = function (ev) {
+ this.lastTouchY = ev.touches[0].pageY;
+ };
+ ;
+ Viewport.prototype.onTouchMove = function (ev) {
+ var deltaY = this.lastTouchY - ev.touches[0].pageY;
+ this.lastTouchY = ev.touches[0].pageY;
+ if (deltaY === 0) {
+ return;
+ }
+ this.viewportElement.scrollTop += deltaY;
+ ev.preventDefault();
+ };
+ ;
+ return Viewport;
+}());
+exports.Viewport = Viewport;
+
+
+
+},{}],16:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+function prepareTextForTerminal(text, isMSWindows) {
+ if (isMSWindows) {
+ return text.replace(/\r?\n/g, '\r');
+ }
+ return text;
+}
+exports.prepareTextForTerminal = prepareTextForTerminal;
+function bracketTextForPaste(text, bracketedPasteMode) {
+ if (bracketedPasteMode) {
+ return '\x1b[200~' + text + '\x1b[201~';
+ }
+ return text;
+}
+exports.bracketTextForPaste = bracketTextForPaste;
+function copyHandler(ev, term, selectionManager) {
+ if (term.browser.isMSIE) {
+ window.clipboardData.setData('Text', selectionManager.selectionText);
+ }
+ else {
+ ev.clipboardData.setData('text/plain', selectionManager.selectionText);
+ }
+ ev.preventDefault();
+}
+exports.copyHandler = copyHandler;
+function pasteHandler(ev, term) {
+ ev.stopPropagation();
+ var text;
+ var dispatchPaste = function (text) {
+ text = prepareTextForTerminal(text, term.browser.isMSWindows);
+ text = bracketTextForPaste(text, term.bracketedPasteMode);
+ term.handler(text);
+ term.textarea.value = '';
+ term.emit('paste', text);
+ term.cancel(ev);
+ };
+ if (term.browser.isMSIE) {
+ if (window.clipboardData) {
+ text = window.clipboardData.getData('Text');
+ dispatchPaste(text);
+ }
+ }
+ else {
+ if (ev.clipboardData) {
+ text = ev.clipboardData.getData('text/plain');
+ dispatchPaste(text);
+ }
+ }
+}
+exports.pasteHandler = pasteHandler;
+function moveTextAreaUnderMouseCursor(ev, textarea) {
+ textarea.style.position = 'fixed';
+ textarea.style.width = '20px';
+ textarea.style.height = '20px';
+ textarea.style.left = (ev.clientX - 10) + 'px';
+ textarea.style.top = (ev.clientY - 10) + 'px';
+ textarea.style.zIndex = '1000';
+ textarea.focus();
+ setTimeout(function () {
+ textarea.style.position = null;
+ textarea.style.width = null;
+ textarea.style.height = null;
+ textarea.style.left = null;
+ textarea.style.top = null;
+ textarea.style.zIndex = null;
+ }, 4);
+}
+exports.moveTextAreaUnderMouseCursor = moveTextAreaUnderMouseCursor;
+function rightClickHandler(ev, textarea, selectionManager) {
+ moveTextAreaUnderMouseCursor(ev, textarea);
+ textarea.value = selectionManager.selectionText;
+ textarea.select();
+}
+exports.rightClickHandler = rightClickHandler;
+
+
+
+},{}],17:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var HOVER_DURATION = 500;
+var MouseZoneManager = (function () {
+ function MouseZoneManager(_terminal) {
+ var _this = this;
+ this._terminal = _terminal;
+ this._zones = [];
+ this._areZonesActive = false;
+ this._tooltipTimeout = null;
+ this._currentZone = null;
+ this._lastHoverCoords = [null, null];
+ this._terminal.element.addEventListener('mousedown', function (e) { return _this._onMouseDown(e); });
+ this._mouseMoveListener = function (e) { return _this._onMouseMove(e); };
+ this._clickListener = function (e) { return _this._onClick(e); };
+ }
+ MouseZoneManager.prototype.add = function (zone) {
+ this._zones.push(zone);
+ if (this._zones.length === 1) {
+ this._activate();
+ }
+ };
+ MouseZoneManager.prototype.clearAll = function (start, end) {
+ if (this._zones.length === 0) {
+ return;
+ }
+ if (!end) {
+ start = 0;
+ end = this._terminal.rows - 1;
+ }
+ for (var i = 0; i < this._zones.length; i++) {
+ var zone = this._zones[i];
+ if (zone.y > start && zone.y <= end + 1) {
+ if (this._currentZone && this._currentZone === zone) {
+ this._currentZone.leaveCallback();
+ this._currentZone = null;
+ }
+ this._zones.splice(i--, 1);
+ }
+ }
+ if (this._zones.length === 0) {
+ this._deactivate();
+ }
+ };
+ MouseZoneManager.prototype._activate = function () {
+ if (!this._areZonesActive) {
+ this._areZonesActive = true;
+ this._terminal.element.addEventListener('mousemove', this._mouseMoveListener);
+ this._terminal.element.addEventListener('click', this._clickListener);
+ }
+ };
+ MouseZoneManager.prototype._deactivate = function () {
+ if (this._areZonesActive) {
+ this._areZonesActive = false;
+ this._terminal.element.removeEventListener('mousemove', this._mouseMoveListener);
+ this._terminal.element.removeEventListener('click', this._clickListener);
+ }
+ };
+ MouseZoneManager.prototype._onMouseMove = function (e) {
+ if (this._lastHoverCoords[0] !== e.pageX || this._lastHoverCoords[1] !== e.pageY) {
+ this._onHover(e);
+ this._lastHoverCoords = [e.pageX, e.pageY];
+ }
+ };
+ MouseZoneManager.prototype._onHover = function (e) {
+ var _this = this;
+ var zone = this._findZoneEventAt(e);
+ if (zone === this._currentZone) {
+ return;
+ }
+ if (this._currentZone) {
+ this._currentZone.leaveCallback();
+ this._currentZone = null;
+ if (this._tooltipTimeout) {
+ clearTimeout(this._tooltipTimeout);
+ }
+ }
+ if (!zone) {
+ return;
+ }
+ this._currentZone = zone;
+ if (zone.hoverCallback) {
+ zone.hoverCallback(e);
+ }
+ this._tooltipTimeout = setTimeout(function () { return _this._onTooltip(e); }, HOVER_DURATION);
+ };
+ MouseZoneManager.prototype._onTooltip = function (e) {
+ this._tooltipTimeout = null;
+ var zone = this._findZoneEventAt(e);
+ if (zone && zone.tooltipCallback) {
+ zone.tooltipCallback(e);
+ }
+ };
+ MouseZoneManager.prototype._onMouseDown = function (e) {
+ if (!this._areZonesActive) {
+ return;
+ }
+ var zone = this._findZoneEventAt(e);
+ if (zone) {
+ e.preventDefault();
+ e.stopImmediatePropagation();
+ }
+ };
+ MouseZoneManager.prototype._onClick = function (e) {
+ var zone = this._findZoneEventAt(e);
+ if (zone) {
+ zone.clickCallback(e);
+ e.preventDefault();
+ e.stopImmediatePropagation();
+ }
+ };
+ MouseZoneManager.prototype._findZoneEventAt = function (e) {
+ var coords = this._terminal.mouseHelper.getCoords(e, this._terminal.element, this._terminal.charMeasure, this._terminal.options.lineHeight, this._terminal.cols, this._terminal.rows);
+ if (!coords) {
+ return null;
+ }
+ for (var i = 0; i < this._zones.length; i++) {
+ var zone = this._zones[i];
+ if (zone.y === coords[1] && zone.x1 <= coords[0] && zone.x2 > coords[0]) {
+ return zone;
+ }
+ }
+ ;
+ return null;
+ };
+ return MouseZoneManager;
+}());
+exports.MouseZoneManager = MouseZoneManager;
+var MouseZone = (function () {
+ function MouseZone(x1, x2, y, clickCallback, hoverCallback, tooltipCallback, leaveCallback) {
+ this.x1 = x1;
+ this.x2 = x2;
+ this.y = y;
+ this.clickCallback = clickCallback;
+ this.hoverCallback = hoverCallback;
+ this.tooltipCallback = tooltipCallback;
+ this.leaveCallback = leaveCallback;
+ }
+ return MouseZone;
+}());
+exports.MouseZone = MouseZone;
+
+
+
+},{}],18:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var CharAtlas_1 = require("./CharAtlas");
+var Buffer_1 = require("../Buffer");
+exports.INVERTED_DEFAULT_COLOR = -1;
+var DIM_OPACITY = 0.5;
+var BaseRenderLayer = (function () {
+ function BaseRenderLayer(container, id, zIndex, _alpha, _colors) {
+ this._alpha = _alpha;
+ this._colors = _colors;
+ this._scaledCharWidth = 0;
+ this._scaledCharHeight = 0;
+ this._scaledCellWidth = 0;
+ this._scaledCellHeight = 0;
+ this._scaledCharLeft = 0;
+ this._scaledCharTop = 0;
+ this._canvas = document.createElement('canvas');
+ this._canvas.id = "xterm-" + id + "-layer";
+ this._canvas.style.zIndex = zIndex.toString();
+ this._ctx = this._canvas.getContext('2d', { alpha: _alpha });
+ this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
+ if (!_alpha) {
+ this.clearAll();
+ }
+ container.appendChild(this._canvas);
+ }
+ BaseRenderLayer.prototype.onOptionsChanged = function (terminal) { };
+ BaseRenderLayer.prototype.onBlur = function (terminal) { };
+ BaseRenderLayer.prototype.onFocus = function (terminal) { };
+ BaseRenderLayer.prototype.onCursorMove = function (terminal) { };
+ BaseRenderLayer.prototype.onGridChanged = function (terminal, startRow, endRow) { };
+ BaseRenderLayer.prototype.onSelectionChanged = function (terminal, start, end) { };
+ BaseRenderLayer.prototype.onThemeChanged = function (terminal, colorSet) {
+ this._refreshCharAtlas(terminal, colorSet);
+ };
+ BaseRenderLayer.prototype._refreshCharAtlas = function (terminal, colorSet) {
+ var _this = this;
+ if (this._scaledCharWidth <= 0 && this._scaledCharHeight <= 0) {
+ return;
+ }
+ this._charAtlas = null;
+ var result = CharAtlas_1.acquireCharAtlas(terminal, this._colors, this._scaledCharWidth, this._scaledCharHeight);
+ if (result instanceof HTMLCanvasElement) {
+ this._charAtlas = result;
+ }
+ else {
+ result.then(function (bitmap) { return _this._charAtlas = bitmap; });
+ }
+ };
+ BaseRenderLayer.prototype.resize = function (terminal, dim, charSizeChanged) {
+ this._scaledCellWidth = dim.scaledCellWidth;
+ this._scaledCellHeight = dim.scaledCellHeight;
+ this._scaledCharWidth = dim.scaledCharWidth;
+ this._scaledCharHeight = dim.scaledCharHeight;
+ this._scaledCharLeft = dim.scaledCharLeft;
+ this._scaledCharTop = dim.scaledCharTop;
+ this._canvas.width = dim.scaledCanvasWidth;
+ this._canvas.height = dim.scaledCanvasHeight;
+ this._canvas.style.width = dim.canvasWidth + "px";
+ this._canvas.style.height = dim.canvasHeight + "px";
+ if (!this._alpha) {
+ this.clearAll();
+ }
+ if (charSizeChanged) {
+ this._refreshCharAtlas(terminal, this._colors);
+ }
+ };
+ BaseRenderLayer.prototype.fillCells = function (x, y, width, height) {
+ this._ctx.fillRect(x * this._scaledCellWidth, y * this._scaledCellHeight, width * this._scaledCellWidth, height * this._scaledCellHeight);
+ };
+ BaseRenderLayer.prototype.fillBottomLineAtCells = function (x, y, width) {
+ if (width === void 0) { width = 1; }
+ this._ctx.fillRect(x * this._scaledCellWidth, (y + 1) * this._scaledCellHeight - window.devicePixelRatio - 1, width * this._scaledCellWidth, window.devicePixelRatio);
+ };
+ BaseRenderLayer.prototype.fillLeftLineAtCell = function (x, y) {
+ this._ctx.fillRect(x * this._scaledCellWidth, y * this._scaledCellHeight, window.devicePixelRatio, this._scaledCellHeight);
+ };
+ BaseRenderLayer.prototype.strokeRectAtCell = function (x, y, width, height) {
+ this._ctx.lineWidth = window.devicePixelRatio;
+ this._ctx.strokeRect(x * this._scaledCellWidth + window.devicePixelRatio / 2, y * this._scaledCellHeight + (window.devicePixelRatio / 2), width * this._scaledCellWidth - window.devicePixelRatio, (height * this._scaledCellHeight) - window.devicePixelRatio);
+ };
+ BaseRenderLayer.prototype.clearAll = function () {
+ if (this._alpha) {
+ this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
+ }
+ else {
+ this._ctx.fillStyle = this._colors.background;
+ this._ctx.fillRect(0, 0, this._canvas.width, this._canvas.height);
+ }
+ };
+ BaseRenderLayer.prototype.clearCells = function (x, y, width, height) {
+ if (this._alpha) {
+ this._ctx.clearRect(x * this._scaledCellWidth, y * this._scaledCellHeight, width * this._scaledCellWidth, height * this._scaledCellHeight);
+ }
+ else {
+ this._ctx.fillStyle = this._colors.background;
+ this._ctx.fillRect(x * this._scaledCellWidth, y * this._scaledCellHeight, width * this._scaledCellWidth, height * this._scaledCellHeight);
+ }
+ };
+ BaseRenderLayer.prototype.fillCharTrueColor = function (terminal, charData, x, y) {
+ this._ctx.font = terminal.options.fontSize * window.devicePixelRatio + "px " + terminal.options.fontFamily;
+ this._ctx.textBaseline = 'top';
+ this._clipRow(terminal, y);
+ this._ctx.fillText(charData[Buffer_1.CHAR_DATA_CHAR_INDEX], x * this._scaledCellWidth + this._scaledCharLeft, y * this._scaledCellHeight + this._scaledCharTop);
+ };
+ BaseRenderLayer.prototype.drawChar = function (terminal, char, code, width, x, y, fg, bg, bold, dim) {
+ var colorIndex = 0;
+ if (fg < 256) {
+ colorIndex = fg + 2;
+ }
+ else {
+ if (bold && terminal.options.enableBold) {
+ colorIndex = 1;
+ }
+ }
+ var isAscii = code < 256;
+ var isBasicColor = (colorIndex > 1 && fg < 16) && (fg < 8 || bold);
+ var isDefaultColor = fg >= 256;
+ var isDefaultBackground = bg >= 256;
+ if (this._charAtlas && isAscii && (isBasicColor || isDefaultColor) && isDefaultBackground) {
+ var charAtlasCellWidth = this._scaledCharWidth + CharAtlas_1.CHAR_ATLAS_CELL_SPACING;
+ var charAtlasCellHeight = this._scaledCharHeight + CharAtlas_1.CHAR_ATLAS_CELL_SPACING;
+ if (dim) {
+ this._ctx.globalAlpha = DIM_OPACITY;
+ }
+ if (bold && !terminal.options.enableBold) {
+ if (colorIndex > 1) {
+ colorIndex -= 8;
+ }
+ }
+ this._ctx.drawImage(this._charAtlas, code * charAtlasCellWidth, colorIndex * charAtlasCellHeight, charAtlasCellWidth, this._scaledCharHeight, x * this._scaledCellWidth + this._scaledCharLeft, y * this._scaledCellHeight + this._scaledCharTop, charAtlasCellWidth, this._scaledCharHeight);
+ }
+ else {
+ this._drawUncachedChar(terminal, char, width, fg, x, y, bold, dim);
+ }
+ };
+ BaseRenderLayer.prototype._drawUncachedChar = function (terminal, char, width, fg, x, y, bold, dim) {
+ this._ctx.save();
+ this._ctx.font = terminal.options.fontSize * window.devicePixelRatio + "px " + terminal.options.fontFamily;
+ if (bold && terminal.options.enableBold) {
+ this._ctx.font = "bold " + this._ctx.font;
+ }
+ this._ctx.textBaseline = 'top';
+ if (fg === exports.INVERTED_DEFAULT_COLOR) {
+ this._ctx.fillStyle = this._colors.background;
+ }
+ else if (fg < 256) {
+ this._ctx.fillStyle = this._colors.ansi[fg];
+ }
+ else {
+ this._ctx.fillStyle = this._colors.foreground;
+ }
+ this._clipRow(terminal, y);
+ if (dim) {
+ this._ctx.globalAlpha = DIM_OPACITY;
+ }
+ this._ctx.fillText(char, x * this._scaledCellWidth + this._scaledCharLeft, y * this._scaledCellHeight + this._scaledCharTop);
+ this._ctx.restore();
+ };
+ BaseRenderLayer.prototype._clipRow = function (terminal, y) {
+ this._ctx.beginPath();
+ this._ctx.rect(0, y * this._scaledCellHeight, terminal.cols * this._scaledCellWidth, this._scaledCellHeight);
+ this._ctx.clip();
+ };
+ return BaseRenderLayer;
+}());
+exports.BaseRenderLayer = BaseRenderLayer;
+
+
+
+},{"../Buffer":1,"./CharAtlas":19}],19:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Browser_1 = require("../utils/Browser");
+exports.CHAR_ATLAS_CELL_SPACING = 1;
+var charAtlasCache = [];
+function acquireCharAtlas(terminal, colors, scaledCharWidth, scaledCharHeight) {
+ var newConfig = generateConfig(scaledCharWidth, scaledCharHeight, terminal, colors);
+ for (var i = 0; i < charAtlasCache.length; i++) {
+ var entry = charAtlasCache[i];
+ var ownedByIndex = entry.ownedBy.indexOf(terminal);
+ if (ownedByIndex >= 0) {
+ if (configEquals(entry.config, newConfig)) {
+ return entry.bitmap;
+ }
+ else {
+ if (entry.ownedBy.length === 1) {
+ charAtlasCache.splice(i, 1);
+ }
+ else {
+ entry.ownedBy.splice(ownedByIndex, 1);
+ }
+ break;
+ }
+ }
+ }
+ for (var i = 0; i < charAtlasCache.length; i++) {
+ var entry = charAtlasCache[i];
+ if (configEquals(entry.config, newConfig)) {
+ entry.ownedBy.push(terminal);
+ return entry.bitmap;
+ }
+ }
+ var newEntry = {
+ bitmap: generator.generate(scaledCharWidth, scaledCharHeight, terminal.options.fontSize, terminal.options.fontFamily, colors.background, colors.foreground, colors.ansi),
+ config: newConfig,
+ ownedBy: [terminal]
+ };
+ charAtlasCache.push(newEntry);
+ return newEntry.bitmap;
+}
+exports.acquireCharAtlas = acquireCharAtlas;
+function generateConfig(scaledCharWidth, scaledCharHeight, terminal, colors) {
+ var clonedColors = {
+ foreground: colors.foreground,
+ background: colors.background,
+ cursor: null,
+ cursorAccent: null,
+ selection: null,
+ ansi: colors.ansi.slice(0, 16)
+ };
+ return {
+ scaledCharWidth: scaledCharWidth,
+ scaledCharHeight: scaledCharHeight,
+ fontFamily: terminal.options.fontFamily,
+ fontSize: terminal.options.fontSize,
+ colors: clonedColors
+ };
+}
+function configEquals(a, b) {
+ for (var i = 0; i < a.colors.ansi.length; i++) {
+ if (a.colors.ansi[i] !== b.colors.ansi[i]) {
+ return false;
+ }
+ }
+ return a.fontFamily === b.fontFamily &&
+ a.fontSize === b.fontSize &&
+ a.scaledCharWidth === b.scaledCharWidth &&
+ a.scaledCharHeight === b.scaledCharHeight &&
+ a.colors.foreground === b.colors.foreground &&
+ a.colors.background === b.colors.background;
+}
+var generator;
+function initialize(document) {
+ if (!generator) {
+ generator = new CharAtlasGenerator(document);
+ }
+}
+exports.initialize = initialize;
+var CharAtlasGenerator = (function () {
+ function CharAtlasGenerator(_document) {
+ this._document = _document;
+ this._canvas = this._document.createElement('canvas');
+ this._ctx = this._canvas.getContext('2d', { alpha: false });
+ this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
+ }
+ CharAtlasGenerator.prototype.generate = function (scaledCharWidth, scaledCharHeight, fontSize, fontFamily, background, foreground, ansiColors) {
+ var cellWidth = scaledCharWidth + exports.CHAR_ATLAS_CELL_SPACING;
+ var cellHeight = scaledCharHeight + exports.CHAR_ATLAS_CELL_SPACING;
+ this._canvas.width = 255 * cellWidth;
+ this._canvas.height = (2 + 16) * cellHeight;
+ this._ctx.fillStyle = background;
+ this._ctx.fillRect(0, 0, this._canvas.width, this._canvas.height);
+ this._ctx.save();
+ this._ctx.fillStyle = foreground;
+ this._ctx.font = fontSize * window.devicePixelRatio + "px " + fontFamily;
+ this._ctx.textBaseline = 'top';
+ for (var i = 0; i < 256; i++) {
+ this._ctx.save();
+ this._ctx.beginPath();
+ this._ctx.rect(i * cellWidth, 0, cellWidth, cellHeight);
+ this._ctx.clip();
+ this._ctx.fillText(String.fromCharCode(i), i * cellWidth, 0);
+ this._ctx.restore();
+ }
+ this._ctx.save();
+ this._ctx.font = "bold " + this._ctx.font;
+ for (var i = 0; i < 256; i++) {
+ this._ctx.save();
+ this._ctx.beginPath();
+ this._ctx.rect(i * cellWidth, cellHeight, cellWidth, cellHeight);
+ this._ctx.clip();
+ this._ctx.fillText(String.fromCharCode(i), i * cellWidth, cellHeight);
+ this._ctx.restore();
+ }
+ this._ctx.restore();
+ this._ctx.font = fontSize * window.devicePixelRatio + "px " + fontFamily;
+ for (var colorIndex = 0; colorIndex < 16; colorIndex++) {
+ if (colorIndex === 8) {
+ this._ctx.font = "bold " + this._ctx.font;
+ }
+ var y = (colorIndex + 2) * cellHeight;
+ for (var i = 0; i < 256; i++) {
+ this._ctx.save();
+ this._ctx.beginPath();
+ this._ctx.rect(i * cellWidth, y, cellWidth, cellHeight);
+ this._ctx.clip();
+ this._ctx.fillStyle = ansiColors[colorIndex];
+ this._ctx.fillText(String.fromCharCode(i), i * cellWidth, y);
+ this._ctx.restore();
+ }
+ }
+ this._ctx.restore();
+ if (!('createImageBitmap' in window) || Browser_1.isFirefox) {
+ var result = this._canvas;
+ this._canvas = this._document.createElement('canvas');
+ this._ctx = this._canvas.getContext('2d');
+ this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
+ return result;
+ }
+ var charAtlasImageData = this._ctx.getImageData(0, 0, this._canvas.width, this._canvas.height);
+ var r = parseInt(background.substr(1, 2), 16);
+ var g = parseInt(background.substr(3, 2), 16);
+ var b = parseInt(background.substr(5, 2), 16);
+ this._clearColor(charAtlasImageData, r, g, b);
+ var promise = window.createImageBitmap(charAtlasImageData);
+ this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
+ return promise;
+ };
+ CharAtlasGenerator.prototype._clearColor = function (imageData, r, g, b) {
+ for (var offset = 0; offset < imageData.data.length; offset += 4) {
+ if (imageData.data[offset] === r &&
+ imageData.data[offset + 1] === g &&
+ imageData.data[offset + 2] === b) {
+ imageData.data[offset + 3] = 0;
+ }
+ }
+ };
+ return CharAtlasGenerator;
+}());
+
+
+
+},{"../utils/Browser":28}],20:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var DEFAULT_FOREGROUND = '#ffffff';
+var DEFAULT_BACKGROUND = '#333333';
+var DEFAULT_CURSOR = '#ffffff';
+var DEFAULT_CURSOR_ACCENT = '#333333';
+var DEFAULT_SELECTION = 'rgba(255, 255, 255, 0.3)';
+exports.DEFAULT_ANSI_COLORS = [
+ '#2e3436',
+ '#cc0000',
+ '#4e9a06',
+ '#c4a000',
+ '#3465a4',
+ '#75507b',
+ '#06989a',
+ '#d3d7cf',
+ '#555753',
+ '#ef2929',
+ '#8ae234',
+ '#fce94f',
+ '#729fcf',
+ '#ad7fa8',
+ '#34e2e2',
+ '#eeeeec'
+];
+function generate256Colors(first16Colors) {
+ var colors = first16Colors.slice();
+ var v = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff];
+ for (var i = 0; i < 216; i++) {
+ var r = toPaddedHex(v[(i / 36) % 6 | 0]);
+ var g = toPaddedHex(v[(i / 6) % 6 | 0]);
+ var b = toPaddedHex(v[i % 6]);
+ colors.push("#" + r + g + b);
+ }
+ for (var i = 0; i < 24; i++) {
+ var c = toPaddedHex(8 + i * 10);
+ colors.push("#" + c + c + c);
+ }
+ return colors;
+}
+function toPaddedHex(c) {
+ var s = c.toString(16);
+ return s.length < 2 ? '0' + s : s;
+}
+var ColorManager = (function () {
+ function ColorManager() {
+ this.colors = {
+ foreground: DEFAULT_FOREGROUND,
+ background: DEFAULT_BACKGROUND,
+ cursor: DEFAULT_CURSOR,
+ cursorAccent: DEFAULT_CURSOR_ACCENT,
+ selection: DEFAULT_SELECTION,
+ ansi: generate256Colors(exports.DEFAULT_ANSI_COLORS)
+ };
+ }
+ ColorManager.prototype.setTheme = function (theme) {
+ this.colors.foreground = theme.foreground || DEFAULT_FOREGROUND;
+ this.colors.background = this._validateColor(theme.background, DEFAULT_BACKGROUND);
+ this.colors.cursor = theme.cursor || DEFAULT_CURSOR;
+ this.colors.cursorAccent = theme.cursorAccent || DEFAULT_CURSOR_ACCENT;
+ this.colors.selection = theme.selection || DEFAULT_SELECTION;
+ this.colors.ansi[0] = theme.black || exports.DEFAULT_ANSI_COLORS[0];
+ this.colors.ansi[1] = theme.red || exports.DEFAULT_ANSI_COLORS[1];
+ this.colors.ansi[2] = theme.green || exports.DEFAULT_ANSI_COLORS[2];
+ this.colors.ansi[3] = theme.yellow || exports.DEFAULT_ANSI_COLORS[3];
+ this.colors.ansi[4] = theme.blue || exports.DEFAULT_ANSI_COLORS[4];
+ this.colors.ansi[5] = theme.magenta || exports.DEFAULT_ANSI_COLORS[5];
+ this.colors.ansi[6] = theme.cyan || exports.DEFAULT_ANSI_COLORS[6];
+ this.colors.ansi[7] = theme.white || exports.DEFAULT_ANSI_COLORS[7];
+ this.colors.ansi[8] = theme.brightBlack || exports.DEFAULT_ANSI_COLORS[8];
+ this.colors.ansi[9] = theme.brightRed || exports.DEFAULT_ANSI_COLORS[9];
+ this.colors.ansi[10] = theme.brightGreen || exports.DEFAULT_ANSI_COLORS[10];
+ this.colors.ansi[11] = theme.brightYellow || exports.DEFAULT_ANSI_COLORS[11];
+ this.colors.ansi[12] = theme.brightBlue || exports.DEFAULT_ANSI_COLORS[12];
+ this.colors.ansi[13] = theme.brightMagenta || exports.DEFAULT_ANSI_COLORS[13];
+ this.colors.ansi[14] = theme.brightCyan || exports.DEFAULT_ANSI_COLORS[14];
+ this.colors.ansi[15] = theme.brightWhite || exports.DEFAULT_ANSI_COLORS[15];
+ };
+ ColorManager.prototype._validateColor = function (color, fallback) {
+ if (!color) {
+ return fallback;
+ }
+ if (color.length === 7 && color.charAt(0) === '#') {
+ return color;
+ }
+ if (color.length === 4 && color.charAt(0) === '#') {
+ var r = color.charAt(1);
+ var g = color.charAt(2);
+ var b = color.charAt(3);
+ return "#" + r + r + g + g + b + b;
+ }
+ return fallback;
+ };
+ return ColorManager;
+}());
+exports.ColorManager = ColorManager;
+
+
+
+},{}],21:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+ var extendStatics = Object.setPrototypeOf ||
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+ function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+ return function (d, b) {
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Buffer_1 = require("../Buffer");
+var BaseRenderLayer_1 = require("./BaseRenderLayer");
+var BLINK_INTERVAL = 600;
+var CursorRenderLayer = (function (_super) {
+ __extends(CursorRenderLayer, _super);
+ function CursorRenderLayer(container, zIndex, colors) {
+ var _this = _super.call(this, container, 'cursor', zIndex, true, colors) || this;
+ _this._state = {
+ x: null,
+ y: null,
+ isFocused: null,
+ style: null,
+ width: null,
+ };
+ _this._cursorRenderers = {
+ 'bar': _this._renderBarCursor.bind(_this),
+ 'block': _this._renderBlockCursor.bind(_this),
+ 'underline': _this._renderUnderlineCursor.bind(_this)
+ };
+ return _this;
+ }
+ CursorRenderLayer.prototype.resize = function (terminal, dim, charSizeChanged) {
+ _super.prototype.resize.call(this, terminal, dim, charSizeChanged);
+ this._state = {
+ x: null,
+ y: null,
+ isFocused: null,
+ style: null,
+ width: null,
+ };
+ };
+ CursorRenderLayer.prototype.reset = function (terminal) {
+ this._clearCursor();
+ if (this._cursorBlinkStateManager) {
+ this._cursorBlinkStateManager.dispose();
+ this._cursorBlinkStateManager = null;
+ this.onOptionsChanged(terminal);
+ }
+ };
+ CursorRenderLayer.prototype.onBlur = function (terminal) {
+ if (this._cursorBlinkStateManager) {
+ this._cursorBlinkStateManager.pause();
+ }
+ terminal.refresh(terminal.buffer.y, terminal.buffer.y);
+ };
+ CursorRenderLayer.prototype.onFocus = function (terminal) {
+ if (this._cursorBlinkStateManager) {
+ this._cursorBlinkStateManager.resume(terminal);
+ }
+ else {
+ terminal.refresh(terminal.buffer.y, terminal.buffer.y);
+ }
+ };
+ CursorRenderLayer.prototype.onOptionsChanged = function (terminal) {
+ var _this = this;
+ if (terminal.options.cursorBlink) {
+ if (!this._cursorBlinkStateManager) {
+ this._cursorBlinkStateManager = new CursorBlinkStateManager(terminal, function () {
+ _this._render(terminal, true);
+ });
+ }
+ }
+ else {
+ if (this._cursorBlinkStateManager) {
+ this._cursorBlinkStateManager.dispose();
+ this._cursorBlinkStateManager = null;
+ }
+ terminal.refresh(terminal.buffer.y, terminal.buffer.y);
+ }
+ };
+ CursorRenderLayer.prototype.onCursorMove = function (terminal) {
+ if (this._cursorBlinkStateManager) {
+ this._cursorBlinkStateManager.restartBlinkAnimation(terminal);
+ }
+ };
+ CursorRenderLayer.prototype.onGridChanged = function (terminal, startRow, endRow) {
+ if (!this._cursorBlinkStateManager || this._cursorBlinkStateManager.isPaused) {
+ this._render(terminal, false);
+ }
+ };
+ CursorRenderLayer.prototype._render = function (terminal, triggeredByAnimationFrame) {
+ if (!terminal.cursorState || terminal.cursorHidden) {
+ this._clearCursor();
+ return;
+ }
+ var cursorY = terminal.buffer.ybase + terminal.buffer.y;
+ var viewportRelativeCursorY = cursorY - terminal.buffer.ydisp;
+ if (viewportRelativeCursorY < 0 || viewportRelativeCursorY >= terminal.rows) {
+ this._clearCursor();
+ return;
+ }
+ var charData = terminal.buffer.lines.get(cursorY)[terminal.buffer.x];
+ if (!charData) {
+ return;
+ }
+ if (!terminal.isFocused) {
+ this._clearCursor();
+ this._ctx.save();
+ this._ctx.fillStyle = this._colors.cursor;
+ this._renderBlurCursor(terminal, terminal.buffer.x, viewportRelativeCursorY, charData);
+ this._ctx.restore();
+ this._state.x = terminal.buffer.x;
+ this._state.y = viewportRelativeCursorY;
+ this._state.isFocused = false;
+ this._state.style = terminal.options.cursorStyle;
+ this._state.width = charData[Buffer_1.CHAR_DATA_WIDTH_INDEX];
+ return;
+ }
+ if (this._cursorBlinkStateManager && !this._cursorBlinkStateManager.isCursorVisible) {
+ this._clearCursor();
+ return;
+ }
+ if (this._state) {
+ if (this._state.x === terminal.buffer.x &&
+ this._state.y === viewportRelativeCursorY &&
+ this._state.isFocused === terminal.isFocused &&
+ this._state.style === terminal.options.cursorStyle &&
+ this._state.width === charData[Buffer_1.CHAR_DATA_WIDTH_INDEX]) {
+ return;
+ }
+ this._clearCursor();
+ }
+ this._ctx.save();
+ this._cursorRenderers[terminal.options.cursorStyle || 'block'](terminal, terminal.buffer.x, viewportRelativeCursorY, charData);
+ this._ctx.restore();
+ this._state.x = terminal.buffer.x;
+ this._state.y = viewportRelativeCursorY;
+ this._state.isFocused = false;
+ this._state.style = terminal.options.cursorStyle;
+ this._state.width = charData[Buffer_1.CHAR_DATA_WIDTH_INDEX];
+ };
+ CursorRenderLayer.prototype._clearCursor = function () {
+ if (this._state) {
+ this.clearCells(this._state.x, this._state.y, this._state.width, 1);
+ this._state = {
+ x: null,
+ y: null,
+ isFocused: null,
+ style: null,
+ width: null,
+ };
+ }
+ };
+ CursorRenderLayer.prototype._renderBarCursor = function (terminal, x, y, charData) {
+ this._ctx.save();
+ this._ctx.fillStyle = this._colors.cursor;
+ this.fillLeftLineAtCell(x, y);
+ this._ctx.restore();
+ };
+ CursorRenderLayer.prototype._renderBlockCursor = function (terminal, x, y, charData) {
+ this._ctx.save();
+ this._ctx.fillStyle = this._colors.cursor;
+ this.fillCells(x, y, charData[Buffer_1.CHAR_DATA_WIDTH_INDEX], 1);
+ this._ctx.fillStyle = this._colors.cursorAccent;
+ this.fillCharTrueColor(terminal, charData, x, y);
+ this._ctx.restore();
+ };
+ CursorRenderLayer.prototype._renderUnderlineCursor = function (terminal, x, y, charData) {
+ this._ctx.save();
+ this._ctx.fillStyle = this._colors.cursor;
+ this.fillBottomLineAtCells(x, y);
+ this._ctx.restore();
+ };
+ CursorRenderLayer.prototype._renderBlurCursor = function (terminal, x, y, charData) {
+ this._ctx.save();
+ this._ctx.strokeStyle = this._colors.cursor;
+ this.strokeRectAtCell(x, y, charData[Buffer_1.CHAR_DATA_WIDTH_INDEX], 1);
+ this._ctx.restore();
+ };
+ return CursorRenderLayer;
+}(BaseRenderLayer_1.BaseRenderLayer));
+exports.CursorRenderLayer = CursorRenderLayer;
+var CursorBlinkStateManager = (function () {
+ function CursorBlinkStateManager(terminal, renderCallback) {
+ this.renderCallback = renderCallback;
+ this.isCursorVisible = true;
+ if (terminal.isFocused) {
+ this._restartInterval();
+ }
+ }
+ Object.defineProperty(CursorBlinkStateManager.prototype, "isPaused", {
+ get: function () { return !(this._blinkStartTimeout || this._blinkInterval); },
+ enumerable: true,
+ configurable: true
+ });
+ CursorBlinkStateManager.prototype.dispose = function () {
+ if (this._blinkInterval) {
+ window.clearInterval(this._blinkInterval);
+ this._blinkInterval = null;
+ }
+ if (this._blinkStartTimeout) {
+ window.clearTimeout(this._blinkStartTimeout);
+ this._blinkStartTimeout = null;
+ }
+ if (this._animationFrame) {
+ window.cancelAnimationFrame(this._animationFrame);
+ this._animationFrame = null;
+ }
+ };
+ CursorBlinkStateManager.prototype.restartBlinkAnimation = function (terminal) {
+ var _this = this;
+ if (this.isPaused) {
+ return;
+ }
+ this._animationTimeRestarted = Date.now();
+ this.isCursorVisible = true;
+ if (!this._animationFrame) {
+ this._animationFrame = window.requestAnimationFrame(function () {
+ _this.renderCallback();
+ _this._animationFrame = null;
+ });
+ }
+ };
+ CursorBlinkStateManager.prototype._restartInterval = function (timeToStart) {
+ var _this = this;
+ if (timeToStart === void 0) { timeToStart = BLINK_INTERVAL; }
+ if (this._blinkInterval) {
+ window.clearInterval(this._blinkInterval);
+ }
+ this._blinkStartTimeout = setTimeout(function () {
+ if (_this._animationTimeRestarted) {
+ var time = BLINK_INTERVAL - (Date.now() - _this._animationTimeRestarted);
+ _this._animationTimeRestarted = null;
+ if (time > 0) {
+ _this._restartInterval(time);
+ return;
+ }
+ }
+ _this.isCursorVisible = false;
+ _this._animationFrame = window.requestAnimationFrame(function () {
+ _this.renderCallback();
+ _this._animationFrame = null;
+ });
+ _this._blinkInterval = setInterval(function () {
+ if (_this._animationTimeRestarted) {
+ var time = BLINK_INTERVAL - (Date.now() - _this._animationTimeRestarted);
+ _this._animationTimeRestarted = null;
+ _this._restartInterval(time);
+ return;
+ }
+ _this.isCursorVisible = !_this.isCursorVisible;
+ _this._animationFrame = window.requestAnimationFrame(function () {
+ _this.renderCallback();
+ _this._animationFrame = null;
+ });
+ }, BLINK_INTERVAL);
+ }, timeToStart);
+ };
+ CursorBlinkStateManager.prototype.pause = function () {
+ this.isCursorVisible = true;
+ if (this._blinkInterval) {
+ window.clearInterval(this._blinkInterval);
+ this._blinkInterval = null;
+ }
+ if (this._blinkStartTimeout) {
+ window.clearTimeout(this._blinkStartTimeout);
+ this._blinkStartTimeout = null;
+ }
+ if (this._animationFrame) {
+ window.cancelAnimationFrame(this._animationFrame);
+ this._animationFrame = null;
+ }
+ };
+ CursorBlinkStateManager.prototype.resume = function (terminal) {
+ this._animationTimeRestarted = null;
+ this._restartInterval();
+ this.restartBlinkAnimation(terminal);
+ };
+ return CursorBlinkStateManager;
+}());
+
+
+
+},{"../Buffer":1,"./BaseRenderLayer":18}],22:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var GridCache = (function () {
+ function GridCache() {
+ this.cache = [];
+ }
+ GridCache.prototype.resize = function (width, height) {
+ for (var x = 0; x < width; x++) {
+ if (this.cache.length <= x) {
+ this.cache.push([]);
+ }
+ for (var y = this.cache[x].length; y < height; y++) {
+ this.cache[x].push(null);
+ }
+ this.cache[x].length = height;
+ }
+ this.cache.length = width;
+ };
+ GridCache.prototype.clear = function () {
+ for (var x = 0; x < this.cache.length; x++) {
+ for (var y = 0; y < this.cache[x].length; y++) {
+ this.cache[x][y] = null;
+ }
+ }
+ };
+ return GridCache;
+}());
+exports.GridCache = GridCache;
+
+
+
+},{}],23:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+ var extendStatics = Object.setPrototypeOf ||
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+ function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+ return function (d, b) {
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var BaseRenderLayer_1 = require("./BaseRenderLayer");
+var Types_1 = require("../Types");
+var LinkRenderLayer = (function (_super) {
+ __extends(LinkRenderLayer, _super);
+ function LinkRenderLayer(container, zIndex, colors, terminal) {
+ var _this = _super.call(this, container, 'link', zIndex, true, colors) || this;
+ _this._state = null;
+ terminal.linkifier.on(Types_1.LinkHoverEventTypes.HOVER, function (e) { return _this._onLinkHover(e); });
+ terminal.linkifier.on(Types_1.LinkHoverEventTypes.LEAVE, function (e) { return _this._onLinkLeave(e); });
+ return _this;
+ }
+ LinkRenderLayer.prototype.resize = function (terminal, dim, charSizeChanged) {
+ _super.prototype.resize.call(this, terminal, dim, charSizeChanged);
+ this._state = null;
+ };
+ LinkRenderLayer.prototype.reset = function (terminal) {
+ this._clearCurrentLink();
+ };
+ LinkRenderLayer.prototype._clearCurrentLink = function () {
+ if (this._state) {
+ this.clearCells(this._state.x, this._state.y, this._state.length, 1);
+ this._state = null;
+ }
+ };
+ LinkRenderLayer.prototype._onLinkHover = function (e) {
+ this._ctx.fillStyle = this._colors.foreground;
+ this.fillBottomLineAtCells(e.x, e.y, e.length);
+ this._state = e;
+ };
+ LinkRenderLayer.prototype._onLinkLeave = function (e) {
+ this._clearCurrentLink();
+ };
+ return LinkRenderLayer;
+}(BaseRenderLayer_1.BaseRenderLayer));
+exports.LinkRenderLayer = LinkRenderLayer;
+
+
+
+},{"../Types":14,"./BaseRenderLayer":18}],24:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+ var extendStatics = Object.setPrototypeOf ||
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+ function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+ return function (d, b) {
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var TextRenderLayer_1 = require("./TextRenderLayer");
+var SelectionRenderLayer_1 = require("./SelectionRenderLayer");
+var CursorRenderLayer_1 = require("./CursorRenderLayer");
+var ColorManager_1 = require("./ColorManager");
+var LinkRenderLayer_1 = require("./LinkRenderLayer");
+var EventEmitter_1 = require("../EventEmitter");
+var Renderer = (function (_super) {
+ __extends(Renderer, _super);
+ function Renderer(_terminal, theme) {
+ var _this = _super.call(this) || this;
+ _this._terminal = _terminal;
+ _this._refreshRowsQueue = [];
+ _this._refreshAnimationFrame = null;
+ _this.colorManager = new ColorManager_1.ColorManager();
+ if (theme) {
+ _this.colorManager.setTheme(theme);
+ }
+ _this._renderLayers = [
+ new TextRenderLayer_1.TextRenderLayer(_this._terminal.element, 0, _this.colorManager.colors),
+ new SelectionRenderLayer_1.SelectionRenderLayer(_this._terminal.element, 1, _this.colorManager.colors),
+ new LinkRenderLayer_1.LinkRenderLayer(_this._terminal.element, 2, _this.colorManager.colors, _this._terminal),
+ new CursorRenderLayer_1.CursorRenderLayer(_this._terminal.element, 3, _this.colorManager.colors)
+ ];
+ _this.dimensions = {
+ scaledCharWidth: null,
+ scaledCharHeight: null,
+ scaledCellWidth: null,
+ scaledCellHeight: null,
+ scaledCharLeft: null,
+ scaledCharTop: null,
+ scaledCanvasWidth: null,
+ scaledCanvasHeight: null,
+ canvasWidth: null,
+ canvasHeight: null,
+ actualCellWidth: null,
+ actualCellHeight: null
+ };
+ _this._devicePixelRatio = window.devicePixelRatio;
+ return _this;
+ }
+ Renderer.prototype.onWindowResize = function (devicePixelRatio) {
+ if (this._devicePixelRatio !== devicePixelRatio) {
+ this._devicePixelRatio = devicePixelRatio;
+ this.onResize(this._terminal.cols, this._terminal.rows, true);
+ }
+ };
+ Renderer.prototype.setTheme = function (theme) {
+ var _this = this;
+ this.colorManager.setTheme(theme);
+ this._renderLayers.forEach(function (l) {
+ l.onThemeChanged(_this._terminal, _this.colorManager.colors);
+ l.reset(_this._terminal);
+ });
+ this._terminal.refresh(0, this._terminal.rows - 1);
+ return this.colorManager.colors;
+ };
+ Renderer.prototype.onResize = function (cols, rows, didCharSizeChange) {
+ var _this = this;
+ if (!this._terminal.charMeasure.width || !this._terminal.charMeasure.height) {
+ return;
+ }
+ this.dimensions.scaledCharWidth = Math.floor(this._terminal.charMeasure.width * window.devicePixelRatio);
+ this.dimensions.scaledCharHeight = Math.ceil(this._terminal.charMeasure.height * window.devicePixelRatio);
+ this.dimensions.scaledCellHeight = Math.floor(this.dimensions.scaledCharHeight * this._terminal.options.lineHeight);
+ this.dimensions.scaledCharTop = this._terminal.options.lineHeight === 1 ? 0 : Math.round((this.dimensions.scaledCellHeight - this.dimensions.scaledCharHeight) / 2);
+ this.dimensions.scaledCellWidth = this.dimensions.scaledCharWidth + Math.round(this._terminal.options.letterSpacing);
+ this.dimensions.scaledCharLeft = Math.floor(this._terminal.options.letterSpacing / 2);
+ this.dimensions.scaledCanvasHeight = this._terminal.rows * this.dimensions.scaledCellHeight;
+ this.dimensions.scaledCanvasWidth = this._terminal.cols * this.dimensions.scaledCellWidth;
+ this.dimensions.canvasHeight = Math.round(this.dimensions.scaledCanvasHeight / window.devicePixelRatio);
+ this.dimensions.canvasWidth = Math.round(this.dimensions.scaledCanvasWidth / window.devicePixelRatio);
+ this.dimensions.actualCellHeight = this.dimensions.canvasHeight / this._terminal.rows;
+ this.dimensions.actualCellWidth = this.dimensions.canvasWidth / this._terminal.cols;
+ this._renderLayers.forEach(function (l) { return l.resize(_this._terminal, _this.dimensions, didCharSizeChange); });
+ this._terminal.refresh(0, this._terminal.rows - 1);
+ this.emit('resize', {
+ width: this.dimensions.canvasWidth,
+ height: this.dimensions.canvasHeight
+ });
+ };
+ Renderer.prototype.onCharSizeChanged = function () {
+ this.onResize(this._terminal.cols, this._terminal.rows, true);
+ };
+ Renderer.prototype.onBlur = function () {
+ var _this = this;
+ this._renderLayers.forEach(function (l) { return l.onBlur(_this._terminal); });
+ };
+ Renderer.prototype.onFocus = function () {
+ var _this = this;
+ this._renderLayers.forEach(function (l) { return l.onFocus(_this._terminal); });
+ };
+ Renderer.prototype.onSelectionChanged = function (start, end) {
+ var _this = this;
+ this._renderLayers.forEach(function (l) { return l.onSelectionChanged(_this._terminal, start, end); });
+ };
+ Renderer.prototype.onCursorMove = function () {
+ var _this = this;
+ this._renderLayers.forEach(function (l) { return l.onCursorMove(_this._terminal); });
+ };
+ Renderer.prototype.onOptionsChanged = function () {
+ var _this = this;
+ this._renderLayers.forEach(function (l) { return l.onOptionsChanged(_this._terminal); });
+ };
+ Renderer.prototype.clear = function () {
+ var _this = this;
+ this._renderLayers.forEach(function (l) { return l.reset(_this._terminal); });
+ };
+ Renderer.prototype.queueRefresh = function (start, end) {
+ this._refreshRowsQueue.push({ start: start, end: end });
+ if (!this._refreshAnimationFrame) {
+ this._refreshAnimationFrame = window.requestAnimationFrame(this._refreshLoop.bind(this));
+ }
+ };
+ Renderer.prototype._refreshLoop = function () {
+ var _this = this;
+ var start;
+ var end;
+ if (this._refreshRowsQueue.length > 4) {
+ start = 0;
+ end = this._terminal.rows - 1;
+ }
+ else {
+ start = this._refreshRowsQueue[0].start;
+ end = this._refreshRowsQueue[0].end;
+ for (var i = 1; i < this._refreshRowsQueue.length; i++) {
+ if (this._refreshRowsQueue[i].start < start) {
+ start = this._refreshRowsQueue[i].start;
+ }
+ if (this._refreshRowsQueue[i].end > end) {
+ end = this._refreshRowsQueue[i].end;
+ }
+ }
+ }
+ this._refreshRowsQueue = [];
+ this._refreshAnimationFrame = null;
+ start = Math.max(start, 0);
+ end = Math.min(end, this._terminal.rows - 1);
+ this._renderLayers.forEach(function (l) { return l.onGridChanged(_this._terminal, start, end); });
+ this._terminal.emit('refresh', { start: start, end: end });
+ };
+ return Renderer;
+}(EventEmitter_1.EventEmitter));
+exports.Renderer = Renderer;
+
+
+
+},{"../EventEmitter":7,"./ColorManager":20,"./CursorRenderLayer":21,"./LinkRenderLayer":23,"./SelectionRenderLayer":25,"./TextRenderLayer":26}],25:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+ var extendStatics = Object.setPrototypeOf ||
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+ function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+ return function (d, b) {
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var BaseRenderLayer_1 = require("./BaseRenderLayer");
+var SelectionRenderLayer = (function (_super) {
+ __extends(SelectionRenderLayer, _super);
+ function SelectionRenderLayer(container, zIndex, colors) {
+ var _this = _super.call(this, container, 'selection', zIndex, true, colors) || this;
+ _this._state = {
+ start: null,
+ end: null
+ };
+ return _this;
+ }
+ SelectionRenderLayer.prototype.resize = function (terminal, dim, charSizeChanged) {
+ _super.prototype.resize.call(this, terminal, dim, charSizeChanged);
+ this._state = {
+ start: null,
+ end: null
+ };
+ };
+ SelectionRenderLayer.prototype.reset = function (terminal) {
+ if (this._state.start && this._state.end) {
+ this._state = {
+ start: null,
+ end: null
+ };
+ this.clearAll();
+ }
+ };
+ SelectionRenderLayer.prototype.onSelectionChanged = function (terminal, start, end) {
+ if (this._state.start === start || this._state.end === end) {
+ return;
+ }
+ this.clearAll();
+ if (!start || !end) {
+ return;
+ }
+ var viewportStartRow = start[1] - terminal.buffer.ydisp;
+ var viewportEndRow = end[1] - terminal.buffer.ydisp;
+ var viewportCappedStartRow = Math.max(viewportStartRow, 0);
+ var viewportCappedEndRow = Math.min(viewportEndRow, terminal.rows - 1);
+ if (viewportCappedStartRow >= terminal.rows || viewportCappedEndRow < 0) {
+ return;
+ }
+ var startCol = viewportStartRow === viewportCappedStartRow ? start[0] : 0;
+ var startRowEndCol = viewportCappedStartRow === viewportCappedEndRow ? end[0] : terminal.cols;
+ this._ctx.fillStyle = this._colors.selection;
+ this.fillCells(startCol, viewportCappedStartRow, startRowEndCol - startCol, 1);
+ var middleRowsCount = Math.max(viewportCappedEndRow - viewportCappedStartRow - 1, 0);
+ this.fillCells(0, viewportCappedStartRow + 1, terminal.cols, middleRowsCount);
+ if (viewportCappedStartRow !== viewportCappedEndRow) {
+ var endCol = viewportEndRow === viewportCappedEndRow ? end[0] : terminal.cols;
+ this.fillCells(0, viewportCappedEndRow, endCol, 1);
+ }
+ this._state.start = [start[0], start[1]];
+ this._state.end = [end[0], end[1]];
+ };
+ return SelectionRenderLayer;
+}(BaseRenderLayer_1.BaseRenderLayer));
+exports.SelectionRenderLayer = SelectionRenderLayer;
+
+
+
+},{"./BaseRenderLayer":18}],26:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+ var extendStatics = Object.setPrototypeOf ||
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+ function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+ return function (d, b) {
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Buffer_1 = require("../Buffer");
+var Types_1 = require("./Types");
+var GridCache_1 = require("./GridCache");
+var BaseRenderLayer_1 = require("./BaseRenderLayer");
+var OVERLAP_OWNED_CHAR_DATA = [null, '', 0, -1];
+var TextRenderLayer = (function (_super) {
+ __extends(TextRenderLayer, _super);
+ function TextRenderLayer(container, zIndex, colors) {
+ var _this = _super.call(this, container, 'text', zIndex, false, colors) || this;
+ _this._characterOverlapCache = {};
+ _this._state = new GridCache_1.GridCache();
+ return _this;
+ }
+ TextRenderLayer.prototype.resize = function (terminal, dim, charSizeChanged) {
+ _super.prototype.resize.call(this, terminal, dim, charSizeChanged);
+ var terminalFont = terminal.options.fontSize * window.devicePixelRatio + "px " + terminal.options.fontFamily;
+ if (this._characterWidth !== dim.scaledCharWidth || this._characterFont !== terminalFont) {
+ this._characterWidth = dim.scaledCharWidth;
+ this._characterFont = terminalFont;
+ this._characterOverlapCache = {};
+ }
+ this._state.clear();
+ this._state.resize(terminal.cols, terminal.rows);
+ };
+ TextRenderLayer.prototype.reset = function (terminal) {
+ this._state.clear();
+ this.clearAll();
+ };
+ TextRenderLayer.prototype.onGridChanged = function (terminal, startRow, endRow) {
+ if (this._state.cache.length === 0) {
+ return;
+ }
+ for (var y = startRow; y <= endRow; y++) {
+ var row = y + terminal.buffer.ydisp;
+ var line = terminal.buffer.lines.get(row);
+ this.clearCells(0, y, terminal.cols, 1);
+ for (var x = 0; x < terminal.cols; x++) {
+ var charData = line[x];
+ var code = charData[Buffer_1.CHAR_DATA_CODE_INDEX];
+ var char = charData[Buffer_1.CHAR_DATA_CHAR_INDEX];
+ var attr = charData[Buffer_1.CHAR_DATA_ATTR_INDEX];
+ var width = charData[Buffer_1.CHAR_DATA_WIDTH_INDEX];
+ if (width === 0) {
+ continue;
+ }
+ if (code === 32) {
+ if (x > 0) {
+ var previousChar = line[x - 1];
+ if (this._isOverlapping(previousChar)) {
+ continue;
+ }
+ }
+ }
+ var flags = attr >> 18;
+ var bg = attr & 0x1ff;
+ var isDefaultBackground = bg >= 256;
+ var isInvisible = flags & Types_1.FLAGS.INVISIBLE;
+ var isInverted = flags & Types_1.FLAGS.INVERSE;
+ if (!code || (code === 32 && isDefaultBackground && !isInverted) || isInvisible) {
+ continue;
+ }
+ if (width !== 0 && this._isOverlapping(charData)) {
+ if (x < line.length - 1 && line[x + 1][Buffer_1.CHAR_DATA_CODE_INDEX] === 32) {
+ width = 2;
+ }
+ }
+ var fg = (attr >> 9) & 0x1ff;
+ if (isInverted) {
+ var temp = bg;
+ bg = fg;
+ fg = temp;
+ if (fg === 256) {
+ fg = BaseRenderLayer_1.INVERTED_DEFAULT_COLOR;
+ }
+ if (bg === 257) {
+ bg = BaseRenderLayer_1.INVERTED_DEFAULT_COLOR;
+ }
+ }
+ if (width === 2) {
+ }
+ if (bg < 256) {
+ this._ctx.save();
+ this._ctx.fillStyle = (bg === BaseRenderLayer_1.INVERTED_DEFAULT_COLOR ? this._colors.foreground : this._colors.ansi[bg]);
+ this.fillCells(x, y, width, 1);
+ this._ctx.restore();
+ }
+ this._ctx.save();
+ if (flags & Types_1.FLAGS.BOLD) {
+ this._ctx.font = "bold " + this._ctx.font;
+ if (fg < 8) {
+ fg += 8;
+ }
+ }
+ if (flags & Types_1.FLAGS.UNDERLINE) {
+ if (fg === BaseRenderLayer_1.INVERTED_DEFAULT_COLOR) {
+ this._ctx.fillStyle = this._colors.background;
+ }
+ else if (fg < 256) {
+ this._ctx.fillStyle = this._colors.ansi[fg];
+ }
+ else {
+ this._ctx.fillStyle = this._colors.foreground;
+ }
+ this.fillBottomLineAtCells(x, y);
+ }
+ this.drawChar(terminal, char, code, width, x, y, fg, bg, !!(flags & Types_1.FLAGS.BOLD), !!(flags & Types_1.FLAGS.DIM));
+ this._ctx.restore();
+ }
+ }
+ };
+ TextRenderLayer.prototype._isOverlapping = function (charData) {
+ if (charData[Buffer_1.CHAR_DATA_WIDTH_INDEX] !== 1) {
+ return false;
+ }
+ var code = charData[Buffer_1.CHAR_DATA_CODE_INDEX];
+ if (code < 256) {
+ return false;
+ }
+ var char = charData[Buffer_1.CHAR_DATA_CHAR_INDEX];
+ if (this._characterOverlapCache.hasOwnProperty(char)) {
+ return this._characterOverlapCache[char];
+ }
+ this._ctx.save();
+ this._ctx.font = this._characterFont;
+ var overlaps = Math.floor(this._ctx.measureText(char).width) > this._characterWidth;
+ this._ctx.restore();
+ this._characterOverlapCache[char] = overlaps;
+ return overlaps;
+ };
+ TextRenderLayer.prototype._clearChar = function (x, y) {
+ var colsToClear = 1;
+ var state = this._state.cache[x][y];
+ if (state && state[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 2) {
+ colsToClear = 2;
+ }
+ this.clearCells(x, y, colsToClear, 1);
+ };
+ return TextRenderLayer;
+}(BaseRenderLayer_1.BaseRenderLayer));
+exports.TextRenderLayer = TextRenderLayer;
+
+
+
+},{"../Buffer":1,"./BaseRenderLayer":18,"./GridCache":22,"./Types":27}],27:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var FLAGS;
+(function (FLAGS) {
+ FLAGS[FLAGS["BOLD"] = 1] = "BOLD";
+ FLAGS[FLAGS["UNDERLINE"] = 2] = "UNDERLINE";
+ FLAGS[FLAGS["BLINK"] = 4] = "BLINK";
+ FLAGS[FLAGS["INVERSE"] = 8] = "INVERSE";
+ FLAGS[FLAGS["INVISIBLE"] = 16] = "INVISIBLE";
+ FLAGS[FLAGS["DIM"] = 32] = "DIM";
+})(FLAGS = exports.FLAGS || (exports.FLAGS = {}));
+;
+
+
+
+},{}],28:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Generic_1 = require("./Generic");
+var isNode = (typeof navigator === 'undefined') ? true : false;
+var userAgent = (isNode) ? 'node' : navigator.userAgent;
+var platform = (isNode) ? 'node' : navigator.platform;
+exports.isFirefox = !!~userAgent.indexOf('Firefox');
+exports.isMSIE = !!~userAgent.indexOf('MSIE') || !!~userAgent.indexOf('Trident');
+exports.isMac = Generic_1.contains(['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'], platform);
+exports.isIpad = platform === 'iPad';
+exports.isIphone = platform === 'iPhone';
+exports.isMSWindows = Generic_1.contains(['Windows', 'Win16', 'Win32', 'WinCE'], platform);
+exports.isLinux = platform.indexOf('Linux') >= 0;
+
+
+
+},{"./Generic":31}],29:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+ var extendStatics = Object.setPrototypeOf ||
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+ function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+ return function (d, b) {
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var EventEmitter_1 = require("../EventEmitter");
+var CharMeasure = (function (_super) {
+ __extends(CharMeasure, _super);
+ function CharMeasure(document, parentElement) {
+ var _this = _super.call(this) || this;
+ _this._document = document;
+ _this._parentElement = parentElement;
+ return _this;
+ }
+ Object.defineProperty(CharMeasure.prototype, "width", {
+ get: function () {
+ return this._width;
+ },
+ enumerable: true,
+ configurable: true
+ });
+ Object.defineProperty(CharMeasure.prototype, "height", {
+ get: function () {
+ return this._height;
+ },
+ enumerable: true,
+ configurable: true
+ });
+ CharMeasure.prototype.measure = function (options) {
+ var _this = this;
+ if (!this._measureElement) {
+ this._measureElement = this._document.createElement('span');
+ this._measureElement.style.position = 'absolute';
+ this._measureElement.style.top = '0';
+ this._measureElement.style.left = '-9999em';
+ this._measureElement.style.lineHeight = 'normal';
+ this._measureElement.textContent = 'W';
+ this._measureElement.setAttribute('aria-hidden', 'true');
+ this._parentElement.appendChild(this._measureElement);
+ setTimeout(function () { return _this._doMeasure(options); }, 0);
+ }
+ else {
+ this._doMeasure(options);
+ }
+ };
+ CharMeasure.prototype._doMeasure = function (options) {
+ this._measureElement.style.fontFamily = options.fontFamily;
+ this._measureElement.style.fontSize = options.fontSize + "px";
+ var geometry = this._measureElement.getBoundingClientRect();
+ if (geometry.width === 0 || geometry.height === 0) {
+ return;
+ }
+ if (this._width !== geometry.width || this._height !== geometry.height) {
+ this._width = geometry.width;
+ this._height = Math.ceil(geometry.height);
+ this.emit('charsizechanged');
+ }
+ };
+ return CharMeasure;
+}(EventEmitter_1.EventEmitter));
+exports.CharMeasure = CharMeasure;
+
+
+
+},{"../EventEmitter":7}],30:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+ var extendStatics = Object.setPrototypeOf ||
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+ function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+ return function (d, b) {
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var EventEmitter_1 = require("../EventEmitter");
+var CircularList = (function (_super) {
+ __extends(CircularList, _super);
+ function CircularList(_maxLength) {
+ var _this = _super.call(this) || this;
+ _this._maxLength = _maxLength;
+ _this._array = new Array(_this._maxLength);
+ _this._startIndex = 0;
+ _this._length = 0;
+ return _this;
+ }
+ Object.defineProperty(CircularList.prototype, "maxLength", {
+ get: function () {
+ return this._maxLength;
+ },
+ set: function (newMaxLength) {
+ if (this._maxLength === newMaxLength) {
+ return;
+ }
+ var newArray = new Array(newMaxLength);
+ for (var i = 0; i < Math.min(newMaxLength, this.length); i++) {
+ newArray[i] = this._array[this._getCyclicIndex(i)];
+ }
+ this._array = newArray;
+ this._maxLength = newMaxLength;
+ this._startIndex = 0;
+ },
+ enumerable: true,
+ configurable: true
+ });
+ Object.defineProperty(CircularList.prototype, "length", {
+ get: function () {
+ return this._length;
+ },
+ set: function (newLength) {
+ if (newLength > this._length) {
+ for (var i = this._length; i < newLength; i++) {
+ this._array[i] = undefined;
+ }
+ }
+ this._length = newLength;
+ },
+ enumerable: true,
+ configurable: true
+ });
+ Object.defineProperty(CircularList.prototype, "forEach", {
+ get: function () {
+ var _this = this;
+ return function (callbackfn) {
+ var i = 0;
+ var length = _this.length;
+ for (var i_1 = 0; i_1 < length; i_1++) {
+ callbackfn(_this.get(i_1), i_1);
+ }
+ };
+ },
+ enumerable: true,
+ configurable: true
+ });
+ CircularList.prototype.get = function (index) {
+ return this._array[this._getCyclicIndex(index)];
+ };
+ CircularList.prototype.set = function (index, value) {
+ this._array[this._getCyclicIndex(index)] = value;
+ };
+ CircularList.prototype.push = function (value) {
+ this._array[this._getCyclicIndex(this._length)] = value;
+ if (this._length === this._maxLength) {
+ this._startIndex++;
+ if (this._startIndex === this._maxLength) {
+ this._startIndex = 0;
+ }
+ this.emit('trim', 1);
+ }
+ else {
+ this._length++;
+ }
+ };
+ CircularList.prototype.pop = function () {
+ return this._array[this._getCyclicIndex(this._length-- - 1)];
+ };
+ CircularList.prototype.splice = function (start, deleteCount) {
+ var items = [];
+ for (var _i = 2; _i < arguments.length; _i++) {
+ items[_i - 2] = arguments[_i];
+ }
+ if (deleteCount) {
+ for (var i = start; i < this._length - deleteCount; i++) {
+ this._array[this._getCyclicIndex(i)] = this._array[this._getCyclicIndex(i + deleteCount)];
+ }
+ this._length -= deleteCount;
+ }
+ if (items && items.length) {
+ for (var i = this._length - 1; i >= start; i--) {
+ this._array[this._getCyclicIndex(i + items.length)] = this._array[this._getCyclicIndex(i)];
+ }
+ for (var i = 0; i < items.length; i++) {
+ this._array[this._getCyclicIndex(start + i)] = items[i];
+ }
+ if (this._length + items.length > this.maxLength) {
+ var countToTrim = (this._length + items.length) - this.maxLength;
+ this._startIndex += countToTrim;
+ this._length = this.maxLength;
+ this.emit('trim', countToTrim);
+ }
+ else {
+ this._length += items.length;
+ }
+ }
+ };
+ CircularList.prototype.trimStart = function (count) {
+ if (count > this._length) {
+ count = this._length;
+ }
+ this._startIndex += count;
+ this._length -= count;
+ this.emit('trim', count);
+ };
+ CircularList.prototype.shiftElements = function (start, count, offset) {
+ if (count <= 0) {
+ return;
+ }
+ if (start < 0 || start >= this._length) {
+ throw new Error('start argument out of range');
+ }
+ if (start + offset < 0) {
+ throw new Error('Cannot shift elements in list beyond index 0');
+ }
+ if (offset > 0) {
+ for (var i = count - 1; i >= 0; i--) {
+ this.set(start + i + offset, this.get(start + i));
+ }
+ var expandListBy = (start + count + offset) - this._length;
+ if (expandListBy > 0) {
+ this._length += expandListBy;
+ while (this._length > this.maxLength) {
+ this._length--;
+ this._startIndex++;
+ this.emit('trim', 1);
+ }
+ }
+ }
+ else {
+ for (var i = 0; i < count; i++) {
+ this.set(start + i + offset, this.get(start + i));
+ }
+ }
+ };
+ CircularList.prototype._getCyclicIndex = function (index) {
+ return (this._startIndex + index) % this.maxLength;
+ };
+ return CircularList;
+}(EventEmitter_1.EventEmitter));
+exports.CircularList = CircularList;
+
+
+
+},{"../EventEmitter":7}],31:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+function contains(arr, el) {
+ return arr.indexOf(el) >= 0;
+}
+exports.contains = contains;
+;
+
+
+
+},{}],32:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var MouseHelper = (function () {
+ function MouseHelper(_renderer) {
+ this._renderer = _renderer;
+ }
+ MouseHelper.getCoordsRelativeToElement = function (event, element) {
+ if (event.pageX == null) {
+ return null;
+ }
+ var originalElement = element;
+ var x = event.pageX;
+ var y = event.pageY;
+ while (element) {
+ x -= element.offsetLeft;
+ y -= element.offsetTop;
+ element = 'offsetParent' in element ? element.offsetParent : element.parentElement;
+ }
+ element = originalElement;
+ while (element && element !== element.ownerDocument.body) {
+ x += element.scrollLeft;
+ y += element.scrollTop;
+ element = element.parentElement;
+ }
+ return [x, y];
+ };
+ MouseHelper.prototype.getCoords = function (event, element, charMeasure, lineHeight, colCount, rowCount, isSelection) {
+ if (!charMeasure.width || !charMeasure.height) {
+ return null;
+ }
+ var coords = MouseHelper.getCoordsRelativeToElement(event, element);
+ if (!coords) {
+ return null;
+ }
+ coords[0] = Math.ceil((coords[0] + (isSelection ? this._renderer.dimensions.actualCellWidth / 2 : 0)) / this._renderer.dimensions.actualCellWidth);
+ coords[1] = Math.ceil(coords[1] / this._renderer.dimensions.actualCellHeight);
+ coords[0] = Math.min(Math.max(coords[0], 1), colCount + (isSelection ? 1 : 0));
+ coords[1] = Math.min(Math.max(coords[1], 1), rowCount);
+ return coords;
+ };
+ MouseHelper.prototype.getRawByteCoords = function (event, element, charMeasure, lineHeight, colCount, rowCount) {
+ var coords = this.getCoords(event, element, charMeasure, lineHeight, colCount, rowCount);
+ var x = coords[0];
+ var y = coords[1];
+ x += 32;
+ y += 32;
+ return { x: x, y: y };
+ };
+ return MouseHelper;
+}());
+exports.MouseHelper = MouseHelper;
+
+
+
+},{}],33:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.BellSound = 'data:audio/wav;base64,UklGRigBAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQQBAADpAFgCwAMlBZoG/wdmCcoKRAypDQ8PbRDBEQQTOxRtFYcWlBePGIUZXhoiG88bcBz7HHIdzh0WHlMeZx51HmkeUx4WHs8dah0AHXwc3hs9G4saxRnyGBIYGBcQFv8U4RPAEoYRQBACD70NWwwHC6gJOwjWBloF7gOBAhABkf8b/qv8R/ve+Xf4Ife79W/0JfPZ8Z/wde9N7ijtE+wU6xvqM+lb6H7nw+YX5mrlxuQz5Mzje+Ma49fioeKD4nXiYeJy4pHitOL04j/jn+MN5IPkFOWs5U3mDefM55/ogOl36m7rdOyE7abuyu8D8Unyj/Pg9D/2qfcb+Yn6/vuK/Qj/lAAlAg==';
+
+
+
+},{}],34:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Terminal_1 = require("./Terminal");
+module.exports = Terminal_1.Terminal;
+
+
+
+},{"./Terminal":13}]},{},[34])(34)
+});
+//# sourceMappingURL=xterm.js.map
diff --git a/route/static/build/xterm.js.map b/route/static/build/xterm.js.map
new file mode 100755
index 000000000..9716c5e22
--- /dev/null
+++ b/route/static/build/xterm.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"xterm.js","sources":["../src/xterm.ts","../src/utils/Sounds.ts","../src/utils/MouseHelper.ts","../src/utils/Generic.ts","../src/utils/CircularList.ts","../src/utils/CharMeasure.ts","../src/utils/Browser.ts","../src/renderer/Types.ts","../src/renderer/TextRenderLayer.ts","../src/renderer/SelectionRenderLayer.ts","../src/renderer/Renderer.ts","../src/renderer/LinkRenderLayer.ts","../src/renderer/GridCache.ts","../src/renderer/CursorRenderLayer.ts","../src/renderer/ColorManager.ts","../src/renderer/CharAtlas.ts","../src/renderer/BaseRenderLayer.ts","../src/input/MouseZoneManager.ts","../src/handlers/Clipboard.ts","../src/Viewport.ts","../src/Types.ts","../src/Terminal.ts","../src/SelectionModel.ts","../src/SelectionManager.ts","../src/Parser.ts","../src/Linkifier.ts","../src/InputHandler.ts","../src/EventEmitter.ts","../src/EscapeSequences.ts","../src/CompositionHelper.ts","../src/Charsets.ts","../src/CharWidth.ts","../src/BufferSet.ts","../src/Buffer.ts","../node_modules/browser-pack/_prelude.js"],"sourcesContent":["/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * This file is the entry point for browserify.\n */\n\nimport { Terminal } from './Terminal';\n\nmodule.exports = Terminal;\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\n// Source: https://freesound.org/people/altemark/sounds/45759/\n// This sound is released under the Creative Commons Attribution 3.0 Unported\n// (CC BY 3.0) license. It was created by 'altemark'. No modifications have been\n// made, apart from the conversion to base64.\nexport const BellSound = 'data:audio/wav;base64,UklGRigBAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQQBAADpAFgCwAMlBZoG/wdmCcoKRAypDQ8PbRDBEQQTOxRtFYcWlBePGIUZXhoiG88bcBz7HHIdzh0WHlMeZx51HmkeUx4WHs8dah0AHXwc3hs9G4saxRnyGBIYGBcQFv8U4RPAEoYRQBACD70NWwwHC6gJOwjWBloF7gOBAhABkf8b/qv8R/ve+Xf4Ife79W/0JfPZ8Z/wde9N7ijtE+wU6xvqM+lb6H7nw+YX5mrlxuQz5Mzje+Ma49fioeKD4nXiYeJy4pHitOL04j/jn+MN5IPkFOWs5U3mDefM55/ogOl36m7rdOyE7abuyu8D8Unyj/Pg9D/2qfcb+Yn6/vuK/Qj/lAAlAg==';\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ICharMeasure } from '../Interfaces';\nimport { IRenderer } from '../renderer/Interfaces';\n\nexport class MouseHelper {\n constructor(private _renderer: IRenderer) {}\n\n public static getCoordsRelativeToElement(event: {pageX: number, pageY: number}, element: HTMLElement): [number, number] {\n // Ignore browsers that don't support MouseEvent.pageX\n if (event.pageX == null) {\n return null;\n }\n\n const originalElement = element;\n let x = event.pageX;\n let y = event.pageY;\n\n // Converts the coordinates from being relative to the document to being\n // relative to the terminal.\n while (element) {\n x -= element.offsetLeft;\n y -= element.offsetTop;\n element = 'offsetParent' in element ? element.offsetParent : element.parentElement;\n }\n element = originalElement;\n while (element && element !== element.ownerDocument.body) {\n x += element.scrollLeft;\n y += element.scrollTop;\n element = element.parentElement;\n }\n return [x, y];\n }\n\n /**\n * Gets coordinates within the terminal for a particular mouse event. The result\n * is returned as an array in the form [x, y] instead of an object as it's a\n * little faster and this function is used in some low level code.\n * @param event The mouse event.\n * @param element The terminal's container element.\n * @param charMeasure The char measure object used to determine character sizes.\n * @param colCount The number of columns in the terminal.\n * @param rowCount The number of rows n the terminal.\n * @param isSelection Whether the request is for the selection or not. This will\n * apply an offset to the x value such that the left half of the cell will\n * select that cell and the right half will select the next cell.\n */\n public getCoords(event: {pageX: number, pageY: number}, element: HTMLElement, charMeasure: ICharMeasure, lineHeight: number, colCount: number, rowCount: number, isSelection?: boolean): [number, number] {\n // Coordinates cannot be measured if charMeasure has not been initialized\n if (!charMeasure.width || !charMeasure.height) {\n return null;\n }\n\n const coords = MouseHelper.getCoordsRelativeToElement(event, element);\n if (!coords) {\n return null;\n }\n\n coords[0] = Math.ceil((coords[0] + (isSelection ? this._renderer.dimensions.actualCellWidth / 2 : 0)) / this._renderer.dimensions.actualCellWidth);\n coords[1] = Math.ceil(coords[1] / this._renderer.dimensions.actualCellHeight);\n\n // Ensure coordinates are within the terminal viewport. Note that selections\n // need an addition point of precision to cover the end point (as characters\n // cover half of one char and half of the next).\n coords[0] = Math.min(Math.max(coords[0], 1), colCount + (isSelection ? 1 : 0));\n coords[1] = Math.min(Math.max(coords[1], 1), rowCount);\n\n return coords;\n }\n\n /**\n * Gets coordinates within the terminal for a particular mouse event, wrapping\n * them to the bounds of the terminal and adding 32 to both the x and y values\n * as expected by xterm.\n * @param event The mouse event.\n * @param element The terminal's container element.\n * @param charMeasure The char measure object used to determine character sizes.\n * @param colCount The number of columns in the terminal.\n * @param rowCount The number of rows in the terminal.\n */\n public getRawByteCoords(event: MouseEvent, element: HTMLElement, charMeasure: ICharMeasure, lineHeight: number, colCount: number, rowCount: number): { x: number, y: number } {\n const coords = this.getCoords(event, element, charMeasure, lineHeight, colCount, rowCount);\n let x = coords[0];\n let y = coords[1];\n\n // xterm sends raw bytes and starts at 32 (SP) for each.\n x += 32;\n y += 32;\n\n return { x, y };\n }\n}\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\n/**\n * Return if the given array contains the given element\n * @param {Array} array The array to search for the given element.\n * @param {Object} el The element to look for into the array\n */\nexport function contains(arr: any[], el: any): boolean {\n return arr.indexOf(el) >= 0;\n};\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { EventEmitter } from '../EventEmitter';\nimport { ICircularList } from '../Interfaces';\n\n/**\n * Represents a circular list; a list with a maximum size that wraps around when push is called,\n * overriding values at the start of the list.\n */\nexport class CircularList extends EventEmitter implements ICircularList {\n protected _array: T[];\n private _startIndex: number;\n private _length: number;\n\n constructor(\n private _maxLength: number\n ) {\n super();\n this._array = new Array(this._maxLength);\n this._startIndex = 0;\n this._length = 0;\n }\n\n public get maxLength(): number {\n return this._maxLength;\n }\n\n public set maxLength(newMaxLength: number) {\n // There was no change in maxLength, return early.\n if (this._maxLength === newMaxLength) {\n return;\n }\n\n // Reconstruct array, starting at index 0. Only transfer values from the\n // indexes 0 to length.\n let newArray = new Array(newMaxLength);\n for (let i = 0; i < Math.min(newMaxLength, this.length); i++) {\n newArray[i] = this._array[this._getCyclicIndex(i)];\n }\n this._array = newArray;\n this._maxLength = newMaxLength;\n this._startIndex = 0;\n }\n\n public get length(): number {\n return this._length;\n }\n\n public set length(newLength: number) {\n if (newLength > this._length) {\n for (let i = this._length; i < newLength; i++) {\n this._array[i] = undefined;\n }\n }\n this._length = newLength;\n }\n\n public get forEach(): (callbackfn: (value: T, index: number) => void) => void {\n return (callbackfn: (value: T, index: number) => void) => {\n let i = 0;\n let length = this.length;\n for (let i = 0; i < length; i++) {\n callbackfn(this.get(i), i);\n }\n };\n }\n\n /**\n * Gets the value at an index.\n *\n * Note that for performance reasons there is no bounds checking here, the index reference is\n * circular so this should always return a value and never throw.\n * @param index The index of the value to get.\n * @return The value corresponding to the index.\n */\n public get(index: number): T {\n return this._array[this._getCyclicIndex(index)];\n }\n\n /**\n * Sets the value at an index.\n *\n * Note that for performance reasons there is no bounds checking here, the index reference is\n * circular so this should always return a value and never throw.\n * @param index The index to set.\n * @param value The value to set.\n */\n public set(index: number, value: T): void {\n this._array[this._getCyclicIndex(index)] = value;\n }\n\n /**\n * Pushes a new value onto the list, wrapping around to the start of the array, overriding index 0\n * if the maximum length is reached.\n * @param value The value to push onto the list.\n */\n public push(value: T): void {\n this._array[this._getCyclicIndex(this._length)] = value;\n if (this._length === this._maxLength) {\n this._startIndex++;\n if (this._startIndex === this._maxLength) {\n this._startIndex = 0;\n }\n this.emit('trim', 1);\n } else {\n this._length++;\n }\n }\n\n /**\n * Removes and returns the last value on the list.\n * @return The popped value.\n */\n public pop(): T {\n return this._array[this._getCyclicIndex(this._length-- - 1)];\n }\n\n /**\n * Deletes and/or inserts items at a particular index (in that order). Unlike\n * Array.prototype.splice, this operation does not return the deleted items as a new array in\n * order to save creating a new array. Note that this operation may shift all values in the list\n * in the worst case.\n * @param start The index to delete and/or insert.\n * @param deleteCount The number of elements to delete.\n * @param items The items to insert.\n */\n public splice(start: number, deleteCount: number, ...items: T[]): void {\n // Delete items\n if (deleteCount) {\n for (let i = start; i < this._length - deleteCount; i++) {\n this._array[this._getCyclicIndex(i)] = this._array[this._getCyclicIndex(i + deleteCount)];\n }\n this._length -= deleteCount;\n }\n\n if (items && items.length) {\n // Add items\n for (let i = this._length - 1; i >= start; i--) {\n this._array[this._getCyclicIndex(i + items.length)] = this._array[this._getCyclicIndex(i)];\n }\n for (let i = 0; i < items.length; i++) {\n this._array[this._getCyclicIndex(start + i)] = items[i];\n }\n\n // Adjust length as needed\n if (this._length + items.length > this.maxLength) {\n const countToTrim = (this._length + items.length) - this.maxLength;\n this._startIndex += countToTrim;\n this._length = this.maxLength;\n this.emit('trim', countToTrim);\n } else {\n this._length += items.length;\n }\n }\n }\n\n /**\n * Trims a number of items from the start of the list.\n * @param count The number of items to remove.\n */\n public trimStart(count: number): void {\n if (count > this._length) {\n count = this._length;\n }\n this._startIndex += count;\n this._length -= count;\n this.emit('trim', count);\n }\n\n public shiftElements(start: number, count: number, offset: number): void {\n if (count <= 0) {\n return;\n }\n if (start < 0 || start >= this._length) {\n throw new Error('start argument out of range');\n }\n if (start + offset < 0) {\n throw new Error('Cannot shift elements in list beyond index 0');\n }\n\n if (offset > 0) {\n for (let i = count - 1; i >= 0; i--) {\n this.set(start + i + offset, this.get(start + i));\n }\n const expandListBy = (start + count + offset) - this._length;\n if (expandListBy > 0) {\n this._length += expandListBy;\n while (this._length > this.maxLength) {\n this._length--;\n this._startIndex++;\n this.emit('trim', 1);\n }\n }\n } else {\n for (let i = 0; i < count; i++) {\n this.set(start + i + offset, this.get(start + i));\n }\n }\n }\n\n /**\n * Gets the cyclic index for the specified regular index. The cyclic index can then be used on the\n * backing array to get the element associated with the regular index.\n * @param index The regular index.\n * @returns The cyclic index.\n */\n private _getCyclicIndex(index: number): number {\n return (this._startIndex + index) % this.maxLength;\n }\n}\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { EventEmitter } from '../EventEmitter';\nimport { ICharMeasure, ITerminal, ITerminalOptions } from '../Interfaces';\n\n/**\n * Utility class that measures the size of a character. Measurements are done in\n * the DOM rather than with a canvas context because support for extracting the\n * height of characters is patchy across browsers.\n */\nexport class CharMeasure extends EventEmitter implements ICharMeasure {\n private _document: Document;\n private _parentElement: HTMLElement;\n private _measureElement: HTMLElement;\n private _width: number;\n private _height: number;\n\n constructor(document: Document, parentElement: HTMLElement) {\n super();\n this._document = document;\n this._parentElement = parentElement;\n }\n\n public get width(): number {\n return this._width;\n }\n\n public get height(): number {\n return this._height;\n }\n\n public measure(options: ITerminalOptions): void {\n if (!this._measureElement) {\n this._measureElement = this._document.createElement('span');\n this._measureElement.style.position = 'absolute';\n this._measureElement.style.top = '0';\n this._measureElement.style.left = '-9999em';\n this._measureElement.style.lineHeight = 'normal';\n this._measureElement.textContent = 'W';\n this._measureElement.setAttribute('aria-hidden', 'true');\n this._parentElement.appendChild(this._measureElement);\n // Perform _doMeasure async if the element was just attached as sometimes\n // getBoundingClientRect does not return accurate values without this.\n setTimeout(() => this._doMeasure(options), 0);\n } else {\n this._doMeasure(options);\n }\n }\n\n private _doMeasure(options: ITerminalOptions): void {\n this._measureElement.style.fontFamily = options.fontFamily;\n this._measureElement.style.fontSize = `${options.fontSize}px`;\n const geometry = this._measureElement.getBoundingClientRect();\n // The element is likely currently display:none, we should retain the\n // previous value.\n if (geometry.width === 0 || geometry.height === 0) {\n return;\n }\n if (this._width !== geometry.width || this._height !== geometry.height) {\n this._width = geometry.width;\n this._height = Math.ceil(geometry.height);\n this.emit('charsizechanged');\n }\n }\n}\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { contains } from './Generic';\n\nconst isNode = (typeof navigator === 'undefined') ? true : false;\nconst userAgent = (isNode) ? 'node' : navigator.userAgent;\nconst platform = (isNode) ? 'node' : navigator.platform;\n\nexport const isFirefox = !!~userAgent.indexOf('Firefox');\nexport const isMSIE = !!~userAgent.indexOf('MSIE') || !!~userAgent.indexOf('Trident');\n\n// Find the users platform. We use this to interpret the meta key\n// and ISO third level shifts.\n// http://stackoverflow.com/q/19877924/577598\nexport const isMac = contains(['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'], platform);\nexport const isIpad = platform === 'iPad';\nexport const isIphone = platform === 'iPhone';\nexport const isMSWindows = contains(['Windows', 'Win16', 'Win32', 'WinCE'], platform);\nexport const isLinux = platform.indexOf('Linux') >= 0;\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\n /**\n * Flags used to render terminal text properly.\n */\nexport enum FLAGS {\n BOLD = 1,\n UNDERLINE = 2,\n BLINK = 4,\n INVERSE = 8,\n INVISIBLE = 16,\n DIM = 32\n};\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IColorSet, IRenderDimensions } from './Interfaces';\nimport { IBuffer, ICharMeasure, ITerminal } from '../Interfaces';\nimport { CHAR_DATA_ATTR_INDEX, CHAR_DATA_CODE_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX } from '../Buffer';\nimport { FLAGS } from './Types';\nimport { GridCache } from './GridCache';\nimport { CharData } from '../Types';\nimport { BaseRenderLayer, INVERTED_DEFAULT_COLOR } from './BaseRenderLayer';\n\n/**\n * This CharData looks like a null character, which will forc a clear and render\n * when the character changes (a regular space ' ' character may not as it's\n * drawn state is a cleared cell).\n */\nconst OVERLAP_OWNED_CHAR_DATA: CharData = [null, '', 0, -1];\n\nexport class TextRenderLayer extends BaseRenderLayer {\n private _state: GridCache;\n private _characterWidth: number;\n private _characterFont: string;\n private _characterOverlapCache: { [key: string]: boolean } = {};\n\n constructor(container: HTMLElement, zIndex: number, colors: IColorSet) {\n super(container, 'text', zIndex, false, colors);\n this._state = new GridCache();\n }\n\n public resize(terminal: ITerminal, dim: IRenderDimensions, charSizeChanged: boolean): void {\n super.resize(terminal, dim, charSizeChanged);\n\n // Clear the character width cache if the font or width has changed\n const terminalFont = `${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`;\n if (this._characterWidth !== dim.scaledCharWidth || this._characterFont !== terminalFont) {\n this._characterWidth = dim.scaledCharWidth;\n this._characterFont = terminalFont;\n this._characterOverlapCache = {};\n }\n // Resizing the canvas discards the contents of the canvas so clear state\n this._state.clear();\n this._state.resize(terminal.cols, terminal.rows);\n }\n\n public reset(terminal: ITerminal): void {\n this._state.clear();\n this.clearAll();\n }\n\n public onGridChanged(terminal: ITerminal, startRow: number, endRow: number): void {\n // Resize has not been called yet\n if (this._state.cache.length === 0) {\n return;\n }\n\n for (let y = startRow; y <= endRow; y++) {\n const row = y + terminal.buffer.ydisp;\n const line = terminal.buffer.lines.get(row);\n\n this.clearCells(0, y, terminal.cols, 1);\n // for (let x = 0; x < terminal.cols; x++) {\n // this._state.cache[x][y] = null;\n // }\n\n for (let x = 0; x < terminal.cols; x++) {\n const charData = line[x];\n const code: number = charData[CHAR_DATA_CODE_INDEX];\n const char: string = charData[CHAR_DATA_CHAR_INDEX];\n const attr: number = charData[CHAR_DATA_ATTR_INDEX];\n let width: number = charData[CHAR_DATA_WIDTH_INDEX];\n\n // The character to the left is a wide character, drawing is owned by\n // the char at x-1\n if (width === 0) {\n // this._state.cache[x][y] = null;\n continue;\n }\n\n // If the character is a space and the character to the left is an\n // overlapping character, skip the character and allow the overlapping\n // char to take full control over this character's cell.\n if (code === 32 /*' '*/) {\n if (x > 0) {\n const previousChar: CharData = line[x - 1];\n if (this._isOverlapping(previousChar)) {\n continue;\n }\n }\n }\n\n // Skip rendering if the character is identical\n // const state = this._state.cache[x][y];\n // if (state && state[CHAR_DATA_CHAR_INDEX] === char && state[CHAR_DATA_ATTR_INDEX] === attr) {\n // // Skip render, contents are identical\n // this._state.cache[x][y] = charData;\n // continue;\n // }\n\n // Clear the old character was not a space with the default background\n // const wasInverted = !!(state && state[CHAR_DATA_ATTR_INDEX] && state[CHAR_DATA_ATTR_INDEX] >> 18 & FLAGS.INVERSE);\n // if (state && !(state[CHAR_DATA_CODE_INDEX] === 32 /*' '*/ && (state[CHAR_DATA_ATTR_INDEX] & 0x1ff) >= 256 && !wasInverted)) {\n // this._clearChar(x, y);\n // }\n // this._state.cache[x][y] = charData;\n\n const flags = attr >> 18;\n let bg = attr & 0x1ff;\n\n // Skip rendering if the character is invisible\n const isDefaultBackground = bg >= 256;\n const isInvisible = flags & FLAGS.INVISIBLE;\n const isInverted = flags & FLAGS.INVERSE;\n if (!code || (code === 32 /*' '*/ && isDefaultBackground && !isInverted) || isInvisible) {\n continue;\n }\n\n // If the character is an overlapping char and the character to the right is a\n // space, take ownership of the cell to the right.\n if (width !== 0 && this._isOverlapping(charData)) {\n // If the character is overlapping, we want to force a re-render on every\n // frame. This is specifically to work around the case where two\n // overlaping chars `a` and `b` are adjacent, the cursor is moved to b and a\n // space is added. Without this, the first half of `b` would never\n // get removed, and `a` would not re-render because it thinks it's\n // already in the correct state.\n // this._state.cache[x][y] = OVERLAP_OWNED_CHAR_DATA;\n if (x < line.length - 1 && line[x + 1][CHAR_DATA_CODE_INDEX] === 32 /*' '*/) {\n width = 2;\n // this._clearChar(x + 1, y);\n // The overlapping char's char data will force a clear and render when the\n // overlapping char is no longer to the left of the character and also when\n // the space changes to another character.\n // this._state.cache[x + 1][y] = OVERLAP_OWNED_CHAR_DATA;\n }\n }\n\n let fg = (attr >> 9) & 0x1ff;\n\n // If inverse flag is on, the foreground should become the background.\n if (isInverted) {\n const temp = bg;\n bg = fg;\n fg = temp;\n if (fg === 256) {\n fg = INVERTED_DEFAULT_COLOR;\n }\n if (bg === 257) {\n bg = INVERTED_DEFAULT_COLOR;\n }\n }\n\n // Clear the cell next to this character if it's wide\n if (width === 2) {\n // this.clearCells(x + 1, y, 1, 1);\n }\n\n // Draw background\n if (bg < 256) {\n this._ctx.save();\n this._ctx.fillStyle = (bg === INVERTED_DEFAULT_COLOR ? this._colors.foreground : this._colors.ansi[bg]);\n this.fillCells(x, y, width, 1);\n this._ctx.restore();\n }\n\n this._ctx.save();\n if (flags & FLAGS.BOLD) {\n this._ctx.font = `bold ${this._ctx.font}`;\n // Convert the FG color to the bold variant\n if (fg < 8) {\n fg += 8;\n }\n }\n\n if (flags & FLAGS.UNDERLINE) {\n if (fg === INVERTED_DEFAULT_COLOR) {\n this._ctx.fillStyle = this._colors.background;\n } else if (fg < 256) {\n // 256 color support\n this._ctx.fillStyle = this._colors.ansi[fg];\n } else {\n this._ctx.fillStyle = this._colors.foreground;\n }\n this.fillBottomLineAtCells(x, y);\n }\n\n this.drawChar(terminal, char, code, width, x, y, fg, bg, !!(flags & FLAGS.BOLD), !!(flags & FLAGS.DIM));\n\n this._ctx.restore();\n }\n }\n }\n\n\t/**\n\t * Whether a character is overlapping to the next cell.\n\t */\n private _isOverlapping(charData: CharData): boolean {\n // Only single cell characters can be overlapping, rendering issues can\n // occur without this check\n if (charData[CHAR_DATA_WIDTH_INDEX] !== 1) {\n return false;\n }\n\n // We assume that any ascii character will not overlap\n const code = charData[CHAR_DATA_CODE_INDEX];\n if (code < 256) {\n return false;\n }\n\n // Deliver from cache if available\n const char = charData[CHAR_DATA_CHAR_INDEX];\n if (this._characterOverlapCache.hasOwnProperty(char)) {\n return this._characterOverlapCache[char];\n }\n\n // Setup the font\n this._ctx.save();\n this._ctx.font = this._characterFont;\n\n // Measure the width of the character, but Math.floor it\n // because that is what the renderer does when it calculates\n // the character dimensions we are comparing against\n const overlaps = Math.floor(this._ctx.measureText(char).width) > this._characterWidth;\n\n // Restore the original context\n this._ctx.restore();\n\n // Cache and return\n this._characterOverlapCache[char] = overlaps;\n return overlaps;\n }\n\n /**\n * Clear the charcater at the cell specified.\n * @param x The column of the char.\n * @param y The row of the char.\n */\n private _clearChar(x: number, y: number): void {\n let colsToClear = 1;\n // Clear the adjacent character if it was wide\n const state = this._state.cache[x][y];\n if (state && state[CHAR_DATA_WIDTH_INDEX] === 2) {\n colsToClear = 2;\n }\n this.clearCells(x, y, colsToClear, 1);\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IColorSet, IRenderDimensions } from './Interfaces';\nimport { IBuffer, ICharMeasure, ITerminal } from '../Interfaces';\nimport { CHAR_DATA_ATTR_INDEX } from '../Buffer';\nimport { GridCache } from './GridCache';\nimport { FLAGS } from './Types';\nimport { BaseRenderLayer } from './BaseRenderLayer';\n\nexport class SelectionRenderLayer extends BaseRenderLayer {\n private _state: {start: [number, number], end: [number, number]};\n\n constructor(container: HTMLElement, zIndex: number, colors: IColorSet) {\n super(container, 'selection', zIndex, true, colors);\n this._state = {\n start: null,\n end: null\n };\n }\n\n public resize(terminal: ITerminal, dim: IRenderDimensions, charSizeChanged: boolean): void {\n super.resize(terminal, dim, charSizeChanged);\n // Resizing the canvas discards the contents of the canvas so clear state\n this._state = {\n start: null,\n end: null\n };\n }\n\n public reset(terminal: ITerminal): void {\n if (this._state.start && this._state.end) {\n this._state = {\n start: null,\n end: null\n };\n this.clearAll();\n }\n }\n\n public onSelectionChanged(terminal: ITerminal, start: [number, number], end: [number, number]): void {\n // Selection has not changed\n if (this._state.start === start || this._state.end === end) {\n return;\n }\n\n // Remove all selections\n this.clearAll();\n\n // Selection does not exist\n if (!start || !end) {\n return;\n }\n\n // Translate from buffer position to viewport position\n const viewportStartRow = start[1] - terminal.buffer.ydisp;\n const viewportEndRow = end[1] - terminal.buffer.ydisp;\n const viewportCappedStartRow = Math.max(viewportStartRow, 0);\n const viewportCappedEndRow = Math.min(viewportEndRow, terminal.rows - 1);\n\n // No need to draw the selection\n if (viewportCappedStartRow >= terminal.rows || viewportCappedEndRow < 0) {\n return;\n }\n\n // Draw first row\n const startCol = viewportStartRow === viewportCappedStartRow ? start[0] : 0;\n const startRowEndCol = viewportCappedStartRow === viewportCappedEndRow ? end[0] : terminal.cols;\n this._ctx.fillStyle = this._colors.selection;\n this.fillCells(startCol, viewportCappedStartRow, startRowEndCol - startCol, 1);\n\n // Draw middle rows\n const middleRowsCount = Math.max(viewportCappedEndRow - viewportCappedStartRow - 1, 0);\n this.fillCells(0, viewportCappedStartRow + 1, terminal.cols, middleRowsCount);\n\n // Draw final row\n if (viewportCappedStartRow !== viewportCappedEndRow) {\n // Only draw viewportEndRow if it's not the same as viewportStartRow\n const endCol = viewportEndRow === viewportCappedEndRow ? end[0] : terminal.cols;\n this.fillCells(0, viewportCappedEndRow, endCol, 1);\n }\n\n // Save state for next render\n this._state.start = [start[0], start[1]];\n this._state.end = [end[0], end[1]];\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ITerminal, ITheme } from '../Interfaces';\nimport { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from '../Buffer';\nimport { TextRenderLayer } from './TextRenderLayer';\nimport { SelectionRenderLayer } from './SelectionRenderLayer';\nimport { CursorRenderLayer } from './CursorRenderLayer';\nimport { ColorManager } from './ColorManager';\nimport { BaseRenderLayer } from './BaseRenderLayer';\nimport { IRenderLayer, IColorSet, IRenderer, IRenderDimensions } from './Interfaces';\nimport { LinkRenderLayer } from './LinkRenderLayer';\nimport { EventEmitter } from '../EventEmitter';\n\nexport class Renderer extends EventEmitter implements IRenderer {\n /** A queue of the rows to be refreshed */\n private _refreshRowsQueue: {start: number, end: number}[] = [];\n private _refreshAnimationFrame = null;\n\n private _renderLayers: IRenderLayer[];\n private _devicePixelRatio: number;\n\n public colorManager: ColorManager;\n public dimensions: IRenderDimensions;\n\n constructor(private _terminal: ITerminal, theme: ITheme) {\n super();\n this.colorManager = new ColorManager();\n if (theme) {\n this.colorManager.setTheme(theme);\n }\n this._renderLayers = [\n new TextRenderLayer(this._terminal.element, 0, this.colorManager.colors),\n new SelectionRenderLayer(this._terminal.element, 1, this.colorManager.colors),\n new LinkRenderLayer(this._terminal.element, 2, this.colorManager.colors, this._terminal),\n new CursorRenderLayer(this._terminal.element, 3, this.colorManager.colors)\n ];\n this.dimensions = {\n scaledCharWidth: null,\n scaledCharHeight: null,\n scaledCellWidth: null,\n scaledCellHeight: null,\n scaledCharLeft: null,\n scaledCharTop: null,\n scaledCanvasWidth: null,\n scaledCanvasHeight: null,\n canvasWidth: null,\n canvasHeight: null,\n actualCellWidth: null,\n actualCellHeight: null\n };\n this._devicePixelRatio = window.devicePixelRatio;\n }\n\n public onWindowResize(devicePixelRatio: number): void {\n // If the device pixel ratio changed, the char atlas needs to be regenerated\n // and the terminal needs to refreshed\n if (this._devicePixelRatio !== devicePixelRatio) {\n this._devicePixelRatio = devicePixelRatio;\n this.onResize(this._terminal.cols, this._terminal.rows, true);\n }\n }\n\n public setTheme(theme: ITheme): IColorSet {\n this.colorManager.setTheme(theme);\n\n // Clear layers and force a full render\n this._renderLayers.forEach(l => {\n l.onThemeChanged(this._terminal, this.colorManager.colors);\n l.reset(this._terminal);\n });\n\n this._terminal.refresh(0, this._terminal.rows - 1);\n\n return this.colorManager.colors;\n }\n\n public onResize(cols: number, rows: number, didCharSizeChange: boolean): void {\n if (!this._terminal.charMeasure.width || !this._terminal.charMeasure.height) {\n return;\n }\n\n // Calculate the scaled character width. Width is floored as it must be\n // drawn to an integer grid in order for the CharAtlas \"stamps\" to not be\n // blurry. When text is drawn to the grid not using the CharAtlas, it is\n // clipped to ensure there is no overlap with the next cell.\n this.dimensions.scaledCharWidth = Math.floor(this._terminal.charMeasure.width * window.devicePixelRatio);\n\n // Calculate the scaled character height. Height is ceiled in case\n // devicePixelRatio is a floating point number in order to ensure there is\n // enough space to draw the character to the cell.\n this.dimensions.scaledCharHeight = Math.ceil(this._terminal.charMeasure.height * window.devicePixelRatio);\n\n // Calculate the scaled cell height, if lineHeight is not 1 then the value\n // will be floored because since lineHeight can never be lower then 1, there\n // is a guarentee that the scaled line height will always be larger than\n // scaled char height.\n this.dimensions.scaledCellHeight = Math.floor(this.dimensions.scaledCharHeight * this._terminal.options.lineHeight);\n\n // Calculate the y coordinate within a cell that text should draw from in\n // order to draw in the center of a cell.\n this.dimensions.scaledCharTop = this._terminal.options.lineHeight === 1 ? 0 : Math.round((this.dimensions.scaledCellHeight - this.dimensions.scaledCharHeight) / 2);\n\n // Calculate the scaled cell width, taking the letterSpacing into account.\n this.dimensions.scaledCellWidth = this.dimensions.scaledCharWidth + Math.round(this._terminal.options.letterSpacing);\n\n // Calculate the x coordinate with a cell that text should draw from in\n // order to draw in the center of a cell.\n this.dimensions.scaledCharLeft = Math.floor(this._terminal.options.letterSpacing / 2);\n\n // Recalculate the canvas dimensions; scaled* define the actual number of\n // pixel in the canvas\n this.dimensions.scaledCanvasHeight = this._terminal.rows * this.dimensions.scaledCellHeight;\n this.dimensions.scaledCanvasWidth = this._terminal.cols * this.dimensions.scaledCellWidth;\n\n // The the size of the canvas on the page. It's very important that this\n // rounds to nearest integer and not ceils as browsers often set\n // window.devicePixelRatio as something like 1.100000023841858, when it's\n // actually 1.1. Ceiling causes blurriness as the backing canvas image is 1\n // pixel too large for the canvas element size.\n this.dimensions.canvasHeight = Math.round(this.dimensions.scaledCanvasHeight / window.devicePixelRatio);\n this.dimensions.canvasWidth = Math.round(this.dimensions.scaledCanvasWidth / window.devicePixelRatio);\n\n // Get the _actual_ dimensions of an individual cell. This needs to be\n // derived from the canvasWidth/Height calculated above which takes into\n // account window.devicePixelRatio. CharMeasure.width/height by itself is\n // insufficient when the page is not at 100% zoom level as CharMeasure is\n // measured in CSS pixels, but the actual char size on the canvas can\n // differ.\n this.dimensions.actualCellHeight = this.dimensions.canvasHeight / this._terminal.rows;\n this.dimensions.actualCellWidth = this.dimensions.canvasWidth / this._terminal.cols;\n\n // Resize all render layers\n this._renderLayers.forEach(l => l.resize(this._terminal, this.dimensions, didCharSizeChange));\n\n // Force a refresh\n this._terminal.refresh(0, this._terminal.rows - 1);\n\n this.emit('resize', {\n width: this.dimensions.canvasWidth,\n height: this.dimensions.canvasHeight\n });\n }\n\n public onCharSizeChanged(): void {\n this.onResize(this._terminal.cols, this._terminal.rows, true);\n }\n\n public onBlur(): void {\n this._renderLayers.forEach(l => l.onBlur(this._terminal));\n }\n\n public onFocus(): void {\n this._renderLayers.forEach(l => l.onFocus(this._terminal));\n }\n\n public onSelectionChanged(start: [number, number], end: [number, number]): void {\n this._renderLayers.forEach(l => l.onSelectionChanged(this._terminal, start, end));\n }\n\n public onCursorMove(): void {\n this._renderLayers.forEach(l => l.onCursorMove(this._terminal));\n }\n\n public onOptionsChanged(): void {\n this._renderLayers.forEach(l => l.onOptionsChanged(this._terminal));\n }\n\n public clear(): void {\n this._renderLayers.forEach(l => l.reset(this._terminal));\n }\n\n /**\n * Queues a refresh between two rows (inclusive), to be done on next animation\n * frame.\n * @param {number} start The start row.\n * @param {number} end The end row.\n */\n public queueRefresh(start: number, end: number): void {\n this._refreshRowsQueue.push({ start: start, end: end });\n if (!this._refreshAnimationFrame) {\n this._refreshAnimationFrame = window.requestAnimationFrame(this._refreshLoop.bind(this));\n }\n }\n\n /**\n * Performs the refresh loop callback, calling refresh only if a refresh is\n * necessary before queueing up the next one.\n */\n private _refreshLoop(): void {\n let start;\n let end;\n if (this._refreshRowsQueue.length > 4) {\n // Just do a full refresh when 5+ refreshes are queued\n start = 0;\n end = this._terminal.rows - 1;\n } else {\n // Get start and end rows that need refreshing\n start = this._refreshRowsQueue[0].start;\n end = this._refreshRowsQueue[0].end;\n for (let i = 1; i < this._refreshRowsQueue.length; i++) {\n if (this._refreshRowsQueue[i].start < start) {\n start = this._refreshRowsQueue[i].start;\n }\n if (this._refreshRowsQueue[i].end > end) {\n end = this._refreshRowsQueue[i].end;\n }\n }\n }\n this._refreshRowsQueue = [];\n this._refreshAnimationFrame = null;\n\n // Render\n start = Math.max(start, 0);\n end = Math.min(end, this._terminal.rows - 1);\n this._renderLayers.forEach(l => l.onGridChanged(this._terminal, start, end));\n this._terminal.emit('refresh', {start, end});\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IColorSet, IRenderDimensions } from './Interfaces';\nimport { IBuffer, ICharMeasure, ITerminal, ILinkifierAccessor } from '../Interfaces';\nimport { CHAR_DATA_ATTR_INDEX } from '../Buffer';\nimport { GridCache } from './GridCache';\nimport { FLAGS } from './Types';\nimport { BaseRenderLayer, INVERTED_DEFAULT_COLOR } from './BaseRenderLayer';\nimport { LinkHoverEvent, LinkHoverEventTypes } from '../Types';\n\nexport class LinkRenderLayer extends BaseRenderLayer {\n private _state: LinkHoverEvent = null;\n\n constructor(container: HTMLElement, zIndex: number, colors: IColorSet, terminal: ILinkifierAccessor) {\n super(container, 'link', zIndex, true, colors);\n terminal.linkifier.on(LinkHoverEventTypes.HOVER, (e: LinkHoverEvent) => this._onLinkHover(e));\n terminal.linkifier.on(LinkHoverEventTypes.LEAVE, (e: LinkHoverEvent) => this._onLinkLeave(e));\n }\n\n public resize(terminal: ITerminal, dim: IRenderDimensions, charSizeChanged: boolean): void {\n super.resize(terminal, dim, charSizeChanged);\n // Resizing the canvas discards the contents of the canvas so clear state\n this._state = null;\n }\n\n public reset(terminal: ITerminal): void {\n this._clearCurrentLink();\n }\n\n private _clearCurrentLink(): void {\n if (this._state) {\n this.clearCells(this._state.x, this._state.y, this._state.length, 1);\n this._state = null;\n }\n }\n\n private _onLinkHover(e: LinkHoverEvent): void {\n this._ctx.fillStyle = this._colors.foreground;\n this.fillBottomLineAtCells(e.x, e.y, e.length);\n this._state = e;\n }\n\n private _onLinkLeave(e: LinkHoverEvent): void {\n this._clearCurrentLink();\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nexport class GridCache {\n public cache: T[][];\n\n public constructor() {\n this.cache = [];\n }\n\n public resize(width: number, height: number): void {\n for (let x = 0; x < width; x++) {\n if (this.cache.length <= x) {\n this.cache.push([]);\n }\n for (let y = this.cache[x].length; y < height; y++) {\n this.cache[x].push(null);\n }\n this.cache[x].length = height;\n }\n this.cache.length = width;\n }\n\n public clear(): void {\n for (let x = 0; x < this.cache.length; x++) {\n for (let y = 0; y < this.cache[x].length; y++) {\n this.cache[x][y] = null;\n }\n }\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IColorSet, IRenderDimensions } from './Interfaces';\nimport { IBuffer, ICharMeasure, ITerminal, ITerminalOptions } from '../Interfaces';\nimport { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CODE_INDEX, CHAR_DATA_CHAR_INDEX } from '../Buffer';\nimport { GridCache } from './GridCache';\nimport { FLAGS } from './Types';\nimport { BaseRenderLayer } from './BaseRenderLayer';\nimport { CharData } from '../Types';\n\ninterface CursorState {\n x: number;\n y: number;\n isFocused: boolean;\n style: string;\n width: number;\n}\n\n/**\n * The time between cursor blinks.\n */\nconst BLINK_INTERVAL = 600;\n\nexport class CursorRenderLayer extends BaseRenderLayer {\n private _state: CursorState;\n private _cursorRenderers: {[key: string]: (terminal: ITerminal, x: number, y: number, charData: CharData) => void};\n private _cursorBlinkStateManager: CursorBlinkStateManager;\n private _isFocused: boolean;\n\n constructor(container: HTMLElement, zIndex: number, colors: IColorSet) {\n super(container, 'cursor', zIndex, true, colors);\n this._state = {\n x: null,\n y: null,\n isFocused: null,\n style: null,\n width: null,\n };\n this._cursorRenderers = {\n 'bar': this._renderBarCursor.bind(this),\n 'block': this._renderBlockCursor.bind(this),\n 'underline': this._renderUnderlineCursor.bind(this)\n };\n // TODO: Consider initial options? Maybe onOptionsChanged should be called at the end of open?\n }\n\n public resize(terminal: ITerminal, dim: IRenderDimensions, charSizeChanged: boolean): void {\n super.resize(terminal, dim, charSizeChanged);\n // Resizing the canvas discards the contents of the canvas so clear state\n this._state = {\n x: null,\n y: null,\n isFocused: null,\n style: null,\n width: null,\n };\n }\n\n public reset(terminal: ITerminal): void {\n this._clearCursor();\n if (this._cursorBlinkStateManager) {\n this._cursorBlinkStateManager.dispose();\n this._cursorBlinkStateManager = null;\n this.onOptionsChanged(terminal);\n }\n }\n\n public onBlur(terminal: ITerminal): void {\n if (this._cursorBlinkStateManager) {\n this._cursorBlinkStateManager.pause();\n }\n terminal.refresh(terminal.buffer.y, terminal.buffer.y);\n }\n\n public onFocus(terminal: ITerminal): void {\n if (this._cursorBlinkStateManager) {\n this._cursorBlinkStateManager.resume(terminal);\n } else {\n terminal.refresh(terminal.buffer.y, terminal.buffer.y);\n }\n }\n\n public onOptionsChanged(terminal: ITerminal): void {\n if (terminal.options.cursorBlink) {\n if (!this._cursorBlinkStateManager) {\n this._cursorBlinkStateManager = new CursorBlinkStateManager(terminal, () => {\n this._render(terminal, true);\n });\n }\n } else {\n if (this._cursorBlinkStateManager) {\n this._cursorBlinkStateManager.dispose();\n this._cursorBlinkStateManager = null;\n }\n // Request a refresh from the terminal as management of rendering is being\n // moved back to the terminal\n terminal.refresh(terminal.buffer.y, terminal.buffer.y);\n }\n }\n\n public onCursorMove(terminal: ITerminal): void {\n if (this._cursorBlinkStateManager) {\n this._cursorBlinkStateManager.restartBlinkAnimation(terminal);\n }\n }\n\n public onGridChanged(terminal: ITerminal, startRow: number, endRow: number): void {\n // Only render if the animation frame is not active\n if (!this._cursorBlinkStateManager || this._cursorBlinkStateManager.isPaused) {\n this._render(terminal, false);\n }\n }\n\n private _render(terminal: ITerminal, triggeredByAnimationFrame: boolean): void {\n // Don't draw the cursor if it's hidden\n if (!terminal.cursorState || terminal.cursorHidden) {\n this._clearCursor();\n return;\n }\n\n const cursorY = terminal.buffer.ybase + terminal.buffer.y;\n const viewportRelativeCursorY = cursorY - terminal.buffer.ydisp;\n\n // Don't draw the cursor if it's off-screen\n if (viewportRelativeCursorY < 0 || viewportRelativeCursorY >= terminal.rows) {\n this._clearCursor();\n return;\n }\n\n const charData = terminal.buffer.lines.get(cursorY)[terminal.buffer.x];\n if (!charData) {\n return;\n }\n\n if (!terminal.isFocused) {\n this._clearCursor();\n this._ctx.save();\n this._ctx.fillStyle = this._colors.cursor;\n this._renderBlurCursor(terminal, terminal.buffer.x, viewportRelativeCursorY, charData);\n this._ctx.restore();\n this._state.x = terminal.buffer.x;\n this._state.y = viewportRelativeCursorY;\n this._state.isFocused = false;\n this._state.style = terminal.options.cursorStyle;\n this._state.width = charData[CHAR_DATA_WIDTH_INDEX];\n return;\n }\n\n // Don't draw the cursor if it's blinking\n if (this._cursorBlinkStateManager && !this._cursorBlinkStateManager.isCursorVisible) {\n this._clearCursor();\n return;\n }\n\n if (this._state) {\n // The cursor is already in the correct spot, don't redraw\n if (this._state.x === terminal.buffer.x &&\n this._state.y === viewportRelativeCursorY &&\n this._state.isFocused === terminal.isFocused &&\n this._state.style === terminal.options.cursorStyle &&\n this._state.width === charData[CHAR_DATA_WIDTH_INDEX]) {\n return;\n }\n this._clearCursor();\n }\n\n this._ctx.save();\n this._cursorRenderers[terminal.options.cursorStyle || 'block'](terminal, terminal.buffer.x, viewportRelativeCursorY, charData);\n this._ctx.restore();\n\n this._state.x = terminal.buffer.x;\n this._state.y = viewportRelativeCursorY;\n this._state.isFocused = false;\n this._state.style = terminal.options.cursorStyle;\n this._state.width = charData[CHAR_DATA_WIDTH_INDEX];\n }\n\n private _clearCursor(): void {\n if (this._state) {\n this.clearCells(this._state.x, this._state.y, this._state.width, 1);\n this._state = {\n x: null,\n y: null,\n isFocused: null,\n style: null,\n width: null,\n };\n }\n }\n\n private _renderBarCursor(terminal: ITerminal, x: number, y: number, charData: CharData): void {\n this._ctx.save();\n this._ctx.fillStyle = this._colors.cursor;\n this.fillLeftLineAtCell(x, y);\n this._ctx.restore();\n }\n\n private _renderBlockCursor(terminal: ITerminal, x: number, y: number, charData: CharData): void {\n this._ctx.save();\n this._ctx.fillStyle = this._colors.cursor;\n this.fillCells(x, y, charData[CHAR_DATA_WIDTH_INDEX], 1);\n this._ctx.fillStyle = this._colors.cursorAccent;\n this.fillCharTrueColor(terminal, charData, x, y);\n this._ctx.restore();\n }\n\n private _renderUnderlineCursor(terminal: ITerminal, x: number, y: number, charData: CharData): void {\n this._ctx.save();\n this._ctx.fillStyle = this._colors.cursor;\n this.fillBottomLineAtCells(x, y);\n this._ctx.restore();\n }\n\n private _renderBlurCursor(terminal: ITerminal, x: number, y: number, charData: CharData): void {\n this._ctx.save();\n this._ctx.strokeStyle = this._colors.cursor;\n this.strokeRectAtCell(x, y, charData[CHAR_DATA_WIDTH_INDEX], 1);\n this._ctx.restore();\n }\n}\n\nclass CursorBlinkStateManager {\n public isCursorVisible: boolean;\n\n private _animationFrame: number;\n private _blinkStartTimeout: number;\n private _blinkInterval: number;\n\n /**\n * The time at which the animation frame was restarted, this is used on the\n * next render to restart the timers so they don't need to restart the timers\n * multiple times over a short period.\n */\n private _animationTimeRestarted: number;\n\n constructor(\n terminal: ITerminal,\n private renderCallback: () => void\n ) {\n this.isCursorVisible = true;\n if (terminal.isFocused) {\n this._restartInterval();\n }\n }\n\n public get isPaused(): boolean { return !(this._blinkStartTimeout || this._blinkInterval); }\n\n public dispose(): void {\n if (this._blinkInterval) {\n window.clearInterval(this._blinkInterval);\n this._blinkInterval = null;\n }\n if (this._blinkStartTimeout) {\n window.clearTimeout(this._blinkStartTimeout);\n this._blinkStartTimeout = null;\n }\n if (this._animationFrame) {\n window.cancelAnimationFrame(this._animationFrame);\n this._animationFrame = null;\n }\n }\n\n public restartBlinkAnimation(terminal: ITerminal): void {\n if (this.isPaused) {\n return;\n }\n // Save a timestamp so that the restart can be done on the next interval\n this._animationTimeRestarted = Date.now();\n // Force a cursor render to ensure it's visible and in the correct position\n this.isCursorVisible = true;\n if (!this._animationFrame) {\n this._animationFrame = window.requestAnimationFrame(() => {\n this.renderCallback();\n this._animationFrame = null;\n });\n }\n }\n\n private _restartInterval(timeToStart: number = BLINK_INTERVAL): void {\n // Clear any existing interval\n if (this._blinkInterval) {\n window.clearInterval(this._blinkInterval);\n }\n\n // Setup the initial timeout which will hide the cursor, this is done before\n // the regular interval is setup in order to support restarting the blink\n // animation in a lightweight way (without thrashing clearInterval and\n // setInterval).\n this._blinkStartTimeout = setTimeout(() => {\n // Check if another animation restart was requested while this was being\n // started\n if (this._animationTimeRestarted) {\n const time = BLINK_INTERVAL - (Date.now() - this._animationTimeRestarted);\n this._animationTimeRestarted = null;\n if (time > 0) {\n this._restartInterval(time);\n return;\n }\n }\n\n // Hide the cursor\n this.isCursorVisible = false;\n this._animationFrame = window.requestAnimationFrame(() => {\n this.renderCallback();\n this._animationFrame = null;\n });\n\n // Setup the blink interval\n this._blinkInterval = setInterval(() => {\n // Adjust the animation time if it was restarted\n if (this._animationTimeRestarted) {\n // calc time diff\n // Make restart interval do a setTimeout initially?\n const time = BLINK_INTERVAL - (Date.now() - this._animationTimeRestarted);\n this._animationTimeRestarted = null;\n this._restartInterval(time);\n return;\n }\n\n // Invert visibility and render\n this.isCursorVisible = !this.isCursorVisible;\n this._animationFrame = window.requestAnimationFrame(() => {\n this.renderCallback();\n this._animationFrame = null;\n });\n }, BLINK_INTERVAL);\n }, timeToStart);\n }\n\n public pause(): void {\n this.isCursorVisible = true;\n if (this._blinkInterval) {\n window.clearInterval(this._blinkInterval);\n this._blinkInterval = null;\n }\n if (this._blinkStartTimeout) {\n window.clearTimeout(this._blinkStartTimeout);\n this._blinkStartTimeout = null;\n }\n if (this._animationFrame) {\n window.cancelAnimationFrame(this._animationFrame);\n this._animationFrame = null;\n }\n }\n\n public resume(terminal: ITerminal): void {\n this._animationTimeRestarted = null;\n this._restartInterval();\n this.restartBlinkAnimation(terminal);\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IColorSet, IColorManager } from './Interfaces';\nimport { ITheme } from '../Interfaces';\n\nconst DEFAULT_FOREGROUND = '#ffffff';\nconst DEFAULT_BACKGROUND = '#000000';\nconst DEFAULT_CURSOR = '#ffffff';\nconst DEFAULT_CURSOR_ACCENT = '#000000';\nconst DEFAULT_SELECTION = 'rgba(255, 255, 255, 0.3)';\nexport const DEFAULT_ANSI_COLORS = [\n // dark:\n '#2e3436',\n '#cc0000',\n '#4e9a06',\n '#c4a000',\n '#3465a4',\n '#75507b',\n '#06989a',\n '#d3d7cf',\n // bright:\n '#555753',\n '#ef2929',\n '#8ae234',\n '#fce94f',\n '#729fcf',\n '#ad7fa8',\n '#34e2e2',\n '#eeeeec'\n];\n\n/**\n * Fills an existing 16 length string with the remaining 240 ANSI colors.\n * @param first16Colors The first 16 ANSI colors.\n */\nfunction generate256Colors(first16Colors: string[]): string[] {\n let colors = first16Colors.slice();\n\n // Generate colors (16-231)\n let v = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff];\n for (let i = 0; i < 216; i++) {\n const r = toPaddedHex(v[(i / 36) % 6 | 0]);\n const g = toPaddedHex(v[(i / 6) % 6 | 0]);\n const b = toPaddedHex(v[i % 6]);\n colors.push(`#${r}${g}${b}`);\n }\n\n // Generate greys (232-255)\n for (let i = 0; i < 24; i++) {\n const c = toPaddedHex(8 + i * 10);\n colors.push(`#${c}${c}${c}`);\n }\n\n return colors;\n}\n\nfunction toPaddedHex(c: number): string {\n let s = c.toString(16);\n return s.length < 2 ? '0' + s : s;\n}\n\n/**\n * Manages the source of truth for a terminal's colors.\n */\nexport class ColorManager implements IColorManager {\n public colors: IColorSet;\n\n constructor() {\n this.colors = {\n foreground: DEFAULT_FOREGROUND,\n background: DEFAULT_BACKGROUND,\n cursor: DEFAULT_CURSOR,\n cursorAccent: DEFAULT_CURSOR_ACCENT,\n selection: DEFAULT_SELECTION,\n ansi: generate256Colors(DEFAULT_ANSI_COLORS)\n };\n }\n\n /**\n * Sets the terminal's theme.\n * @param theme The theme to use. If a partial theme is provided then default\n * colors will be used where colors are not defined.\n */\n public setTheme(theme: ITheme): void {\n this.colors.foreground = theme.foreground || DEFAULT_FOREGROUND;\n this.colors.background = this._validateColor(theme.background, DEFAULT_BACKGROUND);\n this.colors.cursor = theme.cursor || DEFAULT_CURSOR;\n this.colors.cursorAccent = theme.cursorAccent || DEFAULT_CURSOR_ACCENT;\n this.colors.selection = theme.selection || DEFAULT_SELECTION;\n this.colors.ansi[0] = theme.black || DEFAULT_ANSI_COLORS[0];\n this.colors.ansi[1] = theme.red || DEFAULT_ANSI_COLORS[1];\n this.colors.ansi[2] = theme.green || DEFAULT_ANSI_COLORS[2];\n this.colors.ansi[3] = theme.yellow || DEFAULT_ANSI_COLORS[3];\n this.colors.ansi[4] = theme.blue || DEFAULT_ANSI_COLORS[4];\n this.colors.ansi[5] = theme.magenta || DEFAULT_ANSI_COLORS[5];\n this.colors.ansi[6] = theme.cyan || DEFAULT_ANSI_COLORS[6];\n this.colors.ansi[7] = theme.white || DEFAULT_ANSI_COLORS[7];\n this.colors.ansi[8] = theme.brightBlack || DEFAULT_ANSI_COLORS[8];\n this.colors.ansi[9] = theme.brightRed || DEFAULT_ANSI_COLORS[9];\n this.colors.ansi[10] = theme.brightGreen || DEFAULT_ANSI_COLORS[10];\n this.colors.ansi[11] = theme.brightYellow || DEFAULT_ANSI_COLORS[11];\n this.colors.ansi[12] = theme.brightBlue || DEFAULT_ANSI_COLORS[12];\n this.colors.ansi[13] = theme.brightMagenta || DEFAULT_ANSI_COLORS[13];\n this.colors.ansi[14] = theme.brightCyan || DEFAULT_ANSI_COLORS[14];\n this.colors.ansi[15] = theme.brightWhite || DEFAULT_ANSI_COLORS[15];\n }\n\n private _validateColor(color: string, fallback: string): string {\n if (!color) {\n return fallback;\n }\n if (color.length === 7 && color.charAt(0) === '#') {\n return color;\n }\n if (color.length === 4 && color.charAt(0) === '#') {\n const r = color.charAt(1);\n const g = color.charAt(2);\n const b = color.charAt(3);\n return `#${r}${r}${g}${g}${b}${b}`;\n }\n return fallback;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ITerminal, ITheme } from '../Interfaces';\nimport { IColorSet } from '../renderer/Interfaces';\nimport { isFirefox } from '../utils/Browser';\n\nexport const CHAR_ATLAS_CELL_SPACING = 1;\n\ninterface ICharAtlasConfig {\n fontSize: number;\n fontFamily: string;\n scaledCharWidth: number;\n scaledCharHeight: number;\n colors: IColorSet;\n}\n\ninterface ICharAtlasCacheEntry {\n bitmap: HTMLCanvasElement | Promise;\n config: ICharAtlasConfig;\n ownedBy: ITerminal[];\n}\n\nlet charAtlasCache: ICharAtlasCacheEntry[] = [];\n\n/**\n * Acquires a char atlas, either generating a new one or returning an existing\n * one that is in use by another terminal.\n * @param terminal The terminal.\n * @param colors The colors to use.\n */\nexport function acquireCharAtlas(terminal: ITerminal, colors: IColorSet, scaledCharWidth: number, scaledCharHeight: number): HTMLCanvasElement | Promise {\n const newConfig = generateConfig(scaledCharWidth, scaledCharHeight, terminal, colors);\n\n // Check to see if the terminal already owns this config\n for (let i = 0; i < charAtlasCache.length; i++) {\n const entry = charAtlasCache[i];\n const ownedByIndex = entry.ownedBy.indexOf(terminal);\n if (ownedByIndex >= 0) {\n if (configEquals(entry.config, newConfig)) {\n return entry.bitmap;\n } else {\n // The configs differ, release the terminal from the entry\n if (entry.ownedBy.length === 1) {\n charAtlasCache.splice(i, 1);\n } else {\n entry.ownedBy.splice(ownedByIndex, 1);\n }\n break;\n }\n }\n }\n\n // Try match a char atlas from the cache\n for (let i = 0; i < charAtlasCache.length; i++) {\n const entry = charAtlasCache[i];\n if (configEquals(entry.config, newConfig)) {\n // Add the terminal to the cache entry and return\n entry.ownedBy.push(terminal);\n return entry.bitmap;\n }\n }\n\n const newEntry: ICharAtlasCacheEntry = {\n bitmap: generator.generate(scaledCharWidth, scaledCharHeight, terminal.options.fontSize, terminal.options.fontFamily, colors.background, colors.foreground, colors.ansi),\n config: newConfig,\n ownedBy: [terminal]\n };\n charAtlasCache.push(newEntry);\n return newEntry.bitmap;\n}\n\nfunction generateConfig(scaledCharWidth: number, scaledCharHeight: number, terminal: ITerminal, colors: IColorSet): ICharAtlasConfig {\n const clonedColors = {\n foreground: colors.foreground,\n background: colors.background,\n cursor: null,\n cursorAccent: null,\n selection: null,\n ansi: colors.ansi.slice(0, 16)\n };\n return {\n scaledCharWidth,\n scaledCharHeight,\n fontFamily: terminal.options.fontFamily,\n fontSize: terminal.options.fontSize,\n colors: clonedColors\n };\n}\n\nfunction configEquals(a: ICharAtlasConfig, b: ICharAtlasConfig): boolean {\n for (let i = 0; i < a.colors.ansi.length; i++) {\n if (a.colors.ansi[i] !== b.colors.ansi[i]) {\n return false;\n }\n }\n return a.fontFamily === b.fontFamily &&\n a.fontSize === b.fontSize &&\n a.scaledCharWidth === b.scaledCharWidth &&\n a.scaledCharHeight === b.scaledCharHeight &&\n a.colors.foreground === b.colors.foreground &&\n a.colors.background === b.colors.background;\n}\n\nlet generator: CharAtlasGenerator;\n\n/**\n * Initializes the char atlas generator.\n * @param document The document.\n */\nexport function initialize(document: Document): void {\n if (!generator) {\n generator = new CharAtlasGenerator(document);\n }\n}\n\nclass CharAtlasGenerator {\n private _canvas: HTMLCanvasElement;\n private _ctx: CanvasRenderingContext2D;\n\n constructor(private _document: Document) {\n this._canvas = this._document.createElement('canvas');\n this._ctx = this._canvas.getContext('2d', {alpha: false});\n this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio);\n }\n\n public generate(scaledCharWidth: number, scaledCharHeight: number, fontSize: number, fontFamily: string, background: string, foreground: string, ansiColors: string[]): HTMLCanvasElement | Promise {\n const cellWidth = scaledCharWidth + CHAR_ATLAS_CELL_SPACING;\n const cellHeight = scaledCharHeight + CHAR_ATLAS_CELL_SPACING;\n this._canvas.width = 255 * cellWidth;\n this._canvas.height = (/*default+default bold*/2 + /*0-15*/16) * cellHeight;\n\n this._ctx.fillStyle = background;\n this._ctx.fillRect(0, 0, this._canvas.width, this._canvas.height);\n\n this._ctx.save();\n this._ctx.fillStyle = foreground;\n this._ctx.font = `${fontSize * window.devicePixelRatio}px ${fontFamily}`;\n this._ctx.textBaseline = 'top';\n\n // Default color\n for (let i = 0; i < 256; i++) {\n this._ctx.save();\n this._ctx.beginPath();\n this._ctx.rect(i * cellWidth, 0, cellWidth, cellHeight);\n this._ctx.clip();\n this._ctx.fillText(String.fromCharCode(i), i * cellWidth, 0);\n this._ctx.restore();\n }\n // Default color bold\n this._ctx.save();\n this._ctx.font = `bold ${this._ctx.font}`;\n for (let i = 0; i < 256; i++) {\n this._ctx.save();\n this._ctx.beginPath();\n this._ctx.rect(i * cellWidth, cellHeight, cellWidth, cellHeight);\n this._ctx.clip();\n this._ctx.fillText(String.fromCharCode(i), i * cellWidth, cellHeight);\n this._ctx.restore();\n }\n this._ctx.restore();\n\n // Colors 0-15\n this._ctx.font = `${fontSize * window.devicePixelRatio}px ${fontFamily}`;\n for (let colorIndex = 0; colorIndex < 16; colorIndex++) {\n // colors 8-15 are bold\n if (colorIndex === 8) {\n this._ctx.font = `bold ${this._ctx.font}`;\n }\n const y = (colorIndex + 2) * cellHeight;\n // Draw ascii characters\n for (let i = 0; i < 256; i++) {\n this._ctx.save();\n this._ctx.beginPath();\n this._ctx.rect(i * cellWidth, y, cellWidth, cellHeight);\n this._ctx.clip();\n this._ctx.fillStyle = ansiColors[colorIndex];\n this._ctx.fillText(String.fromCharCode(i), i * cellWidth, y);\n this._ctx.restore();\n }\n }\n this._ctx.restore();\n\n // Support is patchy for createImageBitmap at the moment, pass a canvas back\n // if support is lacking as drawImage works there too. Firefox is also\n // included here as ImageBitmap appears both buggy and has horrible\n // performance (tested on v55).\n if (!('createImageBitmap' in window) || isFirefox) {\n // Regenerate canvas and context as they are now owned by the char atlas\n const result = this._canvas;\n this._canvas = this._document.createElement('canvas');\n this._ctx = this._canvas.getContext('2d');\n this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio);\n return result;\n }\n\n const charAtlasImageData = this._ctx.getImageData(0, 0, this._canvas.width, this._canvas.height);\n\n // Remove the background color from the image so characters may overlap\n const r = parseInt(background.substr(1, 2), 16);\n const g = parseInt(background.substr(3, 2), 16);\n const b = parseInt(background.substr(5, 2), 16);\n this._clearColor(charAtlasImageData, r, g, b);\n\n const promise = window.createImageBitmap(charAtlasImageData);\n // Clear the rect while the promise is in progress\n this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);\n return promise;\n }\n\n private _clearColor(imageData: ImageData, r: number, g: number, b: number): void {\n for (let offset = 0; offset < imageData.data.length; offset += 4) {\n if (imageData.data[offset] === r &&\n imageData.data[offset + 1] === g &&\n imageData.data[offset + 2] === b) {\n imageData.data[offset + 3] = 0;\n }\n }\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IRenderLayer, IColorSet, IRenderDimensions } from './Interfaces';\nimport { ITerminal, ITerminalOptions } from '../Interfaces';\nimport { acquireCharAtlas, CHAR_ATLAS_CELL_SPACING } from './CharAtlas';\nimport { CharData } from '../Types';\nimport { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from '../Buffer';\n\nexport const INVERTED_DEFAULT_COLOR = -1;\nconst DIM_OPACITY = 0.5;\n\nexport abstract class BaseRenderLayer implements IRenderLayer {\n private _canvas: HTMLCanvasElement;\n protected _ctx: CanvasRenderingContext2D;\n private _scaledCharWidth: number = 0;\n private _scaledCharHeight: number = 0;\n private _scaledCellWidth: number = 0;\n private _scaledCellHeight: number = 0;\n private _scaledCharLeft: number = 0;\n private _scaledCharTop: number = 0;\n\n private _charAtlas: HTMLCanvasElement | ImageBitmap;\n\n constructor(\n container: HTMLElement,\n id: string,\n zIndex: number,\n private _alpha: boolean,\n protected _colors: IColorSet\n ) {\n this._canvas = document.createElement('canvas');\n this._canvas.id = `xterm-${id}-layer`;\n this._canvas.style.zIndex = zIndex.toString();\n this._ctx = this._canvas.getContext('2d', {alpha: _alpha});\n this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio);\n // Draw the background if this is an opaque layer\n if (!_alpha) {\n this.clearAll();\n }\n container.appendChild(this._canvas);\n }\n\n public onOptionsChanged(terminal: ITerminal): void {}\n public onBlur(terminal: ITerminal): void {}\n public onFocus(terminal: ITerminal): void {}\n public onCursorMove(terminal: ITerminal): void {}\n public onGridChanged(terminal: ITerminal, startRow: number, endRow: number): void {}\n public onSelectionChanged(terminal: ITerminal, start: [number, number], end: [number, number]): void {}\n\n public onThemeChanged(terminal: ITerminal, colorSet: IColorSet): void {\n this._refreshCharAtlas(terminal, colorSet);\n }\n\n /**\n * Refreshes the char atlas, aquiring a new one if necessary.\n * @param terminal The terminal.\n * @param colorSet The color set to use for the char atlas.\n */\n private _refreshCharAtlas(terminal: ITerminal, colorSet: IColorSet): void {\n if (this._scaledCharWidth <= 0 && this._scaledCharHeight <= 0) {\n return;\n }\n this._charAtlas = null;\n const result = acquireCharAtlas(terminal, this._colors, this._scaledCharWidth, this._scaledCharHeight);\n if (result instanceof HTMLCanvasElement) {\n this._charAtlas = result;\n } else {\n result.then(bitmap => this._charAtlas = bitmap);\n }\n }\n\n public resize(terminal: ITerminal, dim: IRenderDimensions, charSizeChanged: boolean): void {\n this._scaledCellWidth = dim.scaledCellWidth;\n this._scaledCellHeight = dim.scaledCellHeight;\n this._scaledCharWidth = dim.scaledCharWidth;\n this._scaledCharHeight = dim.scaledCharHeight;\n this._scaledCharLeft = dim.scaledCharLeft;\n this._scaledCharTop = dim.scaledCharTop;\n this._canvas.width = dim.scaledCanvasWidth;\n this._canvas.height = dim.scaledCanvasHeight;\n this._canvas.style.width = `${dim.canvasWidth}px`;\n this._canvas.style.height = `${dim.canvasHeight}px`;\n\n // Draw the background if this is an opaque layer\n if (!this._alpha) {\n this.clearAll();\n }\n\n if (charSizeChanged) {\n this._refreshCharAtlas(terminal, this._colors);\n }\n }\n\n public abstract reset(terminal: ITerminal): void;\n\n /**\n * Fills 1+ cells completely. This uses the existing fillStyle on the context.\n * @param x The column to start at.\n * @param y The row to start at\n * @param width The number of columns to fill.\n * @param height The number of rows to fill.\n */\n protected fillCells(x: number, y: number, width: number, height: number): void {\n this._ctx.fillRect(\n x * this._scaledCellWidth,\n y * this._scaledCellHeight,\n width * this._scaledCellWidth,\n height * this._scaledCellHeight);\n }\n\n /**\n * Fills a 1px line (2px on HDPI) at the bottom of the cell. This uses the\n * existing fillStyle on the context.\n * @param x The column to fill.\n * @param y The row to fill.\n */\n protected fillBottomLineAtCells(x: number, y: number, width: number = 1): void {\n this._ctx.fillRect(\n x * this._scaledCellWidth,\n (y + 1) * this._scaledCellHeight - window.devicePixelRatio - 1 /* Ensure it's drawn within the cell */,\n width * this._scaledCellWidth,\n window.devicePixelRatio);\n }\n\n /**\n * Fills a 1px line (2px on HDPI) at the left of the cell. This uses the\n * existing fillStyle on the context.\n * @param x The column to fill.\n * @param y The row to fill.\n */\n protected fillLeftLineAtCell(x: number, y: number): void {\n this._ctx.fillRect(\n x * this._scaledCellWidth,\n y * this._scaledCellHeight,\n window.devicePixelRatio,\n this._scaledCellHeight);\n }\n\n /**\n * Strokes a 1px rectangle (2px on HDPI) around a cell. This uses the existing\n * strokeStyle on the context.\n * @param x The column to fill.\n * @param y The row to fill.\n */\n protected strokeRectAtCell(x: number, y: number, width: number, height: number): void {\n this._ctx.lineWidth = window.devicePixelRatio;\n this._ctx.strokeRect(\n x * this._scaledCellWidth + window.devicePixelRatio / 2,\n y * this._scaledCellHeight + (window.devicePixelRatio / 2),\n width * this._scaledCellWidth - window.devicePixelRatio,\n (height * this._scaledCellHeight) - window.devicePixelRatio);\n }\n\n /**\n * Clears the entire canvas.\n */\n protected clearAll(): void {\n if (this._alpha) {\n this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);\n } else {\n this._ctx.fillStyle = this._colors.background;\n this._ctx.fillRect(0, 0, this._canvas.width, this._canvas.height);\n }\n }\n\n /**\n * Clears 1+ cells completely.\n * @param x The column to start at.\n * @param y The row to start at.\n * @param width The number of columns to clear.\n * @param height The number of rows to clear.\n */\n protected clearCells(x: number, y: number, width: number, height: number): void {\n if (this._alpha) {\n this._ctx.clearRect(\n x * this._scaledCellWidth,\n y * this._scaledCellHeight,\n width * this._scaledCellWidth,\n height * this._scaledCellHeight);\n } else {\n this._ctx.fillStyle = this._colors.background;\n this._ctx.fillRect(\n x * this._scaledCellWidth,\n y * this._scaledCellHeight,\n width * this._scaledCellWidth,\n height * this._scaledCellHeight);\n }\n }\n\n /**\n * Draws a truecolor character at the cell. The character will be clipped to\n * ensure that it fits with the cell, including the cell to the right if it's\n * a wide character. This uses the existing fillStyle on the context.\n * @param terminal The terminal.\n * @param charData The char data for the character to draw.\n * @param x The column to draw at.\n * @param y The row to draw at.\n * @param color The color of the character.\n */\n protected fillCharTrueColor(terminal: ITerminal, charData: CharData, x: number, y: number): void {\n this._ctx.font = `${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`;\n this._ctx.textBaseline = 'top';\n this._clipRow(terminal, y);\n this._ctx.fillText(\n charData[CHAR_DATA_CHAR_INDEX],\n x * this._scaledCellWidth + this._scaledCharLeft,\n y * this._scaledCellHeight + this._scaledCharTop);\n }\n\n /**\n * Draws a character at a cell. If possible this will draw using the character\n * atlas to reduce draw time.\n * @param terminal The terminal.\n * @param char The character.\n * @param code The character code.\n * @param width The width of the character.\n * @param x The column to draw at.\n * @param y The row to draw at.\n * @param fg The foreground color, in the format stored within the attributes.\n * @param bg The background color, in the format stored within the attributes.\n * This is used to validate whether a cached image can be used.\n * @param bold Whether the text is bold.\n */\n protected drawChar(terminal: ITerminal, char: string, code: number, width: number, x: number, y: number, fg: number, bg: number, bold: boolean, dim: boolean): void {\n let colorIndex = 0;\n if (fg < 256) {\n colorIndex = fg + 2;\n } else {\n // If default color and bold\n if (bold && terminal.options.enableBold) {\n colorIndex = 1;\n }\n }\n const isAscii = code < 256;\n // A color is basic if it is one of the standard normal or bold weight\n // colors of the characters held in the char atlas. Note that this excludes\n // the normal weight _light_ color characters.\n const isBasicColor = (colorIndex > 1 && fg < 16) && (fg < 8 || bold);\n const isDefaultColor = fg >= 256;\n const isDefaultBackground = bg >= 256;\n if (this._charAtlas && isAscii && (isBasicColor || isDefaultColor) && isDefaultBackground) {\n // ImageBitmap's draw about twice as fast as from a canvas\n const charAtlasCellWidth = this._scaledCharWidth + CHAR_ATLAS_CELL_SPACING;\n const charAtlasCellHeight = this._scaledCharHeight + CHAR_ATLAS_CELL_SPACING;\n\n // Apply alpha to dim the character\n if (dim) {\n this._ctx.globalAlpha = DIM_OPACITY;\n }\n\n // Draw the non-bold version of the same color if bold is not enabled\n if (bold && !terminal.options.enableBold) {\n // Ignore default color as it's not touched above\n if (colorIndex > 1) {\n colorIndex -= 8;\n }\n }\n\n this._ctx.drawImage(this._charAtlas,\n code * charAtlasCellWidth,\n colorIndex * charAtlasCellHeight,\n charAtlasCellWidth,\n this._scaledCharHeight,\n x * this._scaledCellWidth + this._scaledCharLeft,\n y * this._scaledCellHeight + this._scaledCharTop,\n charAtlasCellWidth,\n this._scaledCharHeight);\n } else {\n this._drawUncachedChar(terminal, char, width, fg, x, y, bold, dim);\n }\n // This draws the atlas (for debugging purposes)\n // this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);\n // this._ctx.drawImage(this._charAtlas, 0, 0);\n }\n\n /**\n * Draws a character at a cell. The character will be clipped to\n * ensure that it fits with the cell, including the cell to the right if it's\n * a wide character.\n * @param terminal The terminal.\n * @param char The character.\n * @param width The width of the character.\n * @param fg The foreground color, in the format stored within the attributes.\n * @param x The column to draw at.\n * @param y The row to draw at.\n */\n private _drawUncachedChar(terminal: ITerminal, char: string, width: number, fg: number, x: number, y: number, bold: boolean, dim: boolean): void {\n this._ctx.save();\n this._ctx.font = `${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`;\n if (bold && terminal.options.enableBold) {\n this._ctx.font = `bold ${this._ctx.font}`;\n }\n this._ctx.textBaseline = 'top';\n\n if (fg === INVERTED_DEFAULT_COLOR) {\n this._ctx.fillStyle = this._colors.background;\n } else if (fg < 256) {\n // 256 color support\n this._ctx.fillStyle = this._colors.ansi[fg];\n } else {\n this._ctx.fillStyle = this._colors.foreground;\n }\n\n this._clipRow(terminal, y);\n\n // Apply alpha to dim the character\n if (dim) {\n this._ctx.globalAlpha = DIM_OPACITY;\n }\n // Draw the character\n this._ctx.fillText(\n char,\n x * this._scaledCellWidth + this._scaledCharLeft,\n y * this._scaledCellHeight + this._scaledCharTop);\n this._ctx.restore();\n }\n\n /**\n * Clips a row to ensure no pixels will be drawn outside the cells in the row.\n * @param terminal The terminal.\n * @param y The row to clip.\n */\n private _clipRow(terminal: ITerminal, y: number): void {\n this._ctx.beginPath();\n this._ctx.rect(\n 0,\n y * this._scaledCellHeight,\n terminal.cols * this._scaledCellWidth,\n this._scaledCellHeight);\n this._ctx.clip();\n }\n}\n\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IMouseZoneManager, IMouseZone } from './Interfaces';\nimport { ITerminal } from '../Interfaces';\n\nconst HOVER_DURATION = 500;\n\n/**\n * The MouseZoneManager allows components to register zones within the terminal\n * that trigger hover and click callbacks.\n *\n * This class was intentionally made not so robust initially as the only case it\n * needed to support was single-line links which never overlap. Improvements can\n * be made in the future.\n */\nexport class MouseZoneManager implements IMouseZoneManager {\n private _zones: IMouseZone[] = [];\n\n private _areZonesActive: boolean = false;\n private _mouseMoveListener: (e: MouseEvent) => any;\n private _clickListener: (e: MouseEvent) => any;\n\n private _tooltipTimeout: number = null;\n private _currentZone: IMouseZone = null;\n private _lastHoverCoords: [number, number] = [null, null];\n\n constructor(\n private _terminal: ITerminal\n ) {\n this._terminal.element.addEventListener('mousedown', e => this._onMouseDown(e));\n\n // These events are expensive, only listen to it when mouse zones are active\n this._mouseMoveListener = e => this._onMouseMove(e);\n this._clickListener = e => this._onClick(e);\n }\n\n public add(zone: IMouseZone): void {\n this._zones.push(zone);\n if (this._zones.length === 1) {\n this._activate();\n }\n }\n\n public clearAll(start?: number, end?: number): void {\n // Exit if there's nothing to clear\n if (this._zones.length === 0) {\n return;\n }\n\n // Clear all if start/end weren't set\n if (!end) {\n start = 0;\n end = this._terminal.rows - 1;\n }\n\n // Iterate through zones and clear them out if they're within the range\n for (let i = 0; i < this._zones.length; i++) {\n const zone = this._zones[i];\n if (zone.y > start && zone.y <= end + 1) {\n if (this._currentZone && this._currentZone === zone) {\n this._currentZone.leaveCallback();\n this._currentZone = null;\n }\n this._zones.splice(i--, 1);\n }\n }\n\n // Deactivate the mouse zone manager if all the zones have been removed\n if (this._zones.length === 0) {\n this._deactivate();\n }\n }\n\n private _activate(): void {\n if (!this._areZonesActive) {\n this._areZonesActive = true;\n this._terminal.element.addEventListener('mousemove', this._mouseMoveListener);\n this._terminal.element.addEventListener('click', this._clickListener);\n }\n }\n\n private _deactivate(): void {\n if (this._areZonesActive) {\n this._areZonesActive = false;\n this._terminal.element.removeEventListener('mousemove', this._mouseMoveListener);\n this._terminal.element.removeEventListener('click', this._clickListener);\n }\n }\n\n private _onMouseMove(e: MouseEvent): void {\n // TODO: Ideally this would only clear the hover state when the mouse moves\n // outside of the mouse zone\n if (this._lastHoverCoords[0] !== e.pageX || this._lastHoverCoords[1] !== e.pageY) {\n this._onHover(e);\n // Record the current coordinates\n this._lastHoverCoords = [e.pageX, e.pageY];\n }\n }\n\n private _onHover(e: MouseEvent): void {\n const zone = this._findZoneEventAt(e);\n\n // Do nothing if the zone is the same\n if (zone === this._currentZone) {\n return;\n }\n\n // Fire the hover end callback and cancel any existing timer if a new zone\n // is being hovered\n if (this._currentZone) {\n this._currentZone.leaveCallback();\n this._currentZone = null;\n if (this._tooltipTimeout) {\n clearTimeout(this._tooltipTimeout);\n }\n }\n\n // Exit if there is not zone\n if (!zone) {\n return;\n }\n this._currentZone = zone;\n\n // Trigger the hover callback\n if (zone.hoverCallback) {\n zone.hoverCallback(e);\n }\n\n // Restart the tooltip timeout\n this._tooltipTimeout = setTimeout(() => this._onTooltip(e), HOVER_DURATION);\n }\n\n private _onTooltip(e: MouseEvent): void {\n this._tooltipTimeout = null;\n const zone = this._findZoneEventAt(e);\n if (zone && zone.tooltipCallback) {\n zone.tooltipCallback(e);\n }\n }\n\n private _onMouseDown(e: MouseEvent): void {\n // Ignore the event if there are no zones active\n if (!this._areZonesActive) {\n return;\n }\n\n // Find the active zone, prevent event propagation if found to prevent other\n // components from handling the mouse event.\n const zone = this._findZoneEventAt(e);\n if (zone) {\n // TODO: When link modifier support is added, the event should only be\n // cancelled when the modifier is held (see #1021)\n e.preventDefault();\n e.stopImmediatePropagation();\n }\n }\n\n private _onClick(e: MouseEvent): void {\n // Find the active zone and click it if found\n const zone = this._findZoneEventAt(e);\n if (zone) {\n zone.clickCallback(e);\n e.preventDefault();\n e.stopImmediatePropagation();\n }\n }\n\n private _findZoneEventAt(e: MouseEvent): IMouseZone {\n const coords = this._terminal.mouseHelper.getCoords(e, this._terminal.element, this._terminal.charMeasure, this._terminal.options.lineHeight, this._terminal.cols, this._terminal.rows);\n if (!coords) {\n return null;\n }\n for (let i = 0; i < this._zones.length; i++) {\n const zone = this._zones[i];\n if (zone.y === coords[1] && zone.x1 <= coords[0] && zone.x2 > coords[0]) {\n return zone;\n }\n };\n return null;\n }\n}\n\nexport class MouseZone implements IMouseZone {\n constructor(\n public x1: number,\n public x2: number,\n public y: number,\n public clickCallback: (e: MouseEvent) => any,\n public hoverCallback?: (e: MouseEvent) => any,\n public tooltipCallback?: (e: MouseEvent) => any,\n public leaveCallback?: () => void\n ) {\n }\n}\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ITerminal, ISelectionManager } from '../Interfaces';\n\ninterface IWindow extends Window {\n clipboardData?: {\n getData(format: string): string;\n setData(format: string, data: string): void;\n };\n}\n\ndeclare var window: IWindow;\n\n/**\n * Prepares text to be pasted into the terminal by normalizing the line endings\n * @param text The pasted text that needs processing before inserting into the terminal\n */\nexport function prepareTextForTerminal(text: string, isMSWindows: boolean): string {\n if (isMSWindows) {\n return text.replace(/\\r?\\n/g, '\\r');\n }\n return text;\n}\n\n/**\n * Bracket text for paste, if necessary, as per https://cirw.in/blog/bracketed-paste\n * @param text The pasted text to bracket\n */\nexport function bracketTextForPaste(text: string, bracketedPasteMode: boolean): string {\n if (bracketedPasteMode) {\n return '\\x1b[200~' + text + '\\x1b[201~';\n }\n return text;\n}\n\n/**\n * Binds copy functionality to the given terminal.\n * @param {ClipboardEvent} ev The original copy event to be handled\n */\nexport function copyHandler(ev: ClipboardEvent, term: ITerminal, selectionManager: ISelectionManager): void {\n if (term.browser.isMSIE) {\n window.clipboardData.setData('Text', selectionManager.selectionText);\n } else {\n ev.clipboardData.setData('text/plain', selectionManager.selectionText);\n }\n\n // Prevent or the original text will be copied.\n ev.preventDefault();\n}\n\n/**\n * Redirect the clipboard's data to the terminal's input handler.\n * @param {ClipboardEvent} ev The original paste event to be handled\n * @param {Terminal} term The terminal on which to apply the handled paste event\n */\nexport function pasteHandler(ev: ClipboardEvent, term: ITerminal): void {\n ev.stopPropagation();\n\n let text: string;\n\n let dispatchPaste = function(text: string): void {\n text = prepareTextForTerminal(text, term.browser.isMSWindows);\n text = bracketTextForPaste(text, term.bracketedPasteMode);\n term.handler(text);\n term.textarea.value = '';\n term.emit('paste', text);\n term.cancel(ev);\n };\n\n if (term.browser.isMSIE) {\n if (window.clipboardData) {\n text = window.clipboardData.getData('Text');\n dispatchPaste(text);\n }\n } else {\n if (ev.clipboardData) {\n text = ev.clipboardData.getData('text/plain');\n dispatchPaste(text);\n }\n }\n}\n\n/**\n * Moves the textarea under the mouse cursor and focuses it.\n * @param ev The original right click event to be handled.\n * @param textarea The terminal's textarea.\n */\nexport function moveTextAreaUnderMouseCursor(ev: MouseEvent, textarea: HTMLTextAreaElement): void {\n // Bring textarea at the cursor position\n textarea.style.position = 'fixed';\n textarea.style.width = '20px';\n textarea.style.height = '20px';\n textarea.style.left = (ev.clientX - 10) + 'px';\n textarea.style.top = (ev.clientY - 10) + 'px';\n textarea.style.zIndex = '1000';\n\n textarea.focus();\n\n // Reset the terminal textarea's styling\n setTimeout(() => {\n textarea.style.position = null;\n textarea.style.width = null;\n textarea.style.height = null;\n textarea.style.left = null;\n textarea.style.top = null;\n textarea.style.zIndex = null;\n }, 4);\n}\n\n/**\n * Bind to right-click event and allow right-click copy and paste.\n * @param ev The original right click event to be handled.\n * @param textarea The terminal's textarea.\n * @param selectionManager The terminal's selection manager.\n */\nexport function rightClickHandler(ev: MouseEvent, textarea: HTMLTextAreaElement, selectionManager: ISelectionManager): void {\n moveTextAreaUnderMouseCursor(ev, textarea);\n\n // Get textarea ready to copy from the context menu\n textarea.value = selectionManager.selectionText;\n textarea.select();\n}\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ITerminal, IViewport } from './Interfaces';\nimport { CharMeasure } from './utils/CharMeasure';\nimport { IColorSet } from './renderer/Interfaces';\n\n/**\n * Represents the viewport of a terminal, the visible area within the larger buffer of output.\n * Logic for the virtual scroll bar is included in this object.\n */\nexport class Viewport implements IViewport {\n private currentRowHeight: number = 0;\n private lastRecordedBufferLength: number = 0;\n private lastRecordedViewportHeight: number = 0;\n private lastRecordedBufferHeight: number = 0;\n private lastTouchY: number;\n\n /**\n * Creates a new Viewport.\n * @param terminal The terminal this viewport belongs to.\n * @param viewportElement The DOM element acting as the viewport.\n * @param scrollArea The DOM element acting as the scroll area.\n * @param charMeasure A DOM element used to measure the character size of. the terminal.\n */\n constructor(\n private terminal: ITerminal,\n private viewportElement: HTMLElement,\n private scrollArea: HTMLElement,\n private charMeasure: CharMeasure\n ) {\n this.viewportElement.addEventListener('scroll', this.onScroll.bind(this));\n\n // Perform this async to ensure the CharMeasure is ready.\n setTimeout(() => this.syncScrollArea(), 0);\n }\n\n public onThemeChanged(colors: IColorSet): void {\n this.viewportElement.style.backgroundColor = colors.background;\n }\n\n /**\n * Refreshes row height, setting line-height, viewport height and scroll area height if\n * necessary.\n */\n private refresh(): void {\n if (this.charMeasure.height > 0) {\n this.currentRowHeight = this.terminal.renderer.dimensions.scaledCellHeight / window.devicePixelRatio;\n\n if (this.lastRecordedViewportHeight !== this.terminal.renderer.dimensions.canvasHeight) {\n this.lastRecordedViewportHeight = this.terminal.renderer.dimensions.canvasHeight;\n this.viewportElement.style.height = this.lastRecordedViewportHeight + 'px';\n }\n\n const newBufferHeight = Math.round(this.currentRowHeight * this.lastRecordedBufferLength);\n if (this.lastRecordedBufferHeight !== newBufferHeight) {\n this.lastRecordedBufferHeight = newBufferHeight;\n this.scrollArea.style.height = this.lastRecordedBufferHeight + 'px';\n }\n }\n }\n\n /**\n * Updates dimensions and synchronizes the scroll area if necessary.\n */\n public syncScrollArea(): void {\n if (this.lastRecordedBufferLength !== this.terminal.buffer.lines.length) {\n // If buffer height changed\n this.lastRecordedBufferLength = this.terminal.buffer.lines.length;\n this.refresh();\n } else if (this.lastRecordedViewportHeight !== (this.terminal).renderer.dimensions.canvasHeight) {\n // If viewport height changed\n this.refresh();\n } else {\n // If size has changed, refresh viewport\n if (this.terminal.renderer.dimensions.scaledCellHeight / window.devicePixelRatio !== this.currentRowHeight) {\n this.refresh();\n }\n }\n\n // Sync scrollTop\n const scrollTop = this.terminal.buffer.ydisp * this.currentRowHeight;\n if (this.viewportElement.scrollTop !== scrollTop) {\n this.viewportElement.scrollTop = scrollTop;\n }\n }\n\n /**\n * Handles scroll events on the viewport, calculating the new viewport and requesting the\n * terminal to scroll to it.\n * @param ev The scroll event.\n */\n private onScroll(ev: Event): void {\n const newRow = Math.round(this.viewportElement.scrollTop / this.currentRowHeight);\n const diff = newRow - this.terminal.buffer.ydisp;\n this.terminal.scrollLines(diff, true);\n }\n\n /**\n * Handles mouse wheel events by adjusting the viewport's scrollTop and delegating the actual\n * scrolling to `onScroll`, this event needs to be attached manually by the consumer of\n * `Viewport`.\n * @param ev The mouse wheel event.\n */\n public onWheel(ev: WheelEvent): void {\n if (ev.deltaY === 0) {\n // Do nothing if it's not a vertical scroll event\n return;\n }\n // Fallback to WheelEvent.DOM_DELTA_PIXEL\n let multiplier = 1;\n if (ev.deltaMode === WheelEvent.DOM_DELTA_LINE) {\n multiplier = this.currentRowHeight;\n } else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) {\n multiplier = this.currentRowHeight * this.terminal.rows;\n }\n this.viewportElement.scrollTop += ev.deltaY * multiplier;\n // Prevent the page from scrolling when the terminal scrolls\n ev.preventDefault();\n };\n\n /**\n * Handles the touchstart event, recording the touch occurred.\n * @param ev The touch event.\n */\n public onTouchStart(ev: TouchEvent): void {\n this.lastTouchY = ev.touches[0].pageY;\n };\n\n /**\n * Handles the touchmove event, scrolling the viewport if the position shifted.\n * @param ev The touch event.\n */\n public onTouchMove(ev: TouchEvent): void {\n let deltaY = this.lastTouchY - ev.touches[0].pageY;\n this.lastTouchY = ev.touches[0].pageY;\n if (deltaY === 0) {\n return;\n }\n this.viewportElement.scrollTop += deltaY;\n ev.preventDefault();\n };\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nexport type LinkMatcher = {\n id: number,\n regex: RegExp,\n handler: LinkMatcherHandler,\n hoverTooltipCallback?: LinkMatcherHandler,\n hoverLeaveCallback?: () => void,\n matchIndex?: number,\n validationCallback?: LinkMatcherValidationCallback,\n priority?: number\n};\nexport type LinkMatcherHandler = (event: MouseEvent, uri: string) => boolean | void;\nexport type LinkMatcherValidationCallback = (uri: string, callback: (isValid: boolean) => void) => void;\n\nexport type CustomKeyEventHandler = (event: KeyboardEvent) => boolean;\nexport type Charset = {[key: string]: string};\n\nexport type CharData = [number, string, number, number];\nexport type LineData = CharData[];\n\nexport type LinkHoverEvent = {\n x: number,\n y: number,\n length: number\n};\n\nexport enum LinkHoverEventTypes {\n HOVER = 'linkhover',\n TOOLTIP = 'linktooltip',\n LEAVE = 'linkleave'\n};\n","/**\n * Copyright (c) 2014 The xterm.js authors. All rights reserved.\n * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)\n * @license MIT\n *\n * Originally forked from (with the author's permission):\n * Fabrice Bellard's javascript vt100 for jslinux:\n * http://bellard.org/jslinux/\n * Copyright (c) 2011 Fabrice Bellard\n * The original design remains. The terminal itself\n * has been extended to include xterm CSI codes, among\n * other features.\n *\n * Terminal Emulation References:\n * http://vt100.net/\n * http://invisible-island.net/xterm/ctlseqs/ctlseqs.txt\n * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html\n * http://invisible-island.net/vttest/\n * http://www.inwap.com/pdp10/ansicode.txt\n * http://linux.die.net/man/4/console_codes\n * http://linux.die.net/man/7/urxvt\n */\n\nimport { BufferSet } from './BufferSet';\nimport { Buffer, MAX_BUFFER_SIZE } from './Buffer';\nimport { CompositionHelper } from './CompositionHelper';\nimport { EventEmitter } from './EventEmitter';\nimport { Viewport } from './Viewport';\nimport { rightClickHandler, moveTextAreaUnderMouseCursor, pasteHandler, copyHandler } from './handlers/Clipboard';\nimport { CircularList } from './utils/CircularList';\nimport { C0 } from './EscapeSequences';\nimport { InputHandler } from './InputHandler';\nimport { Parser } from './Parser';\nimport { Renderer } from './renderer/Renderer';\nimport { Linkifier } from './Linkifier';\nimport { SelectionManager } from './SelectionManager';\nimport { CharMeasure } from './utils/CharMeasure';\nimport * as Browser from './utils/Browser';\nimport { MouseHelper } from './utils/MouseHelper';\nimport { CHARSETS } from './Charsets';\nimport { CustomKeyEventHandler, Charset, LinkMatcherHandler, LinkMatcherValidationCallback, CharData, LineData } from './Types';\nimport { ITerminal, IBrowser, ITerminalOptions, IInputHandlingTerminal, ILinkMatcherOptions, IViewport, ICompositionHelper, ITheme, ILinkifier } from './Interfaces';\nimport { BellSound } from './utils/Sounds';\nimport { DEFAULT_ANSI_COLORS } from './renderer/ColorManager';\nimport { IMouseZoneManager } from './input/Interfaces';\nimport { MouseZoneManager } from './input/MouseZoneManager';\nimport { initialize as initializeCharAtlas } from './renderer/CharAtlas';\nimport { IRenderer } from './renderer/Interfaces';\n\n// Declares required for loadAddon\ndeclare var exports: any;\ndeclare var module: any;\ndeclare var define: any;\ndeclare var require: any;\n\n// Let it work inside Node.js for automated testing purposes.\nconst document = (typeof window !== 'undefined') ? window.document : null;\n\n/**\n * The amount of write requests to queue before sending an XOFF signal to the\n * pty process. This number must be small in order for ^C and similar sequences\n * to be responsive.\n */\nconst WRITE_BUFFER_PAUSE_THRESHOLD = 5;\n\n/**\n * The number of writes to perform in a single batch before allowing the\n * renderer to catch up with a 0ms setTimeout.\n */\nconst WRITE_BATCH_SIZE = 300;\n\nconst DEFAULT_OPTIONS: ITerminalOptions = {\n convertEol: false,\n termName: 'xterm',\n geometry: [80, 24],\n cursorBlink: false,\n cursorStyle: 'block',\n bellSound: BellSound,\n bellStyle: 'none',\n enableBold: true,\n fontFamily: 'courier-new, courier, monospace',\n fontSize: 15,\n lineHeight: 1.0,\n letterSpacing: 0,\n scrollback: 1000,\n screenKeys: false,\n debug: false,\n cancelEvents: false,\n disableStdin: false,\n useFlowControl: false,\n tabStopWidth: 8,\n theme: null\n // programFeatures: false,\n // focusKeys: false,\n};\n\nexport class Terminal extends EventEmitter implements ITerminal, IInputHandlingTerminal {\n public textarea: HTMLTextAreaElement;\n public element: HTMLElement;\n\n /**\n * The HTMLElement that the terminal is created in, set by Terminal.open.\n */\n private parent: HTMLElement;\n private context: Window;\n private document: Document;\n private body: HTMLBodyElement;\n private viewportScrollArea: HTMLElement;\n private viewportElement: HTMLElement;\n private helperContainer: HTMLElement;\n private compositionView: HTMLElement;\n private charSizeStyleElement: HTMLStyleElement;\n private bellAudioElement: HTMLAudioElement;\n private visualBellTimer: number;\n\n public browser: IBrowser = Browser;\n\n public options: ITerminalOptions;\n private colors: any;\n\n // TODO: This can be changed to an enum or boolean, 0 and 1 seem to be the only options\n public cursorState: number;\n public cursorHidden: boolean;\n public convertEol: boolean;\n\n private sendDataQueue: string;\n private customKeyEventHandler: CustomKeyEventHandler;\n\n // modes\n public applicationKeypad: boolean;\n public applicationCursor: boolean;\n public originMode: boolean;\n public insertMode: boolean;\n public wraparoundMode: boolean; // defaults: xterm - true, vt100 - false\n public bracketedPasteMode: boolean;\n\n // charset\n // The current charset\n public charset: Charset;\n public gcharset: number;\n public glevel: number;\n public charsets: Charset[];\n\n // mouse properties\n private decLocator: boolean; // This is unstable and never set\n public x10Mouse: boolean;\n public vt200Mouse: boolean;\n private vt300Mouse: boolean; // This is unstable and never set\n public normalMouse: boolean;\n public mouseEvents: boolean;\n public sendFocus: boolean;\n public utfMouse: boolean;\n public sgrMouse: boolean;\n public urxvtMouse: boolean;\n\n // misc\n private refreshStart: number;\n private refreshEnd: number;\n public savedCols: number;\n\n // stream\n private readable: boolean;\n private writable: boolean;\n\n public defAttr: number;\n public curAttr: number;\n\n public params: (string | number)[];\n public currentParam: string | number;\n public prefix: string;\n public postfix: string;\n\n // user input states\n public writeBuffer: string[];\n private writeInProgress: boolean;\n\n /**\n * Whether _xterm.js_ sent XOFF in order to catch up with the pty process.\n * This is a distinct state from writeStopped so that if the user requested\n * XOFF via ^S that it will not automatically resume when the writeBuffer goes\n * below threshold.\n */\n private xoffSentToCatchUp: boolean;\n\n /** Whether writing has been stopped as a result of XOFF */\n private writeStopped: boolean;\n\n // leftover surrogate high from previous write invocation\n private surrogate_high: string;\n\n // Store if user went browsing history in scrollback\n private userScrolling: boolean;\n\n private inputHandler: InputHandler;\n private parser: Parser;\n public renderer: IRenderer;\n public selectionManager: SelectionManager;\n public linkifier: ILinkifier;\n public buffers: BufferSet;\n public buffer: Buffer;\n public viewport: IViewport;\n private compositionHelper: ICompositionHelper;\n public charMeasure: CharMeasure;\n private _mouseZoneManager: IMouseZoneManager;\n public mouseHelper: MouseHelper;\n\n public cols: number;\n public rows: number;\n public geometry: [/*cols*/number, /*rows*/number];\n\n /**\n * Creates a new `Terminal` object.\n *\n * @param {object} options An object containing a set of options, the available options are:\n * - `cursorBlink` (boolean): Whether the terminal cursor blinks\n * - `cols` (number): The number of columns of the terminal (horizontal size)\n * - `rows` (number): The number of rows of the terminal (vertical size)\n *\n * @public\n * @class Xterm Xterm\n * @alias module:xterm/src/xterm\n */\n constructor(\n options: ITerminalOptions = {}\n ) {\n super();\n this.options = options;\n this.setup();\n }\n\n private setup(): void {\n Object.keys(DEFAULT_OPTIONS).forEach((key) => {\n if (this.options[key] == null) {\n this.options[key] = DEFAULT_OPTIONS[key];\n }\n // TODO: We should move away from duplicate options on the Terminal object\n this[key] = this.options[key];\n });\n\n // this.context = options.context || window;\n // this.document = options.document || document;\n // TODO: WHy not document.body?\n this.parent = document ? document.body : null;\n\n this.cols = this.options.cols || this.options.geometry[0];\n this.rows = this.options.rows || this.options.geometry[1];\n this.geometry = [this.cols, this.rows];\n\n if (this.options.handler) {\n this.on('data', this.options.handler);\n }\n\n this.cursorState = 0;\n this.cursorHidden = false;\n this.sendDataQueue = '';\n this.customKeyEventHandler = null;\n\n // modes\n this.applicationKeypad = false;\n this.applicationCursor = false;\n this.originMode = false;\n this.insertMode = false;\n this.wraparoundMode = true; // defaults: xterm - true, vt100 - false\n this.bracketedPasteMode = false;\n\n // charset\n this.charset = null;\n this.gcharset = null;\n this.glevel = 0;\n // TODO: Can this be just []?\n this.charsets = [null];\n\n this.readable = true;\n this.writable = true;\n\n this.defAttr = (0 << 18) | (257 << 9) | (256 << 0);\n this.curAttr = (0 << 18) | (257 << 9) | (256 << 0);\n\n this.params = [];\n this.currentParam = 0;\n this.prefix = '';\n this.postfix = '';\n\n // user input states\n this.writeBuffer = [];\n this.writeInProgress = false;\n\n this.xoffSentToCatchUp = false;\n this.writeStopped = false;\n this.surrogate_high = '';\n this.userScrolling = false;\n\n this.inputHandler = new InputHandler(this);\n this.parser = new Parser(this.inputHandler, this);\n // Reuse renderer if the Terminal is being recreated via a reset call.\n this.renderer = this.renderer || null;\n this.selectionManager = this.selectionManager || null;\n this.linkifier = this.linkifier || new Linkifier(this);\n this._mouseZoneManager = this._mouseZoneManager || null;\n\n // Create the terminal's buffers and set the current buffer\n this.buffers = new BufferSet(this);\n this.buffer = this.buffers.active; // Convenience shortcut;\n this.buffers.on('activate', (buffer: Buffer) => {\n this.buffer = buffer;\n });\n\n // Ensure the selection manager has the correct buffer\n if (this.selectionManager) {\n this.selectionManager.setBuffer(this.buffer);\n }\n }\n\n /**\n * back_color_erase feature for xterm.\n */\n public eraseAttr(): number {\n // if (this.is('screen')) return this.defAttr;\n return (this.defAttr & ~0x1ff) | (this.curAttr & 0x1ff);\n }\n\n /**\n * Focus the terminal. Delegates focus handling to the terminal's DOM element.\n */\n public focus(): void {\n this.textarea.focus();\n }\n\n public get isFocused(): boolean {\n return document.activeElement === this.textarea;\n }\n\n /**\n * Retrieves an option's value from the terminal.\n * @param {string} key The option key.\n */\n public getOption(key: string): any {\n if (!(key in DEFAULT_OPTIONS)) {\n throw new Error('No option with key \"' + key + '\"');\n }\n\n if (typeof this.options[key] !== 'undefined') {\n return this.options[key];\n }\n\n return this[key];\n }\n\n /**\n * Sets an option on the terminal.\n * @param {string} key The option key.\n * @param {any} value The option value.\n */\n public setOption(key: string, value: any): void {\n if (!(key in DEFAULT_OPTIONS)) {\n throw new Error('No option with key \"' + key + '\"');\n }\n switch (key) {\n case 'bellStyle':\n if (!value) {\n value = 'none';\n }\n break;\n case 'cursorStyle':\n if (!value) {\n value = 'block';\n }\n break;\n case 'lineHeight':\n if (value < 1) {\n console.warn(`${key} cannot be less than 1, value: ${value}`);\n return;\n }\n case 'tabStopWidth':\n if (value < 1) {\n console.warn(`${key} cannot be less than 1, value: ${value}`);\n return;\n }\n break;\n case 'theme':\n // If open has been called we do not want to set options.theme as the\n // source of truth is owned by the renderer.\n if (this.renderer) {\n this._setTheme(value);\n return;\n }\n break;\n case 'scrollback':\n value = Math.min(value, MAX_BUFFER_SIZE);\n\n if (value < 0) {\n console.warn(`${key} cannot be less than 0, value: ${value}`);\n return;\n }\n if (this.options[key] !== value) {\n const newBufferLength = this.rows + value;\n if (this.buffer.lines.length > newBufferLength) {\n const amountToTrim = this.buffer.lines.length - newBufferLength;\n const needsRefresh = (this.buffer.ydisp - amountToTrim < 0);\n this.buffer.lines.trimStart(amountToTrim);\n this.buffer.ybase = Math.max(this.buffer.ybase - amountToTrim, 0);\n this.buffer.ydisp = Math.max(this.buffer.ydisp - amountToTrim, 0);\n if (needsRefresh) {\n this.refresh(0, this.rows - 1);\n }\n }\n }\n break;\n }\n this[key] = value;\n this.options[key] = value;\n switch (key) {\n case 'fontFamily':\n case 'fontSize':\n // When the font changes the size of the cells may change which requires a renderer clear\n this.renderer.clear();\n this.charMeasure.measure(this.options);\n break;\n case 'enableBold':\n case 'letterSpacing':\n case 'lineHeight':\n // When the font changes the size of the cells may change which requires a renderer clear\n this.renderer.clear();\n this.renderer.onResize(this.cols, this.rows, false);\n this.refresh(0, this.rows - 1);\n // this.charMeasure.measure(this.options);\n case 'scrollback':\n this.buffers.resize(this.cols, this.rows);\n this.viewport.syncScrollArea();\n break;\n case 'tabStopWidth': this.buffers.setupTabStops(); break;\n case 'bellSound':\n case 'bellStyle': this.syncBellSound(); break;\n }\n // Inform renderer of changes\n if (this.renderer) {\n this.renderer.onOptionsChanged();\n }\n }\n\n /**\n * Binds the desired focus behavior on a given terminal object.\n */\n private _onTextAreaFocus(): void {\n if (this.sendFocus) {\n this.send(C0.ESC + '[I');\n }\n this.element.classList.add('focus');\n this.showCursor();\n this.emit('focus');\n };\n\n /**\n * Blur the terminal, calling the blur function on the terminal's underlying\n * textarea.\n */\n public blur(): void {\n return this.textarea.blur();\n }\n\n /**\n * Binds the desired blur behavior on a given terminal object.\n */\n private _onTextAreaBlur(): void {\n this.refresh(this.buffer.y, this.buffer.y);\n if (this.sendFocus) {\n this.send(C0.ESC + '[O');\n }\n this.element.classList.remove('focus');\n this.emit('blur');\n }\n\n /**\n * Initialize default behavior\n */\n private initGlobal(): void {\n this.bindKeys();\n\n // Bind clipboard functionality\n on(this.element, 'copy', (event: ClipboardEvent) => {\n // If mouse events are active it means the selection manager is disabled and\n // copy should be handled by the host program.\n if (!this.hasSelection()) {\n return;\n }\n copyHandler(event, this, this.selectionManager);\n });\n const pasteHandlerWrapper = event => pasteHandler(event, this);\n on(this.textarea, 'paste', pasteHandlerWrapper);\n on(this.element, 'paste', pasteHandlerWrapper);\n\n // Handle right click context menus\n if (Browser.isFirefox) {\n // Firefox doesn't appear to fire the contextmenu event on right click\n on(this.element, 'mousedown', (event: MouseEvent) => {\n if (event.button === 2) {\n rightClickHandler(event, this.textarea, this.selectionManager);\n }\n });\n } else {\n on(this.element, 'contextmenu', (event: MouseEvent) => {\n rightClickHandler(event, this.textarea, this.selectionManager);\n });\n }\n\n // Move the textarea under the cursor when middle clicking on Linux to ensure\n // middle click to paste selection works. This only appears to work in Chrome\n // at the time is writing.\n if (Browser.isLinux) {\n // Use auxclick event over mousedown the latter doesn't seem to work. Note\n // that the regular click event doesn't fire for the middle mouse button.\n on(this.element, 'auxclick', (event: MouseEvent) => {\n if (event.button === 1) {\n moveTextAreaUnderMouseCursor(event, this.textarea);\n }\n });\n }\n }\n\n /**\n * Apply key handling to the terminal\n */\n private bindKeys(): void {\n const self = this;\n on(this.element, 'keydown', function (ev: KeyboardEvent): void {\n if (document.activeElement !== this) {\n return;\n }\n self._keyDown(ev);\n }, true);\n\n on(this.element, 'keypress', function (ev: KeyboardEvent): void {\n if (document.activeElement !== this) {\n return;\n }\n self._keyPress(ev);\n }, true);\n\n on(this.element, 'keyup', (ev: KeyboardEvent) => {\n if (!wasMondifierKeyOnlyEvent(ev)) {\n this.focus();\n }\n }, true);\n\n on(this.textarea, 'keydown', (ev: KeyboardEvent) => {\n this._keyDown(ev);\n }, true);\n\n on(this.textarea, 'keypress', (ev: KeyboardEvent) => {\n this._keyPress(ev);\n // Truncate the textarea's value, since it is not needed\n this.textarea.value = '';\n }, true);\n\n on(this.textarea, 'compositionstart', () => this.compositionHelper.compositionstart());\n on(this.textarea, 'compositionupdate', (e: CompositionEvent) => this.compositionHelper.compositionupdate(e));\n on(this.textarea, 'compositionend', () => this.compositionHelper.compositionend());\n this.on('refresh', () => this.compositionHelper.updateCompositionElements());\n this.on('refresh', (data) => this.queueLinkification(data.start, data.end));\n }\n\n /**\n * Opens the terminal within an element.\n *\n * @param {HTMLElement} parent The element to create the terminal within.\n */\n public open(parent: HTMLElement): void {\n let i = 0;\n let div;\n\n this.parent = parent || this.parent;\n\n if (!this.parent) {\n throw new Error('Terminal requires a parent element.');\n }\n\n // Grab global elements\n this.context = this.parent.ownerDocument.defaultView;\n this.document = this.parent.ownerDocument;\n this.body = this.document.body;\n\n initializeCharAtlas(this.document);\n\n // Create main element container\n this.element = this.document.createElement('div');\n this.element.classList.add('terminal');\n this.element.classList.add('xterm');\n\n this.element.setAttribute('tabindex', '0');\n\n this.viewportElement = document.createElement('div');\n this.viewportElement.classList.add('xterm-viewport');\n this.element.appendChild(this.viewportElement);\n this.viewportScrollArea = document.createElement('div');\n this.viewportScrollArea.classList.add('xterm-scroll-area');\n this.viewportElement.appendChild(this.viewportScrollArea);\n\n // preload audio\n this.syncBellSound();\n\n this._mouseZoneManager = new MouseZoneManager(this);\n this.on('scroll', () => this._mouseZoneManager.clearAll());\n this.linkifier.attachToDom(this._mouseZoneManager);\n\n // Create the container that will hold helpers like the textarea for\n // capturing DOM Events. Then produce the helpers.\n this.helperContainer = document.createElement('div');\n this.helperContainer.classList.add('xterm-helpers');\n // TODO: This should probably be inserted once it's filled to prevent an additional layout\n this.element.appendChild(this.helperContainer);\n this.textarea = document.createElement('textarea');\n this.textarea.classList.add('xterm-helper-textarea');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.tabIndex = 0;\n this.textarea.addEventListener('focus', () => this._onTextAreaFocus());\n this.textarea.addEventListener('blur', () => this._onTextAreaBlur());\n this.helperContainer.appendChild(this.textarea);\n\n this.compositionView = document.createElement('div');\n this.compositionView.classList.add('composition-view');\n this.compositionHelper = new CompositionHelper(this.textarea, this.compositionView, this);\n this.helperContainer.appendChild(this.compositionView);\n\n this.charSizeStyleElement = document.createElement('style');\n this.helperContainer.appendChild(this.charSizeStyleElement);\n\n this.parent.appendChild(this.element);\n\n this.charMeasure = new CharMeasure(document, this.helperContainer);\n\n this.renderer = new Renderer(this, this.options.theme);\n this.options.theme = null;\n this.viewport = new Viewport(this, this.viewportElement, this.viewportScrollArea, this.charMeasure);\n this.viewport.onThemeChanged(this.renderer.colorManager.colors);\n\n this.on('cursormove', () => this.renderer.onCursorMove());\n this.on('resize', () => this.renderer.onResize(this.cols, this.rows, false));\n this.on('blur', () => this.renderer.onBlur());\n this.on('focus', () => this.renderer.onFocus());\n window.addEventListener('resize', () => this.renderer.onWindowResize(window.devicePixelRatio));\n this.charMeasure.on('charsizechanged', () => this.renderer.onResize(this.cols, this.rows, true));\n this.renderer.on('resize', (dimensions) => this.viewport.syncScrollArea());\n\n this.selectionManager = new SelectionManager(this, this.buffer, this.charMeasure);\n this.element.addEventListener('mousedown', (e: MouseEvent) => this.selectionManager.onMouseDown(e));\n this.selectionManager.on('refresh', data => this.renderer.onSelectionChanged(data.start, data.end));\n this.selectionManager.on('newselection', text => {\n // If there's a new selection, put it into the textarea, focus and select it\n // in order to register it as a selection on the OS. This event is fired\n // only on Linux to enable middle click to paste selection.\n this.textarea.value = text;\n this.textarea.focus();\n this.textarea.select();\n });\n this.on('scroll', () => {\n this.viewport.syncScrollArea();\n this.selectionManager.refresh();\n });\n this.viewportElement.addEventListener('scroll', () => this.selectionManager.refresh());\n\n this.mouseHelper = new MouseHelper(this.renderer);\n\n // Measure the character size\n this.charMeasure.measure(this.options);\n\n // Setup loop that draws to screen\n this.refresh(0, this.rows - 1);\n\n // Initialize global actions that need to be taken on the document.\n this.initGlobal();\n\n // Listen for mouse events and translate\n // them into terminal mouse protocols.\n this.bindMouse();\n }\n\n /**\n * Sets the theme on the renderer. The renderer must have been initialized.\n * @param theme The theme to ste.\n */\n private _setTheme(theme: ITheme): void {\n const colors = this.renderer.setTheme(theme);\n if (this.viewport) {\n this.viewport.onThemeChanged(colors);\n }\n }\n\n /**\n * Attempts to load an add-on using CommonJS or RequireJS (whichever is available).\n * @param {string} addon The name of the addon to load\n * @static\n */\n public static loadAddon(addon: string, callback?: Function): boolean | any {\n // TODO: Improve return type and documentation\n if (typeof exports === 'object' && typeof module === 'object') {\n // CommonJS\n return require('./addons/' + addon + '/' + addon);\n } else if (typeof define === 'function') {\n // RequireJS\n return (require)(['./addons/' + addon + '/' + addon], callback);\n } else {\n console.error('Cannot load a module without a CommonJS or RequireJS environment.');\n return false;\n }\n }\n\n /**\n * XTerm mouse events\n * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#Mouse%20Tracking\n * To better understand these\n * the xterm code is very helpful:\n * Relevant files:\n * button.c, charproc.c, misc.c\n * Relevant functions in xterm/button.c:\n * BtnCode, EmitButtonCode, EditorButton, SendMousePosition\n */\n public bindMouse(): void {\n const el = this.element;\n const self = this;\n let pressed = 32;\n\n // mouseup, mousedown, wheel\n // left click: ^[[M 3<^[[M#3<\n // wheel up: ^[[M`3>\n function sendButton(ev: MouseEvent | WheelEvent): void {\n let button;\n let pos;\n\n // get the xterm-style button\n button = getButton(ev);\n\n // get mouse coordinates\n pos = self.mouseHelper.getRawByteCoords(ev, self.element, self.charMeasure, self.options.lineHeight, self.cols, self.rows);\n if (!pos) return;\n\n sendEvent(button, pos);\n\n switch ((ev).overrideType || ev.type) {\n case 'mousedown':\n pressed = button;\n break;\n case 'mouseup':\n // keep it at the left\n // button, just in case.\n pressed = 32;\n break;\n case 'wheel':\n // nothing. don't\n // interfere with\n // `pressed`.\n break;\n }\n }\n\n // motion example of a left click:\n // ^[[M 3<^[[M@4<^[[M@5<^[[M@6<^[[M@7<^[[M#7<\n function sendMove(ev: MouseEvent): void {\n let button = pressed;\n let pos = self.mouseHelper.getRawByteCoords(ev, self.element, self.charMeasure, self.options.lineHeight, self.cols, self.rows);\n if (!pos) return;\n\n // buttons marked as motions\n // are incremented by 32\n button += 32;\n\n sendEvent(button, pos);\n }\n\n // encode button and\n // position to characters\n function encode(data: number[], ch: number): void {\n if (!self.utfMouse) {\n if (ch === 255) {\n data.push(0);\n return;\n }\n if (ch > 127) ch = 127;\n data.push(ch);\n } else {\n if (ch === 2047) {\n data.push(0);\n return;\n }\n if (ch < 127) {\n data.push(ch);\n } else {\n if (ch > 2047) ch = 2047;\n data.push(0xC0 | (ch >> 6));\n data.push(0x80 | (ch & 0x3F));\n }\n }\n }\n\n // send a mouse event:\n // regular/utf8: ^[[M Cb Cx Cy\n // urxvt: ^[[ Cb ; Cx ; Cy M\n // sgr: ^[[ Cb ; Cx ; Cy M/m\n // vt300: ^[[ 24(1/3/5)~ [ Cx , Cy ] \\r\n // locator: CSI P e ; P b ; P r ; P c ; P p & w\n function sendEvent(button: number, pos: {x: number, y: number}): void {\n // self.emit('mouse', {\n // x: pos.x - 32,\n // y: pos.x - 32,\n // button: button\n // });\n\n if (self.vt300Mouse) {\n // NOTE: Unstable.\n // http://www.vt100.net/docs/vt3xx-gp/chapter15.html\n button &= 3;\n pos.x -= 32;\n pos.y -= 32;\n let data = C0.ESC + '[24';\n if (button === 0) data += '1';\n else if (button === 1) data += '3';\n else if (button === 2) data += '5';\n else if (button === 3) return;\n else data += '0';\n data += '~[' + pos.x + ',' + pos.y + ']\\r';\n self.send(data);\n return;\n }\n\n if (self.decLocator) {\n // NOTE: Unstable.\n button &= 3;\n pos.x -= 32;\n pos.y -= 32;\n if (button === 0) button = 2;\n else if (button === 1) button = 4;\n else if (button === 2) button = 6;\n else if (button === 3) button = 3;\n self.send(C0.ESC + '['\n + button\n + ';'\n + (button === 3 ? 4 : 0)\n + ';'\n + pos.y\n + ';'\n + pos.x\n + ';'\n // Not sure what page is meant to be\n + (pos).page || 0\n + '&w');\n return;\n }\n\n if (self.urxvtMouse) {\n pos.x -= 32;\n pos.y -= 32;\n pos.x++;\n pos.y++;\n self.send(C0.ESC + '[' + button + ';' + pos.x + ';' + pos.y + 'M');\n return;\n }\n\n if (self.sgrMouse) {\n pos.x -= 32;\n pos.y -= 32;\n self.send(C0.ESC + '[<'\n + (((button & 3) === 3 ? button & ~3 : button) - 32)\n + ';'\n + pos.x\n + ';'\n + pos.y\n + ((button & 3) === 3 ? 'm' : 'M'));\n return;\n }\n\n let data: number[] = [];\n\n encode(data, button);\n encode(data, pos.x);\n encode(data, pos.y);\n\n self.send(C0.ESC + '[M' + String.fromCharCode.apply(String, data));\n }\n\n function getButton(ev: MouseEvent): number {\n let button;\n let shift;\n let meta;\n let ctrl;\n let mod;\n\n // two low bits:\n // 0 = left\n // 1 = middle\n // 2 = right\n // 3 = release\n // wheel up/down:\n // 1, and 2 - with 64 added\n switch ((ev).overrideType || ev.type) {\n case 'mousedown':\n button = ev.button != null\n ? +ev.button\n : ev.which != null\n ? ev.which - 1\n : null;\n\n if (Browser.isMSIE) {\n button = button === 1 ? 0 : button === 4 ? 1 : button;\n }\n break;\n case 'mouseup':\n button = 3;\n break;\n case 'DOMMouseScroll':\n button = ev.detail < 0\n ? 64\n : 65;\n break;\n case 'wheel':\n button = (ev).wheelDeltaY > 0\n ? 64\n : 65;\n break;\n }\n\n // next three bits are the modifiers:\n // 4 = shift, 8 = meta, 16 = control\n shift = ev.shiftKey ? 4 : 0;\n meta = ev.metaKey ? 8 : 0;\n ctrl = ev.ctrlKey ? 16 : 0;\n mod = shift | meta | ctrl;\n\n // no mods\n if (self.vt200Mouse) {\n // ctrl only\n mod &= ctrl;\n } else if (!self.normalMouse) {\n mod = 0;\n }\n\n // increment to SP\n button = (32 + (mod << 2)) + button;\n\n return button;\n }\n\n on(el, 'mousedown', (ev: MouseEvent) => {\n\n // Prevent the focus on the textarea from getting lost\n // and make sure we get focused on mousedown\n ev.preventDefault();\n this.focus();\n\n // Don't send the mouse button to the pty if mouse events are disabled or\n // if the selection manager is having selection forced (ie. a modifier is\n // held).\n if (!this.mouseEvents || this.selectionManager.shouldForceSelection(ev)) {\n return;\n }\n\n // send the button\n sendButton(ev);\n\n // fix for odd bug\n // if (this.vt200Mouse && !this.normalMouse) {\n if (this.vt200Mouse) {\n (ev).overrideType = 'mouseup';\n sendButton(ev);\n return this.cancel(ev);\n }\n\n // bind events\n if (this.normalMouse) on(this.document, 'mousemove', sendMove);\n\n // x10 compatibility mode can't send button releases\n if (!this.x10Mouse) {\n const handler = (ev: MouseEvent) => {\n sendButton(ev);\n // TODO: Seems dangerous calling this on document?\n if (this.normalMouse) off(this.document, 'mousemove', sendMove);\n off(this.document, 'mouseup', handler);\n return this.cancel(ev);\n };\n // TODO: Seems dangerous calling this on document?\n on(this.document, 'mouseup', handler);\n }\n\n return this.cancel(ev);\n });\n\n // if (this.normalMouse) {\n // on(this.document, 'mousemove', sendMove);\n // }\n\n on(el, 'wheel', (ev: WheelEvent) => {\n if (!this.mouseEvents) return;\n if (this.x10Mouse || this.vt300Mouse || this.decLocator) return;\n sendButton(ev);\n ev.preventDefault();\n });\n\n // allow wheel scrolling in\n // the shell for example\n on(el, 'wheel', (ev: WheelEvent) => {\n if (this.mouseEvents) return;\n this.viewport.onWheel(ev);\n return this.cancel(ev);\n });\n\n on(el, 'touchstart', (ev: TouchEvent) => {\n if (this.mouseEvents) return;\n this.viewport.onTouchStart(ev);\n return this.cancel(ev);\n });\n\n on(el, 'touchmove', (ev: TouchEvent) => {\n if (this.mouseEvents) return;\n this.viewport.onTouchMove(ev);\n return this.cancel(ev);\n });\n }\n\n /**\n * Destroys the terminal.\n */\n public destroy(): void {\n super.destroy();\n this.readable = false;\n this.writable = false;\n this.handler = () => {};\n this.write = () => {};\n if (this.element && this.element.parentNode) {\n this.element.parentNode.removeChild(this.element);\n }\n // this.emit('close');\n }\n\n /**\n * Tells the renderer to refresh terminal content between two rows (inclusive) at the next\n * opportunity.\n * @param {number} start The row to start from (between 0 and this.rows - 1).\n * @param {number} end The row to end at (between start and this.rows - 1).\n */\n public refresh(start: number, end: number): void {\n if (this.renderer) {\n this.renderer.queueRefresh(start, end);\n }\n }\n\n /**\n * Queues linkification for the specified rows.\n * @param {number} start The row to start from (between 0 and this.rows - 1).\n * @param {number} end The row to end at (between start and this.rows - 1).\n */\n private queueLinkification(start: number, end: number): void {\n if (this.linkifier) {\n this.linkifier.linkifyRows(start, end);\n }\n }\n\n /**\n * Display the cursor element\n */\n public showCursor(): void {\n if (!this.cursorState) {\n this.cursorState = 1;\n this.refresh(this.buffer.y, this.buffer.y);\n }\n }\n\n /**\n * Scroll the terminal down 1 row, creating a blank line.\n * @param isWrapped Whether the new line is wrapped from the previous line.\n */\n public scroll(isWrapped?: boolean): void {\n const newLine = this.blankLine(undefined, isWrapped);\n const topRow = this.buffer.ybase + this.buffer.scrollTop;\n let bottomRow = this.buffer.ybase + this.buffer.scrollBottom;\n\n if (this.buffer.scrollTop === 0) {\n // Determine whether the buffer is going to be trimmed after insertion.\n const willBufferBeTrimmed = this.buffer.lines.length === this.buffer.lines.maxLength;\n\n // Insert the line using the fastest method\n if (bottomRow === this.buffer.lines.length - 1) {\n this.buffer.lines.push(newLine);\n } else {\n this.buffer.lines.splice(bottomRow + 1, 0, newLine);\n }\n\n // Only adjust ybase and ydisp when the buffer is not trimmed\n if (!willBufferBeTrimmed) {\n this.buffer.ybase++;\n // Only scroll the ydisp with ybase if the user has not scrolled up\n if (!this.userScrolling) {\n this.buffer.ydisp++;\n }\n } else {\n // When the buffer is full and the user has scrolled up, keep the text\n // stable unless ydisp is right at the top\n if (this.userScrolling) {\n this.buffer.ydisp = Math.max(this.buffer.ydisp - 1, 0);\n }\n }\n } else {\n // scrollTop is non-zero which means no line will be going to the\n // scrollback, instead we can just shift them in-place.\n const scrollRegionHeight = bottomRow - topRow + 1/*as it's zero-based*/;\n this.buffer.lines.shiftElements(topRow + 1, scrollRegionHeight - 1, -1);\n this.buffer.lines.set(bottomRow, newLine);\n }\n\n // Move the viewport to the bottom of the buffer unless the user is\n // scrolling.\n if (!this.userScrolling) {\n this.buffer.ydisp = this.buffer.ybase;\n }\n\n // Flag rows that need updating\n this.updateRange(this.buffer.scrollTop);\n this.updateRange(this.buffer.scrollBottom);\n\n /**\n * This event is emitted whenever the terminal is scrolled.\n * The one parameter passed is the new y display position.\n *\n * @event scroll\n */\n this.emit('scroll', this.buffer.ydisp);\n }\n\n /**\n * Scroll the display of the terminal\n * @param {number} disp The number of lines to scroll down (negative scroll up).\n * @param {boolean} suppressScrollEvent Don't emit the scroll event as scrollLines. This is used\n * to avoid unwanted events being handled by the viewport when the event was triggered from the\n * viewport originally.\n */\n public scrollLines(disp: number, suppressScrollEvent?: boolean): void {\n if (disp < 0) {\n if (this.buffer.ydisp === 0) {\n return;\n }\n this.userScrolling = true;\n } else if (disp + this.buffer.ydisp >= this.buffer.ybase) {\n this.userScrolling = false;\n }\n\n const oldYdisp = this.buffer.ydisp;\n this.buffer.ydisp = Math.max(Math.min(this.buffer.ydisp + disp, this.buffer.ybase), 0);\n\n // No change occurred, don't trigger scroll/refresh\n if (oldYdisp === this.buffer.ydisp) {\n return;\n }\n\n if (!suppressScrollEvent) {\n this.emit('scroll', this.buffer.ydisp);\n }\n\n this.refresh(0, this.rows - 1);\n }\n\n /**\n * Scroll the display of the terminal by a number of pages.\n * @param {number} pageCount The number of pages to scroll (negative scrolls up).\n */\n public scrollPages(pageCount: number): void {\n this.scrollLines(pageCount * (this.rows - 1));\n }\n\n /**\n * Scrolls the display of the terminal to the top.\n */\n public scrollToTop(): void {\n this.scrollLines(-this.buffer.ydisp);\n }\n\n /**\n * Scrolls the display of the terminal to the bottom.\n */\n public scrollToBottom(): void {\n this.scrollLines(this.buffer.ybase - this.buffer.ydisp);\n }\n\n /**\n * Writes text to the terminal.\n * @param {string} data The text to write to the terminal.\n */\n public write(data: string): void {\n this.writeBuffer.push(data);\n\n // Send XOFF to pause the pty process if the write buffer becomes too large so\n // xterm.js can catch up before more data is sent. This is necessary in order\n // to keep signals such as ^C responsive.\n if (this.options.useFlowControl && !this.xoffSentToCatchUp && this.writeBuffer.length >= WRITE_BUFFER_PAUSE_THRESHOLD) {\n // XOFF - stop pty pipe\n // XON will be triggered by emulator before processing data chunk\n this.send(C0.DC3);\n this.xoffSentToCatchUp = true;\n }\n\n if (!this.writeInProgress && this.writeBuffer.length > 0) {\n // Kick off a write which will write all data in sequence recursively\n this.writeInProgress = true;\n // Kick off an async innerWrite so more writes can come in while processing data\n setTimeout(() => {\n this.innerWrite();\n });\n }\n }\n\n private innerWrite(): void {\n const writeBatch = this.writeBuffer.splice(0, WRITE_BATCH_SIZE);\n while (writeBatch.length > 0) {\n const data = writeBatch.shift();\n\n // If XOFF was sent in order to catch up with the pty process, resume it if\n // the writeBuffer is empty to allow more data to come in.\n if (this.xoffSentToCatchUp && writeBatch.length === 0 && this.writeBuffer.length === 0) {\n this.send(C0.DC1);\n this.xoffSentToCatchUp = false;\n }\n\n this.refreshStart = this.buffer.y;\n this.refreshEnd = this.buffer.y;\n\n // HACK: Set the parser state based on it's state at the time of return.\n // This works around the bug #662 which saw the parser state reset in the\n // middle of parsing escape sequence in two chunks. For some reason the\n // state of the parser resets to 0 after exiting parser.parse. This change\n // just sets the state back based on the correct return statement.\n const state = this.parser.parse(data);\n this.parser.setState(state);\n\n this.updateRange(this.buffer.y);\n this.refresh(this.refreshStart, this.refreshEnd);\n }\n if (this.writeBuffer.length > 0) {\n // Allow renderer to catch up before processing the next batch\n setTimeout(() => this.innerWrite(), 0);\n } else {\n this.writeInProgress = false;\n }\n }\n\n /**\n * Writes text to the terminal, followed by a break line character (\\n).\n * @param {string} data The text to write to the terminal.\n */\n public writeln(data: string): void {\n this.write(data + '\\r\\n');\n }\n\n /**\n * Attaches a custom key event handler which is run before keys are processed,\n * giving consumers of xterm.js ultimate control as to what keys should be\n * processed by the terminal and what keys should not.\n * @param customKeyEventHandler The custom KeyboardEvent handler to attach.\n * This is a function that takes a KeyboardEvent, allowing consumers to stop\n * propogation and/or prevent the default action. The function returns whether\n * the event should be processed by xterm.js.\n */\n public attachCustomKeyEventHandler(customKeyEventHandler: CustomKeyEventHandler): void {\n this.customKeyEventHandler = customKeyEventHandler;\n }\n\n /**\n * Attaches a http(s) link handler, forcing web links to behave differently to\n * regular tags. This will trigger a refresh as links potentially need to be\n * reconstructed. Calling this with null will remove the handler.\n * @param handler The handler callback function.\n */\n public setHypertextLinkHandler(handler: LinkMatcherHandler): void {\n if (!this.linkifier) {\n throw new Error('Cannot attach a hypertext link handler before Terminal.open is called');\n }\n this.linkifier.setHypertextLinkHandler(handler);\n // Refresh to force links to refresh\n this.refresh(0, this.rows - 1);\n }\n\n /**\n * Attaches a validation callback for hypertext links. This is useful to use\n * validation logic or to do something with the link's element and url.\n * @param callback The callback to use, this can\n * be cleared with null.\n */\n public setHypertextValidationCallback(callback: LinkMatcherValidationCallback): void {\n if (!this.linkifier) {\n throw new Error('Cannot attach a hypertext validation callback before Terminal.open is called');\n }\n this.linkifier.setHypertextValidationCallback(callback);\n // // Refresh to force links to refresh\n this.refresh(0, this.rows - 1);\n }\n\n /**\n * Registers a link matcher, allowing custom link patterns to be matched and\n * handled.\n * @param regex The regular expression to search for, specifically\n * this searches the textContent of the rows. You will want to use \\s to match\n * a space ' ' character for example.\n * @param handler The callback when the link is called.\n * @param options Options for the link matcher.\n * @return The ID of the new matcher, this can be used to deregister.\n */\n public registerLinkMatcher(regex: RegExp, handler: LinkMatcherHandler, options?: ILinkMatcherOptions): number {\n if (this.linkifier) {\n const matcherId = this.linkifier.registerLinkMatcher(regex, handler, options);\n this.refresh(0, this.rows - 1);\n return matcherId;\n }\n return 0;\n }\n\n /**\n * Deregisters a link matcher if it has been registered.\n * @param matcherId The link matcher's ID (returned after register)\n */\n public deregisterLinkMatcher(matcherId: number): void {\n if (this.linkifier) {\n if (this.linkifier.deregisterLinkMatcher(matcherId)) {\n this.refresh(0, this.rows - 1);\n }\n }\n }\n\n /**\n * Gets whether the terminal has an active selection.\n */\n public hasSelection(): boolean {\n return this.selectionManager ? this.selectionManager.hasSelection : false;\n }\n\n /**\n * Gets the terminal's current selection, this is useful for implementing copy\n * behavior outside of xterm.js.\n */\n public getSelection(): string {\n return this.selectionManager ? this.selectionManager.selectionText : '';\n }\n\n /**\n * Clears the current terminal selection.\n */\n public clearSelection(): void {\n if (this.selectionManager) {\n this.selectionManager.clearSelection();\n }\n }\n\n /**\n * Selects all text within the terminal.\n */\n public selectAll(): void {\n if (this.selectionManager) {\n this.selectionManager.selectAll();\n }\n }\n\n /**\n * Handle a keydown event\n * Key Resources:\n * - https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent\n * @param {KeyboardEvent} ev The keydown event to be handled.\n */\n protected _keyDown(ev: KeyboardEvent): boolean {\n if (this.customKeyEventHandler && this.customKeyEventHandler(ev) === false) {\n return false;\n }\n\n if (!this.compositionHelper.keydown(ev)) {\n if (this.buffer.ybase !== this.buffer.ydisp) {\n this.scrollToBottom();\n }\n return false;\n }\n\n const result = this._evaluateKeyEscapeSequence(ev);\n\n if (result.key === C0.DC3) { // XOFF\n this.writeStopped = true;\n } else if (result.key === C0.DC1) { // XON\n this.writeStopped = false;\n }\n\n if (result.scrollLines) {\n this.scrollLines(result.scrollLines);\n return this.cancel(ev, true);\n }\n\n if (isThirdLevelShift(this.browser, ev)) {\n return true;\n }\n\n if (result.cancel) {\n // The event is canceled at the end already, is this necessary?\n this.cancel(ev, true);\n }\n\n if (!result.key) {\n return true;\n }\n\n this.emit('keydown', ev);\n this.emit('key', result.key, ev);\n this.showCursor();\n this.handler(result.key);\n\n return this.cancel(ev, true);\n }\n\n /**\n * Returns an object that determines how a KeyboardEvent should be handled. The key of the\n * returned value is the new key code to pass to the PTY.\n *\n * Reference: http://invisible-island.net/xterm/ctlseqs/ctlseqs.html\n * @param ev The keyboard event to be translated to key escape sequence.\n */\n protected _evaluateKeyEscapeSequence(ev: KeyboardEvent): {cancel: boolean, key: string, scrollLines: number} {\n const result: {cancel: boolean, key: string, scrollLines: number} = {\n // Whether to cancel event propogation (NOTE: this may not be needed since the event is\n // canceled at the end of keyDown\n cancel: false,\n // The new key even to emit\n key: undefined,\n // The number of characters to scroll, if this is defined it will cancel the event\n scrollLines: undefined\n };\n const modifiers = (ev.shiftKey ? 1 : 0) | (ev.altKey ? 2 : 0) | (ev.ctrlKey ? 4 : 0) | (ev.metaKey ? 8 : 0);\n switch (ev.keyCode) {\n case 0:\n if (ev.key === 'UIKeyInputUpArrow') {\n if (this.applicationCursor) {\n result.key = C0.ESC + 'OA';\n } else {\n result.key = C0.ESC + '[A';\n }\n }\n else if (ev.key === 'UIKeyInputLeftArrow') {\n if (this.applicationCursor) {\n result.key = C0.ESC + 'OD';\n } else {\n result.key = C0.ESC + '[D';\n }\n }\n else if (ev.key === 'UIKeyInputRightArrow') {\n if (this.applicationCursor) {\n result.key = C0.ESC + 'OC';\n } else {\n result.key = C0.ESC + '[C';\n }\n }\n else if (ev.key === 'UIKeyInputDownArrow') {\n if (this.applicationCursor) {\n result.key = C0.ESC + 'OB';\n } else {\n result.key = C0.ESC + '[B';\n }\n }\n break;\n case 8:\n // backspace\n if (ev.shiftKey) {\n result.key = C0.BS; // ^H\n break;\n }\n result.key = C0.DEL; // ^?\n break;\n case 9:\n // tab\n if (ev.shiftKey) {\n result.key = C0.ESC + '[Z';\n break;\n }\n result.key = C0.HT;\n result.cancel = true;\n break;\n case 13:\n // return/enter\n result.key = C0.CR;\n result.cancel = true;\n break;\n case 27:\n // escape\n result.key = C0.ESC;\n result.cancel = true;\n break;\n case 37:\n // left-arrow\n if (modifiers) {\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'D';\n // HACK: Make Alt + left-arrow behave like Ctrl + left-arrow: move one word backwards\n // http://unix.stackexchange.com/a/108106\n // macOS uses different escape sequences than linux\n if (result.key === C0.ESC + '[1;3D') {\n result.key = (this.browser.isMac) ? C0.ESC + 'b' : C0.ESC + '[1;5D';\n }\n } else if (this.applicationCursor) {\n result.key = C0.ESC + 'OD';\n } else {\n result.key = C0.ESC + '[D';\n }\n break;\n case 39:\n // right-arrow\n if (modifiers) {\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'C';\n // HACK: Make Alt + right-arrow behave like Ctrl + right-arrow: move one word forward\n // http://unix.stackexchange.com/a/108106\n // macOS uses different escape sequences than linux\n if (result.key === C0.ESC + '[1;3C') {\n result.key = (this.browser.isMac) ? C0.ESC + 'f' : C0.ESC + '[1;5C';\n }\n } else if (this.applicationCursor) {\n result.key = C0.ESC + 'OC';\n } else {\n result.key = C0.ESC + '[C';\n }\n break;\n case 38:\n // up-arrow\n if (modifiers) {\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'A';\n // HACK: Make Alt + up-arrow behave like Ctrl + up-arrow\n // http://unix.stackexchange.com/a/108106\n if (result.key === C0.ESC + '[1;3A') {\n result.key = C0.ESC + '[1;5A';\n }\n } else if (this.applicationCursor) {\n result.key = C0.ESC + 'OA';\n } else {\n result.key = C0.ESC + '[A';\n }\n break;\n case 40:\n // down-arrow\n if (modifiers) {\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'B';\n // HACK: Make Alt + down-arrow behave like Ctrl + down-arrow\n // http://unix.stackexchange.com/a/108106\n if (result.key === C0.ESC + '[1;3B') {\n result.key = C0.ESC + '[1;5B';\n }\n } else if (this.applicationCursor) {\n result.key = C0.ESC + 'OB';\n } else {\n result.key = C0.ESC + '[B';\n }\n break;\n case 45:\n // insert\n if (!ev.shiftKey && !ev.ctrlKey) {\n // or + are used to\n // copy-paste on some systems.\n result.key = C0.ESC + '[2~';\n }\n break;\n case 46:\n // delete\n if (modifiers) {\n result.key = C0.ESC + '[3;' + (modifiers + 1) + '~';\n } else {\n result.key = C0.ESC + '[3~';\n }\n break;\n case 36:\n // home\n if (modifiers)\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'H';\n else if (this.applicationCursor)\n result.key = C0.ESC + 'OH';\n else\n result.key = C0.ESC + '[H';\n break;\n case 35:\n // end\n if (modifiers)\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'F';\n else if (this.applicationCursor)\n result.key = C0.ESC + 'OF';\n else\n result.key = C0.ESC + '[F';\n break;\n case 33:\n // page up\n if (ev.shiftKey) {\n result.scrollLines = -(this.rows - 1);\n } else {\n result.key = C0.ESC + '[5~';\n }\n break;\n case 34:\n // page down\n if (ev.shiftKey) {\n result.scrollLines = this.rows - 1;\n } else {\n result.key = C0.ESC + '[6~';\n }\n break;\n case 112:\n // F1-F12\n if (modifiers) {\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'P';\n } else {\n result.key = C0.ESC + 'OP';\n }\n break;\n case 113:\n if (modifiers) {\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'Q';\n } else {\n result.key = C0.ESC + 'OQ';\n }\n break;\n case 114:\n if (modifiers) {\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'R';\n } else {\n result.key = C0.ESC + 'OR';\n }\n break;\n case 115:\n if (modifiers) {\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'S';\n } else {\n result.key = C0.ESC + 'OS';\n }\n break;\n case 116:\n if (modifiers) {\n result.key = C0.ESC + '[15;' + (modifiers + 1) + '~';\n } else {\n result.key = C0.ESC + '[15~';\n }\n break;\n case 117:\n if (modifiers) {\n result.key = C0.ESC + '[17;' + (modifiers + 1) + '~';\n } else {\n result.key = C0.ESC + '[17~';\n }\n break;\n case 118:\n if (modifiers) {\n result.key = C0.ESC + '[18;' + (modifiers + 1) + '~';\n } else {\n result.key = C0.ESC + '[18~';\n }\n break;\n case 119:\n if (modifiers) {\n result.key = C0.ESC + '[19;' + (modifiers + 1) + '~';\n } else {\n result.key = C0.ESC + '[19~';\n }\n break;\n case 120:\n if (modifiers) {\n result.key = C0.ESC + '[20;' + (modifiers + 1) + '~';\n } else {\n result.key = C0.ESC + '[20~';\n }\n break;\n case 121:\n if (modifiers) {\n result.key = C0.ESC + '[21;' + (modifiers + 1) + '~';\n } else {\n result.key = C0.ESC + '[21~';\n }\n break;\n case 122:\n if (modifiers) {\n result.key = C0.ESC + '[23;' + (modifiers + 1) + '~';\n } else {\n result.key = C0.ESC + '[23~';\n }\n break;\n case 123:\n if (modifiers) {\n result.key = C0.ESC + '[24;' + (modifiers + 1) + '~';\n } else {\n result.key = C0.ESC + '[24~';\n }\n break;\n default:\n // a-z and space\n if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) {\n if (ev.keyCode >= 65 && ev.keyCode <= 90) {\n result.key = String.fromCharCode(ev.keyCode - 64);\n } else if (ev.keyCode === 32) {\n // NUL\n result.key = String.fromCharCode(0);\n } else if (ev.keyCode >= 51 && ev.keyCode <= 55) {\n // escape, file sep, group sep, record sep, unit sep\n result.key = String.fromCharCode(ev.keyCode - 51 + 27);\n } else if (ev.keyCode === 56) {\n // delete\n result.key = String.fromCharCode(127);\n } else if (ev.keyCode === 219) {\n // ^[ - Control Sequence Introducer (CSI)\n result.key = String.fromCharCode(27);\n } else if (ev.keyCode === 220) {\n // ^\\ - String Terminator (ST)\n result.key = String.fromCharCode(28);\n } else if (ev.keyCode === 221) {\n // ^] - Operating System Command (OSC)\n result.key = String.fromCharCode(29);\n }\n } else if (!this.browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) {\n // On Mac this is a third level shift. Use instead.\n if (ev.keyCode >= 65 && ev.keyCode <= 90) {\n result.key = C0.ESC + String.fromCharCode(ev.keyCode + 32);\n } else if (ev.keyCode === 192) {\n result.key = C0.ESC + '`';\n } else if (ev.keyCode >= 48 && ev.keyCode <= 57) {\n result.key = C0.ESC + (ev.keyCode - 48);\n }\n } else if (this.browser.isMac && !ev.altKey && !ev.ctrlKey && ev.metaKey) {\n if (ev.keyCode === 65) { // cmd + a\n this.selectAll();\n }\n }\n break;\n }\n\n return result;\n }\n\n /**\n * Set the G level of the terminal\n * @param g\n */\n public setgLevel(g: number): void {\n this.glevel = g;\n this.charset = this.charsets[g];\n }\n\n /**\n * Set the charset for the given G level of the terminal\n * @param g\n * @param charset\n */\n public setgCharset(g: number, charset: Charset): void {\n this.charsets[g] = charset;\n if (this.glevel === g) {\n this.charset = charset;\n }\n }\n\n /**\n * Handle a keypress event.\n * Key Resources:\n * - https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent\n * @param {KeyboardEvent} ev The keypress event to be handled.\n */\n protected _keyPress(ev: KeyboardEvent): boolean {\n let key;\n\n if (this.customKeyEventHandler && this.customKeyEventHandler(ev) === false) {\n return false;\n }\n\n this.cancel(ev);\n\n if (ev.charCode) {\n key = ev.charCode;\n } else if (ev.which == null) {\n key = ev.keyCode;\n } else if (ev.which !== 0 && ev.charCode !== 0) {\n key = ev.which;\n } else {\n return false;\n }\n\n if (!key || (\n (ev.altKey || ev.ctrlKey || ev.metaKey) && !isThirdLevelShift(this.browser, ev)\n )) {\n return false;\n }\n\n key = String.fromCharCode(key);\n\n this.emit('keypress', key, ev);\n this.emit('key', key, ev);\n this.showCursor();\n this.handler(key);\n\n return true;\n }\n\n /**\n * Send data for handling to the terminal\n * @param {string} data\n */\n public send(data: string): void {\n if (!this.sendDataQueue) {\n setTimeout(() => {\n this.handler(this.sendDataQueue);\n this.sendDataQueue = '';\n }, 1);\n }\n\n this.sendDataQueue += data;\n }\n\n /**\n * Ring the bell.\n * Note: We could do sweet things with webaudio here\n */\n public bell(): void {\n this.emit('bell');\n if (this.soundBell()) this.bellAudioElement.play();\n\n if (this.visualBell()) {\n this.element.classList.add('visual-bell-active');\n clearTimeout(this.visualBellTimer);\n this.visualBellTimer = window.setTimeout(() => {\n this.element.classList.remove('visual-bell-active');\n }, 200);\n }\n }\n\n /**\n * Log the current state to the console.\n */\n public log(text: string, data?: any): void {\n if (!this.options.debug) return;\n if (!this.context.console || !this.context.console.log) return;\n this.context.console.log(text, data);\n }\n\n /**\n * Log the current state as error to the console.\n */\n public error(text: string, data?: any): void {\n if (!this.options.debug) return;\n if (!this.context.console || !this.context.console.error) return;\n this.context.console.error(text, data);\n }\n\n /**\n * Resizes the terminal.\n *\n * @param {number} x The number of columns to resize to.\n * @param {number} y The number of rows to resize to.\n */\n public resize(x: number, y: number): void {\n if (isNaN(x) || isNaN(y)) {\n return;\n }\n\n if (x === this.cols && y === this.rows) {\n // Check if we still need to measure the char size (fixes #785).\n if (!this.charMeasure.width || !this.charMeasure.height) {\n this.charMeasure.measure(this.options);\n }\n return;\n }\n\n if (x < 1) x = 1;\n if (y < 1) y = 1;\n\n this.buffers.resize(x, y);\n\n this.cols = x;\n this.rows = y;\n this.buffers.setupTabStops(this.cols);\n\n this.charMeasure.measure(this.options);\n\n this.refresh(0, this.rows - 1);\n\n this.geometry = [this.cols, this.rows];\n this.emit('resize', {cols: x, rows: y});\n }\n\n /**\n * Updates the range of rows to refresh\n * @param {number} y The number of rows to refresh next.\n */\n public updateRange(y: number): void {\n if (y < this.refreshStart) this.refreshStart = y;\n if (y > this.refreshEnd) this.refreshEnd = y;\n // if (y > this.refreshEnd) {\n // this.refreshEnd = y;\n // if (y > this.rows - 1) {\n // this.refreshEnd = this.rows - 1;\n // }\n // }\n }\n\n /**\n * Set the range of refreshing to the maximum value\n */\n public maxRange(): void {\n this.refreshStart = 0;\n this.refreshEnd = this.rows - 1;\n }\n\n /**\n * Erase in the identified line everything from \"x\" to the end of the line (right).\n * @param {number} x The column from which to start erasing to the end of the line.\n * @param {number} y The line in which to operate.\n */\n public eraseRight(x: number, y: number): void {\n const line = this.buffer.lines.get(this.buffer.ybase + y);\n if (!line) {\n return;\n }\n const ch: CharData = [this.eraseAttr(), ' ', 1, 32 /* ' '.charCodeAt(0) */]; // xterm\n for (; x < this.cols; x++) {\n line[x] = ch;\n }\n this.updateRange(y);\n }\n\n /**\n * Erase in the identified line everything from \"x\" to the start of the line (left).\n * @param {number} x The column from which to start erasing to the start of the line.\n * @param {number} y The line in which to operate.\n */\n public eraseLeft(x: number, y: number): void {\n const line = this.buffer.lines.get(this.buffer.ybase + y);\n if (!line) {\n return;\n }\n const ch: CharData = [this.eraseAttr(), ' ', 1, 32 /* ' '.charCodeAt(0) */]; // xterm\n x++;\n while (x--) {\n line[x] = ch;\n }\n this.updateRange(y);\n }\n\n /**\n * Clear the entire buffer, making the prompt line the new first line.\n */\n public clear(): void {\n if (this.buffer.ybase === 0 && this.buffer.y === 0) {\n // Don't clear if it's already clear\n return;\n }\n this.buffer.lines.set(0, this.buffer.lines.get(this.buffer.ybase + this.buffer.y));\n this.buffer.lines.length = 1;\n this.buffer.ydisp = 0;\n this.buffer.ybase = 0;\n this.buffer.y = 0;\n for (let i = 1; i < this.rows; i++) {\n this.buffer.lines.push(this.blankLine());\n }\n this.refresh(0, this.rows - 1);\n this.emit('scroll', this.buffer.ydisp);\n }\n\n /**\n * Erase all content in the given line\n * @param {number} y The line to erase all of its contents.\n */\n public eraseLine(y: number): void {\n this.eraseRight(0, y);\n }\n\n /**\n * Return the data array of a blank line\n * @param {boolean} cur First bunch of data for each \"blank\" character.\n * @param {boolean} isWrapped Whether the new line is wrapped from the previous line.\n * @param {boolean} cols The number of columns in the terminal, if this is not\n * set, the terminal's current column count would be used.\n */\n public blankLine(cur?: boolean, isWrapped?: boolean, cols?: number): LineData {\n const attr = cur ? this.eraseAttr() : this.defAttr;\n\n const ch: CharData = [attr, ' ', 1, 32 /* ' '.charCodeAt(0) */]; // width defaults to 1 halfwidth character\n const line: LineData = [];\n\n // TODO: It is not ideal that this is a property on an array, a buffer line\n // class should be added that will hold this data and other useful functions.\n if (isWrapped) {\n (line).isWrapped = isWrapped;\n }\n\n cols = cols || this.cols;\n for (let i = 0; i < cols; i++) {\n line[i] = ch;\n }\n\n return line;\n }\n\n /**\n * If cur return the back color xterm feature attribute. Else return defAttr.\n * @param cur\n */\n public ch(cur?: boolean): CharData {\n if (cur) {\n return [this.eraseAttr(), ' ', 1, 32 /* ' '.charCodeAt(0) */];\n }\n return [this.defAttr, ' ', 1, 32 /* ' '.charCodeAt(0) */];\n }\n\n /**\n * Evaluate if the current terminal is the given argument.\n * @param term The terminal name to evaluate\n */\n public is(term: string): boolean {\n return (this.options.termName + '').indexOf(term) === 0;\n }\n\n /**\n * Emit the 'data' event and populate the given data.\n * @param {string} data The data to populate in the event.\n */\n public handler(data: string): void {\n // Prevents all events to pty process if stdin is disabled\n if (this.options.disableStdin) {\n return;\n }\n\n // Clear the selection if the selection manager is available and has an active selection\n if (this.selectionManager && this.selectionManager.hasSelection) {\n this.selectionManager.clearSelection();\n }\n\n // Input is being sent to the terminal, the terminal should focus the prompt.\n if (this.buffer.ybase !== this.buffer.ydisp) {\n this.scrollToBottom();\n }\n this.emit('data', data);\n }\n\n /**\n * Emit the 'title' event and populate the given title.\n * @param {string} title The title to populate in the event.\n */\n private handleTitle(title: string): void {\n /**\n * This event is emitted when the title of the terminal is changed\n * from inside the terminal. The parameter is the new title.\n *\n * @event title\n */\n this.emit('title', title);\n }\n\n /**\n * ESC\n */\n\n /**\n * ESC D Index (IND is 0x84).\n */\n public index(): void {\n this.buffer.y++;\n if (this.buffer.y > this.buffer.scrollBottom) {\n this.buffer.y--;\n this.scroll();\n }\n // If the end of the line is hit, prevent this action from wrapping around to the next line.\n if (this.buffer.x >= this.cols) {\n this.buffer.x--;\n }\n }\n\n /**\n * ESC M Reverse Index (RI is 0x8d).\n *\n * Move the cursor up one row, inserting a new blank line if necessary.\n */\n public reverseIndex(): void {\n if (this.buffer.y === this.buffer.scrollTop) {\n // possibly move the code below to term.reverseScroll();\n // test: echo -ne '\\e[1;1H\\e[44m\\eM\\e[0m'\n // blankLine(true) is xterm/linux behavior\n const scrollRegionHeight = this.buffer.scrollBottom - this.buffer.scrollTop;\n this.buffer.lines.shiftElements(this.buffer.y + this.buffer.ybase, scrollRegionHeight, 1);\n this.buffer.lines.set(this.buffer.y + this.buffer.ybase, this.blankLine(true));\n this.updateRange(this.buffer.scrollTop);\n this.updateRange(this.buffer.scrollBottom);\n } else {\n this.buffer.y--;\n }\n }\n\n /**\n * ESC c Full Reset (RIS).\n */\n public reset(): void {\n this.options.rows = this.rows;\n this.options.cols = this.cols;\n const customKeyEventHandler = this.customKeyEventHandler;\n const inputHandler = this.inputHandler;\n const buffers = this.buffers;\n this.setup();\n this.customKeyEventHandler = customKeyEventHandler;\n this.inputHandler = inputHandler;\n this.buffers = buffers;\n this.refresh(0, this.rows - 1);\n this.viewport.syncScrollArea();\n }\n\n\n /**\n * ESC H Tab Set (HTS is 0x88).\n */\n private tabSet(): void {\n this.buffer.tabs[this.buffer.x] = true;\n }\n\n // TODO: Remove cancel function and cancelEvents option\n public cancel(ev: Event, force?: boolean): boolean {\n if (!this.options.cancelEvents && !force) {\n return;\n }\n ev.preventDefault();\n ev.stopPropagation();\n return false;\n }\n\n // TODO: Remove when true color is implemented\n public matchColor(r1: number, g1: number, b1: number): number {\n return matchColor_(r1, g1, b1);\n }\n\n private visualBell(): boolean {\n return this.options.bellStyle === 'visual' ||\n this.options.bellStyle === 'both';\n }\n\n private soundBell(): boolean {\n return this.options.bellStyle === 'sound' ||\n this.options.bellStyle === 'both';\n }\n\n private syncBellSound(): void {\n if (this.soundBell() && this.bellAudioElement) {\n this.bellAudioElement.setAttribute('src', this.options.bellSound);\n } else if (this.soundBell()) {\n this.bellAudioElement = document.createElement('audio');\n this.bellAudioElement.setAttribute('preload', 'auto');\n this.bellAudioElement.setAttribute('src', this.options.bellSound);\n this.helperContainer.appendChild(this.bellAudioElement);\n } else if (this.bellAudioElement) {\n this.helperContainer.removeChild(this.bellAudioElement);\n }\n }\n}\n\n/**\n * Helpers\n */\n\nfunction globalOn(el: any, type: string, handler: (event: Event) => any, capture?: boolean): void {\n if (!Array.isArray(el)) {\n el = [el];\n }\n el.forEach((element: HTMLElement) => {\n element.addEventListener(type, handler, capture || false);\n });\n}\n// TODO: Remove once everything is typed\nconst on = globalOn;\n\nfunction off(el: any, type: string, handler: (event: Event) => any, capture: boolean = false): void {\n el.removeEventListener(type, handler, capture);\n}\n\nfunction isThirdLevelShift(browser: IBrowser, ev: KeyboardEvent): boolean {\n const thirdLevelKey =\n (browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) ||\n (browser.isMSWindows && ev.altKey && ev.ctrlKey && !ev.metaKey);\n\n if (ev.type === 'keypress') {\n return thirdLevelKey;\n }\n\n // Don't invoke for arrows, pageDown, home, backspace, etc. (on non-keypress events)\n return thirdLevelKey && (!ev.keyCode || ev.keyCode > 47);\n}\n\nfunction wasMondifierKeyOnlyEvent(ev: KeyboardEvent): boolean {\n return ev.keyCode === 16 || // Shift\n ev.keyCode === 17 || // Ctrl\n ev.keyCode === 18; // Alt\n}\n\n/**\n * TODO:\n * The below color-related code can be removed when true color is implemented.\n * It's only purpose is to match true color requests with the closest matching\n * ANSI color code.\n */\n\n// Colors 0-15 + 16-255\n// Much thanks to TooTallNate for writing this.\nconst vcolors: number[][] = (function(): number[][] {\n const result = DEFAULT_ANSI_COLORS.map(c => {\n c = c.substring(1);\n return [\n parseInt(c.substring(0, 2), 16),\n parseInt(c.substring(2, 4), 16),\n parseInt(c.substring(4, 6), 16)\n ];\n });\n const r = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff];\n\n // 16-231\n for (let i = 0; i < 216; i++) {\n result.push([\n r[(i / 36) % 6 | 0],\n r[(i / 6) % 6 | 0],\n r[i % 6]\n ]);\n }\n\n // 232-255 (grey)\n let c: number;\n for (let i = 0; i < 24; i++) {\n c = 8 + i * 10;\n result.push([c, c, c]);\n }\n\n return result;\n})();\n\nconst matchColorCache: {[colorRGBHash: number]: number} = {};\n\n// http://stackoverflow.com/questions/1633828\nfunction matchColorDistance(r1: number, g1: number, b1: number, r2: number, g2: number, b2: number): number {\n return Math.pow(30 * (r1 - r2), 2)\n + Math.pow(59 * (g1 - g2), 2)\n + Math.pow(11 * (b1 - b2), 2);\n};\n\n\nfunction matchColor_(r1: number, g1: number, b1: number): number {\n const hash = (r1 << 16) | (g1 << 8) | b1;\n\n if (matchColorCache[hash] != null) {\n return matchColorCache[hash];\n }\n\n let ldiff = Infinity;\n let li = -1;\n let i = 0;\n let c: number[];\n let r2: number;\n let g2: number;\n let b2: number;\n let diff: number;\n\n for (; i < vcolors.length; i++) {\n c = vcolors[i];\n r2 = c[0];\n g2 = c[1];\n b2 = c[2];\n\n diff = matchColorDistance(r1, g1, b1, r2, g2, b2);\n\n if (diff === 0) {\n li = i;\n break;\n }\n\n if (diff < ldiff) {\n ldiff = diff;\n li = i;\n }\n }\n\n return matchColorCache[hash] = li;\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ITerminal } from './Interfaces';\n\n/**\n * Represents a selection within the buffer. This model only cares about column\n * and row coordinates, not wide characters.\n */\nexport class SelectionModel {\n /**\n * Whether select all is currently active.\n */\n public isSelectAllActive: boolean;\n\n /**\n * The [x, y] position the selection starts at.\n */\n public selectionStart: [number, number];\n\n /**\n * The minimal length of the selection from the start position. When double\n * clicking on a word, the word will be selected which makes the selection\n * start at the start of the word and makes this variable the length.\n */\n public selectionStartLength: number;\n\n /**\n * The [x, y] position the selection ends at.\n */\n public selectionEnd: [number, number];\n\n constructor(\n private _terminal: ITerminal\n ) {\n this.clearSelection();\n }\n\n /**\n * Clears the current selection.\n */\n public clearSelection(): void {\n this.selectionStart = null;\n this.selectionEnd = null;\n this.isSelectAllActive = false;\n this.selectionStartLength = 0;\n }\n\n /**\n * The final selection start, taking into consideration select all.\n */\n public get finalSelectionStart(): [number, number] {\n if (this.isSelectAllActive) {\n return [0, 0];\n }\n\n if (!this.selectionEnd || !this.selectionStart) {\n return this.selectionStart;\n }\n\n return this.areSelectionValuesReversed() ? this.selectionEnd : this.selectionStart;\n }\n\n /**\n * The final selection end, taking into consideration select all, double click\n * word selection and triple click line selection.\n */\n public get finalSelectionEnd(): [number, number] {\n if (this.isSelectAllActive) {\n return [this._terminal.cols, this._terminal.buffer.ybase + this._terminal.rows - 1];\n }\n\n if (!this.selectionStart) {\n return null;\n }\n\n // Use the selection start if the end doesn't exist or they're reversed\n if (!this.selectionEnd || this.areSelectionValuesReversed()) {\n return [this.selectionStart[0] + this.selectionStartLength, this.selectionStart[1]];\n }\n\n // Ensure the the word/line is selected after a double/triple click\n if (this.selectionStartLength) {\n // Select the larger of the two when start and end are on the same line\n if (this.selectionEnd[1] === this.selectionStart[1]) {\n return [Math.max(this.selectionStart[0] + this.selectionStartLength, this.selectionEnd[0]), this.selectionEnd[1]];\n }\n }\n return this.selectionEnd;\n }\n\n /**\n * Returns whether the selection start and end are reversed.\n */\n public areSelectionValuesReversed(): boolean {\n const start = this.selectionStart;\n const end = this.selectionEnd;\n if (!start || !end) {\n return false;\n }\n return start[1] > end[1] || (start[1] === end[1] && start[0] > end[0]);\n }\n\n /**\n * Handle the buffer being trimmed, adjust the selection position.\n * @param amount The amount the buffer is being trimmed.\n * @return Whether a refresh is necessary.\n */\n public onTrim(amount: number): boolean {\n // Adjust the selection position based on the trimmed amount.\n if (this.selectionStart) {\n this.selectionStart[1] -= amount;\n }\n if (this.selectionEnd) {\n this.selectionEnd[1] -= amount;\n }\n\n // The selection has moved off the buffer, clear it.\n if (this.selectionEnd && this.selectionEnd[1] < 0) {\n this.clearSelection();\n return true;\n }\n\n // If the selection start is trimmed, ensure the start column is 0.\n if (this.selectionStart && this.selectionStart[1] < 0) {\n this.selectionStart[1] = 0;\n }\n return false;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { MouseHelper } from './utils/MouseHelper';\nimport * as Browser from './utils/Browser';\nimport { CharMeasure } from './utils/CharMeasure';\nimport { CircularList } from './utils/CircularList';\nimport { EventEmitter } from './EventEmitter';\nimport { ITerminal, ICircularList, ISelectionManager, IBuffer } from './Interfaces';\nimport { SelectionModel } from './SelectionModel';\nimport { LineData, CharData } from './Types';\nimport { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from './Buffer';\n\n/**\n * The number of pixels the mouse needs to be above or below the viewport in\n * order to scroll at the maximum speed.\n */\nconst DRAG_SCROLL_MAX_THRESHOLD = 50;\n\n/**\n * The maximum scrolling speed\n */\nconst DRAG_SCROLL_MAX_SPEED = 15;\n\n/**\n * The number of milliseconds between drag scroll updates.\n */\nconst DRAG_SCROLL_INTERVAL = 50;\n\n/**\n * A string containing all characters that are considered word separated by the\n * double click to select work logic.\n */\nconst WORD_SEPARATORS = ' ()[]{}\\'\"';\n\nconst NON_BREAKING_SPACE_CHAR = String.fromCharCode(160);\nconst ALL_NON_BREAKING_SPACE_REGEX = new RegExp(NON_BREAKING_SPACE_CHAR, 'g');\n\n/**\n * Represents a position of a word on a line.\n */\ninterface IWordPosition {\n start: number;\n length: number;\n}\n\n/**\n * A selection mode, this drives how the selection behaves on mouse move.\n */\nenum SelectionMode {\n NORMAL,\n WORD,\n LINE\n}\n\n/**\n * A class that manages the selection of the terminal. With help from\n * SelectionModel, SelectionManager handles with all logic associated with\n * dealing with the selection, including handling mouse interaction, wide\n * characters and fetching the actual text within the selection. Rendering is\n * not handled by the SelectionManager but a 'refresh' event is fired when the\n * selection is ready to be redrawn.\n */\nexport class SelectionManager extends EventEmitter implements ISelectionManager {\n protected _model: SelectionModel;\n\n /**\n * The amount to scroll every drag scroll update (depends on how far the mouse\n * drag is above or below the terminal).\n */\n private _dragScrollAmount: number;\n\n /**\n * The current selection mode.\n */\n private _activeSelectionMode: SelectionMode;\n\n /**\n * A setInterval timer that is active while the mouse is down whose callback\n * scrolls the viewport when necessary.\n */\n private _dragScrollIntervalTimer: NodeJS.Timer;\n\n /**\n * The animation frame ID used for refreshing the selection.\n */\n private _refreshAnimationFrame: number;\n\n /**\n * Whether selection is enabled.\n */\n private _enabled = true;\n\n private _mouseMoveListener: EventListener;\n private _mouseUpListener: EventListener;\n\n constructor(\n private _terminal: ITerminal,\n private _buffer: IBuffer,\n private _charMeasure: CharMeasure\n ) {\n super();\n this._initListeners();\n this.enable();\n\n this._model = new SelectionModel(_terminal);\n this._activeSelectionMode = SelectionMode.NORMAL;\n }\n\n /**\n * Initializes listener variables.\n */\n private _initListeners(): void {\n this._mouseMoveListener = event => this._onMouseMove(event);\n this._mouseUpListener = event => this._onMouseUp(event);\n\n // Only adjust the selection on trim, shiftElements is rarely used (only in\n // reverseIndex) and delete in a splice is only ever used when the same\n // number of elements was just added. Given this is could actually be\n // beneficial to leave the selection as is for these cases.\n this._buffer.lines.on('trim', (amount: number) => this._onTrim(amount));\n }\n\n /**\n * Disables the selection manager. This is useful for when terminal mouse\n * are enabled.\n */\n public disable(): void {\n this.clearSelection();\n this._enabled = false;\n }\n\n /**\n * Enable the selection manager.\n */\n public enable(): void {\n this._enabled = true;\n }\n\n /**\n * Sets the active buffer, this should be called when the alt buffer is\n * switched in or out.\n * @param buffer The active buffer.\n */\n public setBuffer(buffer: IBuffer): void {\n this._buffer = buffer;\n this.clearSelection();\n }\n\n public get selectionStart(): [number, number] { return this._model.finalSelectionStart; }\n public get selectionEnd(): [number, number] { return this._model.finalSelectionEnd; }\n\n /**\n * Gets whether there is an active text selection.\n */\n public get hasSelection(): boolean {\n const start = this._model.finalSelectionStart;\n const end = this._model.finalSelectionEnd;\n if (!start || !end) {\n return false;\n }\n return start[0] !== end[0] || start[1] !== end[1];\n }\n\n /**\n * Gets the text currently selected.\n */\n public get selectionText(): string {\n const start = this._model.finalSelectionStart;\n const end = this._model.finalSelectionEnd;\n if (!start || !end) {\n return '';\n }\n\n // Get first row\n const startRowEndCol = start[1] === end[1] ? end[0] : null;\n let result: string[] = [];\n result.push(this._buffer.translateBufferLineToString(start[1], true, start[0], startRowEndCol));\n\n // Get middle rows\n for (let i = start[1] + 1; i <= end[1] - 1; i++) {\n const bufferLine = this._buffer.lines.get(i);\n const lineText = this._buffer.translateBufferLineToString(i, true);\n if ((bufferLine).isWrapped) {\n result[result.length - 1] += lineText;\n } else {\n result.push(lineText);\n }\n }\n\n // Get final row\n if (start[1] !== end[1]) {\n const bufferLine = this._buffer.lines.get(end[1]);\n const lineText = this._buffer.translateBufferLineToString(end[1], true, 0, end[0]);\n if ((bufferLine).isWrapped) {\n result[result.length - 1] += lineText;\n } else {\n result.push(lineText);\n }\n }\n\n // Format string by replacing non-breaking space chars with regular spaces\n // and joining the array into a multi-line string.\n const formattedResult = result.map(line => {\n return line.replace(ALL_NON_BREAKING_SPACE_REGEX, ' ');\n }).join(Browser.isMSWindows ? '\\r\\n' : '\\n');\n\n return formattedResult;\n }\n\n /**\n * Clears the current terminal selection.\n */\n public clearSelection(): void {\n this._model.clearSelection();\n this._removeMouseDownListeners();\n this.refresh();\n }\n\n /**\n * Queues a refresh, redrawing the selection on the next opportunity.\n * @param isNewSelection Whether the selection should be registered as a new\n * selection on Linux.\n */\n public refresh(isNewSelection?: boolean): void {\n // Queue the refresh for the renderer\n if (!this._refreshAnimationFrame) {\n this._refreshAnimationFrame = window.requestAnimationFrame(() => this._refresh());\n }\n\n // If the platform is Linux and the refresh call comes from a mouse event,\n // we need to update the selection for middle click to paste selection.\n if (Browser.isLinux && isNewSelection) {\n const selectionText = this.selectionText;\n if (selectionText.length) {\n this.emit('newselection', this.selectionText);\n }\n }\n }\n\n /**\n * Fires the refresh event, causing consumers to pick it up and redraw the\n * selection state.\n */\n private _refresh(): void {\n this._refreshAnimationFrame = null;\n this.emit('refresh', { start: this._model.finalSelectionStart, end: this._model.finalSelectionEnd });\n }\n\n /**\n * Selects all text within the terminal.\n */\n public selectAll(): void {\n this._model.isSelectAllActive = true;\n this.refresh();\n this.emit('selection');\n }\n\n /**\n * Handle the buffer being trimmed, adjust the selection position.\n * @param amount The amount the buffer is being trimmed.\n */\n private _onTrim(amount: number): void {\n const needsRefresh = this._model.onTrim(amount);\n if (needsRefresh) {\n this.refresh();\n }\n }\n\n /**\n * Gets the 0-based [x, y] buffer coordinates of the current mouse event.\n * @param event The mouse event.\n */\n private _getMouseBufferCoords(event: MouseEvent): [number, number] {\n const coords = this._terminal.mouseHelper.getCoords(event, this._terminal.element, this._charMeasure, this._terminal.options.lineHeight, this._terminal.cols, this._terminal.rows, true);\n if (!coords) {\n return null;\n }\n\n // Convert to 0-based\n coords[0]--;\n coords[1]--;\n\n // Convert viewport coords to buffer coords\n coords[1] += this._terminal.buffer.ydisp;\n return coords;\n }\n\n /**\n * Gets the amount the viewport should be scrolled based on how far out of the\n * terminal the mouse is.\n * @param event The mouse event.\n */\n private _getMouseEventScrollAmount(event: MouseEvent): number {\n let offset = MouseHelper.getCoordsRelativeToElement(event, this._terminal.element)[1];\n const terminalHeight = this._terminal.rows * Math.ceil(this._charMeasure.height * this._terminal.options.lineHeight);\n if (offset >= 0 && offset <= terminalHeight) {\n return 0;\n }\n if (offset > terminalHeight) {\n offset -= terminalHeight;\n }\n\n offset = Math.min(Math.max(offset, -DRAG_SCROLL_MAX_THRESHOLD), DRAG_SCROLL_MAX_THRESHOLD);\n offset /= DRAG_SCROLL_MAX_THRESHOLD;\n return (offset / Math.abs(offset)) + Math.round(offset * (DRAG_SCROLL_MAX_SPEED - 1));\n }\n\n /**\n * Returns whether the selection manager should force selection, regardless of\n * whether the terminal is in mouse events mode.\n * @param event The mouse event.\n */\n public shouldForceSelection(event: MouseEvent): boolean {\n return Browser.isMac ? event.altKey : event.shiftKey;\n }\n\n /**\n * Handles te mousedown event, setting up for a new selection.\n * @param event The mousedown event.\n */\n public onMouseDown(event: MouseEvent): void {\n // If we have selection, we want the context menu on right click even if the\n // terminal is in mouse mode.\n if (event.button === 2 && this.hasSelection) {\n return;\n }\n\n // Only action the primary button\n if (event.button !== 0) {\n return;\n }\n\n // Allow selection when using a specific modifier key, even when disabled\n if (!this._enabled) {\n if (!this.shouldForceSelection(event)) {\n return;\n }\n\n // Don't send the mouse down event to the current process, we want to select\n event.stopPropagation();\n }\n\n // Tell the browser not to start a regular selection\n event.preventDefault();\n\n // Reset drag scroll state\n this._dragScrollAmount = 0;\n\n if (this._enabled && event.shiftKey) {\n this._onIncrementalClick(event);\n } else {\n if (event.detail === 1) {\n this._onSingleClick(event);\n } else if (event.detail === 2) {\n this._onDoubleClick(event);\n } else if (event.detail === 3) {\n this._onTripleClick(event);\n }\n }\n\n this._addMouseDownListeners();\n this.refresh(true);\n }\n\n /**\n * Adds listeners when mousedown is triggered.\n */\n private _addMouseDownListeners(): void {\n // Listen on the document so that dragging outside of viewport works\n this._terminal.element.ownerDocument.addEventListener('mousemove', this._mouseMoveListener);\n this._terminal.element.ownerDocument.addEventListener('mouseup', this._mouseUpListener);\n this._dragScrollIntervalTimer = setInterval(() => this._dragScroll(), DRAG_SCROLL_INTERVAL);\n }\n\n /**\n * Removes the listeners that are registered when mousedown is triggered.\n */\n private _removeMouseDownListeners(): void {\n this._terminal.element.ownerDocument.removeEventListener('mousemove', this._mouseMoveListener);\n this._terminal.element.ownerDocument.removeEventListener('mouseup', this._mouseUpListener);\n clearInterval(this._dragScrollIntervalTimer);\n this._dragScrollIntervalTimer = null;\n }\n\n /**\n * Performs an incremental click, setting the selection end position to the mouse\n * position.\n * @param event The mouse event.\n */\n private _onIncrementalClick(event: MouseEvent): void {\n if (this._model.selectionStart) {\n this._model.selectionEnd = this._getMouseBufferCoords(event);\n }\n }\n\n /**\n * Performs a single click, resetting relevant state and setting the selection\n * start position.\n * @param event The mouse event.\n */\n private _onSingleClick(event: MouseEvent): void {\n this._model.selectionStartLength = 0;\n this._model.isSelectAllActive = false;\n this._activeSelectionMode = SelectionMode.NORMAL;\n\n // Initialize the new selection\n this._model.selectionStart = this._getMouseBufferCoords(event);\n if (!this._model.selectionStart) {\n return;\n }\n this._model.selectionEnd = null;\n\n // Ensure the line exists\n const line = this._buffer.lines.get(this._model.selectionStart[1]);\n if (!line) {\n return;\n }\n\n // Return early if the click event is not in the buffer (eg. in scroll bar)\n if (line.length >= this._model.selectionStart[0]) {\n return;\n }\n\n // If the mouse is over the second half of a wide character, adjust the\n // selection to cover the whole character\n const char = line[this._model.selectionStart[0]];\n if (char[CHAR_DATA_WIDTH_INDEX] === 0) {\n this._model.selectionStart[0]++;\n }\n }\n\n /**\n * Performs a double click, selecting the current work.\n * @param event The mouse event.\n */\n private _onDoubleClick(event: MouseEvent): void {\n const coords = this._getMouseBufferCoords(event);\n if (coords) {\n this._activeSelectionMode = SelectionMode.WORD;\n this._selectWordAt(coords);\n }\n }\n\n /**\n * Performs a triple click, selecting the current line and activating line\n * select mode.\n * @param event The mouse event.\n */\n private _onTripleClick(event: MouseEvent): void {\n const coords = this._getMouseBufferCoords(event);\n if (coords) {\n this._activeSelectionMode = SelectionMode.LINE;\n this._selectLineAt(coords[1]);\n }\n }\n\n /**\n * Handles the mousemove event when the mouse button is down, recording the\n * end of the selection and refreshing the selection.\n * @param event The mousemove event.\n */\n private _onMouseMove(event: MouseEvent): void {\n // If the mousemove listener is active it means that a selection is\n // currently being made, we should stop propogation to prevent mouse events\n // to be sent to the pty.\n event.stopImmediatePropagation();\n\n // Record the previous position so we know whether to redraw the selection\n // at the end.\n const previousSelectionEnd = this._model.selectionEnd ? [this._model.selectionEnd[0], this._model.selectionEnd[1]] : null;\n\n // Set the initial selection end based on the mouse coordinates\n this._model.selectionEnd = this._getMouseBufferCoords(event);\n if (!this._model.selectionEnd) {\n this.refresh(true);\n return;\n }\n\n // Select the entire line if line select mode is active.\n if (this._activeSelectionMode === SelectionMode.LINE) {\n if (this._model.selectionEnd[1] < this._model.selectionStart[1]) {\n this._model.selectionEnd[0] = 0;\n } else {\n this._model.selectionEnd[0] = this._terminal.cols;\n }\n } else if (this._activeSelectionMode === SelectionMode.WORD) {\n this._selectToWordAt(this._model.selectionEnd);\n }\n\n // Determine the amount of scrolling that will happen.\n this._dragScrollAmount = this._getMouseEventScrollAmount(event);\n\n // If the cursor was above or below the viewport, make sure it's at the\n // start or end of the viewport respectively.\n if (this._dragScrollAmount > 0) {\n this._model.selectionEnd[0] = this._terminal.cols;\n } else if (this._dragScrollAmount < 0) {\n this._model.selectionEnd[0] = 0;\n }\n\n // If the character is a wide character include the cell to the right in the\n // selection. Note that selections at the very end of the line will never\n // have a character.\n if (this._model.selectionEnd[1] < this._buffer.lines.length) {\n const char = this._buffer.lines.get(this._model.selectionEnd[1])[this._model.selectionEnd[0]];\n if (char && char[CHAR_DATA_WIDTH_INDEX] === 0) {\n this._model.selectionEnd[0]++;\n }\n }\n\n // Only draw here if the selection changes.\n if (!previousSelectionEnd ||\n previousSelectionEnd[0] !== this._model.selectionEnd[0] ||\n previousSelectionEnd[1] !== this._model.selectionEnd[1]) {\n this.refresh(true);\n }\n }\n\n /**\n * The callback that occurs every DRAG_SCROLL_INTERVAL ms that does the\n * scrolling of the viewport.\n */\n private _dragScroll(): void {\n if (this._dragScrollAmount) {\n this._terminal.scrollLines(this._dragScrollAmount, false);\n // Re-evaluate selection\n if (this._dragScrollAmount > 0) {\n this._model.selectionEnd = [this._terminal.cols - 1, this._terminal.buffer.ydisp + this._terminal.rows];\n } else {\n this._model.selectionEnd = [0, this._terminal.buffer.ydisp];\n }\n this.refresh();\n }\n }\n\n /**\n * Handles the mouseup event, removing the mousedown listeners.\n * @param event The mouseup event.\n */\n private _onMouseUp(event: MouseEvent): void {\n this._removeMouseDownListeners();\n\n if (this.hasSelection)\n this.emit('selection');\n }\n\n /**\n * Converts a viewport column to the character index on the buffer line, the\n * latter takes into account wide characters.\n * @param coords The coordinates to find the 2 index for.\n */\n private _convertViewportColToCharacterIndex(bufferLine: any, coords: [number, number]): number {\n let charIndex = coords[0];\n for (let i = 0; coords[0] >= i; i++) {\n const char = bufferLine[i];\n if (char[CHAR_DATA_WIDTH_INDEX] === 0) {\n // Wide characters aren't included in the line string so decrement the\n // index so the index is back on the wide character.\n charIndex--;\n } else if (char[CHAR_DATA_CHAR_INDEX].length > 1 && coords[0] !== i) {\n // Emojis take up multiple characters, so adjust accordingly. For these\n // we don't want ot include the character at the column as we're\n // returning the start index in the string, not the end index.\n charIndex += char[CHAR_DATA_CHAR_INDEX].length - 1;\n }\n }\n return charIndex;\n }\n\n public setSelection(col: number, row: number, length: number): void {\n this._model.clearSelection();\n this._removeMouseDownListeners();\n this._model.selectionStart = [col, row];\n this._model.selectionStartLength = length;\n this.refresh();\n }\n\n /**\n * Gets positional information for the word at the coordinated specified.\n * @param coords The coordinates to get the word at.\n */\n private _getWordAt(coords: [number, number]): IWordPosition {\n const bufferLine = this._buffer.lines.get(coords[1]);\n if (!bufferLine) {\n return null;\n }\n\n const line = this._buffer.translateBufferLineToString(coords[1], false);\n\n // Get actual index, taking into consideration wide characters\n let startIndex = this._convertViewportColToCharacterIndex(bufferLine, coords);\n let endIndex = startIndex;\n\n // Record offset to be used later\n const charOffset = coords[0] - startIndex;\n let leftWideCharCount = 0;\n let rightWideCharCount = 0;\n let leftLongCharOffset = 0;\n let rightLongCharOffset = 0;\n\n if (line.charAt(startIndex) === ' ') {\n // Expand until non-whitespace is hit\n while (startIndex > 0 && line.charAt(startIndex - 1) === ' ') {\n startIndex--;\n }\n while (endIndex < line.length && line.charAt(endIndex + 1) === ' ') {\n endIndex++;\n }\n } else {\n // Expand until whitespace is hit. This algorithm works by scanning left\n // and right from the starting position, keeping both the index format\n // (line) and the column format (bufferLine) in sync. When a wide\n // character is hit, it is recorded and the column index is adjusted.\n let startCol = coords[0];\n let endCol = coords[0];\n\n // Consider the initial position, skip it and increment the wide char\n // variable\n if (bufferLine[startCol][CHAR_DATA_WIDTH_INDEX] === 0) {\n leftWideCharCount++;\n startCol--;\n }\n if (bufferLine[endCol][CHAR_DATA_WIDTH_INDEX] === 2) {\n rightWideCharCount++;\n endCol++;\n }\n\n // Adjust the end index for characters whose length are > 1 (emojis)\n if (bufferLine[endCol][CHAR_DATA_CHAR_INDEX].length > 1) {\n rightLongCharOffset += bufferLine[endCol][CHAR_DATA_CHAR_INDEX].length - 1;\n endIndex += bufferLine[endCol][CHAR_DATA_CHAR_INDEX].length - 1;\n }\n\n // Expand the string in both directions until a space is hit\n while (startCol > 0 && startIndex > 0 && !this._isCharWordSeparator(bufferLine[startCol - 1])) {\n const char = bufferLine[startCol - 1];\n if (char[CHAR_DATA_WIDTH_INDEX] === 0) {\n // If the next character is a wide char, record it and skip the column\n leftWideCharCount++;\n startCol--;\n } else if (char[CHAR_DATA_CHAR_INDEX].length > 1) {\n // If the next character's string is longer than 1 char (eg. emoji),\n // adjust the index\n leftLongCharOffset += char[CHAR_DATA_CHAR_INDEX].length - 1;\n startIndex -= char[CHAR_DATA_CHAR_INDEX].length - 1;\n }\n startIndex--;\n startCol--;\n }\n while (endCol < bufferLine.length && endIndex + 1 < line.length && !this._isCharWordSeparator(bufferLine[endCol + 1])) {\n const char = bufferLine[endCol + 1];\n if (char[CHAR_DATA_WIDTH_INDEX] === 2) {\n // If the next character is a wide char, record it and skip the column\n rightWideCharCount++;\n endCol++;\n } else if (char[CHAR_DATA_CHAR_INDEX].length > 1) {\n // If the next character's string is longer than 1 char (eg. emoji),\n // adjust the index\n rightLongCharOffset += char[CHAR_DATA_CHAR_INDEX].length - 1;\n endIndex += char[CHAR_DATA_CHAR_INDEX].length - 1;\n }\n endIndex++;\n endCol++;\n }\n }\n\n // Incremenet the end index so it is at the start of the next character\n endIndex++;\n\n // Calculate the start _column_, converting the the string indexes back to\n // column coordinates.\n const start =\n startIndex // The index of the selection's start char in the line string\n + charOffset // The difference between the initial char's column and index\n - leftWideCharCount // The number of wide chars left of the initial char\n + leftLongCharOffset; // The number of additional chars left of the initial char added by columns with strings longer than 1 (emojis)\n\n // Calculate the length in _columns_, converting the the string indexes back\n // to column coordinates.\n const length = Math.min(this._terminal.cols, // Disallow lengths larger than the terminal cols\n endIndex // The index of the selection's end char in the line string\n - startIndex // The index of the selection's start char in the line string\n + leftWideCharCount // The number of wide chars left of the initial char\n + rightWideCharCount // The number of wide chars right of the initial char (inclusive)\n - leftLongCharOffset // The number of additional chars left of the initial char added by columns with strings longer than 1 (emojis)\n - rightLongCharOffset); // The number of additional chars right of the initial char (inclusive) added by columns with strings longer than 1 (emojis)\n\n return { start, length };\n }\n\n /**\n * Selects the word at the coordinates specified.\n * @param coords The coordinates to get the word at.\n */\n protected _selectWordAt(coords: [number, number]): void {\n const wordPosition = this._getWordAt(coords);\n if (wordPosition) {\n this._model.selectionStart = [wordPosition.start, coords[1]];\n this._model.selectionStartLength = wordPosition.length;\n }\n }\n\n /**\n * Sets the selection end to the word at the coordinated specified.\n * @param coords The coordinates to get the word at.\n */\n private _selectToWordAt(coords: [number, number]): void {\n const wordPosition = this._getWordAt(coords);\n if (wordPosition) {\n this._model.selectionEnd = [this._model.areSelectionValuesReversed() ? wordPosition.start : (wordPosition.start + wordPosition.length), coords[1]];\n }\n }\n\n /**\n * Gets whether the character is considered a word separator by the select\n * word logic.\n * @param char The character to check.\n */\n private _isCharWordSeparator(charData: CharData): boolean {\n // Zero width characters are never separators as they are always to the\n // right of wide characters\n if (charData[CHAR_DATA_WIDTH_INDEX] === 0) {\n return false;\n }\n return WORD_SEPARATORS.indexOf(charData[CHAR_DATA_CHAR_INDEX]) >= 0;\n }\n\n /**\n * Selects the line specified.\n * @param line The line index.\n */\n protected _selectLineAt(line: number): void {\n this._model.selectionStart = [0, line];\n this._model.selectionStartLength = this._terminal.cols;\n }\n}\n","/**\n * Copyright (c) 2014 The xterm.js authors. All rights reserved.\n * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)\n * @license MIT\n */\n\nimport { C0 } from './EscapeSequences';\nimport { IInputHandler } from './Interfaces';\nimport { CHARSETS, DEFAULT_CHARSET } from './Charsets';\n\nconst normalStateHandler: {[key: string]: (parser: Parser, handler: IInputHandler) => void} = {};\nnormalStateHandler[C0.BEL] = (parser, handler) => handler.bell();\nnormalStateHandler[C0.LF] = (parser, handler) => handler.lineFeed();\nnormalStateHandler[C0.VT] = normalStateHandler[C0.LF];\nnormalStateHandler[C0.FF] = normalStateHandler[C0.LF];\nnormalStateHandler[C0.CR] = (parser, handler) => handler.carriageReturn();\nnormalStateHandler[C0.BS] = (parser, handler) => handler.backspace();\nnormalStateHandler[C0.HT] = (parser, handler) => handler.tab();\nnormalStateHandler[C0.SO] = (parser, handler) => handler.shiftOut();\nnormalStateHandler[C0.SI] = (parser, handler) => handler.shiftIn();\nnormalStateHandler[C0.ESC] = (parser, handler) => parser.setState(ParserState.ESCAPED);\n\n// TODO: Remove terminal when parser owns params and currentParam\nconst escapedStateHandler: {[key: string]: (parser: Parser, terminal: any) => void} = {};\nescapedStateHandler['['] = (parser, terminal) => {\n // ESC [ Control Sequence Introducer (CSI is 0x9b)\n terminal.params = [];\n terminal.currentParam = 0;\n parser.setState(ParserState.CSI_PARAM);\n};\nescapedStateHandler[']'] = (parser, terminal) => {\n // ESC ] Operating System Command (OSC is 0x9d)\n terminal.params = [];\n terminal.currentParam = 0;\n parser.setState(ParserState.OSC);\n};\nescapedStateHandler['P'] = (parser, terminal) => {\n // ESC P Device Control String (DCS is 0x90)\n terminal.params = [];\n terminal.currentParam = 0;\n parser.setState(ParserState.DCS);\n};\nescapedStateHandler['_'] = (parser, terminal) => {\n // ESC _ Application Program Command ( APC is 0x9f).\n parser.setState(ParserState.IGNORE);\n};\nescapedStateHandler['^'] = (parser, terminal) => {\n // ESC ^ Privacy Message ( PM is 0x9e).\n parser.setState(ParserState.IGNORE);\n};\nescapedStateHandler['c'] = (parser, terminal) => {\n // ESC c Full Reset (RIS).\n terminal.reset();\n};\nescapedStateHandler['E'] = (parser, terminal) => {\n // ESC E Next Line ( NEL is 0x85).\n terminal.buffer.x = 0;\n terminal.index();\n parser.setState(ParserState.NORMAL);\n};\nescapedStateHandler['D'] = (parser, terminal) => {\n // ESC D Index ( IND is 0x84).\n terminal.index();\n parser.setState(ParserState.NORMAL);\n};\nescapedStateHandler['M'] = (parser, terminal) => {\n // ESC M Reverse Index ( RI is 0x8d).\n terminal.reverseIndex();\n parser.setState(ParserState.NORMAL);\n};\nescapedStateHandler['%'] = (parser, terminal) => {\n // ESC % Select default/utf-8 character set.\n // @ = default, G = utf-8\n terminal.setgLevel(0);\n terminal.setgCharset(0, DEFAULT_CHARSET); // US (default)\n parser.setState(ParserState.NORMAL);\n parser.skipNextChar();\n};\nescapedStateHandler[C0.CAN] = (parser) => parser.setState(ParserState.NORMAL);\n\nconst csiParamStateHandler: {[key: string]: (parser: Parser) => void} = {};\ncsiParamStateHandler['?'] = (parser) => parser.setPrefix('?');\ncsiParamStateHandler['>'] = (parser) => parser.setPrefix('>');\ncsiParamStateHandler['!'] = (parser) => parser.setPrefix('!');\ncsiParamStateHandler['0'] = (parser) => parser.setParam(parser.getParam() * 10);\ncsiParamStateHandler['1'] = (parser) => parser.setParam(parser.getParam() * 10 + 1);\ncsiParamStateHandler['2'] = (parser) => parser.setParam(parser.getParam() * 10 + 2);\ncsiParamStateHandler['3'] = (parser) => parser.setParam(parser.getParam() * 10 + 3);\ncsiParamStateHandler['4'] = (parser) => parser.setParam(parser.getParam() * 10 + 4);\ncsiParamStateHandler['5'] = (parser) => parser.setParam(parser.getParam() * 10 + 5);\ncsiParamStateHandler['6'] = (parser) => parser.setParam(parser.getParam() * 10 + 6);\ncsiParamStateHandler['7'] = (parser) => parser.setParam(parser.getParam() * 10 + 7);\ncsiParamStateHandler['8'] = (parser) => parser.setParam(parser.getParam() * 10 + 8);\ncsiParamStateHandler['9'] = (parser) => parser.setParam(parser.getParam() * 10 + 9);\ncsiParamStateHandler['$'] = (parser) => parser.setPostfix('$');\ncsiParamStateHandler['\"'] = (parser) => parser.setPostfix('\"');\ncsiParamStateHandler[' '] = (parser) => parser.setPostfix(' ');\ncsiParamStateHandler['\\''] = (parser) => parser.setPostfix('\\'');\ncsiParamStateHandler[';'] = (parser) => parser.finalizeParam();\ncsiParamStateHandler[C0.CAN] = (parser) => parser.setState(ParserState.NORMAL);\n\nconst csiStateHandler: {[key: string]: (handler: IInputHandler, params: number[], prefix: string, postfix: string, parser: Parser) => void} = {};\ncsiStateHandler['@'] = (handler, params, prefix) => handler.insertChars(params);\ncsiStateHandler['A'] = (handler, params, prefix) => handler.cursorUp(params);\ncsiStateHandler['B'] = (handler, params, prefix) => handler.cursorDown(params);\ncsiStateHandler['C'] = (handler, params, prefix) => handler.cursorForward(params);\ncsiStateHandler['D'] = (handler, params, prefix) => handler.cursorBackward(params);\ncsiStateHandler['E'] = (handler, params, prefix) => handler.cursorNextLine(params);\ncsiStateHandler['F'] = (handler, params, prefix) => handler.cursorPrecedingLine(params);\ncsiStateHandler['G'] = (handler, params, prefix) => handler.cursorCharAbsolute(params);\ncsiStateHandler['H'] = (handler, params, prefix) => handler.cursorPosition(params);\ncsiStateHandler['I'] = (handler, params, prefix) => handler.cursorForwardTab(params);\ncsiStateHandler['J'] = (handler, params, prefix) => handler.eraseInDisplay(params);\ncsiStateHandler['K'] = (handler, params, prefix) => handler.eraseInLine(params);\ncsiStateHandler['L'] = (handler, params, prefix) => handler.insertLines(params);\ncsiStateHandler['M'] = (handler, params, prefix) => handler.deleteLines(params);\ncsiStateHandler['P'] = (handler, params, prefix) => handler.deleteChars(params);\ncsiStateHandler['S'] = (handler, params, prefix) => handler.scrollUp(params);\ncsiStateHandler['T'] = (handler, params, prefix) => {\n if (params.length < 2 && !prefix) {\n handler.scrollDown(params);\n }\n};\ncsiStateHandler['X'] = (handler, params, prefix) => handler.eraseChars(params);\ncsiStateHandler['Z'] = (handler, params, prefix) => handler.cursorBackwardTab(params);\ncsiStateHandler['`'] = (handler, params, prefix) => handler.charPosAbsolute(params);\ncsiStateHandler['a'] = (handler, params, prefix) => handler.HPositionRelative(params);\ncsiStateHandler['b'] = (handler, params, prefix) => handler.repeatPrecedingCharacter(params);\ncsiStateHandler['c'] = (handler, params, prefix) => handler.sendDeviceAttributes(params);\ncsiStateHandler['d'] = (handler, params, prefix) => handler.linePosAbsolute(params);\ncsiStateHandler['e'] = (handler, params, prefix) => handler.VPositionRelative(params);\ncsiStateHandler['f'] = (handler, params, prefix) => handler.HVPosition(params);\ncsiStateHandler['g'] = (handler, params, prefix) => handler.tabClear(params);\ncsiStateHandler['h'] = (handler, params, prefix) => handler.setMode(params);\ncsiStateHandler['l'] = (handler, params, prefix) => handler.resetMode(params);\ncsiStateHandler['m'] = (handler, params, prefix) => handler.charAttributes(params);\ncsiStateHandler['n'] = (handler, params, prefix) => handler.deviceStatus(params);\ncsiStateHandler['p'] = (handler, params, prefix) => {\n switch (prefix) {\n case '!': handler.softReset(params); break;\n }\n};\ncsiStateHandler['q'] = (handler, params, prefix, postfix) => {\n if (postfix === ' ') {\n handler.setCursorStyle(params);\n }\n};\ncsiStateHandler['r'] = (handler, params) => handler.setScrollRegion(params);\ncsiStateHandler['s'] = (handler, params) => handler.saveCursor(params);\ncsiStateHandler['u'] = (handler, params) => handler.restoreCursor(params);\ncsiStateHandler[C0.CAN] = (handler, params, prefix, postfix, parser) => parser.setState(ParserState.NORMAL);\n\nexport enum ParserState {\n NORMAL = 0,\n ESCAPED = 1,\n CSI_PARAM = 2,\n CSI = 3,\n OSC = 4,\n CHARSET = 5,\n DCS = 6,\n IGNORE = 7\n}\n\n/**\n * The terminal's parser, all input into the terminal goes through the parser\n * which parses and defers the actual input handling the the IInputHandler\n * specified in the constructor.\n */\nexport class Parser {\n private _state: ParserState;\n private _position: number;\n\n // TODO: Remove terminal when handler can do everything\n constructor(\n private _inputHandler: IInputHandler,\n private _terminal: any\n ) {\n this._state = ParserState.NORMAL;\n }\n\n /**\n * Parse and handle data.\n *\n * @param data The data to parse.\n */\n public parse(data: string): ParserState {\n const l = data.length;\n let j;\n let cs;\n let ch;\n let code;\n let low;\n\n const cursorStartX = this._terminal.buffer.x;\n const cursorStartY = this._terminal.buffer.y;\n\n if (this._terminal.debug) {\n this._terminal.log('data: ' + data);\n }\n\n this._position = 0;\n // apply leftover surrogate high from last write\n if (this._terminal.surrogate_high) {\n data = this._terminal.surrogate_high + data;\n this._terminal.surrogate_high = '';\n }\n\n for (; this._position < l; this._position++) {\n ch = data[this._position];\n\n // FIXME: higher chars than 0xa0 are not allowed in escape sequences\n // --> maybe move to default\n code = data.charCodeAt(this._position);\n if (0xD800 <= code && code <= 0xDBFF) {\n // we got a surrogate high\n // get surrogate low (next 2 bytes)\n low = data.charCodeAt(this._position + 1);\n if (isNaN(low)) {\n // end of data stream, save surrogate high\n this._terminal.surrogate_high = ch;\n continue;\n }\n code = ((code - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;\n ch += data.charAt(this._position + 1);\n }\n // surrogate low - already handled above\n if (0xDC00 <= code && code <= 0xDFFF)\n continue;\n\n switch (this._state) {\n case ParserState.NORMAL:\n if (ch in normalStateHandler) {\n normalStateHandler[ch](this, this._inputHandler);\n } else {\n this._inputHandler.addChar(ch, code);\n }\n break;\n case ParserState.ESCAPED:\n if (ch in escapedStateHandler) {\n escapedStateHandler[ch](this, this._terminal);\n // Skip switch as it was just handled\n break;\n }\n switch (ch) {\n\n // ESC (,),*,+,-,. Designate G0-G2 Character Set.\n case '(': // <-- this seems to get all the attention\n case ')':\n case '*':\n case '+':\n case '-':\n case '.':\n switch (ch) {\n case '(':\n this._terminal.gcharset = 0;\n break;\n case ')':\n this._terminal.gcharset = 1;\n break;\n case '*':\n this._terminal.gcharset = 2;\n break;\n case '+':\n this._terminal.gcharset = 3;\n break;\n case '-':\n this._terminal.gcharset = 1;\n break;\n case '.':\n this._terminal.gcharset = 2;\n break;\n }\n this._state = ParserState.CHARSET;\n break;\n\n // Designate G3 Character Set (VT300).\n // A = ISO Latin-1 Supplemental.\n // Not implemented.\n case '/':\n this._terminal.gcharset = 3;\n this._state = ParserState.CHARSET;\n this._position--;\n break;\n\n // ESC N\n // Single Shift Select of G2 Character Set\n // ( SS2 is 0x8e). This affects next character only.\n case 'N':\n break;\n // ESC O\n // Single Shift Select of G3 Character Set\n // ( SS3 is 0x8f). This affects next character only.\n case 'O':\n break;\n // ESC n\n // Invoke the G2 Character Set as GL (LS2).\n case 'n':\n this._terminal.setgLevel(2);\n break;\n // ESC o\n // Invoke the G3 Character Set as GL (LS3).\n case 'o':\n this._terminal.setgLevel(3);\n break;\n // ESC |\n // Invoke the G3 Character Set as GR (LS3R).\n case '|':\n this._terminal.setgLevel(3);\n break;\n // ESC }\n // Invoke the G2 Character Set as GR (LS2R).\n case '}':\n this._terminal.setgLevel(2);\n break;\n // ESC ~\n // Invoke the G1 Character Set as GR (LS1R).\n case '~':\n this._terminal.setgLevel(1);\n break;\n\n // ESC 7 Save Cursor (DECSC).\n case '7':\n this._inputHandler.saveCursor();\n this._state = ParserState.NORMAL;\n break;\n\n // ESC 8 Restore Cursor (DECRC).\n case '8':\n this._inputHandler.restoreCursor();\n this._state = ParserState.NORMAL;\n break;\n\n // ESC # 3 DEC line height/width\n case '#':\n this._state = ParserState.NORMAL;\n this._position++;\n break;\n\n // ESC H Tab Set (HTS is 0x88).\n case 'H':\n this._terminal.tabSet();\n this._state = ParserState.NORMAL;\n break;\n\n // ESC = Application Keypad (DECKPAM).\n case '=':\n this._terminal.log('Serial port requested application keypad.');\n this._terminal.applicationKeypad = true;\n if (this._terminal.viewport) {\n this._terminal.viewport.syncScrollArea();\n }\n this._state = ParserState.NORMAL;\n break;\n\n // ESC > Normal Keypad (DECKPNM).\n case '>':\n this._terminal.log('Switching back to normal keypad.');\n this._terminal.applicationKeypad = false;\n if (this._terminal.viewport) {\n this._terminal.viewport.syncScrollArea();\n }\n this._state = ParserState.NORMAL;\n break;\n\n default:\n this._state = ParserState.NORMAL;\n this._terminal.error('Unknown ESC control: %s.', ch);\n break;\n }\n break;\n\n case ParserState.CHARSET:\n if (ch in CHARSETS) {\n cs = CHARSETS[ch];\n if (ch === '/') { // ISOLatin is actually /A\n this.skipNextChar();\n }\n } else {\n cs = DEFAULT_CHARSET;\n }\n this._terminal.setgCharset(this._terminal.gcharset, cs);\n this._terminal.gcharset = null;\n this._state = ParserState.NORMAL;\n break;\n\n case ParserState.OSC:\n // OSC Ps ; Pt ST\n // OSC Ps ; Pt BEL\n // Set Text Parameters.\n if (ch === C0.ESC || ch === C0.BEL) {\n if (ch === C0.ESC) this._position++;\n\n this._terminal.params.push(this._terminal.currentParam);\n\n switch (this._terminal.params[0]) {\n case 0:\n case 1:\n case 2:\n if (this._terminal.params[1]) {\n this._terminal.title = this._terminal.params[1];\n this._terminal.handleTitle(this._terminal.title);\n }\n break;\n case 3:\n // set X property\n break;\n case 4:\n case 5:\n // change dynamic colors\n break;\n case 10:\n case 11:\n case 12:\n case 13:\n case 14:\n case 15:\n case 16:\n case 17:\n case 18:\n case 19:\n // change dynamic ui colors\n break;\n case 46:\n // change log file\n break;\n case 50:\n // dynamic font\n break;\n case 51:\n // emacs shell\n break;\n case 52:\n // manipulate selection data\n break;\n case 104:\n case 105:\n case 110:\n case 111:\n case 112:\n case 113:\n case 114:\n case 115:\n case 116:\n case 117:\n case 118:\n // reset colors\n break;\n }\n\n this._terminal.params = [];\n this._terminal.currentParam = 0;\n this._state = ParserState.NORMAL;\n } else {\n if (!this._terminal.params.length) {\n if (ch >= '0' && ch <= '9') {\n this._terminal.currentParam =\n this._terminal.currentParam * 10 + ch.charCodeAt(0) - 48;\n } else if (ch === ';') {\n this._terminal.params.push(this._terminal.currentParam);\n this._terminal.currentParam = '';\n }\n } else {\n this._terminal.currentParam += ch;\n }\n }\n break;\n\n case ParserState.CSI_PARAM:\n if (ch in csiParamStateHandler) {\n csiParamStateHandler[ch](this);\n break;\n }\n this.finalizeParam();\n // Fall through the CSI as this character should be the CSI code.\n this._state = ParserState.CSI;\n\n case ParserState.CSI:\n if (ch in csiStateHandler) {\n if (this._terminal.debug) {\n this._terminal.log(`CSI ${this._terminal.prefix ? this._terminal.prefix : ''} ${this._terminal.params ? this._terminal.params.join(';') : ''} ${this._terminal.postfix ? this._terminal.postfix : ''} ${ch}`);\n }\n csiStateHandler[ch](this._inputHandler, this._terminal.params, this._terminal.prefix, this._terminal.postfix, this);\n } else {\n this._terminal.error('Unknown CSI code: %s.', ch);\n }\n\n this._state = ParserState.NORMAL;\n this._terminal.prefix = '';\n this._terminal.postfix = '';\n break;\n\n case ParserState.DCS:\n if (ch === C0.ESC || ch === C0.BEL) {\n if (ch === C0.ESC) this._position++;\n let pt;\n let valid: boolean;\n\n switch (this._terminal.prefix) {\n // User-Defined Keys (DECUDK).\n case '':\n break;\n\n // Request Status String (DECRQSS).\n // test: echo -e '\\eP$q\"p\\e\\\\'\n case '$q':\n pt = this._terminal.currentParam;\n valid = false;\n\n switch (pt) {\n // DECSCA\n case '\"q':\n pt = '0\"q';\n break;\n\n // DECSCL\n case '\"p':\n pt = '61\"p';\n break;\n\n // DECSTBM\n case 'r':\n pt = ''\n + (this._terminal.buffer.scrollTop + 1)\n + ';'\n + (this._terminal.buffer.scrollBottom + 1)\n + 'r';\n break;\n\n // SGR\n case 'm':\n pt = '0m';\n break;\n\n default:\n this._terminal.error('Unknown DCS Pt: %s.', pt);\n pt = '';\n break;\n }\n\n this._terminal.send(C0.ESC + 'P' + +valid + '$r' + pt + C0.ESC + '\\\\');\n break;\n\n // Set Termcap/Terminfo Data (xterm, experimental).\n case '+p':\n break;\n\n // Request Termcap/Terminfo String (xterm, experimental)\n // Regular xterm does not even respond to this sequence.\n // This can cause a small glitch in vim.\n // test: echo -ne '\\eP+q6b64\\e\\\\'\n case '+q':\n pt = this._terminal.currentParam;\n valid = false;\n\n this._terminal.send(C0.ESC + 'P' + +valid + '+r' + pt + C0.ESC + '\\\\');\n break;\n\n default:\n this._terminal.error('Unknown DCS prefix: %s.', this._terminal.prefix);\n break;\n }\n\n this._terminal.currentParam = 0;\n this._terminal.prefix = '';\n this._state = ParserState.NORMAL;\n } else if (!this._terminal.currentParam) {\n if (!this._terminal.prefix && ch !== '$' && ch !== '+') {\n this._terminal.currentParam = ch;\n } else if (this._terminal.prefix.length === 2) {\n this._terminal.currentParam = ch;\n } else {\n this._terminal.prefix += ch;\n }\n } else {\n this._terminal.currentParam += ch;\n }\n break;\n\n case ParserState.IGNORE:\n // For PM and APC.\n if (ch === C0.ESC || ch === C0.BEL) {\n if (ch === C0.ESC) this._position++;\n this._state = ParserState.NORMAL;\n }\n break;\n }\n }\n\n // Fire the cursormove event if it's moved. This is done inside the parser\n // as a render cannot happen in the middle of a parsing round.\n if (this._terminal.buffer.x !== cursorStartX || this._terminal.buffer.y !== cursorStartY) {\n this._terminal.emit('cursormove');\n }\n\n return this._state;\n }\n\n /**\n * Set the parser's current parsing state.\n *\n * @param state The new state.\n */\n public setState(state: ParserState): void {\n this._state = state;\n }\n\n /**\n * Sets the parsier's current prefix. CSI codes can have prefixes of '?', '>'\n * or '!'.\n *\n * @param prefix The prefix.\n */\n public setPrefix(prefix: string): void {\n this._terminal.prefix = prefix;\n }\n\n /**\n * Sets the parsier's current prefix. CSI codes can have postfixes of '$',\n * '\"', ' ', '\\''.\n *\n * @param postfix The postfix.\n */\n public setPostfix(postfix: string): void {\n this._terminal.postfix = postfix;\n }\n\n /**\n * Sets the parser's current parameter.\n *\n * @param param the parameter.\n */\n public setParam(param: number): void {\n this._terminal.currentParam = param;\n }\n\n /**\n * Gets the parser's current parameter.\n */\n public getParam(): number {\n return this._terminal.currentParam;\n }\n\n /**\n * Finalizes the parser's current parameter, adding it to the list of\n * parameters and setting the new current parameter to 0.\n */\n public finalizeParam(): void {\n this._terminal.params.push(this._terminal.currentParam);\n this._terminal.currentParam = 0;\n }\n\n /**\n * Tell the parser to skip the next character.\n */\n public skipNextChar(): void {\n this._position++;\n }\n\n /**\n * Tell the parser to repeat parsing the current character (for example if it\n * needs parsing using a different state.\n */\n // public repeatChar(): void {\n // this._position--;\n // }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ILinkMatcherOptions, ITerminal, IBufferAccessor, ILinkifier, IElementAccessor } from './Interfaces';\nimport { LinkMatcher, LinkMatcherHandler, LinkMatcherValidationCallback, LineData, LinkHoverEvent, LinkHoverEventTypes } from './Types';\nimport { IMouseZoneManager } from './input/Interfaces';\nimport { MouseZone } from './input/MouseZoneManager';\nimport { EventEmitter } from './EventEmitter';\n\nconst protocolClause = '(https?:\\\\/\\\\/)';\nconst domainCharacterSet = '[\\\\da-z\\\\.-]+';\nconst negatedDomainCharacterSet = '[^\\\\da-z\\\\.-]+';\nconst domainBodyClause = '(' + domainCharacterSet + ')';\nconst tldClause = '([a-z\\\\.]{2,6})';\nconst ipClause = '((\\\\d{1,3}\\\\.){3}\\\\d{1,3})';\nconst localHostClause = '(localhost)';\nconst portClause = '(:\\\\d{1,5})';\nconst hostClause = '((' + domainBodyClause + '\\\\.' + tldClause + ')|' + ipClause + '|' + localHostClause + ')' + portClause + '?';\nconst pathClause = '(\\\\/[\\\\/\\\\w\\\\.\\\\-%~]*)*';\nconst queryStringHashFragmentCharacterSet = '[0-9\\\\w\\\\[\\\\]\\\\(\\\\)\\\\/\\\\?\\\\!#@$%&\\'*+,:;~\\\\=\\\\.\\\\-]*';\nconst queryStringClause = '(\\\\?' + queryStringHashFragmentCharacterSet + ')?';\nconst hashFragmentClause = '(#' + queryStringHashFragmentCharacterSet + ')?';\nconst negatedPathCharacterSet = '[^\\\\/\\\\w\\\\.\\\\-%]+';\nconst bodyClause = hostClause + pathClause + queryStringClause + hashFragmentClause;\nconst start = '(?:^|' + negatedDomainCharacterSet + ')(';\nconst end = ')($|' + negatedPathCharacterSet + ')';\nconst strictUrlRegex = new RegExp(start + protocolClause + bodyClause + end);\n\n/**\n * The ID of the built in http(s) link matcher.\n */\nconst HYPERTEXT_LINK_MATCHER_ID = 0;\n\n/**\n * The Linkifier applies links to rows shortly after they have been refreshed.\n */\nexport class Linkifier extends EventEmitter implements ILinkifier {\n /**\n * The time to wait after a row is changed before it is linkified. This prevents\n * the costly operation of searching every row multiple times, potentially a\n * huge amount of times.\n */\n protected static TIME_BEFORE_LINKIFY = 200;\n\n protected _linkMatchers: LinkMatcher[] = [];\n\n private _mouseZoneManager: IMouseZoneManager;\n private _rowsTimeoutId: number;\n private _nextLinkMatcherId = HYPERTEXT_LINK_MATCHER_ID;\n private _rowsToLinkify: {start: number, end: number};\n\n constructor(\n protected _terminal: IBufferAccessor & IElementAccessor\n ) {\n super();\n this._rowsToLinkify = {\n start: null,\n end: null\n };\n this.registerLinkMatcher(strictUrlRegex, null, { matchIndex: 1 });\n }\n\n /**\n * Attaches the linkifier to the DOM, enabling linkification.\n * @param mouseZoneManager The mouse zone manager to register link zones with.\n */\n public attachToDom(mouseZoneManager: IMouseZoneManager): void {\n this._mouseZoneManager = mouseZoneManager;\n }\n\n /**\n * Queue linkification on a set of rows.\n * @param start The row to linkify from (inclusive).\n * @param end The row to linkify to (inclusive).\n */\n public linkifyRows(start: number, end: number): void {\n // Don't attempt linkify if not yet attached to DOM\n if (!this._mouseZoneManager) {\n return;\n }\n\n // Increase range to linkify\n if (!this._rowsToLinkify.start) {\n this._rowsToLinkify.start = start;\n this._rowsToLinkify.end = end;\n } else {\n this._rowsToLinkify.start = this._rowsToLinkify.start < start ? this._rowsToLinkify.start : start;\n this._rowsToLinkify.end = this._rowsToLinkify.end > end ? this._rowsToLinkify.end : end;\n }\n\n // Clear out any existing links on this row range\n this._mouseZoneManager.clearAll(start, end);\n\n // Restart timer\n if (this._rowsTimeoutId) {\n clearTimeout(this._rowsTimeoutId);\n }\n this._rowsTimeoutId = setTimeout(() => this._linkifyRows(), Linkifier.TIME_BEFORE_LINKIFY);\n }\n\n /**\n * Linkifies the rows requested.\n */\n private _linkifyRows(): void {\n this._rowsTimeoutId = null;\n for (let i = this._rowsToLinkify.start; i <= this._rowsToLinkify.end; i++) {\n this._linkifyRow(i);\n }\n this._rowsToLinkify.start = null;\n this._rowsToLinkify.end = null;\n }\n\n /**\n * Attaches a handler for hypertext links, overriding default behavior for\n * tandard http(s) links.\n * @param handler The handler to use, this can be cleared with null.\n */\n public setHypertextLinkHandler(handler: LinkMatcherHandler): void {\n this._linkMatchers[HYPERTEXT_LINK_MATCHER_ID].handler = handler;\n }\n\n /**\n * Attaches a validation callback for hypertext links.\n * @param callback The callback to use, this can be cleared with null.\n */\n public setHypertextValidationCallback(callback: LinkMatcherValidationCallback): void {\n this._linkMatchers[HYPERTEXT_LINK_MATCHER_ID].validationCallback = callback;\n }\n\n /**\n * Registers a link matcher, allowing custom link patterns to be matched and\n * handled.\n * @param regex The regular expression to search for. Specifically, this\n * searches the textContent of the rows. You will want to use \\s to match a\n * space ' ' character for example.\n * @param handler The callback when the link is called.\n * @param options Options for the link matcher.\n * @return The ID of the new matcher, this can be used to deregister.\n */\n public registerLinkMatcher(regex: RegExp, handler: LinkMatcherHandler, options: ILinkMatcherOptions = {}): number {\n if (this._nextLinkMatcherId !== HYPERTEXT_LINK_MATCHER_ID && !handler) {\n throw new Error('handler must be defined');\n }\n const matcher: LinkMatcher = {\n id: this._nextLinkMatcherId++,\n regex,\n handler,\n matchIndex: options.matchIndex,\n validationCallback: options.validationCallback,\n hoverTooltipCallback: options.tooltipCallback,\n hoverLeaveCallback: options.leaveCallback,\n priority: options.priority || 0\n };\n this._addLinkMatcherToList(matcher);\n return matcher.id;\n }\n\n /**\n * Inserts a link matcher to the list in the correct position based on the\n * priority of each link matcher. New link matchers of equal priority are\n * considered after older link matchers.\n * @param matcher The link matcher to be added.\n */\n private _addLinkMatcherToList(matcher: LinkMatcher): void {\n if (this._linkMatchers.length === 0) {\n this._linkMatchers.push(matcher);\n return;\n }\n\n for (let i = this._linkMatchers.length - 1; i >= 0; i--) {\n if (matcher.priority <= this._linkMatchers[i].priority) {\n this._linkMatchers.splice(i + 1, 0, matcher);\n return;\n }\n }\n\n this._linkMatchers.splice(0, 0, matcher);\n }\n\n /**\n * Deregisters a link matcher if it has been registered.\n * @param matcherId The link matcher's ID (returned after register)\n * @return Whether a link matcher was found and deregistered.\n */\n public deregisterLinkMatcher(matcherId: number): boolean {\n // ID 0 is the hypertext link matcher which cannot be deregistered\n for (let i = 1; i < this._linkMatchers.length; i++) {\n if (this._linkMatchers[i].id === matcherId) {\n this._linkMatchers.splice(i, 1);\n return true;\n }\n }\n return false;\n }\n\n /**\n * Linkifies a row.\n * @param rowIndex The index of the row to linkify.\n */\n private _linkifyRow(rowIndex: number): void {\n const absoluteRowIndex = this._terminal.buffer.ydisp + rowIndex;\n if (absoluteRowIndex >= this._terminal.buffer.lines.length) {\n return;\n }\n const text = this._terminal.buffer.translateBufferLineToString(absoluteRowIndex, false);\n for (let i = 0; i < this._linkMatchers.length; i++) {\n this._doLinkifyRow(rowIndex, text, this._linkMatchers[i]);\n }\n }\n\n /**\n * Linkifies a row given a specific handler.\n * @param rowIndex The row index to linkify.\n * @param text The text of the row (excludes text in the row that's already\n * linkified).\n * @param matcher The link matcher for this line.\n * @param offset The how much of the row has already been linkified.\n * @return The link element(s) that were added.\n */\n private _doLinkifyRow(rowIndex: number, text: string, matcher: LinkMatcher, offset: number = 0): void {\n // Iterate over nodes as we want to consider text nodes\n let result = [];\n const isHttpLinkMatcher = matcher.id === HYPERTEXT_LINK_MATCHER_ID;\n\n // Find the first match\n let match = text.match(matcher.regex);\n if (!match || match.length === 0) {\n return;\n }\n let uri = match[typeof matcher.matchIndex !== 'number' ? 0 : matcher.matchIndex];\n\n // Get index, match.index is for the outer match which includes negated chars\n const index = text.indexOf(uri);\n\n // Ensure the link is valid before registering\n if (matcher.validationCallback) {\n matcher.validationCallback(uri, isValid => {\n // Discard link if the line has already changed\n if (this._rowsTimeoutId) {\n return;\n }\n if (isValid) {\n this._addLink(offset + index, rowIndex, uri, matcher);\n }\n });\n } else {\n this._addLink(offset + index, rowIndex, uri, matcher);\n }\n\n // Recursively check for links in the rest of the text\n const remainingStartIndex = index + uri.length;\n const remainingText = text.substr(remainingStartIndex);\n if (remainingText.length > 0) {\n this._doLinkifyRow(rowIndex, remainingText, matcher, offset + remainingStartIndex);\n }\n }\n\n /**\n * Registers a link to the mouse zone manager.\n * @param x The column the link starts.\n * @param y The row the link is on.\n * @param uri The URI of the link.\n * @param matcher The link matcher for the link.\n */\n private _addLink(x: number, y: number, uri: string, matcher: LinkMatcher): void {\n this._mouseZoneManager.add(new MouseZone(\n x + 1,\n x + 1 + uri.length,\n y + 1,\n e => {\n if (matcher.handler) {\n return matcher.handler(e, uri);\n }\n window.open(uri, '_blank');\n },\n e => {\n this.emit(LinkHoverEventTypes.HOVER, { x, y, length: uri.length});\n this._terminal.element.style.cursor = 'pointer';\n },\n e => {\n this.emit(LinkHoverEventTypes.TOOLTIP, { x, y, length: uri.length});\n if (matcher.hoverTooltipCallback) {\n matcher.hoverTooltipCallback(e, uri);\n }\n },\n () => {\n this.emit(LinkHoverEventTypes.LEAVE, { x, y, length: uri.length});\n this._terminal.element.style.cursor = '';\n if (matcher.hoverLeaveCallback) {\n matcher.hoverLeaveCallback();\n }\n }\n ));\n }\n}\n","/**\n * Copyright (c) 2014 The xterm.js authors. All rights reserved.\n * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)\n * @license MIT\n */\n\nimport { IInputHandler, ITerminal, IInputHandlingTerminal } from './Interfaces';\nimport { C0 } from './EscapeSequences';\nimport { DEFAULT_CHARSET } from './Charsets';\nimport { CharData } from './Types';\nimport { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX } from './Buffer';\nimport { FLAGS } from './renderer/Types';\nimport { wcwidth } from './CharWidth';\n\n/**\n * The terminal's standard implementation of IInputHandler, this handles all\n * input from the Parser.\n *\n * Refer to http://invisible-island.net/xterm/ctlseqs/ctlseqs.html to understand\n * each function's header comment.\n */\nexport class InputHandler implements IInputHandler {\n constructor(private _terminal: IInputHandlingTerminal) { }\n\n public addChar(char: string, code: number): void {\n if (char >= ' ') {\n // calculate print space\n // expensive call, therefore we save width in line buffer\n const ch_width = wcwidth(code);\n\n if (this._terminal.charset && this._terminal.charset[char]) {\n char = this._terminal.charset[char];\n }\n\n let row = this._terminal.buffer.y + this._terminal.buffer.ybase;\n\n // insert combining char in last cell\n // FIXME: needs handling after cursor jumps\n if (!ch_width && this._terminal.buffer.x) {\n // dont overflow left\n if (this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1]) {\n if (!this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][CHAR_DATA_WIDTH_INDEX]) {\n // found empty cell after fullwidth, need to go 2 cells back\n if (this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2]) {\n this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2][CHAR_DATA_CHAR_INDEX] += char;\n this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2][3] = char.charCodeAt(0);\n }\n } else {\n this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][CHAR_DATA_CHAR_INDEX] += char;\n this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][3] = char.charCodeAt(0);\n }\n this._terminal.updateRange(this._terminal.buffer.y);\n }\n return;\n }\n\n // goto next line if ch would overflow\n // TODO: needs a global min terminal width of 2\n if (this._terminal.buffer.x + ch_width - 1 >= this._terminal.cols) {\n // autowrap - DECAWM\n if (this._terminal.wraparoundMode) {\n this._terminal.buffer.x = 0;\n this._terminal.buffer.y++;\n if (this._terminal.buffer.y > this._terminal.buffer.scrollBottom) {\n this._terminal.buffer.y--;\n this._terminal.scroll(true);\n } else {\n // The line already exists (eg. the initial viewport), mark it as a\n // wrapped line\n (this._terminal.buffer.lines.get(this._terminal.buffer.y)).isWrapped = true;\n }\n } else {\n if (ch_width === 2) // FIXME: check for xterm behavior\n return;\n }\n }\n row = this._terminal.buffer.y + this._terminal.buffer.ybase;\n\n // insert mode: move characters to right\n if (this._terminal.insertMode) {\n // do this twice for a fullwidth char\n for (let moves = 0; moves < ch_width; ++moves) {\n // remove last cell, if it's width is 0\n // we have to adjust the second last cell as well\n const removed = this._terminal.buffer.lines.get(this._terminal.buffer.y + this._terminal.buffer.ybase).pop();\n if (removed[CHAR_DATA_WIDTH_INDEX] === 0\n && this._terminal.buffer.lines.get(row)[this._terminal.cols - 2]\n && this._terminal.buffer.lines.get(row)[this._terminal.cols - 2][CHAR_DATA_WIDTH_INDEX] === 2) {\n this._terminal.buffer.lines.get(row)[this._terminal.cols - 2] = [this._terminal.curAttr, ' ', 1, ' '.charCodeAt(0)];\n }\n\n // insert empty cell at cursor\n this._terminal.buffer.lines.get(row).splice(this._terminal.buffer.x, 0, [this._terminal.curAttr, ' ', 1, ' '.charCodeAt(0)]);\n }\n }\n\n this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, char, ch_width, char.charCodeAt(0)];\n this._terminal.buffer.x++;\n this._terminal.updateRange(this._terminal.buffer.y);\n\n // fullwidth char - set next cell width to zero and advance cursor\n if (ch_width === 2) {\n this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, '', 0, undefined];\n this._terminal.buffer.x++;\n }\n }\n }\n\n /**\n * BEL\n * Bell (Ctrl-G).\n */\n public bell(): void {\n this._terminal.bell();\n }\n\n /**\n * LF\n * Line Feed or New Line (NL). (LF is Ctrl-J).\n */\n public lineFeed(): void {\n if (this._terminal.convertEol) {\n this._terminal.buffer.x = 0;\n }\n this._terminal.buffer.y++;\n if (this._terminal.buffer.y > this._terminal.buffer.scrollBottom) {\n this._terminal.buffer.y--;\n this._terminal.scroll();\n }\n // If the end of the line is hit, prevent this action from wrapping around to the next line.\n if (this._terminal.buffer.x >= this._terminal.cols) {\n this._terminal.buffer.x--;\n }\n /**\n * This event is emitted whenever the terminal outputs a LF or NL.\n *\n * @event lineFeed\n */\n this._terminal.emit('lineFeed');\n }\n\n /**\n * CR\n * Carriage Return (Ctrl-M).\n */\n public carriageReturn(): void {\n this._terminal.buffer.x = 0;\n }\n\n /**\n * BS\n * Backspace (Ctrl-H).\n */\n public backspace(): void {\n if (this._terminal.buffer.x > 0) {\n this._terminal.buffer.x--;\n }\n }\n\n /**\n * TAB\n * Horizontal Tab (HT) (Ctrl-I).\n */\n public tab(): void {\n this._terminal.buffer.x = this._terminal.buffer.nextStop();\n }\n\n /**\n * SO\n * Shift Out (Ctrl-N) -> Switch to Alternate Character Set. This invokes the\n * G1 character set.\n */\n public shiftOut(): void {\n this._terminal.setgLevel(1);\n }\n\n /**\n * SI\n * Shift In (Ctrl-O) -> Switch to Standard Character Set. This invokes the G0\n * character set (the default).\n */\n public shiftIn(): void {\n this._terminal.setgLevel(0);\n }\n\n /**\n * CSI Ps @\n * Insert Ps (Blank) Character(s) (default = 1) (ICH).\n */\n public insertChars(params: number[]): void {\n let param = params[0];\n if (param < 1) param = 1;\n\n const row = this._terminal.buffer.y + this._terminal.buffer.ybase;\n let j = this._terminal.buffer.x;\n const ch: CharData = [this._terminal.eraseAttr(), ' ', 1, 32]; // xterm\n\n while (param-- && j < this._terminal.cols) {\n this._terminal.buffer.lines.get(row).splice(j++, 0, ch);\n this._terminal.buffer.lines.get(row).pop();\n }\n }\n\n /**\n * CSI Ps A\n * Cursor Up Ps Times (default = 1) (CUU).\n */\n public cursorUp(params: number[]): void {\n let param = params[0];\n if (param < 1) {\n param = 1;\n }\n this._terminal.buffer.y -= param;\n if (this._terminal.buffer.y < 0) {\n this._terminal.buffer.y = 0;\n }\n }\n\n /**\n * CSI Ps B\n * Cursor Down Ps Times (default = 1) (CUD).\n */\n public cursorDown(params: number[]): void {\n let param = params[0];\n if (param < 1) {\n param = 1;\n }\n this._terminal.buffer.y += param;\n if (this._terminal.buffer.y >= this._terminal.rows) {\n this._terminal.buffer.y = this._terminal.rows - 1;\n }\n // If the end of the line is hit, prevent this action from wrapping around to the next line.\n if (this._terminal.buffer.x >= this._terminal.cols) {\n this._terminal.buffer.x--;\n }\n }\n\n /**\n * CSI Ps C\n * Cursor Forward Ps Times (default = 1) (CUF).\n */\n public cursorForward(params: number[]): void {\n let param = params[0];\n if (param < 1) {\n param = 1;\n }\n this._terminal.buffer.x += param;\n if (this._terminal.buffer.x >= this._terminal.cols) {\n this._terminal.buffer.x = this._terminal.cols - 1;\n }\n }\n\n /**\n * CSI Ps D\n * Cursor Backward Ps Times (default = 1) (CUB).\n */\n public cursorBackward(params: number[]): void {\n let param = params[0];\n if (param < 1) {\n param = 1;\n }\n // If the end of the line is hit, prevent this action from wrapping around to the next line.\n if (this._terminal.buffer.x >= this._terminal.cols) {\n this._terminal.buffer.x--;\n }\n this._terminal.buffer.x -= param;\n if (this._terminal.buffer.x < 0) {\n this._terminal.buffer.x = 0;\n }\n }\n\n /**\n * CSI Ps E\n * Cursor Next Line Ps Times (default = 1) (CNL).\n * same as CSI Ps B ?\n */\n public cursorNextLine(params: number[]): void {\n let param = params[0];\n if (param < 1) {\n param = 1;\n }\n this._terminal.buffer.y += param;\n if (this._terminal.buffer.y >= this._terminal.rows) {\n this._terminal.buffer.y = this._terminal.rows - 1;\n }\n this._terminal.buffer.x = 0;\n }\n\n\n /**\n * CSI Ps F\n * Cursor Preceding Line Ps Times (default = 1) (CNL).\n * reuse CSI Ps A ?\n */\n public cursorPrecedingLine(params: number[]): void {\n let param = params[0];\n if (param < 1) {\n param = 1;\n }\n this._terminal.buffer.y -= param;\n if (this._terminal.buffer.y < 0) {\n this._terminal.buffer.y = 0;\n }\n this._terminal.buffer.x = 0;\n }\n\n\n /**\n * CSI Ps G\n * Cursor Character Absolute [column] (default = [row,1]) (CHA).\n */\n public cursorCharAbsolute(params: number[]): void {\n let param = params[0];\n if (param < 1) {\n param = 1;\n }\n this._terminal.buffer.x = param - 1;\n }\n\n /**\n * CSI Ps ; Ps H\n * Cursor Position [row;column] (default = [1,1]) (CUP).\n */\n public cursorPosition(params: number[]): void {\n let col: number;\n let row: number = params[0] - 1;\n\n if (params.length >= 2) {\n col = params[1] - 1;\n } else {\n col = 0;\n }\n\n if (row < 0) {\n row = 0;\n } else if (row >= this._terminal.rows) {\n row = this._terminal.rows - 1;\n }\n\n if (col < 0) {\n col = 0;\n } else if (col >= this._terminal.cols) {\n col = this._terminal.cols - 1;\n }\n\n this._terminal.buffer.x = col;\n this._terminal.buffer.y = row;\n }\n\n /**\n * CSI Ps I\n * Cursor Forward Tabulation Ps tab stops (default = 1) (CHT).\n */\n public cursorForwardTab(params: number[]): void {\n let param = params[0] || 1;\n while (param--) {\n this._terminal.buffer.x = this._terminal.buffer.nextStop();\n }\n }\n\n /**\n * CSI Ps J Erase in Display (ED).\n * Ps = 0 -> Erase Below (default).\n * Ps = 1 -> Erase Above.\n * Ps = 2 -> Erase All.\n * Ps = 3 -> Erase Saved Lines (xterm).\n * CSI ? Ps J\n * Erase in Display (DECSED).\n * Ps = 0 -> Selective Erase Below (default).\n * Ps = 1 -> Selective Erase Above.\n * Ps = 2 -> Selective Erase All.\n */\n public eraseInDisplay(params: number[]): void {\n let j;\n switch (params[0]) {\n case 0:\n this._terminal.eraseRight(this._terminal.buffer.x, this._terminal.buffer.y);\n j = this._terminal.buffer.y + 1;\n for (; j < this._terminal.rows; j++) {\n this._terminal.eraseLine(j);\n }\n break;\n case 1:\n this._terminal.eraseLeft(this._terminal.buffer.x, this._terminal.buffer.y);\n j = this._terminal.buffer.y;\n while (j--) {\n this._terminal.eraseLine(j);\n }\n break;\n case 2:\n j = this._terminal.rows;\n while (j--) this._terminal.eraseLine(j);\n break;\n case 3:\n // Clear scrollback (everything not in viewport)\n const scrollBackSize = this._terminal.buffer.lines.length - this._terminal.rows;\n if (scrollBackSize > 0) {\n this._terminal.buffer.lines.trimStart(scrollBackSize);\n this._terminal.buffer.ybase = Math.max(this._terminal.buffer.ybase - scrollBackSize, 0);\n this._terminal.buffer.ydisp = Math.max(this._terminal.buffer.ydisp - scrollBackSize, 0);\n // Force a scroll event to refresh viewport\n this._terminal.emit('scroll', 0);\n }\n break;\n }\n }\n\n /**\n * CSI Ps K Erase in Line (EL).\n * Ps = 0 -> Erase to Right (default).\n * Ps = 1 -> Erase to Left.\n * Ps = 2 -> Erase All.\n * CSI ? Ps K\n * Erase in Line (DECSEL).\n * Ps = 0 -> Selective Erase to Right (default).\n * Ps = 1 -> Selective Erase to Left.\n * Ps = 2 -> Selective Erase All.\n */\n public eraseInLine(params: number[]): void {\n switch (params[0]) {\n case 0:\n this._terminal.eraseRight(this._terminal.buffer.x, this._terminal.buffer.y);\n break;\n case 1:\n this._terminal.eraseLeft(this._terminal.buffer.x, this._terminal.buffer.y);\n break;\n case 2:\n this._terminal.eraseLine(this._terminal.buffer.y);\n break;\n }\n }\n\n /**\n * CSI Ps L\n * Insert Ps Line(s) (default = 1) (IL).\n */\n public insertLines(params: number[]): void {\n let param: number = params[0];\n if (param < 1) {\n param = 1;\n }\n let row: number = this._terminal.buffer.y + this._terminal.buffer.ybase;\n\n let scrollBottomRowsOffset = this._terminal.rows - 1 - this._terminal.buffer.scrollBottom;\n let scrollBottomAbsolute = this._terminal.rows - 1 + this._terminal.buffer.ybase - scrollBottomRowsOffset + 1;\n while (param--) {\n // test: echo -e '\\e[44m\\e[1L\\e[0m'\n // blankLine(true) - xterm/linux behavior\n this._terminal.buffer.lines.splice(scrollBottomAbsolute - 1, 1);\n this._terminal.buffer.lines.splice(row, 0, this._terminal.blankLine(true));\n }\n\n // this.maxRange();\n this._terminal.updateRange(this._terminal.buffer.y);\n this._terminal.updateRange(this._terminal.buffer.scrollBottom);\n }\n\n /**\n * CSI Ps M\n * Delete Ps Line(s) (default = 1) (DL).\n */\n public deleteLines(params: number[]): void {\n let param = params[0];\n if (param < 1) {\n param = 1;\n }\n const row: number = this._terminal.buffer.y + this._terminal.buffer.ybase;\n\n let j: number;\n j = this._terminal.rows - 1 - this._terminal.buffer.scrollBottom;\n j = this._terminal.rows - 1 + this._terminal.buffer.ybase - j;\n while (param--) {\n // test: echo -e '\\e[44m\\e[1M\\e[0m'\n // blankLine(true) - xterm/linux behavior\n this._terminal.buffer.lines.splice(row, 1);\n this._terminal.buffer.lines.splice(j, 0, this._terminal.blankLine(true));\n }\n\n // this.maxRange();\n this._terminal.updateRange(this._terminal.buffer.y);\n this._terminal.updateRange(this._terminal.buffer.scrollBottom);\n }\n\n /**\n * CSI Ps P\n * Delete Ps Character(s) (default = 1) (DCH).\n */\n public deleteChars(params: number[]): void {\n let param: number = params[0];\n if (param < 1) {\n param = 1;\n }\n\n const row = this._terminal.buffer.y + this._terminal.buffer.ybase;\n const ch: CharData = [this._terminal.eraseAttr(), ' ', 1, 32]; // xterm\n\n while (param--) {\n this._terminal.buffer.lines.get(row).splice(this._terminal.buffer.x, 1);\n this._terminal.buffer.lines.get(row).push(ch);\n }\n this._terminal.updateRange(this._terminal.buffer.y);\n }\n\n /**\n * CSI Ps S Scroll up Ps lines (default = 1) (SU).\n */\n public scrollUp(params: number[]): void {\n let param = params[0] || 1;\n while (param--) {\n this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollTop, 1);\n this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollBottom, 0, this._terminal.blankLine());\n }\n // this.maxRange();\n this._terminal.updateRange(this._terminal.buffer.scrollTop);\n this._terminal.updateRange(this._terminal.buffer.scrollBottom);\n }\n\n /**\n * CSI Ps T Scroll down Ps lines (default = 1) (SD).\n */\n public scrollDown(params: number[]): void {\n let param = params[0] || 1;\n while (param--) {\n this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollBottom, 1);\n this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollTop, 0, this._terminal.blankLine());\n }\n // this.maxRange();\n this._terminal.updateRange(this._terminal.buffer.scrollTop);\n this._terminal.updateRange(this._terminal.buffer.scrollBottom);\n }\n\n /**\n * CSI Ps X\n * Erase Ps Character(s) (default = 1) (ECH).\n */\n public eraseChars(params: number[]): void {\n let param = params[0];\n if (param < 1) {\n param = 1;\n }\n\n const row = this._terminal.buffer.y + this._terminal.buffer.ybase;\n let j = this._terminal.buffer.x;\n const ch: CharData = [this._terminal.eraseAttr(), ' ', 1, 32]; // xterm\n\n while (param-- && j < this._terminal.cols) {\n this._terminal.buffer.lines.get(row)[j++] = ch;\n }\n }\n\n /**\n * CSI Ps Z Cursor Backward Tabulation Ps tab stops (default = 1) (CBT).\n */\n public cursorBackwardTab(params: number[]): void {\n let param = params[0] || 1;\n while (param--) {\n this._terminal.buffer.x = this._terminal.buffer.prevStop();\n }\n }\n\n /**\n * CSI Pm ` Character Position Absolute\n * [column] (default = [row,1]) (HPA).\n */\n public charPosAbsolute(params: number[]): void {\n let param = params[0];\n if (param < 1) {\n param = 1;\n }\n this._terminal.buffer.x = param - 1;\n if (this._terminal.buffer.x >= this._terminal.cols) {\n this._terminal.buffer.x = this._terminal.cols - 1;\n }\n }\n\n /**\n * CSI Pm a Character Position Relative\n * [columns] (default = [row,col+1]) (HPR)\n * reuse CSI Ps C ?\n */\n public HPositionRelative(params: number[]): void {\n let param = params[0];\n if (param < 1) {\n param = 1;\n }\n this._terminal.buffer.x += param;\n if (this._terminal.buffer.x >= this._terminal.cols) {\n this._terminal.buffer.x = this._terminal.cols - 1;\n }\n }\n\n /**\n * CSI Ps b Repeat the preceding graphic character Ps times (REP).\n */\n public repeatPrecedingCharacter(params: number[]): void {\n let param = params[0] || 1;\n const line = this._terminal.buffer.lines.get(this._terminal.buffer.ybase + this._terminal.buffer.y);\n const ch = line[this._terminal.buffer.x - 1] || [this._terminal.defAttr, ' ', 1, 32];\n\n while (param--) {\n line[this._terminal.buffer.x++] = ch;\n }\n }\n\n /**\n * CSI Ps c Send Device Attributes (Primary DA).\n * Ps = 0 or omitted -> request attributes from terminal. The\n * response depends on the decTerminalID resource setting.\n * -> CSI ? 1 ; 2 c (``VT100 with Advanced Video Option'')\n * -> CSI ? 1 ; 0 c (``VT101 with No Options'')\n * -> CSI ? 6 c (``VT102'')\n * -> CSI ? 6 0 ; 1 ; 2 ; 6 ; 8 ; 9 ; 1 5 ; c (``VT220'')\n * The VT100-style response parameters do not mean anything by\n * themselves. VT220 parameters do, telling the host what fea-\n * tures the terminal supports:\n * Ps = 1 -> 132-columns.\n * Ps = 2 -> Printer.\n * Ps = 6 -> Selective erase.\n * Ps = 8 -> User-defined keys.\n * Ps = 9 -> National replacement character sets.\n * Ps = 1 5 -> Technical characters.\n * Ps = 2 2 -> ANSI color, e.g., VT525.\n * Ps = 2 9 -> ANSI text locator (i.e., DEC Locator mode).\n * CSI > Ps c\n * Send Device Attributes (Secondary DA).\n * Ps = 0 or omitted -> request the terminal's identification\n * code. The response depends on the decTerminalID resource set-\n * ting. It should apply only to VT220 and up, but xterm extends\n * this to VT100.\n * -> CSI > Pp ; Pv ; Pc c\n * where Pp denotes the terminal type\n * Pp = 0 -> ``VT100''.\n * Pp = 1 -> ``VT220''.\n * and Pv is the firmware version (for xterm, this was originally\n * the XFree86 patch number, starting with 95). In a DEC termi-\n * nal, Pc indicates the ROM cartridge registration number and is\n * always zero.\n * More information:\n * xterm/charproc.c - line 2012, for more information.\n * vim responds with ^[[?0c or ^[[?1c after the terminal's response (?)\n */\n public sendDeviceAttributes(params: number[]): void {\n if (params[0] > 0) {\n return;\n }\n\n if (!this._terminal.prefix) {\n if (this._terminal.is('xterm') || this._terminal.is('rxvt-unicode') || this._terminal.is('screen')) {\n this._terminal.send(C0.ESC + '[?1;2c');\n } else if (this._terminal.is('linux')) {\n this._terminal.send(C0.ESC + '[?6c');\n }\n } else if (this._terminal.prefix === '>') {\n // xterm and urxvt\n // seem to spit this\n // out around ~370 times (?).\n if (this._terminal.is('xterm')) {\n this._terminal.send(C0.ESC + '[>0;276;0c');\n } else if (this._terminal.is('rxvt-unicode')) {\n this._terminal.send(C0.ESC + '[>85;95;0c');\n } else if (this._terminal.is('linux')) {\n // not supported by linux console.\n // linux console echoes parameters.\n this._terminal.send(params[0] + 'c');\n } else if (this._terminal.is('screen')) {\n this._terminal.send(C0.ESC + '[>83;40003;0c');\n }\n }\n }\n\n /**\n * CSI Pm d Vertical Position Absolute (VPA)\n * [row] (default = [1,column])\n */\n public linePosAbsolute(params: number[]): void {\n let param = params[0];\n if (param < 1) {\n param = 1;\n }\n this._terminal.buffer.y = param - 1;\n if (this._terminal.buffer.y >= this._terminal.rows) {\n this._terminal.buffer.y = this._terminal.rows - 1;\n }\n }\n\n /**\n * CSI Pm e Vertical Position Relative (VPR)\n * [rows] (default = [row+1,column])\n * reuse CSI Ps B ?\n */\n public VPositionRelative(params: number[]): void {\n let param = params[0];\n if (param < 1) {\n param = 1;\n }\n this._terminal.buffer.y += param;\n if (this._terminal.buffer.y >= this._terminal.rows) {\n this._terminal.buffer.y = this._terminal.rows - 1;\n }\n // If the end of the line is hit, prevent this action from wrapping around to the next line.\n if (this._terminal.buffer.x >= this._terminal.cols) {\n this._terminal.buffer.x--;\n }\n }\n\n /**\n * CSI Ps ; Ps f\n * Horizontal and Vertical Position [row;column] (default =\n * [1,1]) (HVP).\n */\n public HVPosition(params: number[]): void {\n if (params[0] < 1) params[0] = 1;\n if (params[1] < 1) params[1] = 1;\n\n this._terminal.buffer.y = params[0] - 1;\n if (this._terminal.buffer.y >= this._terminal.rows) {\n this._terminal.buffer.y = this._terminal.rows - 1;\n }\n\n this._terminal.buffer.x = params[1] - 1;\n if (this._terminal.buffer.x >= this._terminal.cols) {\n this._terminal.buffer.x = this._terminal.cols - 1;\n }\n }\n\n /**\n * CSI Ps g Tab Clear (TBC).\n * Ps = 0 -> Clear Current Column (default).\n * Ps = 3 -> Clear All.\n * Potentially:\n * Ps = 2 -> Clear Stops on Line.\n * http://vt100.net/annarbor/aaa-ug/section6.html\n */\n public tabClear(params: number[]): void {\n let param = params[0];\n if (param <= 0) {\n delete this._terminal.buffer.tabs[this._terminal.buffer.x];\n } else if (param === 3) {\n this._terminal.buffer.tabs = {};\n }\n }\n\n /**\n * CSI Pm h Set Mode (SM).\n * Ps = 2 -> Keyboard Action Mode (AM).\n * Ps = 4 -> Insert Mode (IRM).\n * Ps = 1 2 -> Send/receive (SRM).\n * Ps = 2 0 -> Automatic Newline (LNM).\n * CSI ? Pm h\n * DEC Private Mode Set (DECSET).\n * Ps = 1 -> Application Cursor Keys (DECCKM).\n * Ps = 2 -> Designate USASCII for character sets G0-G3\n * (DECANM), and set VT100 mode.\n * Ps = 3 -> 132 Column Mode (DECCOLM).\n * Ps = 4 -> Smooth (Slow) Scroll (DECSCLM).\n * Ps = 5 -> Reverse Video (DECSCNM).\n * Ps = 6 -> Origin Mode (DECOM).\n * Ps = 7 -> Wraparound Mode (DECAWM).\n * Ps = 8 -> Auto-repeat Keys (DECARM).\n * Ps = 9 -> Send Mouse X & Y on button press. See the sec-\n * tion Mouse Tracking.\n * Ps = 1 0 -> Show toolbar (rxvt).\n * Ps = 1 2 -> Start Blinking Cursor (att610).\n * Ps = 1 8 -> Print form feed (DECPFF).\n * Ps = 1 9 -> Set print extent to full screen (DECPEX).\n * Ps = 2 5 -> Show Cursor (DECTCEM).\n * Ps = 3 0 -> Show scrollbar (rxvt).\n * Ps = 3 5 -> Enable font-shifting functions (rxvt).\n * Ps = 3 8 -> Enter Tektronix Mode (DECTEK).\n * Ps = 4 0 -> Allow 80 -> 132 Mode.\n * Ps = 4 1 -> more(1) fix (see curses resource).\n * Ps = 4 2 -> Enable Nation Replacement Character sets (DECN-\n * RCM).\n * Ps = 4 4 -> Turn On Margin Bell.\n * Ps = 4 5 -> Reverse-wraparound Mode.\n * Ps = 4 6 -> Start Logging. This is normally disabled by a\n * compile-time option.\n * Ps = 4 7 -> Use Alternate Screen Buffer. (This may be dis-\n * abled by the titeInhibit resource).\n * Ps = 6 6 -> Application keypad (DECNKM).\n * Ps = 6 7 -> Backarrow key sends backspace (DECBKM).\n * Ps = 1 0 0 0 -> Send Mouse X & Y on button press and\n * release. See the section Mouse Tracking.\n * Ps = 1 0 0 1 -> Use Hilite Mouse Tracking.\n * Ps = 1 0 0 2 -> Use Cell Motion Mouse Tracking.\n * Ps = 1 0 0 3 -> Use All Motion Mouse Tracking.\n * Ps = 1 0 0 4 -> Send FocusIn/FocusOut events.\n * Ps = 1 0 0 5 -> Enable Extended Mouse Mode.\n * Ps = 1 0 1 0 -> Scroll to bottom on tty output (rxvt).\n * Ps = 1 0 1 1 -> Scroll to bottom on key press (rxvt).\n * Ps = 1 0 3 4 -> Interpret \"meta\" key, sets eighth bit.\n * (enables the eightBitInput resource).\n * Ps = 1 0 3 5 -> Enable special modifiers for Alt and Num-\n * Lock keys. (This enables the numLock resource).\n * Ps = 1 0 3 6 -> Send ESC when Meta modifies a key. (This\n * enables the metaSendsEscape resource).\n * Ps = 1 0 3 7 -> Send DEL from the editing-keypad Delete\n * key.\n * Ps = 1 0 3 9 -> Send ESC when Alt modifies a key. (This\n * enables the altSendsEscape resource).\n * Ps = 1 0 4 0 -> Keep selection even if not highlighted.\n * (This enables the keepSelection resource).\n * Ps = 1 0 4 1 -> Use the CLIPBOARD selection. (This enables\n * the selectToClipboard resource).\n * Ps = 1 0 4 2 -> Enable Urgency window manager hint when\n * Control-G is received. (This enables the bellIsUrgent\n * resource).\n * Ps = 1 0 4 3 -> Enable raising of the window when Control-G\n * is received. (enables the popOnBell resource).\n * Ps = 1 0 4 7 -> Use Alternate Screen Buffer. (This may be\n * disabled by the titeInhibit resource).\n * Ps = 1 0 4 8 -> Save cursor as in DECSC. (This may be dis-\n * abled by the titeInhibit resource).\n * Ps = 1 0 4 9 -> Save cursor as in DECSC and use Alternate\n * Screen Buffer, clearing it first. (This may be disabled by\n * the titeInhibit resource). This combines the effects of the 1\n * 0 4 7 and 1 0 4 8 modes. Use this with terminfo-based\n * applications rather than the 4 7 mode.\n * Ps = 1 0 5 0 -> Set terminfo/termcap function-key mode.\n * Ps = 1 0 5 1 -> Set Sun function-key mode.\n * Ps = 1 0 5 2 -> Set HP function-key mode.\n * Ps = 1 0 5 3 -> Set SCO function-key mode.\n * Ps = 1 0 6 0 -> Set legacy keyboard emulation (X11R6).\n * Ps = 1 0 6 1 -> Set VT220 keyboard emulation.\n * Ps = 2 0 0 4 -> Set bracketed paste mode.\n * Modes:\n * http: *vt100.net/docs/vt220-rm/chapter4.html\n */\n public setMode(params: number[]): void {\n if (params.length > 1) {\n for (let i = 0; i < params.length; i++) {\n this.setMode([params[i]]);\n }\n\n return;\n }\n\n if (!this._terminal.prefix) {\n switch (params[0]) {\n case 4:\n this._terminal.insertMode = true;\n break;\n case 20:\n // this._t.convertEol = true;\n break;\n }\n } else if (this._terminal.prefix === '?') {\n switch (params[0]) {\n case 1:\n this._terminal.applicationCursor = true;\n break;\n case 2:\n this._terminal.setgCharset(0, DEFAULT_CHARSET);\n this._terminal.setgCharset(1, DEFAULT_CHARSET);\n this._terminal.setgCharset(2, DEFAULT_CHARSET);\n this._terminal.setgCharset(3, DEFAULT_CHARSET);\n // set VT100 mode here\n break;\n case 3: // 132 col mode\n this._terminal.savedCols = this._terminal.cols;\n this._terminal.resize(132, this._terminal.rows);\n break;\n case 6:\n this._terminal.originMode = true;\n break;\n case 7:\n this._terminal.wraparoundMode = true;\n break;\n case 12:\n // this.cursorBlink = true;\n break;\n case 66:\n this._terminal.log('Serial port requested application keypad.');\n this._terminal.applicationKeypad = true;\n this._terminal.viewport.syncScrollArea();\n break;\n case 9: // X10 Mouse\n // no release, no motion, no wheel, no modifiers.\n case 1000: // vt200 mouse\n // no motion.\n // no modifiers, except control on the wheel.\n case 1002: // button event mouse\n case 1003: // any event mouse\n // any event - sends motion events,\n // even if there is no button held down.\n\n // TODO: Why are params[0] compares nested within a switch for params[0]?\n\n this._terminal.x10Mouse = params[0] === 9;\n this._terminal.vt200Mouse = params[0] === 1000;\n this._terminal.normalMouse = params[0] > 1000;\n this._terminal.mouseEvents = true;\n this._terminal.element.classList.add('enable-mouse-events');\n this._terminal.selectionManager.disable();\n this._terminal.log('Binding to mouse events.');\n break;\n case 1004: // send focusin/focusout events\n // focusin: ^[[I\n // focusout: ^[[O\n this._terminal.sendFocus = true;\n break;\n case 1005: // utf8 ext mode mouse\n this._terminal.utfMouse = true;\n // for wide terminals\n // simply encodes large values as utf8 characters\n break;\n case 1006: // sgr ext mode mouse\n this._terminal.sgrMouse = true;\n // for wide terminals\n // does not add 32 to fields\n // press: ^[[ Keyboard Action Mode (AM).\n * Ps = 4 -> Replace Mode (IRM).\n * Ps = 1 2 -> Send/receive (SRM).\n * Ps = 2 0 -> Normal Linefeed (LNM).\n * CSI ? Pm l\n * DEC Private Mode Reset (DECRST).\n * Ps = 1 -> Normal Cursor Keys (DECCKM).\n * Ps = 2 -> Designate VT52 mode (DECANM).\n * Ps = 3 -> 80 Column Mode (DECCOLM).\n * Ps = 4 -> Jump (Fast) Scroll (DECSCLM).\n * Ps = 5 -> Normal Video (DECSCNM).\n * Ps = 6 -> Normal Cursor Mode (DECOM).\n * Ps = 7 -> No Wraparound Mode (DECAWM).\n * Ps = 8 -> No Auto-repeat Keys (DECARM).\n * Ps = 9 -> Don't send Mouse X & Y on button press.\n * Ps = 1 0 -> Hide toolbar (rxvt).\n * Ps = 1 2 -> Stop Blinking Cursor (att610).\n * Ps = 1 8 -> Don't print form feed (DECPFF).\n * Ps = 1 9 -> Limit print to scrolling region (DECPEX).\n * Ps = 2 5 -> Hide Cursor (DECTCEM).\n * Ps = 3 0 -> Don't show scrollbar (rxvt).\n * Ps = 3 5 -> Disable font-shifting functions (rxvt).\n * Ps = 4 0 -> Disallow 80 -> 132 Mode.\n * Ps = 4 1 -> No more(1) fix (see curses resource).\n * Ps = 4 2 -> Disable Nation Replacement Character sets (DEC-\n * NRCM).\n * Ps = 4 4 -> Turn Off Margin Bell.\n * Ps = 4 5 -> No Reverse-wraparound Mode.\n * Ps = 4 6 -> Stop Logging. (This is normally disabled by a\n * compile-time option).\n * Ps = 4 7 -> Use Normal Screen Buffer.\n * Ps = 6 6 -> Numeric keypad (DECNKM).\n * Ps = 6 7 -> Backarrow key sends delete (DECBKM).\n * Ps = 1 0 0 0 -> Don't send Mouse X & Y on button press and\n * release. See the section Mouse Tracking.\n * Ps = 1 0 0 1 -> Don't use Hilite Mouse Tracking.\n * Ps = 1 0 0 2 -> Don't use Cell Motion Mouse Tracking.\n * Ps = 1 0 0 3 -> Don't use All Motion Mouse Tracking.\n * Ps = 1 0 0 4 -> Don't send FocusIn/FocusOut events.\n * Ps = 1 0 0 5 -> Disable Extended Mouse Mode.\n * Ps = 1 0 1 0 -> Don't scroll to bottom on tty output\n * (rxvt).\n * Ps = 1 0 1 1 -> Don't scroll to bottom on key press (rxvt).\n * Ps = 1 0 3 4 -> Don't interpret \"meta\" key. (This disables\n * the eightBitInput resource).\n * Ps = 1 0 3 5 -> Disable special modifiers for Alt and Num-\n * Lock keys. (This disables the numLock resource).\n * Ps = 1 0 3 6 -> Don't send ESC when Meta modifies a key.\n * (This disables the metaSendsEscape resource).\n * Ps = 1 0 3 7 -> Send VT220 Remove from the editing-keypad\n * Delete key.\n * Ps = 1 0 3 9 -> Don't send ESC when Alt modifies a key.\n * (This disables the altSendsEscape resource).\n * Ps = 1 0 4 0 -> Do not keep selection when not highlighted.\n * (This disables the keepSelection resource).\n * Ps = 1 0 4 1 -> Use the PRIMARY selection. (This disables\n * the selectToClipboard resource).\n * Ps = 1 0 4 2 -> Disable Urgency window manager hint when\n * Control-G is received. (This disables the bellIsUrgent\n * resource).\n * Ps = 1 0 4 3 -> Disable raising of the window when Control-\n * G is received. (This disables the popOnBell resource).\n * Ps = 1 0 4 7 -> Use Normal Screen Buffer, clearing screen\n * first if in the Alternate Screen. (This may be disabled by\n * the titeInhibit resource).\n * Ps = 1 0 4 8 -> Restore cursor as in DECRC. (This may be\n * disabled by the titeInhibit resource).\n * Ps = 1 0 4 9 -> Use Normal Screen Buffer and restore cursor\n * as in DECRC. (This may be disabled by the titeInhibit\n * resource). This combines the effects of the 1 0 4 7 and 1 0\n * 4 8 modes. Use this with terminfo-based applications rather\n * than the 4 7 mode.\n * Ps = 1 0 5 0 -> Reset terminfo/termcap function-key mode.\n * Ps = 1 0 5 1 -> Reset Sun function-key mode.\n * Ps = 1 0 5 2 -> Reset HP function-key mode.\n * Ps = 1 0 5 3 -> Reset SCO function-key mode.\n * Ps = 1 0 6 0 -> Reset legacy keyboard emulation (X11R6).\n * Ps = 1 0 6 1 -> Reset keyboard emulation to Sun/PC style.\n * Ps = 2 0 0 4 -> Reset bracketed paste mode.\n */\n public resetMode(params: number[]): void {\n if (params.length > 1) {\n for (let i = 0; i < params.length; i++) {\n this.resetMode([params[i]]);\n }\n\n return;\n }\n\n if (!this._terminal.prefix) {\n switch (params[0]) {\n case 4:\n this._terminal.insertMode = false;\n break;\n case 20:\n // this._t.convertEol = false;\n break;\n }\n } else if (this._terminal.prefix === '?') {\n switch (params[0]) {\n case 1:\n this._terminal.applicationCursor = false;\n break;\n case 3:\n if (this._terminal.cols === 132 && this._terminal.savedCols) {\n this._terminal.resize(this._terminal.savedCols, this._terminal.rows);\n }\n delete this._terminal.savedCols;\n break;\n case 6:\n this._terminal.originMode = false;\n break;\n case 7:\n this._terminal.wraparoundMode = false;\n break;\n case 12:\n // this.cursorBlink = false;\n break;\n case 66:\n this._terminal.log('Switching back to normal keypad.');\n this._terminal.applicationKeypad = false;\n this._terminal.viewport.syncScrollArea();\n break;\n case 9: // X10 Mouse\n case 1000: // vt200 mouse\n case 1002: // button event mouse\n case 1003: // any event mouse\n this._terminal.x10Mouse = false;\n this._terminal.vt200Mouse = false;\n this._terminal.normalMouse = false;\n this._terminal.mouseEvents = false;\n this._terminal.element.classList.remove('enable-mouse-events');\n this._terminal.selectionManager.enable();\n break;\n case 1004: // send focusin/focusout events\n this._terminal.sendFocus = false;\n break;\n case 1005: // utf8 ext mode mouse\n this._terminal.utfMouse = false;\n break;\n case 1006: // sgr ext mode mouse\n this._terminal.sgrMouse = false;\n break;\n case 1015: // urxvt ext mode mouse\n this._terminal.urxvtMouse = false;\n break;\n case 25: // hide cursor\n this._terminal.cursorHidden = true;\n break;\n case 1049: // alt screen buffer cursor\n // FALL-THROUGH\n case 47: // normal screen buffer\n case 1047: // normal screen buffer - clearing it first\n // Ensure the selection manager has the correct buffer\n this._terminal.buffers.activateNormalBuffer();\n // TODO: Not sure if we need to save/restore after switching the buffer\n // if (params[0] === 1049) {\n // this.restoreCursor(params);\n // }\n this._terminal.selectionManager.setBuffer(this._terminal.buffer);\n this._terminal.refresh(0, this._terminal.rows - 1);\n this._terminal.viewport.syncScrollArea();\n this._terminal.showCursor();\n break;\n case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste)\n this._terminal.bracketedPasteMode = false;\n break;\n }\n }\n }\n\n /**\n * CSI Pm m Character Attributes (SGR).\n * Ps = 0 -> Normal (default).\n * Ps = 1 -> Bold.\n * Ps = 2 -> Faint, decreased intensity (ISO 6429).\n * Ps = 4 -> Underlined.\n * Ps = 5 -> Blink (appears as Bold).\n * Ps = 7 -> Inverse.\n * Ps = 8 -> Invisible, i.e., hidden (VT300).\n * Ps = 2 2 -> Normal (neither bold nor faint).\n * Ps = 2 4 -> Not underlined.\n * Ps = 2 5 -> Steady (not blinking).\n * Ps = 2 7 -> Positive (not inverse).\n * Ps = 2 8 -> Visible, i.e., not hidden (VT300).\n * Ps = 3 0 -> Set foreground color to Black.\n * Ps = 3 1 -> Set foreground color to Red.\n * Ps = 3 2 -> Set foreground color to Green.\n * Ps = 3 3 -> Set foreground color to Yellow.\n * Ps = 3 4 -> Set foreground color to Blue.\n * Ps = 3 5 -> Set foreground color to Magenta.\n * Ps = 3 6 -> Set foreground color to Cyan.\n * Ps = 3 7 -> Set foreground color to White.\n * Ps = 3 9 -> Set foreground color to default (original).\n * Ps = 4 0 -> Set background color to Black.\n * Ps = 4 1 -> Set background color to Red.\n * Ps = 4 2 -> Set background color to Green.\n * Ps = 4 3 -> Set background color to Yellow.\n * Ps = 4 4 -> Set background color to Blue.\n * Ps = 4 5 -> Set background color to Magenta.\n * Ps = 4 6 -> Set background color to Cyan.\n * Ps = 4 7 -> Set background color to White.\n * Ps = 4 9 -> Set background color to default (original).\n *\n * If 16-color support is compiled, the following apply. Assume\n * that xterm's resources are set so that the ISO color codes are\n * the first 8 of a set of 16. Then the aixterm colors are the\n * bright versions of the ISO colors:\n * Ps = 9 0 -> Set foreground color to Black.\n * Ps = 9 1 -> Set foreground color to Red.\n * Ps = 9 2 -> Set foreground color to Green.\n * Ps = 9 3 -> Set foreground color to Yellow.\n * Ps = 9 4 -> Set foreground color to Blue.\n * Ps = 9 5 -> Set foreground color to Magenta.\n * Ps = 9 6 -> Set foreground color to Cyan.\n * Ps = 9 7 -> Set foreground color to White.\n * Ps = 1 0 0 -> Set background color to Black.\n * Ps = 1 0 1 -> Set background color to Red.\n * Ps = 1 0 2 -> Set background color to Green.\n * Ps = 1 0 3 -> Set background color to Yellow.\n * Ps = 1 0 4 -> Set background color to Blue.\n * Ps = 1 0 5 -> Set background color to Magenta.\n * Ps = 1 0 6 -> Set background color to Cyan.\n * Ps = 1 0 7 -> Set background color to White.\n *\n * If xterm is compiled with the 16-color support disabled, it\n * supports the following, from rxvt:\n * Ps = 1 0 0 -> Set foreground and background color to\n * default.\n *\n * If 88- or 256-color support is compiled, the following apply.\n * Ps = 3 8 ; 5 ; Ps -> Set foreground color to the second\n * Ps.\n * Ps = 4 8 ; 5 ; Ps -> Set background color to the second\n * Ps.\n */\n public charAttributes(params: number[]): void {\n // Optimize a single SGR0.\n if (params.length === 1 && params[0] === 0) {\n this._terminal.curAttr = this._terminal.defAttr;\n return;\n }\n\n const l = params.length;\n let flags = this._terminal.curAttr >> 18;\n let fg = (this._terminal.curAttr >> 9) & 0x1ff;\n let bg = this._terminal.curAttr & 0x1ff;\n let p;\n\n for (let i = 0; i < l; i++) {\n p = params[i];\n if (p >= 30 && p <= 37) {\n // fg color 8\n fg = p - 30;\n } else if (p >= 40 && p <= 47) {\n // bg color 8\n bg = p - 40;\n } else if (p >= 90 && p <= 97) {\n // fg color 16\n p += 8;\n fg = p - 90;\n } else if (p >= 100 && p <= 107) {\n // bg color 16\n p += 8;\n bg = p - 100;\n } else if (p === 0) {\n // default\n flags = this._terminal.defAttr >> 18;\n fg = (this._terminal.defAttr >> 9) & 0x1ff;\n bg = this._terminal.defAttr & 0x1ff;\n // flags = 0;\n // fg = 0x1ff;\n // bg = 0x1ff;\n } else if (p === 1) {\n // bold text\n flags |= FLAGS.BOLD;\n } else if (p === 4) {\n // underlined text\n flags |= FLAGS.UNDERLINE;\n } else if (p === 5) {\n // blink\n flags |= FLAGS.BLINK;\n } else if (p === 7) {\n // inverse and positive\n // test with: echo -e '\\e[31m\\e[42mhello\\e[7mworld\\e[27mhi\\e[m'\n flags |= FLAGS.INVERSE;\n } else if (p === 8) {\n // invisible\n flags |= FLAGS.INVISIBLE;\n } else if (p === 2) {\n // dimmed text\n flags |= FLAGS.DIM;\n } else if (p === 22) {\n // not bold nor faint\n flags &= ~FLAGS.BOLD;\n flags &= ~FLAGS.DIM;\n } else if (p === 24) {\n // not underlined\n flags &= ~FLAGS.UNDERLINE;\n } else if (p === 25) {\n // not blink\n flags &= ~FLAGS.BLINK;\n } else if (p === 27) {\n // not inverse\n flags &= ~FLAGS.INVERSE;\n } else if (p === 28) {\n // not invisible\n flags &= ~FLAGS.INVISIBLE;\n } else if (p === 39) {\n // reset fg\n fg = (this._terminal.defAttr >> 9) & 0x1ff;\n } else if (p === 49) {\n // reset bg\n bg = this._terminal.defAttr & 0x1ff;\n } else if (p === 38) {\n // fg color 256\n if (params[i + 1] === 2) {\n i += 2;\n fg = this._terminal.matchColor(\n params[i] & 0xff,\n params[i + 1] & 0xff,\n params[i + 2] & 0xff);\n if (fg === -1) fg = 0x1ff;\n i += 2;\n } else if (params[i + 1] === 5) {\n i += 2;\n p = params[i] & 0xff;\n fg = p;\n }\n } else if (p === 48) {\n // bg color 256\n if (params[i + 1] === 2) {\n i += 2;\n bg = this._terminal.matchColor(\n params[i] & 0xff,\n params[i + 1] & 0xff,\n params[i + 2] & 0xff);\n if (bg === -1) bg = 0x1ff;\n i += 2;\n } else if (params[i + 1] === 5) {\n i += 2;\n p = params[i] & 0xff;\n bg = p;\n }\n } else if (p === 100) {\n // reset fg/bg\n fg = (this._terminal.defAttr >> 9) & 0x1ff;\n bg = this._terminal.defAttr & 0x1ff;\n } else {\n this._terminal.error('Unknown SGR attribute: %d.', p);\n }\n }\n\n this._terminal.curAttr = (flags << 18) | (fg << 9) | bg;\n }\n\n /**\n * CSI Ps n Device Status Report (DSR).\n * Ps = 5 -> Status Report. Result (``OK'') is\n * CSI 0 n\n * Ps = 6 -> Report Cursor Position (CPR) [row;column].\n * Result is\n * CSI r ; c R\n * CSI ? Ps n\n * Device Status Report (DSR, DEC-specific).\n * Ps = 6 -> Report Cursor Position (CPR) [row;column] as CSI\n * ? r ; c R (assumes page is zero).\n * Ps = 1 5 -> Report Printer status as CSI ? 1 0 n (ready).\n * or CSI ? 1 1 n (not ready).\n * Ps = 2 5 -> Report UDK status as CSI ? 2 0 n (unlocked)\n * or CSI ? 2 1 n (locked).\n * Ps = 2 6 -> Report Keyboard status as\n * CSI ? 2 7 ; 1 ; 0 ; 0 n (North American).\n * The last two parameters apply to VT400 & up, and denote key-\n * board ready and LK01 respectively.\n * Ps = 5 3 -> Report Locator status as\n * CSI ? 5 3 n Locator available, if compiled-in, or\n * CSI ? 5 0 n No Locator, if not.\n */\n public deviceStatus(params: number[]): void {\n if (!this._terminal.prefix) {\n switch (params[0]) {\n case 5:\n // status report\n this._terminal.send(C0.ESC + '[0n');\n break;\n case 6:\n // cursor position\n this._terminal.send(C0.ESC + '['\n + (this._terminal.buffer.y + 1)\n + ';'\n + (this._terminal.buffer.x + 1)\n + 'R');\n break;\n }\n } else if (this._terminal.prefix === '?') {\n // modern xterm doesnt seem to\n // respond to any of these except ?6, 6, and 5\n switch (params[0]) {\n case 6:\n // cursor position\n this._terminal.send(C0.ESC + '[?'\n + (this._terminal.buffer.y + 1)\n + ';'\n + (this._terminal.buffer.x + 1)\n + 'R');\n break;\n case 15:\n // no printer\n // this.send(C0.ESC + '[?11n');\n break;\n case 25:\n // dont support user defined keys\n // this.send(C0.ESC + '[?21n');\n break;\n case 26:\n // north american keyboard\n // this.send(C0.ESC + '[?27;1;0;0n');\n break;\n case 53:\n // no dec locator/mouse\n // this.send(C0.ESC + '[?50n');\n break;\n }\n }\n }\n\n /**\n * CSI ! p Soft terminal reset (DECSTR).\n * http://vt100.net/docs/vt220-rm/table4-10.html\n */\n public softReset(params: number[]): void {\n this._terminal.cursorHidden = false;\n this._terminal.insertMode = false;\n this._terminal.originMode = false;\n this._terminal.wraparoundMode = true; // defaults: xterm - true, vt100 - false\n this._terminal.applicationKeypad = false; // ?\n this._terminal.viewport.syncScrollArea();\n this._terminal.applicationCursor = false;\n this._terminal.buffer.scrollTop = 0;\n this._terminal.buffer.scrollBottom = this._terminal.rows - 1;\n this._terminal.curAttr = this._terminal.defAttr;\n this._terminal.buffer.x = this._terminal.buffer.y = 0; // ?\n this._terminal.charset = null;\n this._terminal.glevel = 0; // ??\n this._terminal.charsets = [null]; // ??\n }\n\n /**\n * CSI Ps SP q Set cursor style (DECSCUSR, VT520).\n * Ps = 0 -> blinking block.\n * Ps = 1 -> blinking block (default).\n * Ps = 2 -> steady block.\n * Ps = 3 -> blinking underline.\n * Ps = 4 -> steady underline.\n * Ps = 5 -> blinking bar (xterm).\n * Ps = 6 -> steady bar (xterm).\n */\n public setCursorStyle(params?: number[]): void {\n const param = params[0] < 1 ? 1 : params[0];\n switch (param) {\n case 1:\n case 2:\n this._terminal.setOption('cursorStyle', 'block');\n break;\n case 3:\n case 4:\n this._terminal.setOption('cursorStyle', 'underline');\n break;\n case 5:\n case 6:\n this._terminal.setOption('cursorStyle', 'bar');\n break;\n }\n const isBlinking = param % 2 === 1;\n this._terminal.setOption('cursorBlink', isBlinking);\n }\n\n /**\n * CSI Ps ; Ps r\n * Set Scrolling Region [top;bottom] (default = full size of win-\n * dow) (DECSTBM).\n * CSI ? Pm r\n */\n public setScrollRegion(params: number[]): void {\n if (this._terminal.prefix) return;\n this._terminal.buffer.scrollTop = (params[0] || 1) - 1;\n this._terminal.buffer.scrollBottom = (params[1] && params[1] <= this._terminal.rows ? params[1] : this._terminal.rows) - 1;\n this._terminal.buffer.x = 0;\n this._terminal.buffer.y = 0;\n }\n\n\n /**\n * CSI s\n * Save cursor (ANSI.SYS).\n */\n public saveCursor(params: number[]): void {\n this._terminal.buffer.savedX = this._terminal.buffer.x;\n this._terminal.buffer.savedY = this._terminal.buffer.y;\n }\n\n\n /**\n * CSI u\n * Restore cursor (ANSI.SYS).\n */\n public restoreCursor(params: number[]): void {\n this._terminal.buffer.x = this._terminal.buffer.savedX || 0;\n this._terminal.buffer.y = this._terminal.buffer.savedY || 0;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IEventEmitter, IListenerType } from './Interfaces';\n\nexport class EventEmitter implements IEventEmitter {\n private _events: {[type: string]: IListenerType[]};\n\n constructor() {\n // Restore the previous events if available, this will happen if the\n // constructor is called multiple times on the same object (terminal reset).\n this._events = this._events || {};\n }\n\n public on(type: string, listener: IListenerType): void {\n this._events[type] = this._events[type] || [];\n this._events[type].push(listener);\n }\n\n public off(type: string, listener: IListenerType): void {\n if (!this._events[type]) {\n return;\n }\n\n let obj = this._events[type];\n let i = obj.length;\n\n while (i--) {\n if (obj[i] === listener || obj[i].listener === listener) {\n obj.splice(i, 1);\n return;\n }\n }\n }\n\n public removeAllListeners(type: string): void {\n if (this._events[type]) {\n delete this._events[type];\n }\n }\n\n public once(type: string, listener: IListenerType): void {\n function on(): void {\n let args = Array.prototype.slice.call(arguments);\n this.off(type, on);\n listener.apply(this, args);\n }\n (on).listener = listener;\n this.on(type, on);\n }\n\n public emit(type: string, ...args: any[]): void {\n if (!this._events[type]) {\n return;\n }\n let obj = this._events[type];\n for (let i = 0; i < obj.length; i++) {\n obj[i].apply(this, args);\n }\n }\n\n public listeners(type: string): IListenerType[] {\n return this._events[type] || [];\n }\n\n protected destroy(): void {\n this._events = {};\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\n/**\n * C0 control codes\n * See = https://en.wikipedia.org/wiki/C0_and_C1_control_codes\n */\nexport namespace C0 {\n /** Null (Caret = ^@, C = \\0) */\n export const NUL = '\\x00';\n /** Start of Heading (Caret = ^A) */\n export const SOH = '\\x01';\n /** Start of Text (Caret = ^B) */\n export const STX = '\\x02';\n /** End of Text (Caret = ^C) */\n export const ETX = '\\x03';\n /** End of Transmission (Caret = ^D) */\n export const EOT = '\\x04';\n /** Enquiry (Caret = ^E) */\n export const ENQ = '\\x05';\n /** Acknowledge (Caret = ^F) */\n export const ACK = '\\x06';\n /** Bell (Caret = ^G, C = \\a) */\n export const BEL = '\\x07';\n /** Backspace (Caret = ^H, C = \\b) */\n export const BS = '\\x08';\n /** Character Tabulation, Horizontal Tabulation (Caret = ^I, C = \\t) */\n export const HT = '\\x09';\n /** Line Feed (Caret = ^J, C = \\n) */\n export const LF = '\\x0a';\n /** Line Tabulation, Vertical Tabulation (Caret = ^K, C = \\v) */\n export const VT = '\\x0b';\n /** Form Feed (Caret = ^L, C = \\f) */\n export const FF = '\\x0c';\n /** Carriage Return (Caret = ^M, C = \\r) */\n export const CR = '\\x0d';\n /** Shift Out (Caret = ^N) */\n export const SO = '\\x0e';\n /** Shift In (Caret = ^O) */\n export const SI = '\\x0f';\n /** Data Link Escape (Caret = ^P) */\n export const DLE = '\\x10';\n /** Device Control One (XON) (Caret = ^Q) */\n export const DC1 = '\\x11';\n /** Device Control Two (Caret = ^R) */\n export const DC2 = '\\x12';\n /** Device Control Three (XOFF) (Caret = ^S) */\n export const DC3 = '\\x13';\n /** Device Control Four (Caret = ^T) */\n export const DC4 = '\\x14';\n /** Negative Acknowledge (Caret = ^U) */\n export const NAK = '\\x15';\n /** Synchronous Idle (Caret = ^V) */\n export const SYN = '\\x16';\n /** End of Transmission Block (Caret = ^W) */\n export const ETB = '\\x17';\n /** Cancel (Caret = ^X) */\n export const CAN = '\\x18';\n /** End of Medium (Caret = ^Y) */\n export const EM = '\\x19';\n /** Substitute (Caret = ^Z) */\n export const SUB = '\\x1a';\n /** Escape (Caret = ^[, C = \\e) */\n export const ESC = '\\x1b';\n /** File Separator (Caret = ^\\) */\n export const FS = '\\x1c';\n /** Group Separator (Caret = ^]) */\n export const GS = '\\x1d';\n /** Record Separator (Caret = ^^) */\n export const RS = '\\x1e';\n /** Unit Separator (Caret = ^_) */\n export const US = '\\x1f';\n /** Space */\n export const SP = '\\x20';\n /** Delete (Caret = ^?) */\n export const DEL = '\\x7f';\n};\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ITerminal } from './Interfaces';\n\ninterface IPosition {\n start: number;\n end: number;\n}\n\n/**\n * Encapsulates the logic for handling compositionstart, compositionupdate and compositionend\n * events, displaying the in-progress composition to the UI and forwarding the final composition\n * to the handler.\n */\nexport class CompositionHelper {\n /**\n * Whether input composition is currently happening, eg. via a mobile keyboard, speech input or\n * IME. This variable determines whether the compositionText should be displayed on the UI.\n */\n private isComposing: boolean;\n\n /**\n * The position within the input textarea's value of the current composition.\n */\n private compositionPosition: IPosition;\n\n /**\n * Whether a composition is in the process of being sent, setting this to false will cancel any\n * in-progress composition.\n */\n private isSendingComposition: boolean;\n\n /**\n * Creates a new CompositionHelper.\n * @param textarea The textarea that xterm uses for input.\n * @param compositionView The element to display the in-progress composition in.\n * @param terminal The Terminal to forward the finished composition to.\n */\n constructor(\n private textarea: HTMLTextAreaElement,\n private compositionView: HTMLElement,\n private terminal: ITerminal\n ) {\n this.isComposing = false;\n this.isSendingComposition = false;\n this.compositionPosition = { start: null, end: null };\n }\n\n /**\n * Handles the compositionstart event, activating the composition view.\n */\n public compositionstart(): void {\n this.isComposing = true;\n this.compositionPosition.start = this.textarea.value.length;\n this.compositionView.textContent = '';\n this.compositionView.classList.add('active');\n }\n\n /**\n * Handles the compositionupdate event, updating the composition view.\n * @param {CompositionEvent} ev The event.\n */\n public compositionupdate(ev: CompositionEvent): void {\n this.compositionView.textContent = ev.data;\n this.updateCompositionElements();\n setTimeout(() => {\n this.compositionPosition.end = this.textarea.value.length;\n }, 0);\n }\n\n /**\n * Handles the compositionend event, hiding the composition view and sending the composition to\n * the handler.\n */\n public compositionend(): void {\n this.finalizeComposition(true);\n }\n\n /**\n * Handles the keydown event, routing any necessary events to the CompositionHelper functions.\n * @param ev The keydown event.\n * @return Whether the Terminal should continue processing the keydown event.\n */\n public keydown(ev: KeyboardEvent): boolean {\n if (this.isComposing || this.isSendingComposition) {\n if (ev.keyCode === 229) {\n // Continue composing if the keyCode is the \"composition character\"\n return false;\n } else if (ev.keyCode === 16 || ev.keyCode === 17 || ev.keyCode === 18) {\n // Continue composing if the keyCode is a modifier key\n return false;\n } else {\n // Finish composition immediately. This is mainly here for the case where enter is\n // pressed and the handler needs to be triggered before the command is executed.\n this.finalizeComposition(false);\n }\n }\n\n if (ev.keyCode === 229) {\n // If the \"composition character\" is used but gets to this point it means a non-composition\n // character (eg. numbers and punctuation) was pressed when the IME was active.\n this.handleAnyTextareaChanges();\n return false;\n }\n\n return true;\n }\n\n /**\n * Finalizes the composition, resuming regular input actions. This is called when a composition\n * is ending.\n * @param waitForPropogation Whether to wait for events to propogate before sending\n * the input. This should be false if a non-composition keystroke is entered before the\n * compositionend event is triggered, such as enter, so that the composition is send before\n * the command is executed.\n */\n private finalizeComposition(waitForPropogation: boolean): void {\n this.compositionView.classList.remove('active');\n this.isComposing = false;\n this.clearTextareaPosition();\n\n if (!waitForPropogation) {\n // Cancel any delayed composition send requests and send the input immediately.\n this.isSendingComposition = false;\n const input = this.textarea.value.substring(this.compositionPosition.start, this.compositionPosition.end);\n this.terminal.handler(input);\n } else {\n // Make a deep copy of the composition position here as a new compositionstart event may\n // fire before the setTimeout executes.\n const currentCompositionPosition = {\n start: this.compositionPosition.start,\n end: this.compositionPosition.end,\n };\n\n // Since composition* events happen before the changes take place in the textarea on most\n // browsers, use a setTimeout with 0ms time to allow the native compositionend event to\n // complete. This ensures the correct character is retrieved, this solution was used\n // because:\n // - The compositionend event's data property is unreliable, at least on Chromium\n // - The last compositionupdate event's data property does not always accurately describe\n // the character, a counter example being Korean where an ending consonsant can move to\n // the following character if the following input is a vowel.\n this.isSendingComposition = true;\n setTimeout(() => {\n // Ensure that the input has not already been sent\n if (this.isSendingComposition) {\n this.isSendingComposition = false;\n let input;\n if (this.isComposing) {\n // Use the end position to get the string if a new composition has started.\n input = this.textarea.value.substring(currentCompositionPosition.start, currentCompositionPosition.end);\n } else {\n // Don't use the end position here in order to pick up any characters after the\n // composition has finished, for example when typing a non-composition character\n // (eg. 2) after a composition character.\n input = this.textarea.value.substring(currentCompositionPosition.start);\n }\n this.terminal.handler(input);\n }\n }, 0);\n }\n }\n\n /**\n * Apply any changes made to the textarea after the current event chain is allowed to complete.\n * This should be called when not currently composing but a keydown event with the \"composition\n * character\" (229) is triggered, in order to allow non-composition text to be entered when an\n * IME is active.\n */\n private handleAnyTextareaChanges(): void {\n const oldValue = this.textarea.value;\n setTimeout(() => {\n // Ignore if a composition has started since the timeout\n if (!this.isComposing) {\n const newValue = this.textarea.value;\n const diff = newValue.replace(oldValue, '');\n if (diff.length > 0) {\n this.terminal.handler(diff);\n }\n }\n }, 0);\n }\n\n /**\n * Positions the composition view on top of the cursor and the textarea just below it (so the\n * IME helper dialog is positioned correctly).\n * @param dontRecurse Whether to use setTimeout to recursively trigger another update, this is\n * necessary as the IME events across browsers are not consistently triggered.\n */\n public updateCompositionElements(dontRecurse?: boolean): void {\n if (!this.isComposing) {\n return;\n }\n\n if (this.terminal.buffer.isCursorInViewport) {\n const cellHeight = Math.ceil(this.terminal.charMeasure.height * this.terminal.options.lineHeight);\n const cursorTop = this.terminal.buffer.y * cellHeight;\n const cursorLeft = this.terminal.buffer.x * this.terminal.charMeasure.width;\n\n this.compositionView.style.left = cursorLeft + 'px';\n this.compositionView.style.top = cursorTop + 'px';\n this.compositionView.style.height = cellHeight + 'px';\n this.compositionView.style.lineHeight = cellHeight + 'px';\n // Sync the textarea to the exact position of the composition view so the IME knows where the\n // text is.\n const compositionViewBounds = this.compositionView.getBoundingClientRect();\n this.textarea.style.left = cursorLeft + 'px';\n this.textarea.style.top = cursorTop + 'px';\n this.textarea.style.width = compositionViewBounds.width + 'px';\n this.textarea.style.height = compositionViewBounds.height + 'px';\n this.textarea.style.lineHeight = compositionViewBounds.height + 'px';\n }\n\n if (!dontRecurse) {\n setTimeout(() => this.updateCompositionElements(true), 0);\n }\n };\n\n /**\n * Clears the textarea's position so that the cursor does not blink on IE.\n * @private\n */\n private clearTextareaPosition(): void {\n this.textarea.style.left = '';\n this.textarea.style.top = '';\n };\n}\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { Charset } from './Types';\n\n/**\n * The character sets supported by the terminal. These enable several languages\n * to be represented within the terminal with only 8-bit encoding. See ISO 2022\n * for a discussion on character sets. Only VT100 character sets are supported.\n */\nexport const CHARSETS: { [key: string]: Charset } = {};\n\n/**\n * The default character set, US.\n */\nexport const DEFAULT_CHARSET: Charset = CHARSETS['B'];\n\n/**\n * DEC Special Character and Line Drawing Set.\n * Reference: http://vt100.net/docs/vt102-ug/table5-13.html\n * A lot of curses apps use this if they see TERM=xterm.\n * testing: echo -e '\\e(0a\\e(B'\n * The xterm output sometimes seems to conflict with the\n * reference above. xterm seems in line with the reference\n * when running vttest however.\n * The table below now uses xterm's output from vttest.\n */\nCHARSETS['0'] = {\n '`': '\\u25c6', // '◆'\n 'a': '\\u2592', // '▒'\n 'b': '\\u0009', // '\\t'\n 'c': '\\u000c', // '\\f'\n 'd': '\\u000d', // '\\r'\n 'e': '\\u000a', // '\\n'\n 'f': '\\u00b0', // '°'\n 'g': '\\u00b1', // '±'\n 'h': '\\u2424', // '\\u2424' (NL)\n 'i': '\\u000b', // '\\v'\n 'j': '\\u2518', // '┘'\n 'k': '\\u2510', // '┐'\n 'l': '\\u250c', // '┌'\n 'm': '\\u2514', // '└'\n 'n': '\\u253c', // '┼'\n 'o': '\\u23ba', // '⎺'\n 'p': '\\u23bb', // '⎻'\n 'q': '\\u2500', // '─'\n 'r': '\\u23bc', // '⎼'\n 's': '\\u23bd', // '⎽'\n 't': '\\u251c', // '├'\n 'u': '\\u2524', // '┤'\n 'v': '\\u2534', // '┴'\n 'w': '\\u252c', // '┬'\n 'x': '\\u2502', // '│'\n 'y': '\\u2264', // '≤'\n 'z': '\\u2265', // '≥'\n '{': '\\u03c0', // 'π'\n '|': '\\u2260', // '≠'\n '}': '\\u00a3', // '£'\n '~': '\\u00b7' // '·'\n};\n\n/**\n * British character set\n * ESC (A\n * Reference: http://vt100.net/docs/vt220-rm/table2-5.html\n */\nCHARSETS['A'] = {\n '#': '£'\n};\n\n/**\n * United States character set\n * ESC (B\n */\nCHARSETS['B'] = null;\n\n/**\n * Dutch character set\n * ESC (4\n * Reference: http://vt100.net/docs/vt220-rm/table2-6.html\n */\nCHARSETS['4'] = {\n '#': '£',\n '@': '¾',\n '[': 'ij',\n '\\\\': '½',\n ']': '|',\n '{': '¨',\n '|': 'f',\n '}': '¼',\n '~': '´'\n};\n\n/**\n * Finnish character set\n * ESC (C or ESC (5\n * Reference: http://vt100.net/docs/vt220-rm/table2-7.html\n */\nCHARSETS['C'] =\nCHARSETS['5'] = {\n '[': 'Ä',\n '\\\\': 'Ö',\n ']': 'Å',\n '^': 'Ü',\n '`': 'é',\n '{': 'ä',\n '|': 'ö',\n '}': 'å',\n '~': 'ü'\n};\n\n/**\n * French character set\n * ESC (R\n * Reference: http://vt100.net/docs/vt220-rm/table2-8.html\n */\nCHARSETS['R'] = {\n '#': '£',\n '@': 'à',\n '[': '°',\n '\\\\': 'ç',\n ']': '§',\n '{': 'é',\n '|': 'ù',\n '}': 'è',\n '~': '¨'\n};\n\n/**\n * French Canadian character set\n * ESC (Q\n * Reference: http://vt100.net/docs/vt220-rm/table2-9.html\n */\nCHARSETS['Q'] = {\n '@': 'à',\n '[': 'â',\n '\\\\': 'ç',\n ']': 'ê',\n '^': 'î',\n '`': 'ô',\n '{': 'é',\n '|': 'ù',\n '}': 'è',\n '~': 'û'\n};\n\n/**\n * German character set\n * ESC (K\n * Reference: http://vt100.net/docs/vt220-rm/table2-10.html\n */\nCHARSETS['K'] = {\n '@': '§',\n '[': 'Ä',\n '\\\\': 'Ö',\n ']': 'Ü',\n '{': 'ä',\n '|': 'ö',\n '}': 'ü',\n '~': 'ß'\n};\n\n/**\n * Italian character set\n * ESC (Y\n * Reference: http://vt100.net/docs/vt220-rm/table2-11.html\n */\nCHARSETS['Y'] = {\n '#': '£',\n '@': '§',\n '[': '°',\n '\\\\': 'ç',\n ']': 'é',\n '`': 'ù',\n '{': 'à',\n '|': 'ò',\n '}': 'è',\n '~': 'ì'\n};\n\n/**\n * Norwegian/Danish character set\n * ESC (E or ESC (6\n * Reference: http://vt100.net/docs/vt220-rm/table2-12.html\n */\nCHARSETS['E'] =\nCHARSETS['6'] = {\n '@': 'Ä',\n '[': 'Æ',\n '\\\\': 'Ø',\n ']': 'Å',\n '^': 'Ü',\n '`': 'ä',\n '{': 'æ',\n '|': 'ø',\n '}': 'å',\n '~': 'ü'\n};\n\n/**\n * Spanish character set\n * ESC (Z\n * Reference: http://vt100.net/docs/vt220-rm/table2-13.html\n */\nCHARSETS['Z'] = {\n '#': '£',\n '@': '§',\n '[': '¡',\n '\\\\': 'Ñ',\n ']': '¿',\n '{': '°',\n '|': 'ñ',\n '}': 'ç'\n};\n\n/**\n * Swedish character set\n * ESC (H or ESC (7\n * Reference: http://vt100.net/docs/vt220-rm/table2-14.html\n */\nCHARSETS['H'] =\nCHARSETS['7'] = {\n '@': 'É',\n '[': 'Ä',\n '\\\\': 'Ö',\n ']': 'Å',\n '^': 'Ü',\n '`': 'é',\n '{': 'ä',\n '|': 'ö',\n '}': 'å',\n '~': 'ü'\n};\n\n/**\n * Swiss character set\n * ESC (=\n * Reference: http://vt100.net/docs/vt220-rm/table2-15.html\n */\nCHARSETS['='] = {\n '#': 'ù',\n '@': 'à',\n '[': 'é',\n '\\\\': 'ç',\n ']': 'ê',\n '^': 'î',\n '_': 'è',\n '`': 'ô',\n '{': 'ä',\n '|': 'ö',\n '}': 'ü',\n '~': 'û'\n};\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nexport const wcwidth = (function(opts: {nul: number, control: number}): (ucs: number) => number {\n // extracted from https://www.cl.cam.ac.uk/%7Emgk25/ucs/wcwidth.c\n // combining characters\n const COMBINING_BMP = [\n [0x0300, 0x036F], [0x0483, 0x0486], [0x0488, 0x0489],\n [0x0591, 0x05BD], [0x05BF, 0x05BF], [0x05C1, 0x05C2],\n [0x05C4, 0x05C5], [0x05C7, 0x05C7], [0x0600, 0x0603],\n [0x0610, 0x0615], [0x064B, 0x065E], [0x0670, 0x0670],\n [0x06D6, 0x06E4], [0x06E7, 0x06E8], [0x06EA, 0x06ED],\n [0x070F, 0x070F], [0x0711, 0x0711], [0x0730, 0x074A],\n [0x07A6, 0x07B0], [0x07EB, 0x07F3], [0x0901, 0x0902],\n [0x093C, 0x093C], [0x0941, 0x0948], [0x094D, 0x094D],\n [0x0951, 0x0954], [0x0962, 0x0963], [0x0981, 0x0981],\n [0x09BC, 0x09BC], [0x09C1, 0x09C4], [0x09CD, 0x09CD],\n [0x09E2, 0x09E3], [0x0A01, 0x0A02], [0x0A3C, 0x0A3C],\n [0x0A41, 0x0A42], [0x0A47, 0x0A48], [0x0A4B, 0x0A4D],\n [0x0A70, 0x0A71], [0x0A81, 0x0A82], [0x0ABC, 0x0ABC],\n [0x0AC1, 0x0AC5], [0x0AC7, 0x0AC8], [0x0ACD, 0x0ACD],\n [0x0AE2, 0x0AE3], [0x0B01, 0x0B01], [0x0B3C, 0x0B3C],\n [0x0B3F, 0x0B3F], [0x0B41, 0x0B43], [0x0B4D, 0x0B4D],\n [0x0B56, 0x0B56], [0x0B82, 0x0B82], [0x0BC0, 0x0BC0],\n [0x0BCD, 0x0BCD], [0x0C3E, 0x0C40], [0x0C46, 0x0C48],\n [0x0C4A, 0x0C4D], [0x0C55, 0x0C56], [0x0CBC, 0x0CBC],\n [0x0CBF, 0x0CBF], [0x0CC6, 0x0CC6], [0x0CCC, 0x0CCD],\n [0x0CE2, 0x0CE3], [0x0D41, 0x0D43], [0x0D4D, 0x0D4D],\n [0x0DCA, 0x0DCA], [0x0DD2, 0x0DD4], [0x0DD6, 0x0DD6],\n [0x0E31, 0x0E31], [0x0E34, 0x0E3A], [0x0E47, 0x0E4E],\n [0x0EB1, 0x0EB1], [0x0EB4, 0x0EB9], [0x0EBB, 0x0EBC],\n [0x0EC8, 0x0ECD], [0x0F18, 0x0F19], [0x0F35, 0x0F35],\n [0x0F37, 0x0F37], [0x0F39, 0x0F39], [0x0F71, 0x0F7E],\n [0x0F80, 0x0F84], [0x0F86, 0x0F87], [0x0F90, 0x0F97],\n [0x0F99, 0x0FBC], [0x0FC6, 0x0FC6], [0x102D, 0x1030],\n [0x1032, 0x1032], [0x1036, 0x1037], [0x1039, 0x1039],\n [0x1058, 0x1059], [0x1160, 0x11FF], [0x135F, 0x135F],\n [0x1712, 0x1714], [0x1732, 0x1734], [0x1752, 0x1753],\n [0x1772, 0x1773], [0x17B4, 0x17B5], [0x17B7, 0x17BD],\n [0x17C6, 0x17C6], [0x17C9, 0x17D3], [0x17DD, 0x17DD],\n [0x180B, 0x180D], [0x18A9, 0x18A9], [0x1920, 0x1922],\n [0x1927, 0x1928], [0x1932, 0x1932], [0x1939, 0x193B],\n [0x1A17, 0x1A18], [0x1B00, 0x1B03], [0x1B34, 0x1B34],\n [0x1B36, 0x1B3A], [0x1B3C, 0x1B3C], [0x1B42, 0x1B42],\n [0x1B6B, 0x1B73], [0x1DC0, 0x1DCA], [0x1DFE, 0x1DFF],\n [0x200B, 0x200F], [0x202A, 0x202E], [0x2060, 0x2063],\n [0x206A, 0x206F], [0x20D0, 0x20EF], [0x302A, 0x302F],\n [0x3099, 0x309A], [0xA806, 0xA806], [0xA80B, 0xA80B],\n [0xA825, 0xA826], [0xFB1E, 0xFB1E], [0xFE00, 0xFE0F],\n [0xFE20, 0xFE23], [0xFEFF, 0xFEFF], [0xFFF9, 0xFFFB],\n ];\n const COMBINING_HIGH = [\n [0x10A01, 0x10A03], [0x10A05, 0x10A06], [0x10A0C, 0x10A0F],\n [0x10A38, 0x10A3A], [0x10A3F, 0x10A3F], [0x1D167, 0x1D169],\n [0x1D173, 0x1D182], [0x1D185, 0x1D18B], [0x1D1AA, 0x1D1AD],\n [0x1D242, 0x1D244], [0xE0001, 0xE0001], [0xE0020, 0xE007F],\n [0xE0100, 0xE01EF]\n ];\n // binary search\n function bisearch(ucs: number, data: number[][]): boolean {\n let min = 0;\n let max = data.length - 1;\n let mid;\n if (ucs < data[0][0] || ucs > data[max][1])\n return false;\n while (max >= min) {\n mid = (min + max) >> 1;\n if (ucs > data[mid][1])\n min = mid + 1;\n else if (ucs < data[mid][0])\n max = mid - 1;\n else\n return true;\n }\n return false;\n }\n function wcwidthBMP(ucs: number): number {\n // test for 8-bit control characters\n if (ucs === 0)\n return opts.nul;\n if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))\n return opts.control;\n // binary search in table of non-spacing characters\n if (bisearch(ucs, COMBINING_BMP))\n return 0;\n // if we arrive here, ucs is not a combining or C0/C1 control character\n if (isWideBMP(ucs)) {\n return 2;\n }\n return 1;\n }\n function isWideBMP(ucs: number): boolean {\n return (\n ucs >= 0x1100 && (\n ucs <= 0x115f || // Hangul Jamo init. consonants\n ucs === 0x2329 ||\n ucs === 0x232a ||\n (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs !== 0x303f) || // CJK..Yi\n (ucs >= 0xac00 && ucs <= 0xd7a3) || // Hangul Syllables\n (ucs >= 0xf900 && ucs <= 0xfaff) || // CJK Compat Ideographs\n (ucs >= 0xfe10 && ucs <= 0xfe19) || // Vertical forms\n (ucs >= 0xfe30 && ucs <= 0xfe6f) || // CJK Compat Forms\n (ucs >= 0xff00 && ucs <= 0xff60) || // Fullwidth Forms\n (ucs >= 0xffe0 && ucs <= 0xffe6)));\n }\n function wcwidthHigh(ucs: number): 0 | 1 | 2 {\n if (bisearch(ucs, COMBINING_HIGH))\n return 0;\n if ((ucs >= 0x20000 && ucs <= 0x2fffd) || (ucs >= 0x30000 && ucs <= 0x3fffd)) {\n return 2;\n }\n return 1;\n }\n const control = opts.control | 0;\n let table: number[] | Uint32Array = null;\n function init_table(): number[] | Uint32Array {\n // lookup table for BMP\n const CODEPOINTS = 65536; // BMP holds 65536 codepoints\n const BITWIDTH = 2; // a codepoint can have a width of 0, 1 or 2\n const ITEMSIZE = 32; // using uint32_t\n const CONTAINERSIZE = CODEPOINTS * BITWIDTH / ITEMSIZE;\n const CODEPOINTS_PER_ITEM = ITEMSIZE / BITWIDTH;\n table = (typeof Uint32Array === 'undefined')\n ? new Array(CONTAINERSIZE)\n : new Uint32Array(CONTAINERSIZE);\n for (let i = 0; i < CONTAINERSIZE; ++i) {\n let num = 0;\n let pos = CODEPOINTS_PER_ITEM;\n while (pos--)\n num = (num << 2) | wcwidthBMP(CODEPOINTS_PER_ITEM * i + pos);\n table[i] = num;\n }\n return table;\n }\n // get width from lookup table\n // position in container : num / CODEPOINTS_PER_ITEM\n // ==> n = table[Math.floor(num / 16)]\n // ==> n = table[num >> 4]\n // 16 codepoints per number: FFEEDDCCBBAA99887766554433221100\n // position in number : (num % CODEPOINTS_PER_ITEM) * BITWIDTH\n // ==> m = (n % 16) * 2\n // ==> m = (num & 15) << 1\n // right shift to position m\n // ==> n = n >> m e.g. m=12 000000000000FFEEDDCCBBAA99887766\n // we are only interested in 2 LSBs, cut off higher bits\n // ==> n = n & 3 e.g. 000000000000000000000000000000XX\n return function (num: number): number {\n num = num | 0; // get asm.js like optimization under V8\n if (num < 32)\n return control | 0;\n if (num < 127)\n return 1;\n let t = table || init_table();\n if (num < 65536)\n return t[num >> 4] >> ((num & 15) << 1) & 3;\n // do a full search for high codepoints\n return wcwidthHigh(num);\n };\n})({nul: 0, control: 0}); // configurable options\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ITerminal, IBufferSet } from './Interfaces';\nimport { Buffer } from './Buffer';\nimport { EventEmitter } from './EventEmitter';\n\n/**\n * The BufferSet represents the set of two buffers used by xterm terminals (normal and alt) and\n * provides also utilities for working with them.\n */\nexport class BufferSet extends EventEmitter implements IBufferSet {\n private _normal: Buffer;\n private _alt: Buffer;\n private _activeBuffer: Buffer;\n\n /**\n * Create a new BufferSet for the given terminal.\n * @param {Terminal} terminal - The terminal the BufferSet will belong to\n */\n constructor(private _terminal: ITerminal) {\n super();\n this._normal = new Buffer(this._terminal, true);\n this._normal.fillViewportRows();\n\n // The alt buffer should never have scrollback.\n // See http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer\n this._alt = new Buffer(this._terminal, false);\n this._activeBuffer = this._normal;\n\n this.setupTabStops();\n }\n\n /**\n * Returns the alt Buffer of the BufferSet\n * @returns {Buffer}\n */\n public get alt(): Buffer {\n return this._alt;\n }\n\n /**\n * Returns the normal Buffer of the BufferSet\n * @returns {Buffer}\n */\n public get active(): Buffer {\n return this._activeBuffer;\n }\n\n /**\n * Returns the currently active Buffer of the BufferSet\n * @returns {Buffer}\n */\n public get normal(): Buffer {\n return this._normal;\n }\n\n /**\n * Sets the normal Buffer of the BufferSet as its currently active Buffer\n */\n public activateNormalBuffer(): void {\n // The alt buffer should always be cleared when we switch to the normal\n // buffer. This frees up memory since the alt buffer should always be new\n // when activated.\n this._alt.clear();\n\n this._activeBuffer = this._normal;\n this.emit('activate', this._normal);\n }\n\n /**\n * Sets the alt Buffer of the BufferSet as its currently active Buffer\n */\n public activateAltBuffer(): void {\n // Since the alt buffer is always cleared when the normal buffer is\n // activated, we want to fill it when switching to it.\n this._alt.fillViewportRows();\n this._activeBuffer = this._alt;\n this.emit('activate', this._alt);\n }\n\n /**\n * Resizes both normal and alt buffers, adjusting their data accordingly.\n * @param newCols The new number of columns.\n * @param newRows The new number of rows.\n */\n public resize(newCols: number, newRows: number): void {\n this._normal.resize(newCols, newRows);\n this._alt.resize(newCols, newRows);\n }\n\n /**\n * Setup the tab stops.\n * @param i The index to start setting up tab stops from.\n */\n public setupTabStops(i?: number): void {\n this._normal.setupTabStops(i);\n this._alt.setupTabStops(i);\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ITerminal, IBuffer } from './Interfaces';\nimport { CircularList } from './utils/CircularList';\nimport { LineData, CharData } from './Types';\n\nexport const CHAR_DATA_ATTR_INDEX = 0;\nexport const CHAR_DATA_CHAR_INDEX = 1;\nexport const CHAR_DATA_WIDTH_INDEX = 2;\nexport const CHAR_DATA_CODE_INDEX = 3;\nexport const MAX_BUFFER_SIZE = 4294967295; // 2^32 - 1\n\n/**\n * This class represents a terminal buffer (an internal state of the terminal), where the\n * following information is stored (in high-level):\n * - text content of this particular buffer\n * - cursor position\n * - scroll position\n */\nexport class Buffer implements IBuffer {\n private _lines: CircularList;\n\n public ydisp: number;\n public ybase: number;\n public y: number;\n public x: number;\n public scrollBottom: number;\n public scrollTop: number;\n public tabs: any;\n public savedY: number;\n public savedX: number;\n\n /**\n * Create a new Buffer.\n * @param _terminal The terminal the Buffer will belong to.\n * @param _hasScrollback Whether the buffer should respect the scrollback of\n * the terminal.\n */\n constructor(\n private _terminal: ITerminal,\n private _hasScrollback: boolean\n ) {\n this.clear();\n }\n\n public get lines(): CircularList {\n return this._lines;\n }\n\n public get hasScrollback(): boolean {\n return this._hasScrollback && this.lines.maxLength > this._terminal.rows;\n }\n\n public get isCursorInViewport(): boolean {\n const absoluteY = this.ybase + this.y;\n const relativeY = absoluteY - this.ydisp;\n return (relativeY >= 0 && relativeY < this._terminal.rows);\n }\n\n /**\n * Gets the correct buffer length based on the rows provided, the terminal's\n * scrollback and whether this buffer is flagged to have scrollback or not.\n * @param rows The terminal rows to use in the calculation.\n */\n private _getCorrectBufferLength(rows: number): number {\n if (!this._hasScrollback) {\n return rows;\n }\n\n const correctBufferLength = rows + this._terminal.options.scrollback;\n\n return correctBufferLength > MAX_BUFFER_SIZE ? MAX_BUFFER_SIZE : correctBufferLength;\n }\n\n /**\n * Fills the buffer's viewport with blank lines.\n */\n public fillViewportRows(): void {\n if (this._lines.length === 0) {\n let i = this._terminal.rows;\n while (i--) {\n this.lines.push(this._terminal.blankLine());\n }\n }\n }\n\n /**\n * Clears the buffer to it's initial state, discarding all previous data.\n */\n public clear(): void {\n this.ydisp = 0;\n this.ybase = 0;\n this.y = 0;\n this.x = 0;\n this._lines = new CircularList(this._getCorrectBufferLength(this._terminal.rows));\n this.scrollTop = 0;\n this.scrollBottom = this._terminal.rows - 1;\n this.setupTabStops();\n }\n\n /**\n * Resizes the buffer, adjusting its data accordingly.\n * @param newCols The new number of columns.\n * @param newRows The new number of rows.\n */\n public resize(newCols: number, newRows: number): void {\n // Increase max length if needed before adjustments to allow space to fill\n // as required.\n const newMaxLength = this._getCorrectBufferLength(newRows);\n if (newMaxLength > this._lines.maxLength) {\n this._lines.maxLength = newMaxLength;\n }\n\n // The following adjustments should only happen if the buffer has been\n // initialized/filled.\n if (this._lines.length > 0) {\n // Deal with columns increasing (we don't do anything when columns reduce)\n if (this._terminal.cols < newCols) {\n const ch: CharData = [this._terminal.defAttr, ' ', 1, 32]; // does xterm use the default attr?\n for (let i = 0; i < this._lines.length; i++) {\n // TODO: This should be removed, with tests setup for the case that was\n // causing the underlying bug, see https://github.com/sourcelair/xterm.js/issues/824\n if (this._lines.get(i) === undefined) {\n this._lines.set(i, this._terminal.blankLine(undefined, undefined, newCols));\n }\n while (this._lines.get(i).length < newCols) {\n this._lines.get(i).push(ch);\n }\n }\n }\n\n // Resize rows in both directions as needed\n let addToY = 0;\n if (this._terminal.rows < newRows) {\n for (let y = this._terminal.rows; y < newRows; y++) {\n if (this._lines.length < newRows + this.ybase) {\n if (this.ybase > 0 && this._lines.length <= this.ybase + this.y + addToY + 1) {\n // There is room above the buffer and there are no empty elements below the line,\n // scroll up\n this.ybase--;\n addToY++;\n if (this.ydisp > 0) {\n // Viewport is at the top of the buffer, must increase downwards\n this.ydisp--;\n }\n } else {\n // Add a blank line if there is no buffer left at the top to scroll to, or if there\n // are blank lines after the cursor\n this._lines.push(this._terminal.blankLine(undefined, undefined, newCols));\n }\n }\n }\n } else { // (this._terminal.rows >= newRows)\n for (let y = this._terminal.rows; y > newRows; y--) {\n if (this._lines.length > newRows + this.ybase) {\n if (this._lines.length > this.ybase + this.y + 1) {\n // The line is a blank line below the cursor, remove it\n this._lines.pop();\n } else {\n // The line is the cursor, scroll down\n this.ybase++;\n this.ydisp++;\n }\n }\n }\n }\n\n // Reduce max length if needed after adjustments, this is done after as it\n // would otherwise cut data from the bottom of the buffer.\n if (newMaxLength < this._lines.maxLength) {\n // Trim from the top of the buffer and adjust ybase and ydisp.\n const amountToTrim = this._lines.length - newMaxLength;\n if (amountToTrim > 0) {\n this._lines.trimStart(amountToTrim);\n this.ybase = Math.max(this.ybase - amountToTrim, 0);\n this.ydisp = Math.max(this.ydisp - amountToTrim, 0);\n }\n this._lines.maxLength = newMaxLength;\n }\n\n // Make sure that the cursor stays on screen\n if (this.y >= newRows) {\n this.y = newRows - 1;\n }\n if (addToY) {\n this.y += addToY;\n }\n\n if (this.x >= newCols) {\n this.x = newCols - 1;\n }\n\n this.scrollTop = 0;\n }\n\n this.scrollBottom = newRows - 1;\n }\n\n /**\n * Translates a buffer line to a string, with optional start and end columns.\n * Wide characters will count as two columns in the resulting string. This\n * function is useful for getting the actual text underneath the raw selection\n * position.\n * @param line The line being translated.\n * @param trimRight Whether to trim whitespace to the right.\n * @param startCol The column to start at.\n * @param endCol The column to end at.\n */\n public translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol: number = 0, endCol: number = null): string {\n // Get full line\n let lineString = '';\n const line = this.lines.get(lineIndex);\n if (!line) {\n return '';\n }\n\n // Initialize column and index values. Column values represent the actual\n // cell column, indexes represent the index in the string. Indexes are\n // needed here because some chars are 0 characters long (eg. after wide\n // chars) and some chars are longer than 1 characters long (eg. emojis).\n let startIndex = startCol;\n endCol = endCol || line.length;\n let endIndex = endCol;\n\n for (let i = 0; i < line.length; i++) {\n const char = line[i];\n lineString += char[CHAR_DATA_CHAR_INDEX];\n // Adjust start and end cols for wide characters if they affect their\n // column indexes\n if (char[CHAR_DATA_WIDTH_INDEX] === 0) {\n if (startCol >= i) {\n startIndex--;\n }\n if (endCol >= i) {\n endIndex--;\n }\n } else {\n // Adjust the columns to take glyphs that are represented by multiple\n // code points into account.\n if (char[CHAR_DATA_CHAR_INDEX].length > 1) {\n if (startCol > i) {\n startIndex += char[CHAR_DATA_CHAR_INDEX].length - 1;\n }\n if (endCol > i) {\n endIndex += char[CHAR_DATA_CHAR_INDEX].length - 1;\n }\n }\n }\n }\n\n // Calculate the final end col by trimming whitespace on the right of the\n // line if needed.\n if (trimRight) {\n const rightWhitespaceIndex = lineString.search(/\\s+$/);\n if (rightWhitespaceIndex !== -1) {\n endIndex = Math.min(endIndex, rightWhitespaceIndex);\n }\n // Return the empty string if only trimmed whitespace is selected\n if (endIndex <= startIndex) {\n return '';\n }\n }\n\n return lineString.substring(startIndex, endIndex);\n }\n\n /**\n * Setup the tab stops.\n * @param i The index to start setting up tab stops from.\n */\n public setupTabStops(i?: number): void {\n if (i != null) {\n if (!this.tabs[i]) {\n i = this.prevStop(i);\n }\n } else {\n this.tabs = {};\n i = 0;\n }\n\n for (; i < this._terminal.cols; i += this._terminal.options.tabStopWidth) {\n this.tabs[i] = true;\n }\n }\n\n /**\n * Move the cursor to the previous tab stop from the given position (default is current).\n * @param x The position to move the cursor to the previous tab stop.\n */\n public prevStop(x?: number): number {\n if (x == null) {\n x = this.x;\n }\n while (!this.tabs[--x] && x > 0);\n return x >= this._terminal.cols ? this._terminal.cols - 1 : x < 0 ? 0 : x;\n }\n\n /**\n * Move the cursor one tab stop forward from the given position (default is current).\n * @param x The position to move the cursor one tab stop forward.\n */\n public nextStop(x?: number): number {\n if (x == null) {\n x = this.x;\n }\n while (!this.tabs[++x] && x < this._terminal.cols);\n return x >= this._terminal.cols ? this._terminal.cols - 1 : x < 0 ? 0 : x;\n }\n}\n",null],"names":[],"mappings":"AkCAA;;;ADMA;AAGa;AACA;AACA;AACA;AACA;AASb;AAmBA;AACA;AACA;AAEA;AACA;AAEA;AAAA;AACA;AACA;;;AAAA;AAEA;AAAA;AACA;AACA;;;AAAA;AAEA;AAAA;AACA;AACA;AACA;AACA;;;AAAA;AAOA;AACA;AACA;AACA;AAEA;AAEA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AAGA;AACA;AACA;AACA;AAIA;AAEA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAEA;AACA;AACA;AAAA;AAGA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAEA;AACA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AAIA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAYA;AAAA;AAAA;AAEA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AAEA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAAA;AAjSa;;;;;;;;;;;;;;;;;ADhBb;AACA;AAMA;AAAA;AASA;AAAA;AAAA;AAEA;AACA;AAIA;AACA;AAEA;;AACA;AAMA;AAAA;AACA;AACA;;;AAAA;AAMA;AAAA;AACA;AACA;;;AAAA;AAMA;AAAA;AACA;AACA;;;AAAA;AAKA;AAIA;AAEA;AACA;AACA;AAKA;AAGA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AAAA;AAxFa;;;;;;;ADRA;AAGb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;;;;;;;ADpJa;AAKA;AAYb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AAMA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AD7OA;AAwBA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AAMA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AAOA;AACA;AACA;AAEA;AACA;AAAA;AAEA;AACA;AAAA;AAGA;AACA;AACA;AAEA;AAGA;AACA;AACA;AAEA;AACA;AAUA;AAAA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AAAA;AAGA;AACA;AACA;AACA;AAUA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAAA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AAQA;AAAA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAQA;AAAA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAA;AAMA;AACA;AACA;AACA;AAAA;AACA;AAAA;AApNa;;;;;;;ADRb;AAAA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AACA;AAAC;;;;;;;ADvED;AAGA;AAGA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAAA;AAAA;AAAA;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAA;AA/Da;;;;;;;ADAb;AACA;AAEA;AACA;AACA;AASA;AACA;AAAA;AAAA;AAEA;AACA;AAGA;AAEA;AACA;AACA;AAEA;AAIA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAGA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AAGA;AAEA;AAGA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAEA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAMA;AACA;AAMA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AAOA;AACA;AACA;AAOA;AACA;AACA;AAMA;AACA;AACA;AAAA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AAEA;AACA;AACA;AAAA;AACA;AACA;AAEA;AACA;AACA;AAAA;AACA;AACA;AAEA;AACA;AACA;AAAA;AACA;AACA;AAEA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AAcA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAGA;AACA;AACA;AAGA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAGA;AACA;AACA;AAGA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAuCA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAAA;AAIA;AACA;AACA;AAAA;AACA;AACA;AAAA;AAGA;AACA;AAAA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAOA;AACA;AAAA;AACA;AAAA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAUA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAwFA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAGA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AACA;AAKA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAoFA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAmEA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAAA;AAEA;AACA;AAAA;AAEA;AACA;AACA;AAAA;AAEA;AACA;AACA;AAAA;AAEA;AACA;AACA;AAIA;AAAA;AAEA;AACA;AAAA;AAEA;AACA;AAAA;AAEA;AACA;AAAA;AAGA;AACA;AAAA;AAEA;AACA;AAAA;AAEA;AACA;AAAA;AAEA;AACA;AACA;AAAA;AAEA;AACA;AAAA;AAEA;AACA;AAAA;AAEA;AACA;AAAA;AAEA;AACA;AAAA;AAEA;AACA;AAAA;AAEA;AACA;AAAA;AAEA;AACA;AACA;AAIA;AAAA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AAAA;AAEA;AACA;AACA;AAIA;AAAA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AAAA;AAEA;AACA;AACA;AAAA;AACA;AACA;AACA;AAEA;AACA;AAyBA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAGA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AAGA;AACA;AAGA;AACA;AAGA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAYA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAQA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AAAA;AAz5Ca;;;;;;;;;;;;;;;;;ADfb;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AAKA;AAAA;AAeA;AAAA;AACA;AARA;AAIA;AAOA;AACA;AACA;AACA;AACA;;AACA;AAMA;AACA;AACA;AAOA;AAAA;AAEA;AACA;AACA;AAGA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAGA;AAGA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AAMA;AACA;AACA;AAYA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAQA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAOA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAWA;AAAA;AAAA;AAEA;AACA;AAGA;AACA;AACA;AACA;AACA;AAGA;AAGA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AASA;AAAA;AACA;AAKA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AA3PA;AA4PA;AAlQA;AAAa;;;;;;;ADhCb;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AAKA;AACA;AACA;AAEA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAIA;AACA;AAGA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AAKA;AACA;AAIA;AACA;AAGA;AACA;AACA;AAGA;AACA;AACA;AAGA;AACA;AACA;AAGA;AACA;AACA;AAGA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAIA;AACA;AAAA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AAAA;AACA;AACA;AAEA;AAEA;AACA;AAIA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAGA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AAGA;AACA;AAMA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAAA;AACA;AACA;AAAA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAEA;AAEA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AAEA;AACA;AAOA;AACA;AACA;AAQA;AACA;AACA;AAQA;AACA;AACA;AAOA;AACA;AACA;AAKA;AACA;AACA;AAMA;AACA;AACA;AACA;AAKA;AACA;AACA;AASA;AAAA;AAjfa;;;;;;;;;;;;;;;;;ADnKb;AACA;AAGA;AAEA;AAEA;AAMA;AAKA;AAKA;AAMA;AAEA;AACA;AAaA;AAAA;AACA;AACA;AACA;AACA;AAUA;AAAA;AAiCA;AAAA;AACA;AACA;AACA;AARA;AAWA;AACA;AAEA;AACA;;AACA;AAKA;AAAA;AACA;AACA;AAMA;AACA;AAMA;AACA;AACA;AACA;AAKA;AACA;AACA;AAOA;AACA;AACA;AACA;AAEA;AAAA;;;AAAA;AACA;AAAA;;;AAAA;AAKA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAAA;AAKA;AAAA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAIA;AACA;AACA;AAEA;AACA;;;AAAA;AAKA;AACA;AACA;AACA;AACA;AAOA;AAAA;AAEA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AAGA;AACA;AAGA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAOA;AACA;AACA;AAMA;AAGA;AACA;AACA;AAGA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AAGA;AAGA;AAEA;AACA;AACA;AAAA;AACA;AACA;AACA;AAAA;AACA;AACA;AAAA;AACA;AACA;AACA;AAEA;AACA;AACA;AAKA;AAAA;AAEA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AAIA;AAIA;AAGA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAAA;AACA;AACA;AAGA;AAIA;AACA;AACA;AAAA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AAEA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AAEA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AAGA;AACA;AAAA;AAIA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AAEA;AAGA;AACA;AAGA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAKA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AACA;AAEA;AACA;AACA;AAAA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAAA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AAIA;AAEA;AACA;AACA;AAIA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AAOA;AAGA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AAAA;AAjqBa;;;;;;;ADtDb;AAuBA;AACA;AAEA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AAKA;AAAA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;;;AAAA;AAMA;AAAA;AACA;AACA;AACA;AAEA;AACA;AACA;AAGA;AACA;AACA;AAGA;AAEA;AACA;AACA;AACA;AACA;AACA;;;AAAA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AAEA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAAA;AAxHa;;;;;;;;;;;;;;;;;ADYb;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AAEA;AACA;AAUA;AAOA;AAMA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AAEA;AAAA;AA8HA;AACA;AADA;AA3GA;AA+GA;AACA;;AACA;AAEA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AAKA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAEA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AAGA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAKA;AAEA;AACA;AAKA;AACA;AACA;AAEA;AAAA;AACA;AACA;;;AAAA;AAMA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;AAAA;AAAA;AACA;AAEA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAMA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AAAA;AACA;AAGA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AAEA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAKA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAOA;AAAA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAGA;AACA;AACA;AAEA;AAGA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AAGA;AAEA;AACA;AACA;AAIA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAEA;AAEA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAGA;AAGA;AAGA;AAIA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AAOA;AAEA;AAEA;AACA;AAAA;AAEA;AACA;AAAA;AACA;AACA;AACA;AACA;AAYA;AAAA;AACA;AACA;AACA;AAKA;AACA;AACA;AAGA;AAGA;AACA;AAAA;AAEA;AAEA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAIA;AACA;AACA;AAIA;AACA;AACA;AACA;AAAA;AAIA;AAEA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AAQA;AAOA;AAGA;AACA;AACA;AACA;AACA;AAAA;AACA;AAAA;AACA;AAAA;AACA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AAAA;AACA;AAAA;AACA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AAGA;AAEA;AACA;AAAA;AACA;AACA;AAGA;AAEA;AACA;AAEA;AAIA;AACA;AAKA;AACA;AACA;AAGA;AAIA;AACA;AACA;AACA;AACA;AAGA;AAAA;AAGA;AACA;AACA;AAEA;AAAA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAMA;AACA;AAAA;AACA;AAAA;AACA;AACA;AACA;AAIA;AACA;AAAA;AACA;AACA;AACA;AAEA;AACA;AAAA;AACA;AACA;AACA;AAEA;AACA;AAAA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAQA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AAEA;AAEA;AAGA;AACA;AACA;AAAA;AACA;AACA;AAGA;AACA;AAEA;AACA;AACA;AACA;AAAA;AAGA;AACA;AACA;AACA;AACA;AAAA;AAGA;AACA;AACA;AACA;AAIA;AACA;AACA;AAGA;AACA;AAQA;AACA;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AAEA;AACA;AAGA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAMA;AACA;AACA;AAKA;AACA;AACA;AAKA;AACA;AACA;AAMA;AAAA;AACA;AAKA;AAGA;AACA;AACA;AAEA;AAEA;AAEA;AACA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AAEA;AACA;AAOA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAAA;AACA;AACA;AACA;AAMA;AACA;AACA;AAWA;AACA;AACA;AAQA;AACA;AACA;AACA;AACA;AAEA;AACA;AAQA;AACA;AACA;AACA;AACA;AAEA;AACA;AAYA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AAMA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AAQA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAAA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AAEA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AASA;AACA;AAGA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAIA;AACA;AACA;AACA;AAAA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AAIA;AACA;AACA;AACA;AAAA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AAGA;AACA;AACA;AACA;AAAA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AAGA;AACA;AACA;AACA;AAAA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AAGA;AACA;AACA;AACA;AAEA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAA;AAEA;AACA;AAAA;AAEA;AACA;AAAA;AAEA;AACA;AAAA;AAEA;AACA;AAAA;AAEA;AACA;AAAA;AAEA;AACA;AACA;AAAA;AAEA;AACA;AACA;AAAA;AACA;AACA;AAAA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAMA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AAQA;AACA;AAEA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAAA;AACA;AACA;AAAA;AACA;AACA;AAAA;AACA;AACA;AAEA;AAGA;AACA;AAEA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAMA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAMA;AAAA;AACA;AACA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AAAA;AACA;AAAA;AACA;AACA;AAKA;AACA;AAAA;AACA;AAAA;AACA;AACA;AAQA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AAEA;AAAA;AACA;AAAA;AAEA;AAEA;AACA;AACA;AAEA;AAEA;AAEA;AACA;AACA;AAMA;AACA;AAAA;AACA;AAAA;AAOA;AAKA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AASA;AACA;AAEA;AACA;AAIA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AAMA;AAEA;AACA;AACA;AAGA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AAMA;AAOA;AACA;AASA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAOA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAAA;AA//Da;AAqgEb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AAAA;AACA;AACA;AAEA;AACA;AAEA;AAEA;AACA;AACA;AAGA;AACA;AAEA;AACA;AACA;AACA;AACA;AAWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AAGA;AACA;AACA;AACA;AACA;AAAC;AAGD;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;;;;;;;AD9rEA;AAAA;AACA;AACA;AACA;AACA;AAAC;;;;;;;ADrBD;AAcA;AAAA;AACA;AACA;AACA;AACA;AAjBA;AACA;AACA;AACA;AAgBA;AAGA;AACA;AAEA;AACA;AACA;AAMA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AAEA;AACA;AACA;AAAA;AAEA;AACA;AAAA;AAEA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AAQA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAEA;AACA;AAAA;AAMA;AACA;AACA;AAAA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AAAA;AAnIa;;;;;;;ADOb;AACA;AACA;AACA;AACA;AACA;AALA;AAWA;AACA;AACA;AACA;AACA;AACA;AALA;AAWA;AACA;AACA;AACA;AAAA;AACA;AACA;AAGA;AACA;AATA;AAgBA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAzBA;AAgCA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AApBA;AA4BA;AACA;AAGA;AACA;AACA;AANA;;;;;;;AD9GA;AAUA;AAWA;AAAA;AACA;AAXA;AAEA;AAIA;AACA;AACA;AAKA;AAGA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAGA;AACA;AAEA;AACA;AACA;AAEA;AAAA;AACA;AAGA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AACA;AAGA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAIA;AACA;AAGA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAAA;AArKa;AAuKb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAAA;AAXa;;;;;;;ADlLb;AAEA;AAEa;AACb;AAEA;AAYA;AAIA;AACA;AAdA;AACA;AACA;AACA;AACA;AACA;AAWA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAOA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAEA;AACA;AACA;AACA;AAWA;AACA;AAKA;AAQA;AAAA;AACA;AAKA;AAQA;AACA;AAKA;AAQA;AACA;AACA;AAKA;AAKA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AASA;AACA;AACA;AAKA;AAAA;AACA;AACA;AAKA;AACA;AAYA;AACA;AACA;AACA;AACA;AAIA;AAgBA;AACA;AACA;AACA;AACA;AAAA;AAEA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AAEA;AACA;AAGA;AACA;AACA;AAGA;AAEA;AACA;AACA;AACA;AAEA;AASA;AAAA;AACA;AACA;AAIA;AAaA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAAA;AAEA;AACA;AAAA;AACA;AACA;AAEA;AAGA;AACA;AACA;AAEA;AAIA;AACA;AAOA;AACA;AACA;AAKA;AACA;AACA;AAAA;AAhUsB;;;;;;;ADPtB;AAEa;AAgBb;AAQA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAEA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAvCA;AAyCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAMA;AACA;AACA;AACA;AACA;AAJA;AAMA;AAIA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AAGA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;;;;;;;ADrNA;AACA;AACA;AACA;AACA;AACa;AAEb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AAKA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AA1Da;;;;;;;;;;;;;;;;;AD5Db;AAGA;AAcA;AAEA;AAAA;AAMA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAGA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AApMa;AAsMb;AAcA;AAEA;AAEA;AACA;AACA;AACA;AACA;AAEA;AAAA;;;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAAA;AAAA;AAEA;AACA;AACA;AAMA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AAGA;AAEA;AAGA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAAA;;;;;;;AD5VA;AAGA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AA3Ba;;;;;;;;;;;;;;;;;ADKb;AACA;AAEA;AAAA;AAGA;AAAA;AAFA;AAIA;AACA;;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAA;AAnCa;;;;;;;;;;;;;;;;;ADNb;AACA;AACA;AACA;AAGA;AACA;AAEA;AAAA;AAWA;AAAA;AAAA;AATA;AACA;AAUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA;AAEA;AAGA;AACA;AACA;AACA;AACA;AAEA;AAAA;AACA;AAGA;AACA;AACA;AACA;AAEA;AAEA;AACA;AAEA;AAAA;AACA;AACA;AACA;AAMA;AAKA;AAMA;AAIA;AAGA;AAIA;AAIA;AACA;AAOA;AACA;AAQA;AACA;AAGA;AAGA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AAAA;AACA;AACA;AAEA;AAAA;AACA;AACA;AAEA;AAAA;AACA;AACA;AAEA;AAAA;AACA;AACA;AAEA;AAAA;AACA;AACA;AAEA;AAAA;AACA;AACA;AAQA;AACA;AACA;AACA;AACA;AACA;AAMA;AAAA;AACA;AACA;AACA;AAEA;AACA;AACA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAAA;AA5Ma;;;;;;;;;;;;;;;;;ADNb;AAEA;AAAA;AAGA;AAAA;AAEA;AACA;AACA;AACA;;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAGA;AAGA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AAGA;AAEA;AACA;AACA;AAGA;AACA;AACA;AACA;AAAA;AA5Ea;;;;;;;;;;;;;;;;;ADLb;AACA;AACA;AAEA;AAOA;AAEA;AAAA;AAMA;AAAA;AAFA;AAIA;;AACA;AAEA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAEA;AAKA;AACA;AACA;AACA;AACA;AACA;AAIA;AAEA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAiBA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAIA;AAQA;AACA;AAMA;AACA;AAEA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AAEA;AAGA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAA;AAEA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AAKA;AAGA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AAKA;AAGA;AAGA;AACA;AACA;AAOA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAnOa;;;;;;;ADZb;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAC;;;;;;;ADVD;AAEA;AACA;AACA;AAEa;AACA;AAKA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;ADhBb;AAQA;AAAA;AAOA;AAAA;AAEA;AACA;;AACA;AAEA;AAAA;AACA;AACA;;;AAAA;AAEA;AAAA;AACA;AACA;;;AAAA;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AAAA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAtDa;;;;;;;;;;;;;;;;;ADRb;AAOA;AAAA;AAKA;AAAA;AACA;AAGA;AACA;AACA;;AACA;AAEA;AAAA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAjBA;AAmBA;AAAA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AATA;AAWA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAAA;AAUA;AACA;AACA;AAUA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAMA;AACA;AACA;AAWA;AAAA;AAAA;AAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AAQA;AACA;AACA;AACA;AAAA;AAxMa;;;;;;;ADFb;AACA;AACA;AAFA;AAEC;;;;;;;ADJD;AACA;AAAA;AAAA;AAEA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAeA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAKA;AACA;AAEA;AACA;AAYA;AACA;AACA;AACA;AAGA;AACA;AAEA;AACA;AACA;AAAA;AAtFa;;;;;;;ADCA;;;;;;;ADFb;AAEA;;;"}
\ No newline at end of file