diff --git a/.gitignore b/.gitignore
index f90e8ec..82f321e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
.vagrant
+.venv
venv
venv2
.vscode
@@ -13,4 +14,5 @@ dhcpd.*
webvirtcloud/settings.py
*migrations/*
.coverage
-htmlcov
\ No newline at end of file
+htmlcov
+*.log
diff --git a/conf/daemon/consolecallback b/conf/daemon/consolecallback
index d7810b9..a510fdf 100755
--- a/conf/daemon/consolecallback
+++ b/conf/daemon/consolecallback
@@ -19,7 +19,7 @@ def error_handler(unused, error) -> None:
# The console stream errors on VM shutdown; we don't care
if error[0] == libvirt.VIR_ERR_RPC and error[1] == libvirt.VIR_FROM_STREAMS:
return
- logging.warn(error)
+ logging.warning(error)
class Console(object):
diff --git a/conf/requirements.txt b/conf/requirements.txt
index b94a34f..04908bf 100644
--- a/conf/requirements.txt
+++ b/conf/requirements.txt
@@ -14,3 +14,4 @@ websockify==0.10.0
zipp==3.6.0
ldap3==2.9.1
python-socketio==5.7.0
+eventlet==0.33.1
\ No newline at end of file
diff --git a/console/novncd b/console/novncd
index 34c962e..4d3f94b 100755
--- a/console/novncd
+++ b/console/novncd
@@ -17,7 +17,8 @@ django.setup()
import re
import socket
-from six.moves import http_cookies as Cookie
+#from six.moves import http_cookies as Cookie
+from http import cookies as Cookie
from webvirtcloud.settings import WS_PORT, WS_HOST, WS_CERT
from vrtManager.connection import CONN_SSH, CONN_SOCKET
from console.sshtunnels import SSHTunnels
diff --git a/console/socketiod b/console/socketiod
index 895a98b..7057d9a 100755
--- a/console/socketiod
+++ b/console/socketiod
@@ -32,7 +32,8 @@ import tty
import termios
import libvirt
-from six.moves import http_cookies as Cookie
+#from six.moves import http_cookies as Cookie
+from http import cookies as Cookie
from webvirtcloud.settings import SOCKETIO_PORT, SOCKETIO_HOST
from vrtManager.connection import CONN_SSH, CONN_SOCKET
from optparse import OptionParser
@@ -79,7 +80,7 @@ else:
logging.basicConfig(level=logging.WARNING, format=FORMAT)
async_mode = "eventlet"
-sio = socketio.Server(async_mode=async_mode, cors_allowed_origins="https://vmm.cyborgside.net")
+sio = socketio.Server(async_mode=async_mode, cors_allowed_origins=[])
fd = None
child_pid = None
@@ -171,7 +172,8 @@ def connect(sid, environ):
(instance, conn) = get_connection_infos(token)
uuid = conn.get_uuid()
uri = conn.wvm.getURI()
- subprocess.run(["/srv/webvirtcloud/venv/bin/python3", "/srv/webvirtcloud/venv/bin/consolecallback", uri, uuid])
+
+ subprocess.run(['conf/daemon/consolecallback', uri, uuid])
else:
# this is the parent process fork.
sio.start_background_task(target=read_and_forward_pty_output)
diff --git a/console/templates/console-xterm.html b/console/templates/console-xterm.html
index 21fe8c2..82d43ce 100644
--- a/console/templates/console-xterm.html
+++ b/console/templates/console-xterm.html
@@ -4,28 +4,45 @@
{% block head %}
WebVirtCloud - XTerm
-
-
-
-
+
+
+
+
-
+
{% endblock %}
{% block content %}
Status: connecting...
- Connect
+ Connect
diff --git a/console/views.py b/console/views.py
index a83a0bd..43dd82e 100644
--- a/console/views.py
+++ b/console/views.py
@@ -15,6 +15,9 @@ from webvirtcloud.settings import (
WS_PUBLIC_HOST,
WS_PUBLIC_PATH,
WS_PUBLIC_PORT,
+ SOCKETIO_PUBLIC_HOST,
+ SOCKETIO_PUBLIC_PORT,
+ SOCKETIO_PUBLIC_PATH
)
@@ -80,6 +83,13 @@ def console(request):
console_page = "console-" + console_type + "-" + view_type + ".html"
response = render(request, console_page, locals())
elif console_type == "pty":
+ socketio_host = SOCKETIO_PUBLIC_HOST if SOCKETIO_PUBLIC_HOST else request.get_host()
+ socketio_port = SOCKETIO_PUBLIC_PORT if SOCKETIO_PUBLIC_PORT else 6081
+ socketio_path = SOCKETIO_PUBLIC_PATH if SOCKETIO_PUBLIC_PATH else "/"
+
+ if ":" in socketio_host:
+ socketio_host = re.sub(":[0-9]+", "", socketio_host)
+
response = render(request, "console-xterm.html", locals())
else:
if console_type is None:
diff --git a/static/css/xterm.css b/static/css/xterm.css
new file mode 100644
index 0000000..8e129f5
--- /dev/null
+++ b/static/css/xterm.css
@@ -0,0 +1,164 @@
+/**
+ * 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: #000;
+ 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: #000;
+ overflow-y: scroll;
+ cursor: default;
+ position: absolute;
+ right: 0;
+ left: 0;
+ top: 0;
+ bottom: 0;
+}
+
+.xterm .xterm-screen {
+ position: relative;
+}
+
+.xterm .xterm-screen canvas {
+ position: absolute;
+ left: 0;
+ top: 0;
+}
+
+.xterm .xterm-scroll-area {
+ visibility: hidden;
+}
+
+.xterm-char-measure-element {
+ display: inline-block;
+ visibility: hidden;
+ position: absolute;
+ top: 0;
+ left: -9999em;
+ line-height: normal;
+}
+
+.xterm {
+ cursor: text;
+}
+
+.xterm.enable-mouse-events {
+ /* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */
+ cursor: default;
+}
+
+.xterm.xterm-cursor-pointer {
+ cursor: pointer;
+}
+
+.xterm.xterm-cursor-crosshair {
+ /* Column selection mode */
+ cursor: crosshair;
+}
+
+.xterm .xterm-accessibility,
+.xterm .xterm-message {
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: 0;
+ right: 0;
+ z-index: 100;
+ color: transparent;
+}
+
+.xterm .live-region {
+ position: absolute;
+ left: -9999px;
+ width: 1px;
+ height: 1px;
+ overflow: hidden;
+}
diff --git a/static/js/socket.io.js b/static/js/socket.io.js
new file mode 100644
index 0000000..a2b0af2
--- /dev/null
+++ b/static/js/socket.io.js
@@ -0,0 +1,4440 @@
+/*!
+ * Socket.IO v4.5.0
+ * (c) 2014-2022 Guillermo Rauch
+ * Released under the MIT License.
+ */
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.io = factory());
+ })(this, (function () { 'use strict';
+
+ function _typeof(obj) {
+ "@babel/helpers - typeof";
+
+ if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
+ _typeof = function (obj) {
+ return typeof obj;
+ };
+ } else {
+ _typeof = function (obj) {
+ return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
+ };
+ }
+
+ return _typeof(obj);
+ }
+
+ function _classCallCheck(instance, Constructor) {
+ if (!(instance instanceof Constructor)) {
+ throw new TypeError("Cannot call a class as a function");
+ }
+ }
+
+ function _defineProperties(target, props) {
+ for (var i = 0; i < props.length; i++) {
+ var descriptor = props[i];
+ descriptor.enumerable = descriptor.enumerable || false;
+ descriptor.configurable = true;
+ if ("value" in descriptor) descriptor.writable = true;
+ Object.defineProperty(target, descriptor.key, descriptor);
+ }
+ }
+
+ function _createClass(Constructor, protoProps, staticProps) {
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
+ if (staticProps) _defineProperties(Constructor, staticProps);
+ return Constructor;
+ }
+
+ function _extends() {
+ _extends = Object.assign || function (target) {
+ for (var i = 1; i < arguments.length; i++) {
+ var source = arguments[i];
+
+ for (var key in source) {
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
+ target[key] = source[key];
+ }
+ }
+ }
+
+ return target;
+ };
+
+ return _extends.apply(this, arguments);
+ }
+
+ function _inherits(subClass, superClass) {
+ if (typeof superClass !== "function" && superClass !== null) {
+ throw new TypeError("Super expression must either be null or a function");
+ }
+
+ subClass.prototype = Object.create(superClass && superClass.prototype, {
+ constructor: {
+ value: subClass,
+ writable: true,
+ configurable: true
+ }
+ });
+ if (superClass) _setPrototypeOf(subClass, superClass);
+ }
+
+ function _getPrototypeOf(o) {
+ _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
+ return o.__proto__ || Object.getPrototypeOf(o);
+ };
+ return _getPrototypeOf(o);
+ }
+
+ function _setPrototypeOf(o, p) {
+ _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
+ o.__proto__ = p;
+ return o;
+ };
+
+ return _setPrototypeOf(o, p);
+ }
+
+ function _isNativeReflectConstruct() {
+ if (typeof Reflect === "undefined" || !Reflect.construct) return false;
+ if (Reflect.construct.sham) return false;
+ if (typeof Proxy === "function") return true;
+
+ try {
+ Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
+ return true;
+ } catch (e) {
+ return false;
+ }
+ }
+
+ function _construct(Parent, args, Class) {
+ if (_isNativeReflectConstruct()) {
+ _construct = Reflect.construct;
+ } else {
+ _construct = function _construct(Parent, args, Class) {
+ var a = [null];
+ a.push.apply(a, args);
+ var Constructor = Function.bind.apply(Parent, a);
+ var instance = new Constructor();
+ if (Class) _setPrototypeOf(instance, Class.prototype);
+ return instance;
+ };
+ }
+
+ return _construct.apply(null, arguments);
+ }
+
+ function _isNativeFunction(fn) {
+ return Function.toString.call(fn).indexOf("[native code]") !== -1;
+ }
+
+ function _wrapNativeSuper(Class) {
+ var _cache = typeof Map === "function" ? new Map() : undefined;
+
+ _wrapNativeSuper = function _wrapNativeSuper(Class) {
+ if (Class === null || !_isNativeFunction(Class)) return Class;
+
+ if (typeof Class !== "function") {
+ throw new TypeError("Super expression must either be null or a function");
+ }
+
+ if (typeof _cache !== "undefined") {
+ if (_cache.has(Class)) return _cache.get(Class);
+
+ _cache.set(Class, Wrapper);
+ }
+
+ function Wrapper() {
+ return _construct(Class, arguments, _getPrototypeOf(this).constructor);
+ }
+
+ Wrapper.prototype = Object.create(Class.prototype, {
+ constructor: {
+ value: Wrapper,
+ enumerable: false,
+ writable: true,
+ configurable: true
+ }
+ });
+ return _setPrototypeOf(Wrapper, Class);
+ };
+
+ return _wrapNativeSuper(Class);
+ }
+
+ function _assertThisInitialized(self) {
+ if (self === void 0) {
+ throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
+ }
+
+ return self;
+ }
+
+ function _possibleConstructorReturn(self, call) {
+ if (call && (typeof call === "object" || typeof call === "function")) {
+ return call;
+ } else if (call !== void 0) {
+ throw new TypeError("Derived constructors may only return object or undefined");
+ }
+
+ return _assertThisInitialized(self);
+ }
+
+ function _createSuper(Derived) {
+ var hasNativeReflectConstruct = _isNativeReflectConstruct();
+
+ return function _createSuperInternal() {
+ var Super = _getPrototypeOf(Derived),
+ result;
+
+ if (hasNativeReflectConstruct) {
+ var NewTarget = _getPrototypeOf(this).constructor;
+
+ result = Reflect.construct(Super, arguments, NewTarget);
+ } else {
+ result = Super.apply(this, arguments);
+ }
+
+ return _possibleConstructorReturn(this, result);
+ };
+ }
+
+ function _superPropBase(object, property) {
+ while (!Object.prototype.hasOwnProperty.call(object, property)) {
+ object = _getPrototypeOf(object);
+ if (object === null) break;
+ }
+
+ return object;
+ }
+
+ function _get(target, property, receiver) {
+ if (typeof Reflect !== "undefined" && Reflect.get) {
+ _get = Reflect.get;
+ } else {
+ _get = function _get(target, property, receiver) {
+ var base = _superPropBase(target, property);
+
+ if (!base) return;
+ var desc = Object.getOwnPropertyDescriptor(base, property);
+
+ if (desc.get) {
+ return desc.get.call(receiver);
+ }
+
+ return desc.value;
+ };
+ }
+
+ return _get(target, property, receiver || target);
+ }
+
+ function _unsupportedIterableToArray(o, minLen) {
+ if (!o) return;
+ if (typeof o === "string") return _arrayLikeToArray(o, minLen);
+ var n = Object.prototype.toString.call(o).slice(8, -1);
+ if (n === "Object" && o.constructor) n = o.constructor.name;
+ if (n === "Map" || n === "Set") return Array.from(o);
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
+ }
+
+ function _arrayLikeToArray(arr, len) {
+ if (len == null || len > arr.length) len = arr.length;
+
+ for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
+
+ return arr2;
+ }
+
+ function _createForOfIteratorHelper(o, allowArrayLike) {
+ var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
+
+ if (!it) {
+ if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
+ if (it) o = it;
+ var i = 0;
+
+ var F = function () {};
+
+ return {
+ s: F,
+ n: function () {
+ if (i >= o.length) return {
+ done: true
+ };
+ return {
+ done: false,
+ value: o[i++]
+ };
+ },
+ e: function (e) {
+ throw e;
+ },
+ f: F
+ };
+ }
+
+ throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
+ }
+
+ var normalCompletion = true,
+ didErr = false,
+ err;
+ return {
+ s: function () {
+ it = it.call(o);
+ },
+ n: function () {
+ var step = it.next();
+ normalCompletion = step.done;
+ return step;
+ },
+ e: function (e) {
+ didErr = true;
+ err = e;
+ },
+ f: function () {
+ try {
+ if (!normalCompletion && it.return != null) it.return();
+ } finally {
+ if (didErr) throw err;
+ }
+ }
+ };
+ }
+
+ var PACKET_TYPES = Object.create(null); // no Map = no polyfill
+
+ PACKET_TYPES["open"] = "0";
+ PACKET_TYPES["close"] = "1";
+ PACKET_TYPES["ping"] = "2";
+ PACKET_TYPES["pong"] = "3";
+ PACKET_TYPES["message"] = "4";
+ PACKET_TYPES["upgrade"] = "5";
+ PACKET_TYPES["noop"] = "6";
+ var PACKET_TYPES_REVERSE = Object.create(null);
+ Object.keys(PACKET_TYPES).forEach(function (key) {
+ PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key;
+ });
+ var ERROR_PACKET = {
+ type: "error",
+ data: "parser error"
+ };
+
+ var withNativeBlob$1 = typeof Blob === "function" || typeof Blob !== "undefined" && Object.prototype.toString.call(Blob) === "[object BlobConstructor]";
+ var withNativeArrayBuffer$2 = typeof ArrayBuffer === "function"; // ArrayBuffer.isView method is not defined in IE10
+
+ var isView$1 = function isView(obj) {
+ return typeof ArrayBuffer.isView === "function" ? ArrayBuffer.isView(obj) : obj && obj.buffer instanceof ArrayBuffer;
+ };
+
+ var encodePacket = function encodePacket(_ref, supportsBinary, callback) {
+ var type = _ref.type,
+ data = _ref.data;
+
+ if (withNativeBlob$1 && data instanceof Blob) {
+ if (supportsBinary) {
+ return callback(data);
+ } else {
+ return encodeBlobAsBase64(data, callback);
+ }
+ } else if (withNativeArrayBuffer$2 && (data instanceof ArrayBuffer || isView$1(data))) {
+ if (supportsBinary) {
+ return callback(data);
+ } else {
+ return encodeBlobAsBase64(new Blob([data]), callback);
+ }
+ } // plain string
+
+
+ return callback(PACKET_TYPES[type] + (data || ""));
+ };
+
+ var encodeBlobAsBase64 = function encodeBlobAsBase64(data, callback) {
+ var fileReader = new FileReader();
+
+ fileReader.onload = function () {
+ var content = fileReader.result.split(",")[1];
+ callback("b" + content);
+ };
+
+ return fileReader.readAsDataURL(data);
+ };
+
+ /*
+ * base64-arraybuffer 1.0.1
+ * Copyright (c) 2022 Niklas von Hertzen
+ * Released under MIT License
+ */
+ var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; // Use a lookup table to find the index.
+
+ var lookup$1 = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);
+
+ for (var i$1 = 0; i$1 < chars.length; i$1++) {
+ lookup$1[chars.charCodeAt(i$1)] = i$1;
+ }
+
+ var decode$1 = function decode(base64) {
+ var bufferLength = base64.length * 0.75,
+ len = base64.length,
+ i,
+ p = 0,
+ encoded1,
+ encoded2,
+ encoded3,
+ encoded4;
+
+ if (base64[base64.length - 1] === '=') {
+ bufferLength--;
+
+ if (base64[base64.length - 2] === '=') {
+ bufferLength--;
+ }
+ }
+
+ var arraybuffer = new ArrayBuffer(bufferLength),
+ bytes = new Uint8Array(arraybuffer);
+
+ for (i = 0; i < len; i += 4) {
+ encoded1 = lookup$1[base64.charCodeAt(i)];
+ encoded2 = lookup$1[base64.charCodeAt(i + 1)];
+ encoded3 = lookup$1[base64.charCodeAt(i + 2)];
+ encoded4 = lookup$1[base64.charCodeAt(i + 3)];
+ bytes[p++] = encoded1 << 2 | encoded2 >> 4;
+ bytes[p++] = (encoded2 & 15) << 4 | encoded3 >> 2;
+ bytes[p++] = (encoded3 & 3) << 6 | encoded4 & 63;
+ }
+
+ return arraybuffer;
+ };
+
+ var withNativeArrayBuffer$1 = typeof ArrayBuffer === "function";
+
+ var decodePacket = function decodePacket(encodedPacket, binaryType) {
+ if (typeof encodedPacket !== "string") {
+ return {
+ type: "message",
+ data: mapBinary(encodedPacket, binaryType)
+ };
+ }
+
+ var type = encodedPacket.charAt(0);
+
+ if (type === "b") {
+ return {
+ type: "message",
+ data: decodeBase64Packet(encodedPacket.substring(1), binaryType)
+ };
+ }
+
+ var packetType = PACKET_TYPES_REVERSE[type];
+
+ if (!packetType) {
+ return ERROR_PACKET;
+ }
+
+ return encodedPacket.length > 1 ? {
+ type: PACKET_TYPES_REVERSE[type],
+ data: encodedPacket.substring(1)
+ } : {
+ type: PACKET_TYPES_REVERSE[type]
+ };
+ };
+
+ var decodeBase64Packet = function decodeBase64Packet(data, binaryType) {
+ if (withNativeArrayBuffer$1) {
+ var decoded = decode$1(data);
+ return mapBinary(decoded, binaryType);
+ } else {
+ return {
+ base64: true,
+ data: data
+ }; // fallback for old browsers
+ }
+ };
+
+ var mapBinary = function mapBinary(data, binaryType) {
+ switch (binaryType) {
+ case "blob":
+ return data instanceof ArrayBuffer ? new Blob([data]) : data;
+
+ case "arraybuffer":
+ default:
+ return data;
+ // assuming the data is already an ArrayBuffer
+ }
+ };
+
+ var SEPARATOR = String.fromCharCode(30); // see https://en.wikipedia.org/wiki/Delimiter#ASCII_delimited_text
+
+ var encodePayload = function encodePayload(packets, callback) {
+ // some packets may be added to the array while encoding, so the initial length must be saved
+ var length = packets.length;
+ var encodedPackets = new Array(length);
+ var count = 0;
+ packets.forEach(function (packet, i) {
+ // force base64 encoding for binary packets
+ encodePacket(packet, false, function (encodedPacket) {
+ encodedPackets[i] = encodedPacket;
+
+ if (++count === length) {
+ callback(encodedPackets.join(SEPARATOR));
+ }
+ });
+ });
+ };
+
+ var decodePayload = function decodePayload(encodedPayload, binaryType) {
+ var encodedPackets = encodedPayload.split(SEPARATOR);
+ var packets = [];
+
+ for (var i = 0; i < encodedPackets.length; i++) {
+ var decodedPacket = decodePacket(encodedPackets[i], binaryType);
+ packets.push(decodedPacket);
+
+ if (decodedPacket.type === "error") {
+ break;
+ }
+ }
+
+ return packets;
+ };
+
+ var protocol$1 = 4;
+
+ /**
+ * Initialize a new `Emitter`.
+ *
+ * @api public
+ */
+ function Emitter(obj) {
+ if (obj) return mixin(obj);
+ }
+ /**
+ * Mixin the emitter properties.
+ *
+ * @param {Object} obj
+ * @return {Object}
+ * @api private
+ */
+
+ function mixin(obj) {
+ for (var key in Emitter.prototype) {
+ obj[key] = Emitter.prototype[key];
+ }
+
+ return obj;
+ }
+ /**
+ * Listen on the given `event` with `fn`.
+ *
+ * @param {String} event
+ * @param {Function} fn
+ * @return {Emitter}
+ * @api public
+ */
+
+
+ Emitter.prototype.on = Emitter.prototype.addEventListener = function (event, fn) {
+ this._callbacks = this._callbacks || {};
+ (this._callbacks['$' + event] = this._callbacks['$' + event] || []).push(fn);
+ return this;
+ };
+ /**
+ * Adds an `event` listener that will be invoked a single
+ * time then automatically removed.
+ *
+ * @param {String} event
+ * @param {Function} fn
+ * @return {Emitter}
+ * @api public
+ */
+
+
+ Emitter.prototype.once = function (event, fn) {
+ function on() {
+ this.off(event, on);
+ fn.apply(this, arguments);
+ }
+
+ on.fn = fn;
+ this.on(event, on);
+ return this;
+ };
+ /**
+ * Remove the given callback for `event` or all
+ * registered callbacks.
+ *
+ * @param {String} event
+ * @param {Function} fn
+ * @return {Emitter}
+ * @api public
+ */
+
+
+ Emitter.prototype.off = Emitter.prototype.removeListener = Emitter.prototype.removeAllListeners = Emitter.prototype.removeEventListener = function (event, fn) {
+ this._callbacks = this._callbacks || {}; // all
+
+ if (0 == arguments.length) {
+ this._callbacks = {};
+ return this;
+ } // specific event
+
+
+ var callbacks = this._callbacks['$' + event];
+ if (!callbacks) return this; // remove all handlers
+
+ if (1 == arguments.length) {
+ delete this._callbacks['$' + event];
+ return this;
+ } // remove specific handler
+
+
+ var cb;
+
+ for (var i = 0; i < callbacks.length; i++) {
+ cb = callbacks[i];
+
+ if (cb === fn || cb.fn === fn) {
+ callbacks.splice(i, 1);
+ break;
+ }
+ } // Remove event specific arrays for event types that no
+ // one is subscribed for to avoid memory leak.
+
+
+ if (callbacks.length === 0) {
+ delete this._callbacks['$' + event];
+ }
+
+ return this;
+ };
+ /**
+ * Emit `event` with the given args.
+ *
+ * @param {String} event
+ * @param {Mixed} ...
+ * @return {Emitter}
+ */
+
+
+ Emitter.prototype.emit = function (event) {
+ this._callbacks = this._callbacks || {};
+ var args = new Array(arguments.length - 1),
+ callbacks = this._callbacks['$' + event];
+
+ for (var i = 1; i < arguments.length; i++) {
+ args[i - 1] = arguments[i];
+ }
+
+ if (callbacks) {
+ callbacks = callbacks.slice(0);
+
+ for (var i = 0, len = callbacks.length; i < len; ++i) {
+ callbacks[i].apply(this, args);
+ }
+ }
+
+ return this;
+ }; // alias used for reserved events (protected method)
+
+
+ Emitter.prototype.emitReserved = Emitter.prototype.emit;
+ /**
+ * Return array of callbacks for `event`.
+ *
+ * @param {String} event
+ * @return {Array}
+ * @api public
+ */
+
+ Emitter.prototype.listeners = function (event) {
+ this._callbacks = this._callbacks || {};
+ return this._callbacks['$' + event] || [];
+ };
+ /**
+ * Check if this emitter has `event` handlers.
+ *
+ * @param {String} event
+ * @return {Boolean}
+ * @api public
+ */
+
+
+ Emitter.prototype.hasListeners = function (event) {
+ return !!this.listeners(event).length;
+ };
+
+ var globalThis = (function () {
+ if (typeof self !== "undefined") {
+ return self;
+ } else if (typeof window !== "undefined") {
+ return window;
+ } else {
+ return Function("return this")();
+ }
+ })();
+
+ function pick(obj) {
+ for (var _len = arguments.length, attr = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+ attr[_key - 1] = arguments[_key];
+ }
+
+ return attr.reduce(function (acc, k) {
+ if (obj.hasOwnProperty(k)) {
+ acc[k] = obj[k];
+ }
+
+ return acc;
+ }, {});
+ } // Keep a reference to the real timeout functions so they can be used when overridden
+
+ var NATIVE_SET_TIMEOUT = setTimeout;
+ var NATIVE_CLEAR_TIMEOUT = clearTimeout;
+ function installTimerFunctions(obj, opts) {
+ if (opts.useNativeTimers) {
+ obj.setTimeoutFn = NATIVE_SET_TIMEOUT.bind(globalThis);
+ obj.clearTimeoutFn = NATIVE_CLEAR_TIMEOUT.bind(globalThis);
+ } else {
+ obj.setTimeoutFn = setTimeout.bind(globalThis);
+ obj.clearTimeoutFn = clearTimeout.bind(globalThis);
+ }
+ } // base64 encoded buffers are about 33% bigger (https://en.wikipedia.org/wiki/Base64)
+
+ var BASE64_OVERHEAD = 1.33; // we could also have used `new Blob([obj]).size`, but it isn't supported in IE9
+
+ function byteLength(obj) {
+ if (typeof obj === "string") {
+ return utf8Length(obj);
+ } // arraybuffer or blob
+
+
+ return Math.ceil((obj.byteLength || obj.size) * BASE64_OVERHEAD);
+ }
+
+ function utf8Length(str) {
+ var c = 0,
+ length = 0;
+
+ for (var i = 0, l = str.length; i < l; i++) {
+ c = str.charCodeAt(i);
+
+ if (c < 0x80) {
+ length += 1;
+ } else if (c < 0x800) {
+ length += 2;
+ } else if (c < 0xd800 || c >= 0xe000) {
+ length += 3;
+ } else {
+ i++;
+ length += 4;
+ }
+ }
+
+ return length;
+ }
+
+ var TransportError = /*#__PURE__*/function (_Error) {
+ _inherits(TransportError, _Error);
+
+ var _super = _createSuper(TransportError);
+
+ function TransportError(reason, description, context) {
+ var _this;
+
+ _classCallCheck(this, TransportError);
+
+ _this = _super.call(this, reason);
+ _this.description = description;
+ _this.context = context;
+ _this.type = "TransportError";
+ return _this;
+ }
+
+ return TransportError;
+ }( /*#__PURE__*/_wrapNativeSuper(Error));
+
+ var Transport = /*#__PURE__*/function (_Emitter) {
+ _inherits(Transport, _Emitter);
+
+ var _super2 = _createSuper(Transport);
+
+ /**
+ * Transport abstract constructor.
+ *
+ * @param {Object} options.
+ * @api private
+ */
+ function Transport(opts) {
+ var _this2;
+
+ _classCallCheck(this, Transport);
+
+ _this2 = _super2.call(this);
+ _this2.writable = false;
+ installTimerFunctions(_assertThisInitialized(_this2), opts);
+ _this2.opts = opts;
+ _this2.query = opts.query;
+ _this2.readyState = "";
+ _this2.socket = opts.socket;
+ return _this2;
+ }
+ /**
+ * Emits an error.
+ *
+ * @param {String} reason
+ * @param description
+ * @param context - the error context
+ * @return {Transport} for chaining
+ * @api protected
+ */
+
+
+ _createClass(Transport, [{
+ key: "onError",
+ value: function onError(reason, description, context) {
+ _get(_getPrototypeOf(Transport.prototype), "emitReserved", this).call(this, "error", new TransportError(reason, description, context));
+
+ return this;
+ }
+ /**
+ * Opens the transport.
+ *
+ * @api public
+ */
+
+ }, {
+ key: "open",
+ value: function open() {
+ if ("closed" === this.readyState || "" === this.readyState) {
+ this.readyState = "opening";
+ this.doOpen();
+ }
+
+ return this;
+ }
+ /**
+ * Closes the transport.
+ *
+ * @api public
+ */
+
+ }, {
+ key: "close",
+ value: function close() {
+ if ("opening" === this.readyState || "open" === this.readyState) {
+ this.doClose();
+ this.onClose();
+ }
+
+ return this;
+ }
+ /**
+ * Sends multiple packets.
+ *
+ * @param {Array} packets
+ * @api public
+ */
+
+ }, {
+ key: "send",
+ value: function send(packets) {
+ if ("open" === this.readyState) {
+ this.write(packets);
+ }
+ }
+ /**
+ * Called upon open
+ *
+ * @api protected
+ */
+
+ }, {
+ key: "onOpen",
+ value: function onOpen() {
+ this.readyState = "open";
+ this.writable = true;
+
+ _get(_getPrototypeOf(Transport.prototype), "emitReserved", this).call(this, "open");
+ }
+ /**
+ * Called with data.
+ *
+ * @param {String} data
+ * @api protected
+ */
+
+ }, {
+ key: "onData",
+ value: function onData(data) {
+ var packet = decodePacket(data, this.socket.binaryType);
+ this.onPacket(packet);
+ }
+ /**
+ * Called with a decoded packet.
+ *
+ * @api protected
+ */
+
+ }, {
+ key: "onPacket",
+ value: function onPacket(packet) {
+ _get(_getPrototypeOf(Transport.prototype), "emitReserved", this).call(this, "packet", packet);
+ }
+ /**
+ * Called upon close.
+ *
+ * @api protected
+ */
+
+ }, {
+ key: "onClose",
+ value: function onClose(details) {
+ this.readyState = "closed";
+
+ _get(_getPrototypeOf(Transport.prototype), "emitReserved", this).call(this, "close", details);
+ }
+ }]);
+
+ return Transport;
+ }(Emitter);
+
+ // imported from https://github.com/unshiftio/yeast
+
+ var alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_'.split(''),
+ length = 64,
+ map = {};
+ var seed = 0,
+ i = 0,
+ prev;
+ /**
+ * Return a string representing the specified number.
+ *
+ * @param {Number} num The number to convert.
+ * @returns {String} The string representation of the number.
+ * @api public
+ */
+
+ function encode$1(num) {
+ var encoded = '';
+
+ do {
+ encoded = alphabet[num % length] + encoded;
+ num = Math.floor(num / length);
+ } while (num > 0);
+
+ return encoded;
+ }
+ /**
+ * Yeast: A tiny growing id generator.
+ *
+ * @returns {String} A unique id.
+ * @api public
+ */
+
+ function yeast() {
+ var now = encode$1(+new Date());
+ if (now !== prev) return seed = 0, prev = now;
+ return now + '.' + encode$1(seed++);
+ } //
+ // Map each character to its index.
+ //
+
+ for (; i < length; i++) {
+ map[alphabet[i]] = i;
+ }
+
+ // imported from https://github.com/galkn/querystring
+
+ /**
+ * Compiles a querystring
+ * Returns string representation of the object
+ *
+ * @param {Object}
+ * @api private
+ */
+ function encode(obj) {
+ var str = '';
+
+ for (var i in obj) {
+ if (obj.hasOwnProperty(i)) {
+ if (str.length) str += '&';
+ str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
+ }
+ }
+
+ return str;
+ }
+ /**
+ * Parses a simple querystring into an object
+ *
+ * @param {String} qs
+ * @api private
+ */
+
+ function decode(qs) {
+ var qry = {};
+ var pairs = qs.split('&');
+
+ for (var i = 0, l = pairs.length; i < l; i++) {
+ var pair = pairs[i].split('=');
+ qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
+ }
+
+ return qry;
+ }
+
+ // imported from https://github.com/component/has-cors
+ var value = false;
+
+ try {
+ value = typeof XMLHttpRequest !== 'undefined' && 'withCredentials' in new XMLHttpRequest();
+ } catch (err) {// if XMLHttp support is disabled in IE then it will throw
+ // when trying to create
+ }
+
+ var hasCORS = value;
+
+ // browser shim for xmlhttprequest module
+ function XMLHttpRequest$1 (opts) {
+ var xdomain = opts.xdomain; // XMLHttpRequest can be disabled on IE
+
+ try {
+ if ("undefined" !== typeof XMLHttpRequest && (!xdomain || hasCORS)) {
+ return new XMLHttpRequest();
+ }
+ } catch (e) {}
+
+ if (!xdomain) {
+ try {
+ return new globalThis[["Active"].concat("Object").join("X")]("Microsoft.XMLHTTP");
+ } catch (e) {}
+ }
+ }
+
+ function empty() {}
+
+ var hasXHR2 = function () {
+ var xhr = new XMLHttpRequest$1({
+ xdomain: false
+ });
+ return null != xhr.responseType;
+ }();
+
+ var Polling = /*#__PURE__*/function (_Transport) {
+ _inherits(Polling, _Transport);
+
+ var _super = _createSuper(Polling);
+
+ /**
+ * XHR Polling constructor.
+ *
+ * @param {Object} opts
+ * @api public
+ */
+ function Polling(opts) {
+ var _this;
+
+ _classCallCheck(this, Polling);
+
+ _this = _super.call(this, opts);
+ _this.polling = false;
+
+ if (typeof location !== "undefined") {
+ var isSSL = "https:" === location.protocol;
+ var port = location.port; // some user agents have empty `location.port`
+
+ if (!port) {
+ port = isSSL ? "443" : "80";
+ }
+
+ _this.xd = typeof location !== "undefined" && opts.hostname !== location.hostname || port !== opts.port;
+ _this.xs = opts.secure !== isSSL;
+ }
+ /**
+ * XHR supports binary
+ */
+
+
+ var forceBase64 = opts && opts.forceBase64;
+ _this.supportsBinary = hasXHR2 && !forceBase64;
+ return _this;
+ }
+ /**
+ * Transport name.
+ */
+
+
+ _createClass(Polling, [{
+ key: "name",
+ get: function get() {
+ return "polling";
+ }
+ /**
+ * Opens the socket (triggers polling). We write a PING message to determine
+ * when the transport is open.
+ *
+ * @api private
+ */
+
+ }, {
+ key: "doOpen",
+ value: function doOpen() {
+ this.poll();
+ }
+ /**
+ * Pauses polling.
+ *
+ * @param {Function} callback upon buffers are flushed and transport is paused
+ * @api private
+ */
+
+ }, {
+ key: "pause",
+ value: function pause(onPause) {
+ var _this2 = this;
+
+ this.readyState = "pausing";
+
+ var pause = function pause() {
+ _this2.readyState = "paused";
+ onPause();
+ };
+
+ if (this.polling || !this.writable) {
+ var total = 0;
+
+ if (this.polling) {
+ total++;
+ this.once("pollComplete", function () {
+ --total || pause();
+ });
+ }
+
+ if (!this.writable) {
+ total++;
+ this.once("drain", function () {
+ --total || pause();
+ });
+ }
+ } else {
+ pause();
+ }
+ }
+ /**
+ * Starts polling cycle.
+ *
+ * @api public
+ */
+
+ }, {
+ key: "poll",
+ value: function poll() {
+ this.polling = true;
+ this.doPoll();
+ this.emitReserved("poll");
+ }
+ /**
+ * Overloads onData to detect payloads.
+ *
+ * @api private
+ */
+
+ }, {
+ key: "onData",
+ value: function onData(data) {
+ var _this3 = this;
+
+ var callback = function callback(packet) {
+ // if its the first message we consider the transport open
+ if ("opening" === _this3.readyState && packet.type === "open") {
+ _this3.onOpen();
+ } // if its a close packet, we close the ongoing requests
+
+
+ if ("close" === packet.type) {
+ _this3.onClose({
+ description: "transport closed by the server"
+ });
+
+ return false;
+ } // otherwise bypass onData and handle the message
+
+
+ _this3.onPacket(packet);
+ }; // decode payload
+
+
+ decodePayload(data, this.socket.binaryType).forEach(callback); // if an event did not trigger closing
+
+ if ("closed" !== this.readyState) {
+ // if we got data we're not polling
+ this.polling = false;
+ this.emitReserved("pollComplete");
+
+ if ("open" === this.readyState) {
+ this.poll();
+ }
+ }
+ }
+ /**
+ * For polling, send a close packet.
+ *
+ * @api private
+ */
+
+ }, {
+ key: "doClose",
+ value: function doClose() {
+ var _this4 = this;
+
+ var close = function close() {
+ _this4.write([{
+ type: "close"
+ }]);
+ };
+
+ if ("open" === this.readyState) {
+ close();
+ } else {
+ // in case we're trying to close while
+ // handshaking is in progress (GH-164)
+ this.once("open", close);
+ }
+ }
+ /**
+ * Writes a packets payload.
+ *
+ * @param {Array} data packets
+ * @param {Function} drain callback
+ * @api private
+ */
+
+ }, {
+ key: "write",
+ value: function write(packets) {
+ var _this5 = this;
+
+ this.writable = false;
+ encodePayload(packets, function (data) {
+ _this5.doWrite(data, function () {
+ _this5.writable = true;
+
+ _this5.emitReserved("drain");
+ });
+ });
+ }
+ /**
+ * Generates uri for connection.
+ *
+ * @api private
+ */
+
+ }, {
+ key: "uri",
+ value: function uri() {
+ var query = this.query || {};
+ var schema = this.opts.secure ? "https" : "http";
+ var port = ""; // cache busting is forced
+
+ if (false !== this.opts.timestampRequests) {
+ query[this.opts.timestampParam] = yeast();
+ }
+
+ if (!this.supportsBinary && !query.sid) {
+ query.b64 = 1;
+ } // avoid port if default for schema
+
+
+ if (this.opts.port && ("https" === schema && Number(this.opts.port) !== 443 || "http" === schema && Number(this.opts.port) !== 80)) {
+ port = ":" + this.opts.port;
+ }
+
+ var encodedQuery = encode(query);
+ var ipv6 = this.opts.hostname.indexOf(":") !== -1;
+ return schema + "://" + (ipv6 ? "[" + this.opts.hostname + "]" : this.opts.hostname) + port + this.opts.path + (encodedQuery.length ? "?" + encodedQuery : "");
+ }
+ /**
+ * Creates a request.
+ *
+ * @param {String} method
+ * @api private
+ */
+
+ }, {
+ key: "request",
+ value: function request() {
+ var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+
+ _extends(opts, {
+ xd: this.xd,
+ xs: this.xs
+ }, this.opts);
+
+ return new Request(this.uri(), opts);
+ }
+ /**
+ * Sends data.
+ *
+ * @param {String} data to send.
+ * @param {Function} called upon flush.
+ * @api private
+ */
+
+ }, {
+ key: "doWrite",
+ value: function doWrite(data, fn) {
+ var _this6 = this;
+
+ var req = this.request({
+ method: "POST",
+ data: data
+ });
+ req.on("success", fn);
+ req.on("error", function (xhrStatus, context) {
+ _this6.onError("xhr post error", xhrStatus, context);
+ });
+ }
+ /**
+ * Starts a poll cycle.
+ *
+ * @api private
+ */
+
+ }, {
+ key: "doPoll",
+ value: function doPoll() {
+ var _this7 = this;
+
+ var req = this.request();
+ req.on("data", this.onData.bind(this));
+ req.on("error", function (xhrStatus, context) {
+ _this7.onError("xhr poll error", xhrStatus, context);
+ });
+ this.pollXhr = req;
+ }
+ }]);
+
+ return Polling;
+ }(Transport);
+ var Request = /*#__PURE__*/function (_Emitter) {
+ _inherits(Request, _Emitter);
+
+ var _super2 = _createSuper(Request);
+
+ /**
+ * Request constructor
+ *
+ * @param {Object} options
+ * @api public
+ */
+ function Request(uri, opts) {
+ var _this8;
+
+ _classCallCheck(this, Request);
+
+ _this8 = _super2.call(this);
+ installTimerFunctions(_assertThisInitialized(_this8), opts);
+ _this8.opts = opts;
+ _this8.method = opts.method || "GET";
+ _this8.uri = uri;
+ _this8.async = false !== opts.async;
+ _this8.data = undefined !== opts.data ? opts.data : null;
+
+ _this8.create();
+
+ return _this8;
+ }
+ /**
+ * Creates the XHR object and sends the request.
+ *
+ * @api private
+ */
+
+
+ _createClass(Request, [{
+ key: "create",
+ value: function create() {
+ var _this9 = this;
+
+ var opts = pick(this.opts, "agent", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "autoUnref");
+ opts.xdomain = !!this.opts.xd;
+ opts.xscheme = !!this.opts.xs;
+ var xhr = this.xhr = new XMLHttpRequest$1(opts);
+
+ try {
+ xhr.open(this.method, this.uri, this.async);
+
+ try {
+ if (this.opts.extraHeaders) {
+ xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);
+
+ for (var i in this.opts.extraHeaders) {
+ if (this.opts.extraHeaders.hasOwnProperty(i)) {
+ xhr.setRequestHeader(i, this.opts.extraHeaders[i]);
+ }
+ }
+ }
+ } catch (e) {}
+
+ if ("POST" === this.method) {
+ try {
+ xhr.setRequestHeader("Content-type", "text/plain;charset=UTF-8");
+ } catch (e) {}
+ }
+
+ try {
+ xhr.setRequestHeader("Accept", "*/*");
+ } catch (e) {} // ie6 check
+
+
+ if ("withCredentials" in xhr) {
+ xhr.withCredentials = this.opts.withCredentials;
+ }
+
+ if (this.opts.requestTimeout) {
+ xhr.timeout = this.opts.requestTimeout;
+ }
+
+ xhr.onreadystatechange = function () {
+ if (4 !== xhr.readyState) return;
+
+ if (200 === xhr.status || 1223 === xhr.status) {
+ _this9.onLoad();
+ } else {
+ // make sure the `error` event handler that's user-set
+ // does not throw in the same tick and gets caught here
+ _this9.setTimeoutFn(function () {
+ _this9.onError(typeof xhr.status === "number" ? xhr.status : 0);
+ }, 0);
+ }
+ };
+
+ xhr.send(this.data);
+ } catch (e) {
+ // Need to defer since .create() is called directly from the constructor
+ // and thus the 'error' event can only be only bound *after* this exception
+ // occurs. Therefore, also, we cannot throw here at all.
+ this.setTimeoutFn(function () {
+ _this9.onError(e);
+ }, 0);
+ return;
+ }
+
+ if (typeof document !== "undefined") {
+ this.index = Request.requestsCount++;
+ Request.requests[this.index] = this;
+ }
+ }
+ /**
+ * Called upon error.
+ *
+ * @api private
+ */
+
+ }, {
+ key: "onError",
+ value: function onError(err) {
+ this.emitReserved("error", err, this.xhr);
+ this.cleanup(true);
+ }
+ /**
+ * Cleans up house.
+ *
+ * @api private
+ */
+
+ }, {
+ key: "cleanup",
+ value: function cleanup(fromError) {
+ if ("undefined" === typeof this.xhr || null === this.xhr) {
+ return;
+ }
+
+ this.xhr.onreadystatechange = empty;
+
+ if (fromError) {
+ try {
+ this.xhr.abort();
+ } catch (e) {}
+ }
+
+ if (typeof document !== "undefined") {
+ delete Request.requests[this.index];
+ }
+
+ this.xhr = null;
+ }
+ /**
+ * Called upon load.
+ *
+ * @api private
+ */
+
+ }, {
+ key: "onLoad",
+ value: function onLoad() {
+ var data = this.xhr.responseText;
+
+ if (data !== null) {
+ this.emitReserved("data", data);
+ this.emitReserved("success");
+ this.cleanup();
+ }
+ }
+ /**
+ * Aborts the request.
+ *
+ * @api public
+ */
+
+ }, {
+ key: "abort",
+ value: function abort() {
+ this.cleanup();
+ }
+ }]);
+
+ return Request;
+ }(Emitter);
+ Request.requestsCount = 0;
+ Request.requests = {};
+ /**
+ * Aborts pending requests when unloading the window. This is needed to prevent
+ * memory leaks (e.g. when using IE) and to ensure that no spurious error is
+ * emitted.
+ */
+
+ if (typeof document !== "undefined") {
+ // @ts-ignore
+ if (typeof attachEvent === "function") {
+ // @ts-ignore
+ attachEvent("onunload", unloadHandler);
+ } else if (typeof addEventListener === "function") {
+ var terminationEvent = "onpagehide" in globalThis ? "pagehide" : "unload";
+ addEventListener(terminationEvent, unloadHandler, false);
+ }
+ }
+
+ function unloadHandler() {
+ for (var i in Request.requests) {
+ if (Request.requests.hasOwnProperty(i)) {
+ Request.requests[i].abort();
+ }
+ }
+ }
+
+ var nextTick = function () {
+ var isPromiseAvailable = typeof Promise === "function" && typeof Promise.resolve === "function";
+
+ if (isPromiseAvailable) {
+ return function (cb) {
+ return Promise.resolve().then(cb);
+ };
+ } else {
+ return function (cb, setTimeoutFn) {
+ return setTimeoutFn(cb, 0);
+ };
+ }
+ }();
+ var WebSocket = globalThis.WebSocket || globalThis.MozWebSocket;
+ var usingBrowserWebSocket = true;
+ var defaultBinaryType = "arraybuffer";
+
+ var isReactNative = typeof navigator !== "undefined" && typeof navigator.product === "string" && navigator.product.toLowerCase() === "reactnative";
+ var WS = /*#__PURE__*/function (_Transport) {
+ _inherits(WS, _Transport);
+
+ var _super = _createSuper(WS);
+
+ /**
+ * WebSocket transport constructor.
+ *
+ * @api {Object} connection options
+ * @api public
+ */
+ function WS(opts) {
+ var _this;
+
+ _classCallCheck(this, WS);
+
+ _this = _super.call(this, opts);
+ _this.supportsBinary = !opts.forceBase64;
+ return _this;
+ }
+ /**
+ * Transport name.
+ *
+ * @api public
+ */
+
+
+ _createClass(WS, [{
+ key: "name",
+ get: function get() {
+ return "websocket";
+ }
+ /**
+ * Opens socket.
+ *
+ * @api private
+ */
+
+ }, {
+ key: "doOpen",
+ value: function doOpen() {
+ if (!this.check()) {
+ // let probe timeout
+ return;
+ }
+
+ var uri = this.uri();
+ var protocols = this.opts.protocols; // React Native only supports the 'headers' option, and will print a warning if anything else is passed
+
+ var opts = isReactNative ? {} : pick(this.opts, "agent", "perMessageDeflate", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "localAddress", "protocolVersion", "origin", "maxPayload", "family", "checkServerIdentity");
+
+ if (this.opts.extraHeaders) {
+ opts.headers = this.opts.extraHeaders;
+ }
+
+ try {
+ this.ws = usingBrowserWebSocket && !isReactNative ? protocols ? new WebSocket(uri, protocols) : new WebSocket(uri) : new WebSocket(uri, protocols, opts);
+ } catch (err) {
+ return this.emitReserved("error", err);
+ }
+
+ this.ws.binaryType = this.socket.binaryType || defaultBinaryType;
+ this.addEventListeners();
+ }
+ /**
+ * Adds event listeners to the socket
+ *
+ * @api private
+ */
+
+ }, {
+ key: "addEventListeners",
+ value: function addEventListeners() {
+ var _this2 = this;
+
+ this.ws.onopen = function () {
+ if (_this2.opts.autoUnref) {
+ _this2.ws._socket.unref();
+ }
+
+ _this2.onOpen();
+ };
+
+ this.ws.onclose = function (closeEvent) {
+ return _this2.onClose({
+ description: "websocket connection closed",
+ context: closeEvent
+ });
+ };
+
+ this.ws.onmessage = function (ev) {
+ return _this2.onData(ev.data);
+ };
+
+ this.ws.onerror = function (e) {
+ return _this2.onError("websocket error", e);
+ };
+ }
+ /**
+ * Writes data to socket.
+ *
+ * @param {Array} array of packets.
+ * @api private
+ */
+
+ }, {
+ key: "write",
+ value: function write(packets) {
+ var _this3 = this;
+
+ this.writable = false; // encodePacket efficient as it uses WS framing
+ // no need for encodePayload
+
+ var _loop = function _loop(i) {
+ var packet = packets[i];
+ var lastPacket = i === packets.length - 1;
+ encodePacket(packet, _this3.supportsBinary, function (data) {
+ // always create a new object (GH-437)
+ var opts = {};
+ // have a chance of informing us about it yet, in that case send will
+ // throw an error
+
+
+ try {
+ if (usingBrowserWebSocket) {
+ // TypeError is thrown when passing the second argument on Safari
+ _this3.ws.send(data);
+ }
+ } catch (e) {}
+
+ if (lastPacket) {
+ // fake drain
+ // defer to next tick to allow Socket to clear writeBuffer
+ nextTick(function () {
+ _this3.writable = true;
+
+ _this3.emitReserved("drain");
+ }, _this3.setTimeoutFn);
+ }
+ });
+ };
+
+ for (var i = 0; i < packets.length; i++) {
+ _loop(i);
+ }
+ }
+ /**
+ * Closes socket.
+ *
+ * @api private
+ */
+
+ }, {
+ key: "doClose",
+ value: function doClose() {
+ if (typeof this.ws !== "undefined") {
+ this.ws.close();
+ this.ws = null;
+ }
+ }
+ /**
+ * Generates uri for connection.
+ *
+ * @api private
+ */
+
+ }, {
+ key: "uri",
+ value: function uri() {
+ var query = this.query || {};
+ var schema = this.opts.secure ? "wss" : "ws";
+ var port = ""; // avoid port if default for schema
+
+ if (this.opts.port && ("wss" === schema && Number(this.opts.port) !== 443 || "ws" === schema && Number(this.opts.port) !== 80)) {
+ port = ":" + this.opts.port;
+ } // append timestamp to URI
+
+
+ if (this.opts.timestampRequests) {
+ query[this.opts.timestampParam] = yeast();
+ } // communicate binary support capabilities
+
+
+ if (!this.supportsBinary) {
+ query.b64 = 1;
+ }
+
+ var encodedQuery = encode(query);
+ var ipv6 = this.opts.hostname.indexOf(":") !== -1;
+ return schema + "://" + (ipv6 ? "[" + this.opts.hostname + "]" : this.opts.hostname) + port + this.opts.path + (encodedQuery.length ? "?" + encodedQuery : "");
+ }
+ /**
+ * Feature detection for WebSocket.
+ *
+ * @return {Boolean} whether this transport is available.
+ * @api public
+ */
+
+ }, {
+ key: "check",
+ value: function check() {
+ return !!WebSocket && !("__initialize" in WebSocket && this.name === WS.prototype.name);
+ }
+ }]);
+
+ return WS;
+ }(Transport);
+
+ var transports = {
+ websocket: WS,
+ polling: Polling
+ };
+
+ // imported from https://github.com/galkn/parseuri
+
+ /**
+ * Parses an URI
+ *
+ * @author Steven Levithan (MIT license)
+ * @api private
+ */
+ var re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
+ var parts = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'];
+ function parse(str) {
+ var src = str,
+ b = str.indexOf('['),
+ e = str.indexOf(']');
+
+ if (b != -1 && e != -1) {
+ str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);
+ }
+
+ var m = re.exec(str || ''),
+ uri = {},
+ i = 14;
+
+ while (i--) {
+ uri[parts[i]] = m[i] || '';
+ }
+
+ if (b != -1 && e != -1) {
+ uri.source = src;
+ uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');
+ uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');
+ uri.ipv6uri = true;
+ }
+
+ uri.pathNames = pathNames(uri, uri['path']);
+ uri.queryKey = queryKey(uri, uri['query']);
+ return uri;
+ }
+
+ function pathNames(obj, path) {
+ var regx = /\/{2,9}/g,
+ names = path.replace(regx, "/").split("/");
+
+ if (path.substr(0, 1) == '/' || path.length === 0) {
+ names.splice(0, 1);
+ }
+
+ if (path.substr(path.length - 1, 1) == '/') {
+ names.splice(names.length - 1, 1);
+ }
+
+ return names;
+ }
+
+ function queryKey(uri, query) {
+ var data = {};
+ query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function ($0, $1, $2) {
+ if ($1) {
+ data[$1] = $2;
+ }
+ });
+ return data;
+ }
+
+ var Socket$1 = /*#__PURE__*/function (_Emitter) {
+ _inherits(Socket, _Emitter);
+
+ var _super = _createSuper(Socket);
+
+ /**
+ * Socket constructor.
+ *
+ * @param {String|Object} uri or options
+ * @param {Object} opts - options
+ * @api public
+ */
+ function Socket(uri) {
+ var _this;
+
+ var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+
+ _classCallCheck(this, Socket);
+
+ _this = _super.call(this);
+
+ if (uri && "object" === _typeof(uri)) {
+ opts = uri;
+ uri = null;
+ }
+
+ if (uri) {
+ uri = parse(uri);
+ opts.hostname = uri.host;
+ opts.secure = uri.protocol === "https" || uri.protocol === "wss";
+ opts.port = uri.port;
+ if (uri.query) opts.query = uri.query;
+ } else if (opts.host) {
+ opts.hostname = parse(opts.host).host;
+ }
+
+ installTimerFunctions(_assertThisInitialized(_this), opts);
+ _this.secure = null != opts.secure ? opts.secure : typeof location !== "undefined" && "https:" === location.protocol;
+
+ if (opts.hostname && !opts.port) {
+ // if no port is specified manually, use the protocol default
+ opts.port = _this.secure ? "443" : "80";
+ }
+
+ _this.hostname = opts.hostname || (typeof location !== "undefined" ? location.hostname : "localhost");
+ _this.port = opts.port || (typeof location !== "undefined" && location.port ? location.port : _this.secure ? "443" : "80");
+ _this.transports = opts.transports || ["polling", "websocket"];
+ _this.readyState = "";
+ _this.writeBuffer = [];
+ _this.prevBufferLen = 0;
+ _this.opts = _extends({
+ path: "/engine.io",
+ agent: false,
+ withCredentials: false,
+ upgrade: true,
+ timestampParam: "t",
+ rememberUpgrade: false,
+ rejectUnauthorized: true,
+ perMessageDeflate: {
+ threshold: 1024
+ },
+ transportOptions: {},
+ closeOnBeforeunload: true
+ }, opts);
+ _this.opts.path = _this.opts.path.replace(/\/$/, "") + "/";
+
+ if (typeof _this.opts.query === "string") {
+ _this.opts.query = decode(_this.opts.query);
+ } // set on handshake
+
+
+ _this.id = null;
+ _this.upgrades = null;
+ _this.pingInterval = null;
+ _this.pingTimeout = null; // set on heartbeat
+
+ _this.pingTimeoutTimer = null;
+
+ if (typeof addEventListener === "function") {
+ if (_this.opts.closeOnBeforeunload) {
+ // Firefox closes the connection when the "beforeunload" event is emitted but not Chrome. This event listener
+ // ensures every browser behaves the same (no "disconnect" event at the Socket.IO level when the page is
+ // closed/reloaded)
+ addEventListener("beforeunload", function () {
+ if (_this.transport) {
+ // silently close the transport
+ _this.transport.removeAllListeners();
+
+ _this.transport.close();
+ }
+ }, false);
+ }
+
+ if (_this.hostname !== "localhost") {
+ _this.offlineEventListener = function () {
+ _this.onClose("transport close", {
+ description: "network connection lost"
+ });
+ };
+
+ addEventListener("offline", _this.offlineEventListener, false);
+ }
+ }
+
+ _this.open();
+
+ return _this;
+ }
+ /**
+ * Creates transport of the given type.
+ *
+ * @param {String} transport name
+ * @return {Transport}
+ * @api private
+ */
+
+
+ _createClass(Socket, [{
+ key: "createTransport",
+ value: function createTransport(name) {
+ var query = _extends({}, this.opts.query); // append engine.io protocol identifier
+
+
+ query.EIO = protocol$1; // transport name
+
+ query.transport = name; // session id if we already have one
+
+ if (this.id) query.sid = this.id;
+
+ var opts = _extends({}, this.opts.transportOptions[name], this.opts, {
+ query: query,
+ socket: this,
+ hostname: this.hostname,
+ secure: this.secure,
+ port: this.port
+ });
+
+ return new transports[name](opts);
+ }
+ /**
+ * Initializes transport to use and starts probe.
+ *
+ * @api private
+ */
+
+ }, {
+ key: "open",
+ value: function open() {
+ var _this2 = this;
+
+ var transport;
+
+ if (this.opts.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf("websocket") !== -1) {
+ transport = "websocket";
+ } else if (0 === this.transports.length) {
+ // Emit error on next tick so it can be listened to
+ this.setTimeoutFn(function () {
+ _this2.emitReserved("error", "No transports available");
+ }, 0);
+ return;
+ } else {
+ transport = this.transports[0];
+ }
+
+ this.readyState = "opening"; // Retry with the next transport if the transport is disabled (jsonp: false)
+
+ try {
+ transport = this.createTransport(transport);
+ } catch (e) {
+ this.transports.shift();
+ this.open();
+ return;
+ }
+
+ transport.open();
+ this.setTransport(transport);
+ }
+ /**
+ * Sets the current transport. Disables the existing one (if any).
+ *
+ * @api private
+ */
+
+ }, {
+ key: "setTransport",
+ value: function setTransport(transport) {
+ var _this3 = this;
+
+ if (this.transport) {
+ this.transport.removeAllListeners();
+ } // set up transport
+
+
+ this.transport = transport; // set up transport listeners
+
+ transport.on("drain", this.onDrain.bind(this)).on("packet", this.onPacket.bind(this)).on("error", this.onError.bind(this)).on("close", function (reason) {
+ return _this3.onClose("transport close", reason);
+ });
+ }
+ /**
+ * Probes a transport.
+ *
+ * @param {String} transport name
+ * @api private
+ */
+
+ }, {
+ key: "probe",
+ value: function probe(name) {
+ var _this4 = this;
+
+ var transport = this.createTransport(name);
+ var failed = false;
+ Socket.priorWebsocketSuccess = false;
+
+ var onTransportOpen = function onTransportOpen() {
+ if (failed) return;
+ transport.send([{
+ type: "ping",
+ data: "probe"
+ }]);
+ transport.once("packet", function (msg) {
+ if (failed) return;
+
+ if ("pong" === msg.type && "probe" === msg.data) {
+ _this4.upgrading = true;
+
+ _this4.emitReserved("upgrading", transport);
+
+ if (!transport) return;
+ Socket.priorWebsocketSuccess = "websocket" === transport.name;
+
+ _this4.transport.pause(function () {
+ if (failed) return;
+ if ("closed" === _this4.readyState) return;
+ cleanup();
+
+ _this4.setTransport(transport);
+
+ transport.send([{
+ type: "upgrade"
+ }]);
+
+ _this4.emitReserved("upgrade", transport);
+
+ transport = null;
+ _this4.upgrading = false;
+
+ _this4.flush();
+ });
+ } else {
+ var err = new Error("probe error"); // @ts-ignore
+
+ err.transport = transport.name;
+
+ _this4.emitReserved("upgradeError", err);
+ }
+ });
+ };
+
+ function freezeTransport() {
+ if (failed) return; // Any callback called by transport should be ignored since now
+
+ failed = true;
+ cleanup();
+ transport.close();
+ transport = null;
+ } // Handle any error that happens while probing
+
+
+ var onerror = function onerror(err) {
+ var error = new Error("probe error: " + err); // @ts-ignore
+
+ error.transport = transport.name;
+ freezeTransport();
+
+ _this4.emitReserved("upgradeError", error);
+ };
+
+ function onTransportClose() {
+ onerror("transport closed");
+ } // When the socket is closed while we're probing
+
+
+ function onclose() {
+ onerror("socket closed");
+ } // When the socket is upgraded while we're probing
+
+
+ function onupgrade(to) {
+ if (transport && to.name !== transport.name) {
+ freezeTransport();
+ }
+ } // Remove all listeners on the transport and on self
+
+
+ var cleanup = function cleanup() {
+ transport.removeListener("open", onTransportOpen);
+ transport.removeListener("error", onerror);
+ transport.removeListener("close", onTransportClose);
+
+ _this4.off("close", onclose);
+
+ _this4.off("upgrading", onupgrade);
+ };
+
+ transport.once("open", onTransportOpen);
+ transport.once("error", onerror);
+ transport.once("close", onTransportClose);
+ this.once("close", onclose);
+ this.once("upgrading", onupgrade);
+ transport.open();
+ }
+ /**
+ * Called when connection is deemed open.
+ *
+ * @api private
+ */
+
+ }, {
+ key: "onOpen",
+ value: function onOpen() {
+ this.readyState = "open";
+ Socket.priorWebsocketSuccess = "websocket" === this.transport.name;
+ this.emitReserved("open");
+ this.flush(); // we check for `readyState` in case an `open`
+ // listener already closed the socket
+
+ if ("open" === this.readyState && this.opts.upgrade && this.transport.pause) {
+ var i = 0;
+ var l = this.upgrades.length;
+
+ for (; i < l; i++) {
+ this.probe(this.upgrades[i]);
+ }
+ }
+ }
+ /**
+ * Handles a packet.
+ *
+ * @api private
+ */
+
+ }, {
+ key: "onPacket",
+ value: function onPacket(packet) {
+ if ("opening" === this.readyState || "open" === this.readyState || "closing" === this.readyState) {
+ this.emitReserved("packet", packet); // Socket is live - any packet counts
+
+ this.emitReserved("heartbeat");
+
+ switch (packet.type) {
+ case "open":
+ this.onHandshake(JSON.parse(packet.data));
+ break;
+
+ case "ping":
+ this.resetPingTimeout();
+ this.sendPacket("pong");
+ this.emitReserved("ping");
+ this.emitReserved("pong");
+ break;
+
+ case "error":
+ var err = new Error("server error"); // @ts-ignore
+
+ err.code = packet.data;
+ this.onError(err);
+ break;
+
+ case "message":
+ this.emitReserved("data", packet.data);
+ this.emitReserved("message", packet.data);
+ break;
+ }
+ }
+ }
+ /**
+ * Called upon handshake completion.
+ *
+ * @param {Object} data - handshake obj
+ * @api private
+ */
+
+ }, {
+ key: "onHandshake",
+ value: function onHandshake(data) {
+ this.emitReserved("handshake", data);
+ this.id = data.sid;
+ this.transport.query.sid = data.sid;
+ this.upgrades = this.filterUpgrades(data.upgrades);
+ this.pingInterval = data.pingInterval;
+ this.pingTimeout = data.pingTimeout;
+ this.maxPayload = data.maxPayload;
+ this.onOpen(); // In case open handler closes socket
+
+ if ("closed" === this.readyState) return;
+ this.resetPingTimeout();
+ }
+ /**
+ * Sets and resets ping timeout timer based on server pings.
+ *
+ * @api private
+ */
+
+ }, {
+ key: "resetPingTimeout",
+ value: function resetPingTimeout() {
+ var _this5 = this;
+
+ this.clearTimeoutFn(this.pingTimeoutTimer);
+ this.pingTimeoutTimer = this.setTimeoutFn(function () {
+ _this5.onClose("ping timeout");
+ }, this.pingInterval + this.pingTimeout);
+
+ if (this.opts.autoUnref) {
+ this.pingTimeoutTimer.unref();
+ }
+ }
+ /**
+ * Called on `drain` event
+ *
+ * @api private
+ */
+
+ }, {
+ key: "onDrain",
+ value: function onDrain() {
+ this.writeBuffer.splice(0, this.prevBufferLen); // setting prevBufferLen = 0 is very important
+ // for example, when upgrading, upgrade packet is sent over,
+ // and a nonzero prevBufferLen could cause problems on `drain`
+
+ this.prevBufferLen = 0;
+
+ if (0 === this.writeBuffer.length) {
+ this.emitReserved("drain");
+ } else {
+ this.flush();
+ }
+ }
+ /**
+ * Flush write buffers.
+ *
+ * @api private
+ */
+
+ }, {
+ key: "flush",
+ value: function flush() {
+ if ("closed" !== this.readyState && this.transport.writable && !this.upgrading && this.writeBuffer.length) {
+ var packets = this.getWritablePackets();
+ this.transport.send(packets); // keep track of current length of writeBuffer
+ // splice writeBuffer and callbackBuffer on `drain`
+
+ this.prevBufferLen = packets.length;
+ this.emitReserved("flush");
+ }
+ }
+ /**
+ * Ensure the encoded size of the writeBuffer is below the maxPayload value sent by the server (only for HTTP
+ * long-polling)
+ *
+ * @private
+ */
+
+ }, {
+ key: "getWritablePackets",
+ value: function getWritablePackets() {
+ var shouldCheckPayloadSize = this.maxPayload && this.transport.name === "polling" && this.writeBuffer.length > 1;
+
+ if (!shouldCheckPayloadSize) {
+ return this.writeBuffer;
+ }
+
+ var payloadSize = 1; // first packet type
+
+ for (var i = 0; i < this.writeBuffer.length; i++) {
+ var data = this.writeBuffer[i].data;
+
+ if (data) {
+ payloadSize += byteLength(data);
+ }
+
+ if (i > 0 && payloadSize > this.maxPayload) {
+ return this.writeBuffer.slice(0, i);
+ }
+
+ payloadSize += 2; // separator + packet type
+ }
+
+ return this.writeBuffer;
+ }
+ /**
+ * Sends a message.
+ *
+ * @param {String} message.
+ * @param {Function} callback function.
+ * @param {Object} options.
+ * @return {Socket} for chaining.
+ * @api public
+ */
+
+ }, {
+ key: "write",
+ value: function write(msg, options, fn) {
+ this.sendPacket("message", msg, options, fn);
+ return this;
+ }
+ }, {
+ key: "send",
+ value: function send(msg, options, fn) {
+ this.sendPacket("message", msg, options, fn);
+ return this;
+ }
+ /**
+ * Sends a packet.
+ *
+ * @param {String} packet type.
+ * @param {String} data.
+ * @param {Object} options.
+ * @param {Function} callback function.
+ * @api private
+ */
+
+ }, {
+ key: "sendPacket",
+ value: function sendPacket(type, data, options, fn) {
+ if ("function" === typeof data) {
+ fn = data;
+ data = undefined;
+ }
+
+ if ("function" === typeof options) {
+ fn = options;
+ options = null;
+ }
+
+ if ("closing" === this.readyState || "closed" === this.readyState) {
+ return;
+ }
+
+ options = options || {};
+ options.compress = false !== options.compress;
+ var packet = {
+ type: type,
+ data: data,
+ options: options
+ };
+ this.emitReserved("packetCreate", packet);
+ this.writeBuffer.push(packet);
+ if (fn) this.once("flush", fn);
+ this.flush();
+ }
+ /**
+ * Closes the connection.
+ *
+ * @api public
+ */
+
+ }, {
+ key: "close",
+ value: function close() {
+ var _this6 = this;
+
+ var close = function close() {
+ _this6.onClose("forced close");
+
+ _this6.transport.close();
+ };
+
+ var cleanupAndClose = function cleanupAndClose() {
+ _this6.off("upgrade", cleanupAndClose);
+
+ _this6.off("upgradeError", cleanupAndClose);
+
+ close();
+ };
+
+ var waitForUpgrade = function waitForUpgrade() {
+ // wait for upgrade to finish since we can't send packets while pausing a transport
+ _this6.once("upgrade", cleanupAndClose);
+
+ _this6.once("upgradeError", cleanupAndClose);
+ };
+
+ if ("opening" === this.readyState || "open" === this.readyState) {
+ this.readyState = "closing";
+
+ if (this.writeBuffer.length) {
+ this.once("drain", function () {
+ if (_this6.upgrading) {
+ waitForUpgrade();
+ } else {
+ close();
+ }
+ });
+ } else if (this.upgrading) {
+ waitForUpgrade();
+ } else {
+ close();
+ }
+ }
+
+ return this;
+ }
+ /**
+ * Called upon transport error
+ *
+ * @api private
+ */
+
+ }, {
+ key: "onError",
+ value: function onError(err) {
+ Socket.priorWebsocketSuccess = false;
+ this.emitReserved("error", err);
+ this.onClose("transport error", err);
+ }
+ /**
+ * Called upon transport close.
+ *
+ * @api private
+ */
+
+ }, {
+ key: "onClose",
+ value: function onClose(reason, description) {
+ if ("opening" === this.readyState || "open" === this.readyState || "closing" === this.readyState) {
+ // clear timers
+ this.clearTimeoutFn(this.pingTimeoutTimer); // stop event from firing again for transport
+
+ this.transport.removeAllListeners("close"); // ensure transport won't stay open
+
+ this.transport.close(); // ignore further transport communication
+
+ this.transport.removeAllListeners();
+
+ if (typeof removeEventListener === "function") {
+ removeEventListener("offline", this.offlineEventListener, false);
+ } // set ready state
+
+
+ this.readyState = "closed"; // clear session id
+
+ this.id = null; // emit close event
+
+ this.emitReserved("close", reason, description); // clean buffers after, so users can still
+ // grab the buffers on `close` event
+
+ this.writeBuffer = [];
+ this.prevBufferLen = 0;
+ }
+ }
+ /**
+ * Filters upgrades, returning only those matching client transports.
+ *
+ * @param {Array} server upgrades
+ * @api private
+ *
+ */
+
+ }, {
+ key: "filterUpgrades",
+ value: function filterUpgrades(upgrades) {
+ var filteredUpgrades = [];
+ var i = 0;
+ var j = upgrades.length;
+
+ for (; i < j; i++) {
+ if (~this.transports.indexOf(upgrades[i])) filteredUpgrades.push(upgrades[i]);
+ }
+
+ return filteredUpgrades;
+ }
+ }]);
+
+ return Socket;
+ }(Emitter);
+ Socket$1.protocol = protocol$1;
+
+ /**
+ * URL parser.
+ *
+ * @param uri - url
+ * @param path - the request path of the connection
+ * @param loc - An object meant to mimic window.location.
+ * Defaults to window.location.
+ * @public
+ */
+
+ function url(uri) {
+ var path = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "";
+ var loc = arguments.length > 2 ? arguments[2] : undefined;
+ var obj = uri; // default to window.location
+
+ loc = loc || typeof location !== "undefined" && location;
+ if (null == uri) uri = loc.protocol + "//" + loc.host; // relative path support
+
+ if (typeof uri === "string") {
+ if ("/" === uri.charAt(0)) {
+ if ("/" === uri.charAt(1)) {
+ uri = loc.protocol + uri;
+ } else {
+ uri = loc.host + uri;
+ }
+ }
+
+ if (!/^(https?|wss?):\/\//.test(uri)) {
+ if ("undefined" !== typeof loc) {
+ uri = loc.protocol + "//" + uri;
+ } else {
+ uri = "https://" + uri;
+ }
+ } // parse
+
+
+ obj = parse(uri);
+ } // make sure we treat `localhost:80` and `localhost` equally
+
+
+ if (!obj.port) {
+ if (/^(http|ws)$/.test(obj.protocol)) {
+ obj.port = "80";
+ } else if (/^(http|ws)s$/.test(obj.protocol)) {
+ obj.port = "443";
+ }
+ }
+
+ obj.path = obj.path || "/";
+ var ipv6 = obj.host.indexOf(":") !== -1;
+ var host = ipv6 ? "[" + obj.host + "]" : obj.host; // define unique id
+
+ obj.id = obj.protocol + "://" + host + ":" + obj.port + path; // define href
+
+ obj.href = obj.protocol + "://" + host + (loc && loc.port === obj.port ? "" : ":" + obj.port);
+ return obj;
+ }
+
+ var withNativeArrayBuffer = typeof ArrayBuffer === "function";
+
+ var isView = function isView(obj) {
+ return typeof ArrayBuffer.isView === "function" ? ArrayBuffer.isView(obj) : obj.buffer instanceof ArrayBuffer;
+ };
+
+ var toString = Object.prototype.toString;
+ var withNativeBlob = typeof Blob === "function" || typeof Blob !== "undefined" && toString.call(Blob) === "[object BlobConstructor]";
+ var withNativeFile = typeof File === "function" || typeof File !== "undefined" && toString.call(File) === "[object FileConstructor]";
+ /**
+ * Returns true if obj is a Buffer, an ArrayBuffer, a Blob or a File.
+ *
+ * @private
+ */
+
+ function isBinary(obj) {
+ return withNativeArrayBuffer && (obj instanceof ArrayBuffer || isView(obj)) || withNativeBlob && obj instanceof Blob || withNativeFile && obj instanceof File;
+ }
+ function hasBinary(obj, toJSON) {
+ if (!obj || _typeof(obj) !== "object") {
+ return false;
+ }
+
+ if (Array.isArray(obj)) {
+ for (var i = 0, l = obj.length; i < l; i++) {
+ if (hasBinary(obj[i])) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ if (isBinary(obj)) {
+ return true;
+ }
+
+ if (obj.toJSON && typeof obj.toJSON === "function" && arguments.length === 1) {
+ return hasBinary(obj.toJSON(), true);
+ }
+
+ for (var key in obj) {
+ if (Object.prototype.hasOwnProperty.call(obj, key) && hasBinary(obj[key])) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Replaces every Buffer | ArrayBuffer | Blob | File in packet with a numbered placeholder.
+ *
+ * @param {Object} packet - socket.io event packet
+ * @return {Object} with deconstructed packet and list of buffers
+ * @public
+ */
+
+ function deconstructPacket(packet) {
+ var buffers = [];
+ var packetData = packet.data;
+ var pack = packet;
+ pack.data = _deconstructPacket(packetData, buffers);
+ pack.attachments = buffers.length; // number of binary 'attachments'
+
+ return {
+ packet: pack,
+ buffers: buffers
+ };
+ }
+
+ function _deconstructPacket(data, buffers) {
+ if (!data) return data;
+
+ if (isBinary(data)) {
+ var placeholder = {
+ _placeholder: true,
+ num: buffers.length
+ };
+ buffers.push(data);
+ return placeholder;
+ } else if (Array.isArray(data)) {
+ var newData = new Array(data.length);
+
+ for (var i = 0; i < data.length; i++) {
+ newData[i] = _deconstructPacket(data[i], buffers);
+ }
+
+ return newData;
+ } else if (_typeof(data) === "object" && !(data instanceof Date)) {
+ var _newData = {};
+
+ for (var key in data) {
+ if (Object.prototype.hasOwnProperty.call(data, key)) {
+ _newData[key] = _deconstructPacket(data[key], buffers);
+ }
+ }
+
+ return _newData;
+ }
+
+ return data;
+ }
+ /**
+ * Reconstructs a binary packet from its placeholder packet and buffers
+ *
+ * @param {Object} packet - event packet with placeholders
+ * @param {Array} buffers - binary buffers to put in placeholder positions
+ * @return {Object} reconstructed packet
+ * @public
+ */
+
+
+ function reconstructPacket(packet, buffers) {
+ packet.data = _reconstructPacket(packet.data, buffers);
+ packet.attachments = undefined; // no longer useful
+
+ return packet;
+ }
+
+ function _reconstructPacket(data, buffers) {
+ if (!data) return data;
+
+ if (data && data._placeholder) {
+ return buffers[data.num]; // appropriate buffer (should be natural order anyway)
+ } else if (Array.isArray(data)) {
+ for (var i = 0; i < data.length; i++) {
+ data[i] = _reconstructPacket(data[i], buffers);
+ }
+ } else if (_typeof(data) === "object") {
+ for (var key in data) {
+ if (Object.prototype.hasOwnProperty.call(data, key)) {
+ data[key] = _reconstructPacket(data[key], buffers);
+ }
+ }
+ }
+
+ return data;
+ }
+
+ /**
+ * Protocol version.
+ *
+ * @public
+ */
+
+ var protocol = 5;
+ var PacketType;
+
+ (function (PacketType) {
+ PacketType[PacketType["CONNECT"] = 0] = "CONNECT";
+ PacketType[PacketType["DISCONNECT"] = 1] = "DISCONNECT";
+ PacketType[PacketType["EVENT"] = 2] = "EVENT";
+ PacketType[PacketType["ACK"] = 3] = "ACK";
+ PacketType[PacketType["CONNECT_ERROR"] = 4] = "CONNECT_ERROR";
+ PacketType[PacketType["BINARY_EVENT"] = 5] = "BINARY_EVENT";
+ PacketType[PacketType["BINARY_ACK"] = 6] = "BINARY_ACK";
+ })(PacketType || (PacketType = {}));
+ /**
+ * A socket.io Encoder instance
+ */
+
+
+ var Encoder = /*#__PURE__*/function () {
+ /**
+ * Encoder constructor
+ *
+ * @param {function} replacer - custom replacer to pass down to JSON.parse
+ */
+ function Encoder(replacer) {
+ _classCallCheck(this, Encoder);
+
+ this.replacer = replacer;
+ }
+ /**
+ * Encode a packet as a single string if non-binary, or as a
+ * buffer sequence, depending on packet type.
+ *
+ * @param {Object} obj - packet object
+ */
+
+
+ _createClass(Encoder, [{
+ key: "encode",
+ value: function encode(obj) {
+ if (obj.type === PacketType.EVENT || obj.type === PacketType.ACK) {
+ if (hasBinary(obj)) {
+ obj.type = obj.type === PacketType.EVENT ? PacketType.BINARY_EVENT : PacketType.BINARY_ACK;
+ return this.encodeAsBinary(obj);
+ }
+ }
+
+ return [this.encodeAsString(obj)];
+ }
+ /**
+ * Encode packet as string.
+ */
+
+ }, {
+ key: "encodeAsString",
+ value: function encodeAsString(obj) {
+ // first is type
+ var str = "" + obj.type; // attachments if we have them
+
+ if (obj.type === PacketType.BINARY_EVENT || obj.type === PacketType.BINARY_ACK) {
+ str += obj.attachments + "-";
+ } // if we have a namespace other than `/`
+ // we append it followed by a comma `,`
+
+
+ if (obj.nsp && "/" !== obj.nsp) {
+ str += obj.nsp + ",";
+ } // immediately followed by the id
+
+
+ if (null != obj.id) {
+ str += obj.id;
+ } // json data
+
+
+ if (null != obj.data) {
+ str += JSON.stringify(obj.data, this.replacer);
+ }
+
+ return str;
+ }
+ /**
+ * Encode packet as 'buffer sequence' by removing blobs, and
+ * deconstructing packet into object with placeholders and
+ * a list of buffers.
+ */
+
+ }, {
+ key: "encodeAsBinary",
+ value: function encodeAsBinary(obj) {
+ var deconstruction = deconstructPacket(obj);
+ var pack = this.encodeAsString(deconstruction.packet);
+ var buffers = deconstruction.buffers;
+ buffers.unshift(pack); // add packet info to beginning of data list
+
+ return buffers; // write all the buffers
+ }
+ }]);
+
+ return Encoder;
+ }();
+ /**
+ * A socket.io Decoder instance
+ *
+ * @return {Object} decoder
+ */
+
+ var Decoder = /*#__PURE__*/function (_Emitter) {
+ _inherits(Decoder, _Emitter);
+
+ var _super = _createSuper(Decoder);
+
+ /**
+ * Decoder constructor
+ *
+ * @param {function} reviver - custom reviver to pass down to JSON.stringify
+ */
+ function Decoder(reviver) {
+ var _this;
+
+ _classCallCheck(this, Decoder);
+
+ _this = _super.call(this);
+ _this.reviver = reviver;
+ return _this;
+ }
+ /**
+ * Decodes an encoded packet string into packet JSON.
+ *
+ * @param {String} obj - encoded packet
+ */
+
+
+ _createClass(Decoder, [{
+ key: "add",
+ value: function add(obj) {
+ var packet;
+
+ if (typeof obj === "string") {
+ packet = this.decodeString(obj);
+
+ if (packet.type === PacketType.BINARY_EVENT || packet.type === PacketType.BINARY_ACK) {
+ // binary packet's json
+ this.reconstructor = new BinaryReconstructor(packet); // no attachments, labeled binary but no binary data to follow
+
+ if (packet.attachments === 0) {
+ _get(_getPrototypeOf(Decoder.prototype), "emitReserved", this).call(this, "decoded", packet);
+ }
+ } else {
+ // non-binary full packet
+ _get(_getPrototypeOf(Decoder.prototype), "emitReserved", this).call(this, "decoded", packet);
+ }
+ } else if (isBinary(obj) || obj.base64) {
+ // raw binary data
+ if (!this.reconstructor) {
+ throw new Error("got binary data when not reconstructing a packet");
+ } else {
+ packet = this.reconstructor.takeBinaryData(obj);
+
+ if (packet) {
+ // received final buffer
+ this.reconstructor = null;
+
+ _get(_getPrototypeOf(Decoder.prototype), "emitReserved", this).call(this, "decoded", packet);
+ }
+ }
+ } else {
+ throw new Error("Unknown type: " + obj);
+ }
+ }
+ /**
+ * Decode a packet String (JSON data)
+ *
+ * @param {String} str
+ * @return {Object} packet
+ */
+
+ }, {
+ key: "decodeString",
+ value: function decodeString(str) {
+ var i = 0; // look up type
+
+ var p = {
+ type: Number(str.charAt(0))
+ };
+
+ if (PacketType[p.type] === undefined) {
+ throw new Error("unknown packet type " + p.type);
+ } // look up attachments if type binary
+
+
+ if (p.type === PacketType.BINARY_EVENT || p.type === PacketType.BINARY_ACK) {
+ var start = i + 1;
+
+ while (str.charAt(++i) !== "-" && i != str.length) {}
+
+ var buf = str.substring(start, i);
+
+ if (buf != Number(buf) || str.charAt(i) !== "-") {
+ throw new Error("Illegal attachments");
+ }
+
+ p.attachments = Number(buf);
+ } // look up namespace (if any)
+
+
+ if ("/" === str.charAt(i + 1)) {
+ var _start = i + 1;
+
+ while (++i) {
+ var c = str.charAt(i);
+ if ("," === c) break;
+ if (i === str.length) break;
+ }
+
+ p.nsp = str.substring(_start, i);
+ } else {
+ p.nsp = "/";
+ } // look up id
+
+
+ var next = str.charAt(i + 1);
+
+ if ("" !== next && Number(next) == next) {
+ var _start2 = i + 1;
+
+ while (++i) {
+ var _c = str.charAt(i);
+
+ if (null == _c || Number(_c) != _c) {
+ --i;
+ break;
+ }
+
+ if (i === str.length) break;
+ }
+
+ p.id = Number(str.substring(_start2, i + 1));
+ } // look up json data
+
+
+ if (str.charAt(++i)) {
+ var payload = this.tryParse(str.substr(i));
+
+ if (Decoder.isPayloadValid(p.type, payload)) {
+ p.data = payload;
+ } else {
+ throw new Error("invalid payload");
+ }
+ }
+
+ return p;
+ }
+ }, {
+ key: "tryParse",
+ value: function tryParse(str) {
+ try {
+ return JSON.parse(str, this.reviver);
+ } catch (e) {
+ return false;
+ }
+ }
+ }, {
+ key: "destroy",
+ value:
+ /**
+ * Deallocates a parser's resources
+ */
+ function destroy() {
+ if (this.reconstructor) {
+ this.reconstructor.finishedReconstruction();
+ }
+ }
+ }], [{
+ key: "isPayloadValid",
+ value: function isPayloadValid(type, payload) {
+ switch (type) {
+ case PacketType.CONNECT:
+ return _typeof(payload) === "object";
+
+ case PacketType.DISCONNECT:
+ return payload === undefined;
+
+ case PacketType.CONNECT_ERROR:
+ return typeof payload === "string" || _typeof(payload) === "object";
+
+ case PacketType.EVENT:
+ case PacketType.BINARY_EVENT:
+ return Array.isArray(payload) && payload.length > 0;
+
+ case PacketType.ACK:
+ case PacketType.BINARY_ACK:
+ return Array.isArray(payload);
+ }
+ }
+ }]);
+
+ return Decoder;
+ }(Emitter);
+ /**
+ * A manager of a binary event's 'buffer sequence'. Should
+ * be constructed whenever a packet of type BINARY_EVENT is
+ * decoded.
+ *
+ * @param {Object} packet
+ * @return {BinaryReconstructor} initialized reconstructor
+ */
+
+ var BinaryReconstructor = /*#__PURE__*/function () {
+ function BinaryReconstructor(packet) {
+ _classCallCheck(this, BinaryReconstructor);
+
+ this.packet = packet;
+ this.buffers = [];
+ this.reconPack = packet;
+ }
+ /**
+ * Method to be called when binary data received from connection
+ * after a BINARY_EVENT packet.
+ *
+ * @param {Buffer | ArrayBuffer} binData - the raw binary data received
+ * @return {null | Object} returns null if more binary data is expected or
+ * a reconstructed packet object if all buffers have been received.
+ */
+
+
+ _createClass(BinaryReconstructor, [{
+ key: "takeBinaryData",
+ value: function takeBinaryData(binData) {
+ this.buffers.push(binData);
+
+ if (this.buffers.length === this.reconPack.attachments) {
+ // done with buffer list
+ var packet = reconstructPacket(this.reconPack, this.buffers);
+ this.finishedReconstruction();
+ return packet;
+ }
+
+ return null;
+ }
+ /**
+ * Cleans up binary packet reconstruction variables.
+ */
+
+ }, {
+ key: "finishedReconstruction",
+ value: function finishedReconstruction() {
+ this.reconPack = null;
+ this.buffers = [];
+ }
+ }]);
+
+ return BinaryReconstructor;
+ }();
+
+ var parser = /*#__PURE__*/Object.freeze({
+ __proto__: null,
+ protocol: protocol,
+ get PacketType () { return PacketType; },
+ Encoder: Encoder,
+ Decoder: Decoder
+ });
+
+ function on(obj, ev, fn) {
+ obj.on(ev, fn);
+ return function subDestroy() {
+ obj.off(ev, fn);
+ };
+ }
+
+ /**
+ * Internal events.
+ * These events can't be emitted by the user.
+ */
+
+ var RESERVED_EVENTS = Object.freeze({
+ connect: 1,
+ connect_error: 1,
+ disconnect: 1,
+ disconnecting: 1,
+ // EventEmitter reserved events: https://nodejs.org/api/events.html#events_event_newlistener
+ newListener: 1,
+ removeListener: 1
+ });
+ var Socket = /*#__PURE__*/function (_Emitter) {
+ _inherits(Socket, _Emitter);
+
+ var _super = _createSuper(Socket);
+
+ /**
+ * `Socket` constructor.
+ *
+ * @public
+ */
+ function Socket(io, nsp, opts) {
+ var _this;
+
+ _classCallCheck(this, Socket);
+
+ _this = _super.call(this);
+ _this.connected = false;
+ _this.receiveBuffer = [];
+ _this.sendBuffer = [];
+ _this.ids = 0;
+ _this.acks = {};
+ _this.flags = {};
+ _this.io = io;
+ _this.nsp = nsp;
+
+ if (opts && opts.auth) {
+ _this.auth = opts.auth;
+ }
+
+ if (_this.io._autoConnect) _this.open();
+ return _this;
+ }
+ /**
+ * Whether the socket is currently disconnected
+ */
+
+
+ _createClass(Socket, [{
+ key: "disconnected",
+ get: function get() {
+ return !this.connected;
+ }
+ /**
+ * Subscribe to open, close and packet events
+ *
+ * @private
+ */
+
+ }, {
+ key: "subEvents",
+ value: function subEvents() {
+ if (this.subs) return;
+ var io = this.io;
+ this.subs = [on(io, "open", this.onopen.bind(this)), on(io, "packet", this.onpacket.bind(this)), on(io, "error", this.onerror.bind(this)), on(io, "close", this.onclose.bind(this))];
+ }
+ /**
+ * Whether the Socket will try to reconnect when its Manager connects or reconnects
+ */
+
+ }, {
+ key: "active",
+ get: function get() {
+ return !!this.subs;
+ }
+ /**
+ * "Opens" the socket.
+ *
+ * @public
+ */
+
+ }, {
+ key: "connect",
+ value: function connect() {
+ if (this.connected) return this;
+ this.subEvents();
+ if (!this.io["_reconnecting"]) this.io.open(); // ensure open
+
+ if ("open" === this.io._readyState) this.onopen();
+ return this;
+ }
+ /**
+ * Alias for connect()
+ */
+
+ }, {
+ key: "open",
+ value: function open() {
+ return this.connect();
+ }
+ /**
+ * Sends a `message` event.
+ *
+ * @return self
+ * @public
+ */
+
+ }, {
+ key: "send",
+ value: function send() {
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
+ args[_key] = arguments[_key];
+ }
+
+ args.unshift("message");
+ this.emit.apply(this, args);
+ return this;
+ }
+ /**
+ * Override `emit`.
+ * If the event is in `events`, it's emitted normally.
+ *
+ * @return self
+ * @public
+ */
+
+ }, {
+ key: "emit",
+ value: function emit(ev) {
+ if (RESERVED_EVENTS.hasOwnProperty(ev)) {
+ throw new Error('"' + ev + '" is a reserved event name');
+ }
+
+ for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
+ args[_key2 - 1] = arguments[_key2];
+ }
+
+ args.unshift(ev);
+ var packet = {
+ type: PacketType.EVENT,
+ data: args
+ };
+ packet.options = {};
+ packet.options.compress = this.flags.compress !== false; // event ack callback
+
+ if ("function" === typeof args[args.length - 1]) {
+ var id = this.ids++;
+ var ack = args.pop();
+
+ this._registerAckCallback(id, ack);
+
+ packet.id = id;
+ }
+
+ var isTransportWritable = this.io.engine && this.io.engine.transport && this.io.engine.transport.writable;
+ var discardPacket = this.flags["volatile"] && (!isTransportWritable || !this.connected);
+
+ if (discardPacket) ; else if (this.connected) {
+ this.notifyOutgoingListeners(packet);
+ this.packet(packet);
+ } else {
+ this.sendBuffer.push(packet);
+ }
+
+ this.flags = {};
+ return this;
+ }
+ /**
+ * @private
+ */
+
+ }, {
+ key: "_registerAckCallback",
+ value: function _registerAckCallback(id, ack) {
+ var _this2 = this;
+
+ var timeout = this.flags.timeout;
+
+ if (timeout === undefined) {
+ this.acks[id] = ack;
+ return;
+ } // @ts-ignore
+
+
+ var timer = this.io.setTimeoutFn(function () {
+ delete _this2.acks[id];
+
+ for (var i = 0; i < _this2.sendBuffer.length; i++) {
+ if (_this2.sendBuffer[i].id === id) {
+ _this2.sendBuffer.splice(i, 1);
+ }
+ }
+
+ ack.call(_this2, new Error("operation has timed out"));
+ }, timeout);
+
+ this.acks[id] = function () {
+ // @ts-ignore
+ _this2.io.clearTimeoutFn(timer);
+
+ for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
+ args[_key3] = arguments[_key3];
+ }
+
+ ack.apply(_this2, [null].concat(args));
+ };
+ }
+ /**
+ * Sends a packet.
+ *
+ * @param packet
+ * @private
+ */
+
+ }, {
+ key: "packet",
+ value: function packet(_packet) {
+ _packet.nsp = this.nsp;
+
+ this.io._packet(_packet);
+ }
+ /**
+ * Called upon engine `open`.
+ *
+ * @private
+ */
+
+ }, {
+ key: "onopen",
+ value: function onopen() {
+ var _this3 = this;
+
+ if (typeof this.auth == "function") {
+ this.auth(function (data) {
+ _this3.packet({
+ type: PacketType.CONNECT,
+ data: data
+ });
+ });
+ } else {
+ this.packet({
+ type: PacketType.CONNECT,
+ data: this.auth
+ });
+ }
+ }
+ /**
+ * Called upon engine or manager `error`.
+ *
+ * @param err
+ * @private
+ */
+
+ }, {
+ key: "onerror",
+ value: function onerror(err) {
+ if (!this.connected) {
+ this.emitReserved("connect_error", err);
+ }
+ }
+ /**
+ * Called upon engine `close`.
+ *
+ * @param reason
+ * @param description
+ * @private
+ */
+
+ }, {
+ key: "onclose",
+ value: function onclose(reason, description) {
+ this.connected = false;
+ delete this.id;
+ this.emitReserved("disconnect", reason, description);
+ }
+ /**
+ * Called with socket packet.
+ *
+ * @param packet
+ * @private
+ */
+
+ }, {
+ key: "onpacket",
+ value: function onpacket(packet) {
+ var sameNamespace = packet.nsp === this.nsp;
+ if (!sameNamespace) return;
+
+ switch (packet.type) {
+ case PacketType.CONNECT:
+ if (packet.data && packet.data.sid) {
+ var id = packet.data.sid;
+ this.onconnect(id);
+ } else {
+ this.emitReserved("connect_error", new Error("It seems you are trying to reach a Socket.IO server in v2.x with a v3.x client, but they are not compatible (more information here: https://socket.io/docs/v3/migrating-from-2-x-to-3-0/)"));
+ }
+
+ break;
+
+ case PacketType.EVENT:
+ case PacketType.BINARY_EVENT:
+ this.onevent(packet);
+ break;
+
+ case PacketType.ACK:
+ case PacketType.BINARY_ACK:
+ this.onack(packet);
+ break;
+
+ case PacketType.DISCONNECT:
+ this.ondisconnect();
+ break;
+
+ case PacketType.CONNECT_ERROR:
+ this.destroy();
+ var err = new Error(packet.data.message); // @ts-ignore
+
+ err.data = packet.data.data;
+ this.emitReserved("connect_error", err);
+ break;
+ }
+ }
+ /**
+ * Called upon a server event.
+ *
+ * @param packet
+ * @private
+ */
+
+ }, {
+ key: "onevent",
+ value: function onevent(packet) {
+ var args = packet.data || [];
+
+ if (null != packet.id) {
+ args.push(this.ack(packet.id));
+ }
+
+ if (this.connected) {
+ this.emitEvent(args);
+ } else {
+ this.receiveBuffer.push(Object.freeze(args));
+ }
+ }
+ }, {
+ key: "emitEvent",
+ value: function emitEvent(args) {
+ if (this._anyListeners && this._anyListeners.length) {
+ var listeners = this._anyListeners.slice();
+
+ var _iterator = _createForOfIteratorHelper(listeners),
+ _step;
+
+ try {
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
+ var listener = _step.value;
+ listener.apply(this, args);
+ }
+ } catch (err) {
+ _iterator.e(err);
+ } finally {
+ _iterator.f();
+ }
+ }
+
+ _get(_getPrototypeOf(Socket.prototype), "emit", this).apply(this, args);
+ }
+ /**
+ * Produces an ack callback to emit with an event.
+ *
+ * @private
+ */
+
+ }, {
+ key: "ack",
+ value: function ack(id) {
+ var self = this;
+ var sent = false;
+ return function () {
+ // prevent double callbacks
+ if (sent) return;
+ sent = true;
+
+ for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
+ args[_key4] = arguments[_key4];
+ }
+
+ self.packet({
+ type: PacketType.ACK,
+ id: id,
+ data: args
+ });
+ };
+ }
+ /**
+ * Called upon a server acknowlegement.
+ *
+ * @param packet
+ * @private
+ */
+
+ }, {
+ key: "onack",
+ value: function onack(packet) {
+ var ack = this.acks[packet.id];
+
+ if ("function" === typeof ack) {
+ ack.apply(this, packet.data);
+ delete this.acks[packet.id];
+ }
+ }
+ /**
+ * Called upon server connect.
+ *
+ * @private
+ */
+
+ }, {
+ key: "onconnect",
+ value: function onconnect(id) {
+ this.id = id;
+ this.connected = true;
+ this.emitBuffered();
+ this.emitReserved("connect");
+ }
+ /**
+ * Emit buffered events (received and emitted).
+ *
+ * @private
+ */
+
+ }, {
+ key: "emitBuffered",
+ value: function emitBuffered() {
+ var _this4 = this;
+
+ this.receiveBuffer.forEach(function (args) {
+ return _this4.emitEvent(args);
+ });
+ this.receiveBuffer = [];
+ this.sendBuffer.forEach(function (packet) {
+ _this4.notifyOutgoingListeners(packet);
+
+ _this4.packet(packet);
+ });
+ this.sendBuffer = [];
+ }
+ /**
+ * Called upon server disconnect.
+ *
+ * @private
+ */
+
+ }, {
+ key: "ondisconnect",
+ value: function ondisconnect() {
+ this.destroy();
+ this.onclose("io server disconnect");
+ }
+ /**
+ * Called upon forced client/server side disconnections,
+ * this method ensures the manager stops tracking us and
+ * that reconnections don't get triggered for this.
+ *
+ * @private
+ */
+
+ }, {
+ key: "destroy",
+ value: function destroy() {
+ if (this.subs) {
+ // clean subscriptions to avoid reconnections
+ this.subs.forEach(function (subDestroy) {
+ return subDestroy();
+ });
+ this.subs = undefined;
+ }
+
+ this.io["_destroy"](this);
+ }
+ /**
+ * Disconnects the socket manually.
+ *
+ * @return self
+ * @public
+ */
+
+ }, {
+ key: "disconnect",
+ value: function disconnect() {
+ if (this.connected) {
+ this.packet({
+ type: PacketType.DISCONNECT
+ });
+ } // remove socket from pool
+
+
+ this.destroy();
+
+ if (this.connected) {
+ // fire events
+ this.onclose("io client disconnect");
+ }
+
+ return this;
+ }
+ /**
+ * Alias for disconnect()
+ *
+ * @return self
+ * @public
+ */
+
+ }, {
+ key: "close",
+ value: function close() {
+ return this.disconnect();
+ }
+ /**
+ * Sets the compress flag.
+ *
+ * @param compress - if `true`, compresses the sending data
+ * @return self
+ * @public
+ */
+
+ }, {
+ key: "compress",
+ value: function compress(_compress) {
+ this.flags.compress = _compress;
+ return this;
+ }
+ /**
+ * Sets a modifier for a subsequent event emission that the event message will be dropped when this socket is not
+ * ready to send messages.
+ *
+ * @returns self
+ * @public
+ */
+
+ }, {
+ key: "volatile",
+ get: function get() {
+ this.flags["volatile"] = true;
+ return this;
+ }
+ /**
+ * Sets a modifier for a subsequent event emission that the callback will be called with an error when the
+ * given number of milliseconds have elapsed without an acknowledgement from the server:
+ *
+ * ```
+ * socket.timeout(5000).emit("my-event", (err) => {
+ * if (err) {
+ * // the server did not acknowledge the event in the given delay
+ * }
+ * });
+ * ```
+ *
+ * @returns self
+ * @public
+ */
+
+ }, {
+ key: "timeout",
+ value: function timeout(_timeout) {
+ this.flags.timeout = _timeout;
+ return this;
+ }
+ /**
+ * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
+ * callback.
+ *
+ * @param listener
+ * @public
+ */
+
+ }, {
+ key: "onAny",
+ value: function onAny(listener) {
+ this._anyListeners = this._anyListeners || [];
+
+ this._anyListeners.push(listener);
+
+ return this;
+ }
+ /**
+ * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
+ * callback. The listener is added to the beginning of the listeners array.
+ *
+ * @param listener
+ * @public
+ */
+
+ }, {
+ key: "prependAny",
+ value: function prependAny(listener) {
+ this._anyListeners = this._anyListeners || [];
+
+ this._anyListeners.unshift(listener);
+
+ return this;
+ }
+ /**
+ * Removes the listener that will be fired when any event is emitted.
+ *
+ * @param listener
+ * @public
+ */
+
+ }, {
+ key: "offAny",
+ value: function offAny(listener) {
+ if (!this._anyListeners) {
+ return this;
+ }
+
+ if (listener) {
+ var listeners = this._anyListeners;
+
+ for (var i = 0; i < listeners.length; i++) {
+ if (listener === listeners[i]) {
+ listeners.splice(i, 1);
+ return this;
+ }
+ }
+ } else {
+ this._anyListeners = [];
+ }
+
+ return this;
+ }
+ /**
+ * Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
+ * e.g. to remove listeners.
+ *
+ * @public
+ */
+
+ }, {
+ key: "listenersAny",
+ value: function listenersAny() {
+ return this._anyListeners || [];
+ }
+ /**
+ * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
+ * callback.
+ *
+ * @param listener
+ *
+ *
+ *
+ * socket.onAnyOutgoing((event, ...args) => {
+ * console.log(event);
+ * });
+ *
+ *
+ *
+ * @public
+ */
+
+ }, {
+ key: "onAnyOutgoing",
+ value: function onAnyOutgoing(listener) {
+ this._anyOutgoingListeners = this._anyOutgoingListeners || [];
+
+ this._anyOutgoingListeners.push(listener);
+
+ return this;
+ }
+ /**
+ * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
+ * callback. The listener is added to the beginning of the listeners array.
+ *
+ * @param listener
+ *
+ *
+ *
+ * socket.prependAnyOutgoing((event, ...args) => {
+ * console.log(event);
+ * });
+ *
+ *
+ *
+ * @public
+ */
+
+ }, {
+ key: "prependAnyOutgoing",
+ value: function prependAnyOutgoing(listener) {
+ this._anyOutgoingListeners = this._anyOutgoingListeners || [];
+
+ this._anyOutgoingListeners.unshift(listener);
+
+ return this;
+ }
+ /**
+ * Removes the listener that will be fired when any event is emitted.
+ *
+ * @param listener
+ *
+ *
+ *
+ * const handler = (event, ...args) => {
+ * console.log(event);
+ * }
+ *
+ * socket.onAnyOutgoing(handler);
+ *
+ * // then later
+ * socket.offAnyOutgoing(handler);
+ *
+ *
+ *
+ * @public
+ */
+
+ }, {
+ key: "offAnyOutgoing",
+ value: function offAnyOutgoing(listener) {
+ if (!this._anyOutgoingListeners) {
+ return this;
+ }
+
+ if (listener) {
+ var listeners = this._anyOutgoingListeners;
+
+ for (var i = 0; i < listeners.length; i++) {
+ if (listener === listeners[i]) {
+ listeners.splice(i, 1);
+ return this;
+ }
+ }
+ } else {
+ this._anyOutgoingListeners = [];
+ }
+
+ return this;
+ }
+ /**
+ * Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
+ * e.g. to remove listeners.
+ *
+ * @public
+ */
+
+ }, {
+ key: "listenersAnyOutgoing",
+ value: function listenersAnyOutgoing() {
+ return this._anyOutgoingListeners || [];
+ }
+ /**
+ * Notify the listeners for each packet sent
+ *
+ * @param packet
+ *
+ * @private
+ */
+
+ }, {
+ key: "notifyOutgoingListeners",
+ value: function notifyOutgoingListeners(packet) {
+ if (this._anyOutgoingListeners && this._anyOutgoingListeners.length) {
+ var listeners = this._anyOutgoingListeners.slice();
+
+ var _iterator2 = _createForOfIteratorHelper(listeners),
+ _step2;
+
+ try {
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
+ var listener = _step2.value;
+ listener.apply(this, packet.data);
+ }
+ } catch (err) {
+ _iterator2.e(err);
+ } finally {
+ _iterator2.f();
+ }
+ }
+ }
+ }]);
+
+ return Socket;
+ }(Emitter);
+
+ /**
+ * Initialize backoff timer with `opts`.
+ *
+ * - `min` initial timeout in milliseconds [100]
+ * - `max` max timeout [10000]
+ * - `jitter` [0]
+ * - `factor` [2]
+ *
+ * @param {Object} opts
+ * @api public
+ */
+ function Backoff(opts) {
+ opts = opts || {};
+ this.ms = opts.min || 100;
+ this.max = opts.max || 10000;
+ this.factor = opts.factor || 2;
+ this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0;
+ this.attempts = 0;
+ }
+ /**
+ * Return the backoff duration.
+ *
+ * @return {Number}
+ * @api public
+ */
+
+ Backoff.prototype.duration = function () {
+ var ms = this.ms * Math.pow(this.factor, this.attempts++);
+
+ if (this.jitter) {
+ var rand = Math.random();
+ var deviation = Math.floor(rand * this.jitter * ms);
+ ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation;
+ }
+
+ return Math.min(ms, this.max) | 0;
+ };
+ /**
+ * Reset the number of attempts.
+ *
+ * @api public
+ */
+
+
+ Backoff.prototype.reset = function () {
+ this.attempts = 0;
+ };
+ /**
+ * Set the minimum duration
+ *
+ * @api public
+ */
+
+
+ Backoff.prototype.setMin = function (min) {
+ this.ms = min;
+ };
+ /**
+ * Set the maximum duration
+ *
+ * @api public
+ */
+
+
+ Backoff.prototype.setMax = function (max) {
+ this.max = max;
+ };
+ /**
+ * Set the jitter
+ *
+ * @api public
+ */
+
+
+ Backoff.prototype.setJitter = function (jitter) {
+ this.jitter = jitter;
+ };
+
+ var Manager = /*#__PURE__*/function (_Emitter) {
+ _inherits(Manager, _Emitter);
+
+ var _super = _createSuper(Manager);
+
+ function Manager(uri, opts) {
+ var _this;
+
+ _classCallCheck(this, Manager);
+
+ var _a;
+
+ _this = _super.call(this);
+ _this.nsps = {};
+ _this.subs = [];
+
+ if (uri && "object" === _typeof(uri)) {
+ opts = uri;
+ uri = undefined;
+ }
+
+ opts = opts || {};
+ opts.path = opts.path || "/socket.io";
+ _this.opts = opts;
+ installTimerFunctions(_assertThisInitialized(_this), opts);
+
+ _this.reconnection(opts.reconnection !== false);
+
+ _this.reconnectionAttempts(opts.reconnectionAttempts || Infinity);
+
+ _this.reconnectionDelay(opts.reconnectionDelay || 1000);
+
+ _this.reconnectionDelayMax(opts.reconnectionDelayMax || 5000);
+
+ _this.randomizationFactor((_a = opts.randomizationFactor) !== null && _a !== void 0 ? _a : 0.5);
+
+ _this.backoff = new Backoff({
+ min: _this.reconnectionDelay(),
+ max: _this.reconnectionDelayMax(),
+ jitter: _this.randomizationFactor()
+ });
+
+ _this.timeout(null == opts.timeout ? 20000 : opts.timeout);
+
+ _this._readyState = "closed";
+ _this.uri = uri;
+
+ var _parser = opts.parser || parser;
+
+ _this.encoder = new _parser.Encoder();
+ _this.decoder = new _parser.Decoder();
+ _this._autoConnect = opts.autoConnect !== false;
+ if (_this._autoConnect) _this.open();
+ return _this;
+ }
+
+ _createClass(Manager, [{
+ key: "reconnection",
+ value: function reconnection(v) {
+ if (!arguments.length) return this._reconnection;
+ this._reconnection = !!v;
+ return this;
+ }
+ }, {
+ key: "reconnectionAttempts",
+ value: function reconnectionAttempts(v) {
+ if (v === undefined) return this._reconnectionAttempts;
+ this._reconnectionAttempts = v;
+ return this;
+ }
+ }, {
+ key: "reconnectionDelay",
+ value: function reconnectionDelay(v) {
+ var _a;
+
+ if (v === undefined) return this._reconnectionDelay;
+ this._reconnectionDelay = v;
+ (_a = this.backoff) === null || _a === void 0 ? void 0 : _a.setMin(v);
+ return this;
+ }
+ }, {
+ key: "randomizationFactor",
+ value: function randomizationFactor(v) {
+ var _a;
+
+ if (v === undefined) return this._randomizationFactor;
+ this._randomizationFactor = v;
+ (_a = this.backoff) === null || _a === void 0 ? void 0 : _a.setJitter(v);
+ return this;
+ }
+ }, {
+ key: "reconnectionDelayMax",
+ value: function reconnectionDelayMax(v) {
+ var _a;
+
+ if (v === undefined) return this._reconnectionDelayMax;
+ this._reconnectionDelayMax = v;
+ (_a = this.backoff) === null || _a === void 0 ? void 0 : _a.setMax(v);
+ return this;
+ }
+ }, {
+ key: "timeout",
+ value: function timeout(v) {
+ if (!arguments.length) return this._timeout;
+ this._timeout = v;
+ return this;
+ }
+ /**
+ * Starts trying to reconnect if reconnection is enabled and we have not
+ * started reconnecting yet
+ *
+ * @private
+ */
+
+ }, {
+ key: "maybeReconnectOnOpen",
+ value: function maybeReconnectOnOpen() {
+ // Only try to reconnect if it's the first time we're connecting
+ if (!this._reconnecting && this._reconnection && this.backoff.attempts === 0) {
+ // keeps reconnection from firing twice for the same reconnection loop
+ this.reconnect();
+ }
+ }
+ /**
+ * Sets the current transport `socket`.
+ *
+ * @param {Function} fn - optional, callback
+ * @return self
+ * @public
+ */
+
+ }, {
+ key: "open",
+ value: function open(fn) {
+ var _this2 = this;
+
+ if (~this._readyState.indexOf("open")) return this;
+ this.engine = new Socket$1(this.uri, this.opts);
+ var socket = this.engine;
+ var self = this;
+ this._readyState = "opening";
+ this.skipReconnect = false; // emit `open`
+
+ var openSubDestroy = on(socket, "open", function () {
+ self.onopen();
+ fn && fn();
+ }); // emit `error`
+
+ var errorSub = on(socket, "error", function (err) {
+ self.cleanup();
+ self._readyState = "closed";
+
+ _this2.emitReserved("error", err);
+
+ if (fn) {
+ fn(err);
+ } else {
+ // Only do this if there is no fn to handle the error
+ self.maybeReconnectOnOpen();
+ }
+ });
+
+ if (false !== this._timeout) {
+ var timeout = this._timeout;
+
+ if (timeout === 0) {
+ openSubDestroy(); // prevents a race condition with the 'open' event
+ } // set timer
+
+
+ var timer = this.setTimeoutFn(function () {
+ openSubDestroy();
+ socket.close(); // @ts-ignore
+
+ socket.emit("error", new Error("timeout"));
+ }, timeout);
+
+ if (this.opts.autoUnref) {
+ timer.unref();
+ }
+
+ this.subs.push(function subDestroy() {
+ clearTimeout(timer);
+ });
+ }
+
+ this.subs.push(openSubDestroy);
+ this.subs.push(errorSub);
+ return this;
+ }
+ /**
+ * Alias for open()
+ *
+ * @return self
+ * @public
+ */
+
+ }, {
+ key: "connect",
+ value: function connect(fn) {
+ return this.open(fn);
+ }
+ /**
+ * Called upon transport open.
+ *
+ * @private
+ */
+
+ }, {
+ key: "onopen",
+ value: function onopen() {
+ // clear old subs
+ this.cleanup(); // mark as open
+
+ this._readyState = "open";
+ this.emitReserved("open"); // add new subs
+
+ var socket = this.engine;
+ this.subs.push(on(socket, "ping", this.onping.bind(this)), on(socket, "data", this.ondata.bind(this)), on(socket, "error", this.onerror.bind(this)), on(socket, "close", this.onclose.bind(this)), on(this.decoder, "decoded", this.ondecoded.bind(this)));
+ }
+ /**
+ * Called upon a ping.
+ *
+ * @private
+ */
+
+ }, {
+ key: "onping",
+ value: function onping() {
+ this.emitReserved("ping");
+ }
+ /**
+ * Called with data.
+ *
+ * @private
+ */
+
+ }, {
+ key: "ondata",
+ value: function ondata(data) {
+ this.decoder.add(data);
+ }
+ /**
+ * Called when parser fully decodes a packet.
+ *
+ * @private
+ */
+
+ }, {
+ key: "ondecoded",
+ value: function ondecoded(packet) {
+ this.emitReserved("packet", packet);
+ }
+ /**
+ * Called upon socket error.
+ *
+ * @private
+ */
+
+ }, {
+ key: "onerror",
+ value: function onerror(err) {
+ this.emitReserved("error", err);
+ }
+ /**
+ * Creates a new socket for the given `nsp`.
+ *
+ * @return {Socket}
+ * @public
+ */
+
+ }, {
+ key: "socket",
+ value: function socket(nsp, opts) {
+ var socket = this.nsps[nsp];
+
+ if (!socket) {
+ socket = new Socket(this, nsp, opts);
+ this.nsps[nsp] = socket;
+ }
+
+ return socket;
+ }
+ /**
+ * Called upon a socket close.
+ *
+ * @param socket
+ * @private
+ */
+
+ }, {
+ key: "_destroy",
+ value: function _destroy(socket) {
+ var nsps = Object.keys(this.nsps);
+
+ for (var _i = 0, _nsps = nsps; _i < _nsps.length; _i++) {
+ var nsp = _nsps[_i];
+ var _socket = this.nsps[nsp];
+
+ if (_socket.active) {
+ return;
+ }
+ }
+
+ this._close();
+ }
+ /**
+ * Writes a packet.
+ *
+ * @param packet
+ * @private
+ */
+
+ }, {
+ key: "_packet",
+ value: function _packet(packet) {
+ var encodedPackets = this.encoder.encode(packet);
+
+ for (var i = 0; i < encodedPackets.length; i++) {
+ this.engine.write(encodedPackets[i], packet.options);
+ }
+ }
+ /**
+ * Clean up transport subscriptions and packet buffer.
+ *
+ * @private
+ */
+
+ }, {
+ key: "cleanup",
+ value: function cleanup() {
+ this.subs.forEach(function (subDestroy) {
+ return subDestroy();
+ });
+ this.subs.length = 0;
+ this.decoder.destroy();
+ }
+ /**
+ * Close the current socket.
+ *
+ * @private
+ */
+
+ }, {
+ key: "_close",
+ value: function _close() {
+ this.skipReconnect = true;
+ this._reconnecting = false;
+ this.onclose("forced close");
+ if (this.engine) this.engine.close();
+ }
+ /**
+ * Alias for close()
+ *
+ * @private
+ */
+
+ }, {
+ key: "disconnect",
+ value: function disconnect() {
+ return this._close();
+ }
+ /**
+ * Called upon engine close.
+ *
+ * @private
+ */
+
+ }, {
+ key: "onclose",
+ value: function onclose(reason, description) {
+ this.cleanup();
+ this.backoff.reset();
+ this._readyState = "closed";
+ this.emitReserved("close", reason, description);
+
+ if (this._reconnection && !this.skipReconnect) {
+ this.reconnect();
+ }
+ }
+ /**
+ * Attempt a reconnection.
+ *
+ * @private
+ */
+
+ }, {
+ key: "reconnect",
+ value: function reconnect() {
+ var _this3 = this;
+
+ if (this._reconnecting || this.skipReconnect) return this;
+ var self = this;
+
+ if (this.backoff.attempts >= this._reconnectionAttempts) {
+ this.backoff.reset();
+ this.emitReserved("reconnect_failed");
+ this._reconnecting = false;
+ } else {
+ var delay = this.backoff.duration();
+ this._reconnecting = true;
+ var timer = this.setTimeoutFn(function () {
+ if (self.skipReconnect) return;
+
+ _this3.emitReserved("reconnect_attempt", self.backoff.attempts); // check again for the case socket closed in above events
+
+
+ if (self.skipReconnect) return;
+ self.open(function (err) {
+ if (err) {
+ self._reconnecting = false;
+ self.reconnect();
+
+ _this3.emitReserved("reconnect_error", err);
+ } else {
+ self.onreconnect();
+ }
+ });
+ }, delay);
+
+ if (this.opts.autoUnref) {
+ timer.unref();
+ }
+
+ this.subs.push(function subDestroy() {
+ clearTimeout(timer);
+ });
+ }
+ }
+ /**
+ * Called upon successful reconnect.
+ *
+ * @private
+ */
+
+ }, {
+ key: "onreconnect",
+ value: function onreconnect() {
+ var attempt = this.backoff.attempts;
+ this._reconnecting = false;
+ this.backoff.reset();
+ this.emitReserved("reconnect", attempt);
+ }
+ }]);
+
+ return Manager;
+ }(Emitter);
+
+ /**
+ * Managers cache.
+ */
+
+ var cache = {};
+
+ function lookup(uri, opts) {
+ if (_typeof(uri) === "object") {
+ opts = uri;
+ uri = undefined;
+ }
+
+ opts = opts || {};
+ var parsed = url(uri, opts.path || "/socket.io");
+ var source = parsed.source;
+ var id = parsed.id;
+ var path = parsed.path;
+ var sameNamespace = cache[id] && path in cache[id]["nsps"];
+ var newConnection = opts.forceNew || opts["force new connection"] || false === opts.multiplex || sameNamespace;
+ var io;
+
+ if (newConnection) {
+ io = new Manager(source, opts);
+ } else {
+ if (!cache[id]) {
+ cache[id] = new Manager(source, opts);
+ }
+
+ io = cache[id];
+ }
+
+ if (parsed.query && !opts.query) {
+ opts.query = parsed.queryKey;
+ }
+
+ return io.socket(parsed.path, opts);
+ } // so that "lookup" can be used both as a function (e.g. `io(...)`) and as a
+ // namespace (e.g. `io.connect(...)`), for backward compatibility
+
+
+ _extends(lookup, {
+ Manager: Manager,
+ Socket: Socket,
+ io: lookup,
+ connect: lookup
+ });
+
+ return lookup;
+
+ }));
+ //# sourceMappingURL=socket.io.js.map
\ No newline at end of file
diff --git a/static/js/xterm@3.6.0/addons/fit/fit.js b/static/js/xterm@3.6.0/addons/fit/fit.js
new file mode 100644
index 0000000..b137d99
--- /dev/null
+++ b/static/js/xterm@3.6.0/addons/fit/fit.js
@@ -0,0 +1,51 @@
+(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.fit = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;iterm)._core.viewport.scrollBarWidth;\n const geometry = {\n cols: Math.floor(availableWidth / (term)._core.renderer.dimensions.actualCellWidth),\n rows: Math.floor(availableHeight / (term)._core.renderer.dimensions.actualCellHeight)\n };\n return geometry;\n}\n\nexport function fit(term: Terminal): void {\n const geometry = proposeGeometry(term);\n if (geometry) {\n // Force a full render\n if (term.rows !== geometry.rows || term.cols !== geometry.cols) {\n (term)._core.renderer.clear();\n term.resize(geometry.cols, geometry.rows);\n }\n }\n}\n\nexport function apply(terminalConstructor: typeof Terminal): void {\n (terminalConstructor.prototype).proposeGeometry = function (): IGeometry {\n return proposeGeometry(this);\n };\n\n (terminalConstructor.prototype).fit = function (): void {\n fit(this);\n };\n}\n",null],"names":[],"mappings":"ACAA;;;ADsBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAvBA;AAyBA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AATA;AAWA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AARA;"}
\ No newline at end of file
diff --git a/static/js/xterm@3.6.0/addons/fullscreen/fullscreen.css b/static/js/xterm@3.6.0/addons/fullscreen/fullscreen.css
new file mode 100644
index 0000000..60e8c51
--- /dev/null
+++ b/static/js/xterm@3.6.0/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/static/js/xterm@3.6.0/addons/fullscreen/fullscreen.js b/static/js/xterm@3.6.0/addons/fullscreen/fullscreen.js
new file mode 100644
index 0000000..d12b72e
--- /dev/null
+++ b/static/js/xterm@3.6.0/addons/fullscreen/fullscreen.js
@@ -0,0 +1,27 @@
+(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.fullscreen = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;iterminalConstructor.prototype).toggleFullScreen = function (fullscreen: boolean): void {\n toggleFullScreen(this, fullscreen);\n };\n}\n",null],"names":[],"mappings":"ACAA;;;ADYA;AACA;AAEA;AACA;AACA;AAAA;AACA;AACA;AAAA;AACA;AACA;AAEA;AACA;AAZA;AAcA;AACA;AACA;AACA;AACA;AAJA;"}
\ No newline at end of file
diff --git a/static/js/xterm@3.6.0/xterm.js b/static/js/xterm@3.6.0/xterm.js
new file mode 100644
index 0000000..36ba827
--- /dev/null
+++ b/static/js/xterm@3.6.0/xterm.js
@@ -0,0 +1,8588 @@
+(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(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i rows) {
+ this._rowContainer.removeChild(this._rowElements.pop());
+ }
+ this._rowElements[this._rowElements.length - 1].addEventListener('focus', this._bottomBoundaryFocusListener);
+ this._refreshRowsDimensions();
+ };
+ AccessibilityManager.prototype._createAccessibilityTreeNode = function () {
+ var element = document.createElement('div');
+ element.setAttribute('role', 'listitem');
+ element.tabIndex = -1;
+ this._refreshRowDimensions(element);
+ return element;
+ };
+ AccessibilityManager.prototype._onTab = function (spaceCount) {
+ for (var i = 0; i < spaceCount; i++) {
+ this._onChar(' ');
+ }
+ };
+ AccessibilityManager.prototype._onChar = function (char) {
+ var _this = this;
+ if (this._liveRegionLineCount < MAX_ROWS_TO_READ + 1) {
+ if (this._charsToConsume.length > 0) {
+ var shiftedChar = this._charsToConsume.shift();
+ if (shiftedChar !== char) {
+ this._announceCharacter(char);
+ }
+ }
+ else {
+ this._announceCharacter(char);
+ }
+ if (char === '\n') {
+ this._liveRegionLineCount++;
+ if (this._liveRegionLineCount === MAX_ROWS_TO_READ + 1) {
+ this._liveRegion.textContent += Strings.tooMuchOutput;
+ }
+ }
+ if (Browser_1.isMac) {
+ if (this._liveRegion.textContent && this._liveRegion.textContent.length > 0 && !this._liveRegion.parentNode) {
+ setTimeout(function () {
+ _this._accessibilityTreeRoot.appendChild(_this._liveRegion);
+ }, 0);
+ }
+ }
+ }
+ };
+ AccessibilityManager.prototype._clearLiveRegion = function () {
+ this._liveRegion.textContent = '';
+ this._liveRegionLineCount = 0;
+ if (Browser_1.isMac) {
+ if (this._liveRegion.parentNode) {
+ this._accessibilityTreeRoot.removeChild(this._liveRegion);
+ }
+ }
+ };
+ AccessibilityManager.prototype._onKey = function (keyChar) {
+ this._clearLiveRegion();
+ this._charsToConsume.push(keyChar);
+ };
+ AccessibilityManager.prototype._refreshRows = function (start, end) {
+ this._renderRowsDebouncer.refresh(start, end);
+ };
+ AccessibilityManager.prototype._renderRows = function (start, end) {
+ var buffer = this._terminal.buffer;
+ var setSize = buffer.lines.length.toString();
+ for (var i = start; i <= end; i++) {
+ var lineData = buffer.translateBufferLineToString(buffer.ydisp + i, true);
+ var posInSet = (buffer.ydisp + i + 1).toString();
+ var element = this._rowElements[i];
+ element.textContent = lineData.length === 0 ? Strings.blankLine : lineData;
+ element.setAttribute('aria-posinset', posInSet);
+ element.setAttribute('aria-setsize', setSize);
+ }
+ };
+ AccessibilityManager.prototype._refreshRowsDimensions = function () {
+ if (!this._terminal.renderer.dimensions.actualCellHeight) {
+ return;
+ }
+ if (this._rowElements.length !== this._terminal.rows) {
+ this._onResize(this._terminal.rows);
+ }
+ for (var i = 0; i < this._terminal.rows; i++) {
+ this._refreshRowDimensions(this._rowElements[i]);
+ }
+ };
+ AccessibilityManager.prototype._refreshRowDimensions = function (element) {
+ element.style.height = this._terminal.renderer.dimensions.actualCellHeight + "px";
+ };
+ AccessibilityManager.prototype._announceCharacter = function (char) {
+ if (char === ' ') {
+ this._liveRegion.innerHTML += ' ';
+ }
+ else {
+ this._liveRegion.textContent += char;
+ }
+ };
+ return AccessibilityManager;
+}(Lifecycle_2.Disposable));
+exports.AccessibilityManager = AccessibilityManager;
+
+},{"./Strings":13,"./common/Lifecycle":17,"./shared/utils/Browser":45,"./ui/Lifecycle":47,"./ui/RenderDebouncer":49}],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 CircularList_1 = require("./common/CircularList");
+var EventEmitter_1 = require("./EventEmitter");
+exports.DEFAULT_ATTR = (0 << 18) | (257 << 9) | (256 << 0);
+exports.CHAR_DATA_ATTR_INDEX = 0;
+exports.CHAR_DATA_CHAR_INDEX = 1;
+exports.CHAR_DATA_WIDTH_INDEX = 2;
+exports.CHAR_DATA_CODE_INDEX = 3;
+exports.MAX_BUFFER_SIZE = 4294967295;
+exports.NULL_CELL_CHAR = ' ';
+exports.NULL_CELL_WIDTH = 1;
+exports.NULL_CELL_CODE = 32;
+var Buffer = (function () {
+ function Buffer(_terminal, _hasScrollback) {
+ this._terminal = _terminal;
+ this._hasScrollback = _hasScrollback;
+ this.markers = [];
+ this.clear();
+ }
+ Object.defineProperty(Buffer.prototype, "hasScrollback", {
+ get: function () {
+ return this._hasScrollback && this.lines.maxLength > 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 = [exports.DEFAULT_ATTR, exports.NULL_CELL_CHAR, exports.NULL_CELL_WIDTH, exports.NULL_CELL_CODE];
+ for (var i = 0; i < this.lines.length; i++) {
+ 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;
+ }
+ this.x = Math.min(this.x, newCols - 1);
+ this.y = Math.min(this.y, newRows - 1);
+ if (addToY) {
+ this.y += addToY;
+ }
+ this.savedY = Math.min(this.savedY, newRows - 1);
+ this.savedX = Math.min(this.savedX, 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;
+ if (endCol === null) {
+ 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.getWrappedRangeForLine = function (y) {
+ var first = y;
+ var last = y;
+ while (first > 0 && this.lines.get(first).isWrapped) {
+ first--;
+ }
+ while (last + 1 < this.lines.length && this.lines.get(last + 1).isWrapped) {
+ last++;
+ }
+ return { first: first, last: last };
+ };
+ 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;
+ };
+ Buffer.prototype.addMarker = function (y) {
+ var _this = this;
+ var marker = new Marker(y);
+ this.markers.push(marker);
+ marker.register(this.lines.addDisposableListener('trim', function (amount) {
+ marker.line -= amount;
+ if (marker.line < 0) {
+ marker.dispose();
+ }
+ }));
+ marker.register(marker.addDisposableListener('dispose', function () { return _this._removeMarker(marker); }));
+ return marker;
+ };
+ Buffer.prototype._removeMarker = function (marker) {
+ this.markers.splice(this.markers.indexOf(marker), 1);
+ };
+ return Buffer;
+}());
+exports.Buffer = Buffer;
+var Marker = (function (_super) {
+ __extends(Marker, _super);
+ function Marker(line) {
+ var _this = _super.call(this) || this;
+ _this.line = line;
+ _this._id = Marker._nextId++;
+ _this.isDisposed = false;
+ return _this;
+ }
+ Object.defineProperty(Marker.prototype, "id", {
+ get: function () { return this._id; },
+ enumerable: true,
+ configurable: true
+ });
+ Marker.prototype.dispose = function () {
+ if (this.isDisposed) {
+ return;
+ }
+ this.isDisposed = true;
+ this.emit('dispose');
+ _super.prototype.dispose.call(this);
+ };
+ Marker._nextId = 1;
+ return Marker;
+}(EventEmitter_1.EventEmitter));
+exports.Marker = Marker;
+
+},{"./EventEmitter":7,"./common/CircularList":16}],3:[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 () {
+ if (this._activeBuffer === this._normal) {
+ return;
+ }
+ this._alt.clear();
+ this._activeBuffer = this._normal;
+ this.emit('activate', {
+ activeBuffer: this._normal,
+ inactiveBuffer: this._alt
+ });
+ };
+ BufferSet.prototype.activateAltBuffer = function () {
+ if (this._activeBuffer === this._alt) {
+ return;
+ }
+ this._alt.fillViewportRows();
+ this._activeBuffer = this._alt;
+ this.emit('activate', {
+ activeBuffer: this._alt,
+ inactiveBuffer: this._normal
+ });
+ };
+ 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":2,"./EventEmitter":7}],4:[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 initTable() {
+ 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 || initTable();
+ if (num < 65536) {
+ return t[num >> 4] >> ((num & 15) << 1) & 3;
+ }
+ return wcwidthHigh(num);
+ };
+})({ nul: 0, control: 0 });
+
+},{}],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;
+ }
+ 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";
+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 Lifecycle_1 = require("./common/Lifecycle");
+function r(low, high) {
+ var c = high - low;
+ var arr = new Array(c);
+ while (c--) {
+ arr[c] = --high;
+ }
+ return arr;
+}
+var TransitionTable = (function () {
+ function TransitionTable(length) {
+ this.table = (typeof Uint8Array === 'undefined')
+ ? new Array(length)
+ : new Uint8Array(length);
+ }
+ TransitionTable.prototype.add = function (code, state, action, next) {
+ this.table[state << 8 | code] = ((action | 0) << 4) | ((next === undefined) ? state : next);
+ };
+ TransitionTable.prototype.addMany = function (codes, state, action, next) {
+ for (var i = 0; i < codes.length; i++) {
+ this.add(codes[i], state, action, next);
+ }
+ };
+ return TransitionTable;
+}());
+exports.TransitionTable = TransitionTable;
+var PRINTABLES = r(0x20, 0x7f);
+var EXECUTABLES = r(0x00, 0x18);
+EXECUTABLES.push(0x19);
+EXECUTABLES.concat(r(0x1c, 0x20));
+var DEFAULT_TRANSITION = 1 << 4 | 0;
+exports.VT500_TRANSITION_TABLE = (function () {
+ var table = new TransitionTable(4095);
+ var states = r(0, 13 + 1);
+ var state;
+ for (state in states) {
+ for (var code = 0; code < 160; ++code) {
+ table.add(code, state, 1, 0);
+ }
+ }
+ table.addMany(PRINTABLES, 0, 2, 0);
+ for (state in states) {
+ table.addMany([0x18, 0x1a, 0x99, 0x9a], state, 3, 0);
+ table.addMany(r(0x80, 0x90), state, 3, 0);
+ table.addMany(r(0x90, 0x98), state, 3, 0);
+ table.add(0x9c, state, 0, 0);
+ table.add(0x1b, state, 11, 1);
+ table.add(0x9d, state, 4, 8);
+ table.addMany([0x98, 0x9e, 0x9f], state, 0, 7);
+ table.add(0x9b, state, 11, 3);
+ table.add(0x90, state, 11, 9);
+ }
+ table.addMany(EXECUTABLES, 0, 3, 0);
+ table.addMany(EXECUTABLES, 1, 3, 1);
+ table.add(0x7f, 1, 0, 1);
+ table.addMany(EXECUTABLES, 8, 0, 8);
+ table.addMany(EXECUTABLES, 3, 3, 3);
+ table.add(0x7f, 3, 0, 3);
+ table.addMany(EXECUTABLES, 4, 3, 4);
+ table.add(0x7f, 4, 0, 4);
+ table.addMany(EXECUTABLES, 6, 3, 6);
+ table.addMany(EXECUTABLES, 5, 3, 5);
+ table.add(0x7f, 5, 0, 5);
+ table.addMany(EXECUTABLES, 2, 3, 2);
+ table.add(0x7f, 2, 0, 2);
+ table.add(0x5d, 1, 4, 8);
+ table.addMany(PRINTABLES, 8, 5, 8);
+ table.add(0x7f, 8, 5, 8);
+ table.addMany([0x9c, 0x1b, 0x18, 0x1a, 0x07], 8, 6, 0);
+ table.addMany(r(0x1c, 0x20), 8, 0, 8);
+ table.addMany([0x58, 0x5e, 0x5f], 1, 0, 7);
+ table.addMany(PRINTABLES, 7, 0, 7);
+ table.addMany(EXECUTABLES, 7, 0, 7);
+ table.add(0x9c, 7, 0, 0);
+ table.add(0x5b, 1, 11, 3);
+ table.addMany(r(0x40, 0x7f), 3, 7, 0);
+ table.addMany(r(0x30, 0x3a), 3, 8, 4);
+ table.add(0x3b, 3, 8, 4);
+ table.addMany([0x3c, 0x3d, 0x3e, 0x3f], 3, 9, 4);
+ table.addMany(r(0x30, 0x3a), 4, 8, 4);
+ table.add(0x3b, 4, 8, 4);
+ table.addMany(r(0x40, 0x7f), 4, 7, 0);
+ table.addMany([0x3a, 0x3c, 0x3d, 0x3e, 0x3f], 4, 0, 6);
+ table.addMany(r(0x20, 0x40), 6, 0, 6);
+ table.add(0x7f, 6, 0, 6);
+ table.addMany(r(0x40, 0x7f), 6, 0, 0);
+ table.add(0x3a, 3, 0, 6);
+ table.addMany(r(0x20, 0x30), 3, 9, 5);
+ table.addMany(r(0x20, 0x30), 5, 9, 5);
+ table.addMany(r(0x30, 0x40), 5, 0, 6);
+ table.addMany(r(0x40, 0x7f), 5, 7, 0);
+ table.addMany(r(0x20, 0x30), 4, 9, 5);
+ table.addMany(r(0x20, 0x30), 1, 9, 2);
+ table.addMany(r(0x20, 0x30), 2, 9, 2);
+ table.addMany(r(0x30, 0x7f), 2, 10, 0);
+ table.addMany(r(0x30, 0x50), 1, 10, 0);
+ table.addMany(r(0x51, 0x58), 1, 10, 0);
+ table.addMany([0x59, 0x5a, 0x5c], 1, 10, 0);
+ table.addMany(r(0x60, 0x7f), 1, 10, 0);
+ table.add(0x50, 1, 11, 9);
+ table.addMany(EXECUTABLES, 9, 0, 9);
+ table.add(0x7f, 9, 0, 9);
+ table.addMany(r(0x1c, 0x20), 9, 0, 9);
+ table.addMany(r(0x20, 0x30), 9, 9, 12);
+ table.add(0x3a, 9, 0, 11);
+ table.addMany(r(0x30, 0x3a), 9, 8, 10);
+ table.add(0x3b, 9, 8, 10);
+ table.addMany([0x3c, 0x3d, 0x3e, 0x3f], 9, 9, 10);
+ table.addMany(EXECUTABLES, 11, 0, 11);
+ table.addMany(r(0x20, 0x80), 11, 0, 11);
+ table.addMany(r(0x1c, 0x20), 11, 0, 11);
+ table.addMany(EXECUTABLES, 10, 0, 10);
+ table.add(0x7f, 10, 0, 10);
+ table.addMany(r(0x1c, 0x20), 10, 0, 10);
+ table.addMany(r(0x30, 0x3a), 10, 8, 10);
+ table.add(0x3b, 10, 8, 10);
+ table.addMany([0x3a, 0x3c, 0x3d, 0x3e, 0x3f], 10, 0, 11);
+ table.addMany(r(0x20, 0x30), 10, 9, 12);
+ table.addMany(EXECUTABLES, 12, 0, 12);
+ table.add(0x7f, 12, 0, 12);
+ table.addMany(r(0x1c, 0x20), 12, 0, 12);
+ table.addMany(r(0x20, 0x30), 12, 9, 12);
+ table.addMany(r(0x30, 0x40), 12, 0, 11);
+ table.addMany(r(0x40, 0x7f), 12, 12, 13);
+ table.addMany(r(0x40, 0x7f), 10, 12, 13);
+ table.addMany(r(0x40, 0x7f), 9, 12, 13);
+ table.addMany(EXECUTABLES, 13, 13, 13);
+ table.addMany(PRINTABLES, 13, 13, 13);
+ table.add(0x7f, 13, 0, 13);
+ table.addMany([0x1b, 0x9c], 13, 14, 0);
+ return table;
+})();
+var DcsDummy = (function () {
+ function DcsDummy() {
+ }
+ DcsDummy.prototype.hook = function (collect, params, flag) { };
+ DcsDummy.prototype.put = function (data, start, end) { };
+ DcsDummy.prototype.unhook = function () { };
+ return DcsDummy;
+}());
+var EscapeSequenceParser = (function (_super) {
+ __extends(EscapeSequenceParser, _super);
+ function EscapeSequenceParser(TRANSITIONS) {
+ if (TRANSITIONS === void 0) { TRANSITIONS = exports.VT500_TRANSITION_TABLE; }
+ var _this = _super.call(this) || this;
+ _this.TRANSITIONS = TRANSITIONS;
+ _this.initialState = 0;
+ _this.currentState = _this.initialState;
+ _this._osc = '';
+ _this._params = [0];
+ _this._collect = '';
+ _this._printHandlerFb = function (data, start, end) { };
+ _this._executeHandlerFb = function (code) { };
+ _this._csiHandlerFb = function (collect, params, flag) { };
+ _this._escHandlerFb = function (collect, flag) { };
+ _this._oscHandlerFb = function (identifier, data) { };
+ _this._dcsHandlerFb = new DcsDummy();
+ _this._errorHandlerFb = function (state) { return state; };
+ _this._printHandler = _this._printHandlerFb;
+ _this._executeHandlers = Object.create(null);
+ _this._csiHandlers = Object.create(null);
+ _this._escHandlers = Object.create(null);
+ _this._oscHandlers = Object.create(null);
+ _this._dcsHandlers = Object.create(null);
+ _this._activeDcsHandler = null;
+ _this._errorHandler = _this._errorHandlerFb;
+ return _this;
+ }
+ EscapeSequenceParser.prototype.dispose = function () {
+ this._printHandlerFb = null;
+ this._executeHandlerFb = null;
+ this._csiHandlerFb = null;
+ this._escHandlerFb = null;
+ this._oscHandlerFb = null;
+ this._dcsHandlerFb = null;
+ this._errorHandlerFb = null;
+ this._printHandler = null;
+ this._executeHandlers = null;
+ this._csiHandlers = null;
+ this._escHandlers = null;
+ this._oscHandlers = null;
+ this._dcsHandlers = null;
+ this._activeDcsHandler = null;
+ this._errorHandler = null;
+ };
+ EscapeSequenceParser.prototype.setPrintHandler = function (callback) {
+ this._printHandler = callback;
+ };
+ EscapeSequenceParser.prototype.clearPrintHandler = function () {
+ this._printHandler = this._printHandlerFb;
+ };
+ EscapeSequenceParser.prototype.setExecuteHandler = function (flag, callback) {
+ this._executeHandlers[flag.charCodeAt(0)] = callback;
+ };
+ EscapeSequenceParser.prototype.clearExecuteHandler = function (flag) {
+ if (this._executeHandlers[flag.charCodeAt(0)])
+ delete this._executeHandlers[flag.charCodeAt(0)];
+ };
+ EscapeSequenceParser.prototype.setExecuteHandlerFallback = function (callback) {
+ this._executeHandlerFb = callback;
+ };
+ EscapeSequenceParser.prototype.setCsiHandler = function (flag, callback) {
+ this._csiHandlers[flag.charCodeAt(0)] = callback;
+ };
+ EscapeSequenceParser.prototype.clearCsiHandler = function (flag) {
+ if (this._csiHandlers[flag.charCodeAt(0)])
+ delete this._csiHandlers[flag.charCodeAt(0)];
+ };
+ EscapeSequenceParser.prototype.setCsiHandlerFallback = function (callback) {
+ this._csiHandlerFb = callback;
+ };
+ EscapeSequenceParser.prototype.setEscHandler = function (collectAndFlag, callback) {
+ this._escHandlers[collectAndFlag] = callback;
+ };
+ EscapeSequenceParser.prototype.clearEscHandler = function (collectAndFlag) {
+ if (this._escHandlers[collectAndFlag])
+ delete this._escHandlers[collectAndFlag];
+ };
+ EscapeSequenceParser.prototype.setEscHandlerFallback = function (callback) {
+ this._escHandlerFb = callback;
+ };
+ EscapeSequenceParser.prototype.setOscHandler = function (ident, callback) {
+ this._oscHandlers[ident] = callback;
+ };
+ EscapeSequenceParser.prototype.clearOscHandler = function (ident) {
+ if (this._oscHandlers[ident])
+ delete this._oscHandlers[ident];
+ };
+ EscapeSequenceParser.prototype.setOscHandlerFallback = function (callback) {
+ this._oscHandlerFb = callback;
+ };
+ EscapeSequenceParser.prototype.setDcsHandler = function (collectAndFlag, handler) {
+ this._dcsHandlers[collectAndFlag] = handler;
+ };
+ EscapeSequenceParser.prototype.clearDcsHandler = function (collectAndFlag) {
+ if (this._dcsHandlers[collectAndFlag])
+ delete this._dcsHandlers[collectAndFlag];
+ };
+ EscapeSequenceParser.prototype.setDcsHandlerFallback = function (handler) {
+ this._dcsHandlerFb = handler;
+ };
+ EscapeSequenceParser.prototype.setErrorHandler = function (callback) {
+ this._errorHandler = callback;
+ };
+ EscapeSequenceParser.prototype.clearErrorHandler = function () {
+ this._errorHandler = this._errorHandlerFb;
+ };
+ EscapeSequenceParser.prototype.reset = function () {
+ this.currentState = this.initialState;
+ this._osc = '';
+ this._params = [0];
+ this._collect = '';
+ this._activeDcsHandler = null;
+ };
+ EscapeSequenceParser.prototype.parse = function (data) {
+ var code = 0;
+ var transition = 0;
+ var error = false;
+ var currentState = this.currentState;
+ var print = -1;
+ var dcs = -1;
+ var osc = this._osc;
+ var collect = this._collect;
+ var params = this._params;
+ var table = this.TRANSITIONS.table;
+ var dcsHandler = this._activeDcsHandler;
+ var callback = null;
+ var l = data.length;
+ for (var i = 0; i < l; ++i) {
+ code = data.charCodeAt(i);
+ if (currentState === 0 && code > 0x1f && code < 0x80) {
+ print = (~print) ? print : i;
+ do
+ i++;
+ while (i < l && data.charCodeAt(i) > 0x1f && data.charCodeAt(i) < 0x80);
+ i--;
+ continue;
+ }
+ if (currentState === 4 && (code > 0x2f && code < 0x39)) {
+ params[params.length - 1] = params[params.length - 1] * 10 + code - 48;
+ continue;
+ }
+ transition = (code < 0xa0) ? (table[currentState << 8 | code]) : DEFAULT_TRANSITION;
+ switch (transition >> 4) {
+ case 2:
+ print = (~print) ? print : i;
+ break;
+ case 3:
+ if (~print) {
+ this._printHandler(data, print, i);
+ print = -1;
+ }
+ callback = this._executeHandlers[code];
+ if (callback)
+ callback();
+ else
+ this._executeHandlerFb(code);
+ break;
+ case 0:
+ if (~print) {
+ this._printHandler(data, print, i);
+ print = -1;
+ }
+ else if (~dcs) {
+ dcsHandler.put(data, dcs, i);
+ dcs = -1;
+ }
+ break;
+ case 1:
+ if (code > 0x9f) {
+ switch (currentState) {
+ case 0:
+ print = (~print) ? print : i;
+ break;
+ case 8:
+ osc += String.fromCharCode(code);
+ transition |= 8;
+ break;
+ case 6:
+ transition |= 6;
+ break;
+ case 11:
+ transition |= 11;
+ break;
+ case 13:
+ dcs = (~dcs) ? dcs : i;
+ transition |= 13;
+ break;
+ default:
+ error = true;
+ }
+ }
+ else {
+ error = true;
+ }
+ if (error) {
+ var inject = this._errorHandler({
+ position: i,
+ code: code,
+ currentState: currentState,
+ print: print,
+ dcs: dcs,
+ osc: osc,
+ collect: collect,
+ params: params,
+ abort: false
+ });
+ if (inject.abort)
+ return;
+ error = false;
+ }
+ break;
+ case 7:
+ callback = this._csiHandlers[code];
+ if (callback)
+ callback(params, collect);
+ else
+ this._csiHandlerFb(collect, params, code);
+ break;
+ case 8:
+ if (code === 0x3b)
+ params.push(0);
+ else
+ params[params.length - 1] = params[params.length - 1] * 10 + code - 48;
+ break;
+ case 9:
+ collect += String.fromCharCode(code);
+ break;
+ case 10:
+ callback = this._escHandlers[collect + String.fromCharCode(code)];
+ if (callback)
+ callback(collect, code);
+ else
+ this._escHandlerFb(collect, code);
+ break;
+ case 11:
+ if (~print) {
+ this._printHandler(data, print, i);
+ print = -1;
+ }
+ osc = '';
+ params = [0];
+ collect = '';
+ dcs = -1;
+ break;
+ case 12:
+ dcsHandler = this._dcsHandlers[collect + String.fromCharCode(code)];
+ if (!dcsHandler)
+ dcsHandler = this._dcsHandlerFb;
+ dcsHandler.hook(collect, params, code);
+ break;
+ case 13:
+ dcs = (~dcs) ? dcs : i;
+ break;
+ case 14:
+ if (dcsHandler) {
+ if (~dcs)
+ dcsHandler.put(data, dcs, i);
+ dcsHandler.unhook();
+ dcsHandler = null;
+ }
+ if (code === 0x1b)
+ transition |= 1;
+ osc = '';
+ params = [0];
+ collect = '';
+ dcs = -1;
+ break;
+ case 4:
+ if (~print) {
+ this._printHandler(data, print, i);
+ print = -1;
+ }
+ osc = '';
+ break;
+ case 5:
+ osc += data.charAt(i);
+ break;
+ case 6:
+ if (osc && code !== 0x18 && code !== 0x1a) {
+ var idx = osc.indexOf(';');
+ if (idx === -1) {
+ this._oscHandlerFb(-1, osc);
+ }
+ else {
+ var identifier = parseInt(osc.substring(0, idx));
+ var content = osc.substring(idx + 1);
+ callback = this._oscHandlers[identifier];
+ if (callback)
+ callback(content);
+ else
+ this._oscHandlerFb(identifier, content);
+ }
+ }
+ if (code === 0x1b)
+ transition |= 1;
+ osc = '';
+ params = [0];
+ collect = '';
+ dcs = -1;
+ break;
+ }
+ currentState = transition & 15;
+ }
+ if (currentState === 0 && ~print) {
+ this._printHandler(data, print, data.length);
+ }
+ else if (currentState === 13 && ~dcs && dcsHandler) {
+ dcsHandler.put(data, dcs, data.length);
+ }
+ this._osc = osc;
+ this._collect = collect;
+ this._params = params;
+ this._activeDcsHandler = dcsHandler;
+ this.currentState = currentState;
+ };
+ return EscapeSequenceParser;
+}(Lifecycle_1.Disposable));
+exports.EscapeSequenceParser = EscapeSequenceParser;
+
+},{"./common/Lifecycle":17}],7:[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 Lifecycle_1 = require("./common/Lifecycle");
+var EventEmitter = (function (_super) {
+ __extends(EventEmitter, _super);
+ function EventEmitter() {
+ var _this = _super.call(this) || this;
+ _this._events = _this._events || {};
+ return _this;
+ }
+ EventEmitter.prototype.on = function (type, listener) {
+ this._events[type] = this._events[type] || [];
+ this._events[type].push(listener);
+ };
+ EventEmitter.prototype.addDisposableListener = function (type, handler) {
+ var _this = this;
+ this.on(type, handler);
+ return {
+ dispose: function () {
+ if (!handler) {
+ return;
+ }
+ _this.off(type, handler);
+ handler = null;
+ }
+ };
+ };
+ 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.splice(i, 1);
+ return;
+ }
+ }
+ };
+ EventEmitter.prototype.removeAllListeners = function (type) {
+ if (this._events[type]) {
+ delete this._events[type];
+ }
+ };
+ 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.dispose = function () {
+ _super.prototype.dispose.call(this);
+ this._events = {};
+ };
+ return EventEmitter;
+}(Lifecycle_1.Disposable));
+exports.EventEmitter = EventEmitter;
+
+},{"./common/Lifecycle":17}],8:[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 EscapeSequences_1 = require("./common/data/EscapeSequences");
+var Charsets_1 = require("./core/data/Charsets");
+var Buffer_1 = require("./Buffer");
+var CharWidth_1 = require("./CharWidth");
+var EscapeSequenceParser_1 = require("./EscapeSequenceParser");
+var Lifecycle_1 = require("./common/Lifecycle");
+var GLEVEL = { '(': 0, ')': 1, '*': 2, '+': 3, '-': 1, '.': 2 };
+var RequestTerminfo = (function () {
+ function RequestTerminfo(_terminal) {
+ this._terminal = _terminal;
+ }
+ RequestTerminfo.prototype.hook = function (collect, params, flag) {
+ this._data = '';
+ };
+ RequestTerminfo.prototype.put = function (data, start, end) {
+ this._data += data.substring(start, end);
+ };
+ RequestTerminfo.prototype.unhook = function () {
+ this._terminal.handler(EscapeSequences_1.C0.ESC + "P0+r" + this._data + EscapeSequences_1.C0.ESC + "\\");
+ };
+ return RequestTerminfo;
+}());
+var DECRQSS = (function () {
+ function DECRQSS(_terminal) {
+ this._terminal = _terminal;
+ }
+ DECRQSS.prototype.hook = function (collect, params, flag) {
+ this._data = '';
+ };
+ DECRQSS.prototype.put = function (data, start, end) {
+ this._data += data.substring(start, end);
+ };
+ DECRQSS.prototype.unhook = function () {
+ switch (this._data) {
+ case '"q':
+ return this._terminal.handler(EscapeSequences_1.C0.ESC + "P1$r0\"q" + EscapeSequences_1.C0.ESC + "\\");
+ case '"p':
+ return this._terminal.handler(EscapeSequences_1.C0.ESC + "P1$r61\"p" + EscapeSequences_1.C0.ESC + "\\");
+ case 'r':
+ var pt = '' + (this._terminal.buffer.scrollTop + 1) +
+ ';' + (this._terminal.buffer.scrollBottom + 1) + 'r';
+ return this._terminal.handler(EscapeSequences_1.C0.ESC + "P1$r" + pt + EscapeSequences_1.C0.ESC + "\\");
+ case 'm':
+ return this._terminal.handler(EscapeSequences_1.C0.ESC + "P1$r0m" + EscapeSequences_1.C0.ESC + "\\");
+ case ' q':
+ var STYLES = { 'block': 2, 'underline': 4, 'bar': 6 };
+ var style = STYLES[this._terminal.getOption('cursorStyle')];
+ style -= this._terminal.getOption('cursorBlink');
+ return this._terminal.handler(EscapeSequences_1.C0.ESC + "P1$r" + style + " q" + EscapeSequences_1.C0.ESC + "\\");
+ default:
+ this._terminal.error('Unknown DCS $q %s', this._data);
+ this._terminal.handler(EscapeSequences_1.C0.ESC + "P0$r" + this._data + EscapeSequences_1.C0.ESC + "\\");
+ }
+ };
+ return DECRQSS;
+}());
+var InputHandler = (function (_super) {
+ __extends(InputHandler, _super);
+ function InputHandler(_terminal, _parser) {
+ if (_parser === void 0) { _parser = new EscapeSequenceParser_1.EscapeSequenceParser(); }
+ var _this = _super.call(this) || this;
+ _this._terminal = _terminal;
+ _this._parser = _parser;
+ _this.register(_this._parser);
+ _this._surrogateHigh = '';
+ _this._parser.setCsiHandlerFallback(function (collect, params, flag) {
+ _this._terminal.error('Unknown CSI code: ', { collect: collect, params: params, flag: String.fromCharCode(flag) });
+ });
+ _this._parser.setEscHandlerFallback(function (collect, flag) {
+ _this._terminal.error('Unknown ESC code: ', { collect: collect, flag: String.fromCharCode(flag) });
+ });
+ _this._parser.setExecuteHandlerFallback(function (code) {
+ _this._terminal.error('Unknown EXECUTE code: ', { code: code });
+ });
+ _this._parser.setOscHandlerFallback(function (identifier, data) {
+ _this._terminal.error('Unknown OSC code: ', { identifier: identifier, data: data });
+ });
+ _this._parser.setPrintHandler(function (data, start, end) { return _this.print(data, start, end); });
+ _this._parser.setCsiHandler('@', function (params, collect) { return _this.insertChars(params); });
+ _this._parser.setCsiHandler('A', function (params, collect) { return _this.cursorUp(params); });
+ _this._parser.setCsiHandler('B', function (params, collect) { return _this.cursorDown(params); });
+ _this._parser.setCsiHandler('C', function (params, collect) { return _this.cursorForward(params); });
+ _this._parser.setCsiHandler('D', function (params, collect) { return _this.cursorBackward(params); });
+ _this._parser.setCsiHandler('E', function (params, collect) { return _this.cursorNextLine(params); });
+ _this._parser.setCsiHandler('F', function (params, collect) { return _this.cursorPrecedingLine(params); });
+ _this._parser.setCsiHandler('G', function (params, collect) { return _this.cursorCharAbsolute(params); });
+ _this._parser.setCsiHandler('H', function (params, collect) { return _this.cursorPosition(params); });
+ _this._parser.setCsiHandler('I', function (params, collect) { return _this.cursorForwardTab(params); });
+ _this._parser.setCsiHandler('J', function (params, collect) { return _this.eraseInDisplay(params); });
+ _this._parser.setCsiHandler('K', function (params, collect) { return _this.eraseInLine(params); });
+ _this._parser.setCsiHandler('L', function (params, collect) { return _this.insertLines(params); });
+ _this._parser.setCsiHandler('M', function (params, collect) { return _this.deleteLines(params); });
+ _this._parser.setCsiHandler('P', function (params, collect) { return _this.deleteChars(params); });
+ _this._parser.setCsiHandler('S', function (params, collect) { return _this.scrollUp(params); });
+ _this._parser.setCsiHandler('T', function (params, collect) { return _this.scrollDown(params, collect); });
+ _this._parser.setCsiHandler('X', function (params, collect) { return _this.eraseChars(params); });
+ _this._parser.setCsiHandler('Z', function (params, collect) { return _this.cursorBackwardTab(params); });
+ _this._parser.setCsiHandler('`', function (params, collect) { return _this.charPosAbsolute(params); });
+ _this._parser.setCsiHandler('a', function (params, collect) { return _this.hPositionRelative(params); });
+ _this._parser.setCsiHandler('b', function (params, collect) { return _this.repeatPrecedingCharacter(params); });
+ _this._parser.setCsiHandler('c', function (params, collect) { return _this.sendDeviceAttributes(params, collect); });
+ _this._parser.setCsiHandler('d', function (params, collect) { return _this.linePosAbsolute(params); });
+ _this._parser.setCsiHandler('e', function (params, collect) { return _this.vPositionRelative(params); });
+ _this._parser.setCsiHandler('f', function (params, collect) { return _this.hVPosition(params); });
+ _this._parser.setCsiHandler('g', function (params, collect) { return _this.tabClear(params); });
+ _this._parser.setCsiHandler('h', function (params, collect) { return _this.setMode(params, collect); });
+ _this._parser.setCsiHandler('l', function (params, collect) { return _this.resetMode(params, collect); });
+ _this._parser.setCsiHandler('m', function (params, collect) { return _this.charAttributes(params); });
+ _this._parser.setCsiHandler('n', function (params, collect) { return _this.deviceStatus(params, collect); });
+ _this._parser.setCsiHandler('p', function (params, collect) { return _this.softReset(params, collect); });
+ _this._parser.setCsiHandler('q', function (params, collect) { return _this.setCursorStyle(params, collect); });
+ _this._parser.setCsiHandler('r', function (params, collect) { return _this.setScrollRegion(params, collect); });
+ _this._parser.setCsiHandler('s', function (params, collect) { return _this.saveCursor(params); });
+ _this._parser.setCsiHandler('u', function (params, collect) { return _this.restoreCursor(params); });
+ _this._parser.setExecuteHandler(EscapeSequences_1.C0.BEL, function () { return _this.bell(); });
+ _this._parser.setExecuteHandler(EscapeSequences_1.C0.LF, function () { return _this.lineFeed(); });
+ _this._parser.setExecuteHandler(EscapeSequences_1.C0.VT, function () { return _this.lineFeed(); });
+ _this._parser.setExecuteHandler(EscapeSequences_1.C0.FF, function () { return _this.lineFeed(); });
+ _this._parser.setExecuteHandler(EscapeSequences_1.C0.CR, function () { return _this.carriageReturn(); });
+ _this._parser.setExecuteHandler(EscapeSequences_1.C0.BS, function () { return _this.backspace(); });
+ _this._parser.setExecuteHandler(EscapeSequences_1.C0.HT, function () { return _this.tab(); });
+ _this._parser.setExecuteHandler(EscapeSequences_1.C0.SO, function () { return _this.shiftOut(); });
+ _this._parser.setExecuteHandler(EscapeSequences_1.C0.SI, function () { return _this.shiftIn(); });
+ _this._parser.setExecuteHandler(EscapeSequences_1.C1.IND, function () { return _this.index(); });
+ _this._parser.setExecuteHandler(EscapeSequences_1.C1.NEL, function () { return _this.nextLine(); });
+ _this._parser.setExecuteHandler(EscapeSequences_1.C1.HTS, function () { return _this.tabSet(); });
+ _this._parser.setOscHandler(0, function (data) { return _this.setTitle(data); });
+ _this._parser.setOscHandler(2, function (data) { return _this.setTitle(data); });
+ _this._parser.setEscHandler('7', function () { return _this.saveCursor([]); });
+ _this._parser.setEscHandler('8', function () { return _this.restoreCursor([]); });
+ _this._parser.setEscHandler('D', function () { return _this.index(); });
+ _this._parser.setEscHandler('E', function () { return _this.nextLine(); });
+ _this._parser.setEscHandler('H', function () { return _this.tabSet(); });
+ _this._parser.setEscHandler('M', function () { return _this.reverseIndex(); });
+ _this._parser.setEscHandler('=', function () { return _this.keypadApplicationMode(); });
+ _this._parser.setEscHandler('>', function () { return _this.keypadNumericMode(); });
+ _this._parser.setEscHandler('c', function () { return _this.reset(); });
+ _this._parser.setEscHandler('n', function () { return _this.setgLevel(2); });
+ _this._parser.setEscHandler('o', function () { return _this.setgLevel(3); });
+ _this._parser.setEscHandler('|', function () { return _this.setgLevel(3); });
+ _this._parser.setEscHandler('}', function () { return _this.setgLevel(2); });
+ _this._parser.setEscHandler('~', function () { return _this.setgLevel(1); });
+ _this._parser.setEscHandler('%@', function () { return _this.selectDefaultCharset(); });
+ _this._parser.setEscHandler('%G', function () { return _this.selectDefaultCharset(); });
+ var _loop_1 = function (flag) {
+ this_1._parser.setEscHandler('(' + flag, function () { return _this.selectCharset('(' + flag); });
+ this_1._parser.setEscHandler(')' + flag, function () { return _this.selectCharset(')' + flag); });
+ this_1._parser.setEscHandler('*' + flag, function () { return _this.selectCharset('*' + flag); });
+ this_1._parser.setEscHandler('+' + flag, function () { return _this.selectCharset('+' + flag); });
+ this_1._parser.setEscHandler('-' + flag, function () { return _this.selectCharset('-' + flag); });
+ this_1._parser.setEscHandler('.' + flag, function () { return _this.selectCharset('.' + flag); });
+ this_1._parser.setEscHandler('/' + flag, function () { return _this.selectCharset('/' + flag); });
+ };
+ var this_1 = this;
+ for (var flag in Charsets_1.CHARSETS) {
+ _loop_1(flag);
+ }
+ _this._parser.setErrorHandler(function (state) {
+ _this._terminal.error('Parsing error: ', state);
+ return state;
+ });
+ _this._parser.setDcsHandler('$q', new DECRQSS(_this._terminal));
+ _this._parser.setDcsHandler('+q', new RequestTerminfo(_this._terminal));
+ return _this;
+ }
+ InputHandler.prototype.dispose = function () {
+ _super.prototype.dispose.call(this);
+ this._terminal = null;
+ };
+ InputHandler.prototype.parse = function (data) {
+ if (!this._terminal) {
+ return;
+ }
+ var buffer = this._terminal.buffer;
+ var cursorStartX = buffer.x;
+ var cursorStartY = buffer.y;
+ if (this._terminal.debug) {
+ this._terminal.log('data: ' + data);
+ }
+ if (this._surrogateHigh) {
+ data = this._surrogateHigh + data;
+ this._surrogateHigh = '';
+ }
+ this._parser.parse(data);
+ buffer = this._terminal.buffer;
+ if (buffer.x !== cursorStartX || buffer.y !== cursorStartY) {
+ this._terminal.emit('cursormove');
+ }
+ };
+ InputHandler.prototype.print = function (data, start, end) {
+ var char;
+ var code;
+ var low;
+ var chWidth;
+ var buffer = this._terminal.buffer;
+ var charset = this._terminal.charset;
+ var screenReaderMode = this._terminal.options.screenReaderMode;
+ var cols = this._terminal.cols;
+ var wraparoundMode = this._terminal.wraparoundMode;
+ var insertMode = this._terminal.insertMode;
+ var curAttr = this._terminal.curAttr;
+ var bufferRow = buffer.lines.get(buffer.y + buffer.ybase);
+ this._terminal.updateRange(buffer.y);
+ for (var stringPosition = start; stringPosition < end; ++stringPosition) {
+ char = data.charAt(stringPosition);
+ code = data.charCodeAt(stringPosition);
+ if (0xD800 <= code && code <= 0xDBFF) {
+ low = data.charCodeAt(stringPosition + 1);
+ if (isNaN(low)) {
+ this._surrogateHigh = char;
+ continue;
+ }
+ code = ((code - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
+ char += data.charAt(stringPosition + 1);
+ }
+ if (0xDC00 <= code && code <= 0xDFFF) {
+ continue;
+ }
+ chWidth = CharWidth_1.wcwidth(code);
+ if (charset) {
+ char = charset[char] || char;
+ code = char.charCodeAt(0);
+ }
+ if (screenReaderMode) {
+ this._terminal.emit('a11y.char', char);
+ }
+ if (!chWidth && buffer.x) {
+ if (bufferRow[buffer.x - 1]) {
+ if (!bufferRow[buffer.x - 1][Buffer_1.CHAR_DATA_WIDTH_INDEX]) {
+ if (bufferRow[buffer.x - 2]) {
+ bufferRow[buffer.x - 2][Buffer_1.CHAR_DATA_CHAR_INDEX] += char;
+ bufferRow[buffer.x - 2][Buffer_1.CHAR_DATA_CODE_INDEX] = code;
+ }
+ }
+ else {
+ bufferRow[buffer.x - 1][Buffer_1.CHAR_DATA_CHAR_INDEX] += char;
+ bufferRow[buffer.x - 1][Buffer_1.CHAR_DATA_CODE_INDEX] = code;
+ }
+ }
+ continue;
+ }
+ if (buffer.x + chWidth - 1 >= cols) {
+ if (wraparoundMode) {
+ buffer.x = 0;
+ buffer.y++;
+ if (buffer.y > buffer.scrollBottom) {
+ buffer.y--;
+ this._terminal.scroll(true);
+ }
+ else {
+ buffer.lines.get(buffer.y).isWrapped = true;
+ }
+ bufferRow = buffer.lines.get(buffer.y + buffer.ybase);
+ }
+ else {
+ if (chWidth === 2) {
+ continue;
+ }
+ }
+ }
+ if (insertMode) {
+ for (var moves = 0; moves < chWidth; ++moves) {
+ var removed = bufferRow.pop();
+ if (removed[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0
+ && bufferRow[this._terminal.cols - 2]
+ && bufferRow[this._terminal.cols - 2][Buffer_1.CHAR_DATA_WIDTH_INDEX] === 2) {
+ bufferRow[this._terminal.cols - 2] = [curAttr, Buffer_1.NULL_CELL_CHAR, Buffer_1.NULL_CELL_WIDTH, Buffer_1.NULL_CELL_CODE];
+ }
+ bufferRow.splice(buffer.x, 0, [curAttr, Buffer_1.NULL_CELL_CHAR, Buffer_1.NULL_CELL_WIDTH, Buffer_1.NULL_CELL_CODE]);
+ }
+ }
+ bufferRow[buffer.x++] = [curAttr, char, chWidth, code];
+ if (chWidth === 2) {
+ bufferRow[buffer.x++] = [curAttr, '', 0, undefined];
+ }
+ }
+ this._terminal.updateRange(buffer.y);
+ };
+ InputHandler.prototype.bell = function () {
+ this._terminal.bell();
+ };
+ InputHandler.prototype.lineFeed = function () {
+ var buffer = this._terminal.buffer;
+ if (this._terminal.convertEol) {
+ buffer.x = 0;
+ }
+ buffer.y++;
+ if (buffer.y > buffer.scrollBottom) {
+ buffer.y--;
+ this._terminal.scroll();
+ }
+ if (buffer.x >= this._terminal.cols) {
+ 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 () {
+ var originalX = this._terminal.buffer.x;
+ this._terminal.buffer.x = this._terminal.buffer.nextStop();
+ if (this._terminal.options.screenReaderMode) {
+ this._terminal.emit('a11y.tab', this._terminal.buffer.x - originalX);
+ }
+ };
+ 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 buffer = this._terminal.buffer;
+ var row = buffer.y + buffer.ybase;
+ var j = buffer.x;
+ var ch = [this._terminal.eraseAttr(), Buffer_1.NULL_CELL_CHAR, Buffer_1.NULL_CELL_WIDTH, Buffer_1.NULL_CELL_CODE];
+ while (param-- && j < this._terminal.cols) {
+ buffer.lines.get(row).splice(j++, 0, ch);
+ 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 buffer = this._terminal.buffer;
+ var row = buffer.y + buffer.ybase;
+ var scrollBottomRowsOffset = this._terminal.rows - 1 - buffer.scrollBottom;
+ var scrollBottomAbsolute = this._terminal.rows - 1 + buffer.ybase - scrollBottomRowsOffset + 1;
+ while (param--) {
+ buffer.lines.splice(scrollBottomAbsolute - 1, 1);
+ buffer.lines.splice(row, 0, this._terminal.blankLine(true));
+ }
+ this._terminal.updateRange(buffer.y);
+ this._terminal.updateRange(buffer.scrollBottom);
+ };
+ InputHandler.prototype.deleteLines = function (params) {
+ var param = params[0];
+ if (param < 1) {
+ param = 1;
+ }
+ var buffer = this._terminal.buffer;
+ var row = buffer.y + buffer.ybase;
+ var j;
+ j = this._terminal.rows - 1 - buffer.scrollBottom;
+ j = this._terminal.rows - 1 + buffer.ybase - j;
+ while (param--) {
+ buffer.lines.splice(row, 1);
+ buffer.lines.splice(j, 0, this._terminal.blankLine(true));
+ }
+ this._terminal.updateRange(buffer.y);
+ this._terminal.updateRange(buffer.scrollBottom);
+ };
+ InputHandler.prototype.deleteChars = function (params) {
+ var param = params[0];
+ if (param < 1) {
+ param = 1;
+ }
+ var buffer = this._terminal.buffer;
+ var row = buffer.y + buffer.ybase;
+ var ch = [this._terminal.eraseAttr(), Buffer_1.NULL_CELL_CHAR, Buffer_1.NULL_CELL_WIDTH, Buffer_1.NULL_CELL_CODE];
+ while (param--) {
+ buffer.lines.get(row).splice(buffer.x, 1);
+ buffer.lines.get(row).push(ch);
+ }
+ this._terminal.updateRange(buffer.y);
+ };
+ InputHandler.prototype.scrollUp = function (params) {
+ var param = params[0] || 1;
+ var buffer = this._terminal.buffer;
+ while (param--) {
+ buffer.lines.splice(buffer.ybase + buffer.scrollTop, 1);
+ buffer.lines.splice(buffer.ybase + buffer.scrollBottom, 0, this._terminal.blankLine());
+ }
+ this._terminal.updateRange(buffer.scrollTop);
+ this._terminal.updateRange(buffer.scrollBottom);
+ };
+ InputHandler.prototype.scrollDown = function (params, collect) {
+ if (params.length < 2 && !collect) {
+ var param = params[0] || 1;
+ var buffer = this._terminal.buffer;
+ while (param--) {
+ buffer.lines.splice(buffer.ybase + buffer.scrollBottom, 1);
+ buffer.lines.splice(buffer.ybase + buffer.scrollTop, 0, this._terminal.blankLine());
+ }
+ this._terminal.updateRange(buffer.scrollTop);
+ this._terminal.updateRange(buffer.scrollBottom);
+ }
+ };
+ InputHandler.prototype.eraseChars = function (params) {
+ var param = params[0];
+ if (param < 1) {
+ param = 1;
+ }
+ var buffer = this._terminal.buffer;
+ var row = buffer.y + buffer.ybase;
+ var j = buffer.x;
+ var ch = [this._terminal.eraseAttr(), Buffer_1.NULL_CELL_CHAR, Buffer_1.NULL_CELL_WIDTH, Buffer_1.NULL_CELL_CODE];
+ while (param-- && j < this._terminal.cols) {
+ buffer.lines.get(row)[j++] = ch;
+ }
+ };
+ InputHandler.prototype.cursorBackwardTab = function (params) {
+ var param = params[0] || 1;
+ var buffer = this._terminal.buffer;
+ while (param--) {
+ buffer.x = 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 buffer = this._terminal.buffer;
+ var line = buffer.lines.get(buffer.ybase + buffer.y);
+ var ch = line[buffer.x - 1] || [Buffer_1.DEFAULT_ATTR, Buffer_1.NULL_CELL_CHAR, Buffer_1.NULL_CELL_WIDTH, Buffer_1.NULL_CELL_CODE];
+ while (param--) {
+ line[buffer.x++] = ch;
+ }
+ };
+ InputHandler.prototype.sendDeviceAttributes = function (params, collect) {
+ if (params[0] > 0) {
+ return;
+ }
+ if (!collect) {
+ if (this._terminal.is('xterm') || this._terminal.is('rxvt-unicode') || this._terminal.is('screen')) {
+ this._terminal.handler(EscapeSequences_1.C0.ESC + '[?1;2c');
+ }
+ else if (this._terminal.is('linux')) {
+ this._terminal.handler(EscapeSequences_1.C0.ESC + '[?6c');
+ }
+ }
+ else if (collect === '>') {
+ if (this._terminal.is('xterm')) {
+ this._terminal.handler(EscapeSequences_1.C0.ESC + '[>0;276;0c');
+ }
+ else if (this._terminal.is('rxvt-unicode')) {
+ this._terminal.handler(EscapeSequences_1.C0.ESC + '[>85;95;0c');
+ }
+ else if (this._terminal.is('linux')) {
+ this._terminal.handler(params[0] + 'c');
+ }
+ else if (this._terminal.is('screen')) {
+ this._terminal.handler(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, collect) {
+ if (params.length > 1) {
+ for (var i = 0; i < params.length; i++) {
+ this.setMode([params[i]]);
+ }
+ return;
+ }
+ if (!collect) {
+ switch (params[0]) {
+ case 4:
+ this._terminal.insertMode = true;
+ break;
+ case 20:
+ break;
+ }
+ }
+ else if (collect === '?') {
+ 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.viewport.syncScrollArea();
+ this._terminal.showCursor();
+ break;
+ case 2004:
+ this._terminal.bracketedPasteMode = true;
+ break;
+ }
+ }
+ };
+ InputHandler.prototype.resetMode = function (params, collect) {
+ if (params.length > 1) {
+ for (var i = 0; i < params.length; i++) {
+ this.resetMode([params[i]]);
+ }
+ return;
+ }
+ if (!collect) {
+ switch (params[0]) {
+ case 4:
+ this._terminal.insertMode = false;
+ break;
+ case 20:
+ break;
+ }
+ }
+ else if (collect === '?') {
+ 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.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 = Buffer_1.DEFAULT_ATTR;
+ 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 = Buffer_1.DEFAULT_ATTR >> 18;
+ fg = (Buffer_1.DEFAULT_ATTR >> 9) & 0x1ff;
+ bg = Buffer_1.DEFAULT_ATTR & 0x1ff;
+ }
+ else if (p === 1) {
+ flags |= 1;
+ }
+ else if (p === 3) {
+ flags |= 64;
+ }
+ else if (p === 4) {
+ flags |= 2;
+ }
+ else if (p === 5) {
+ flags |= 4;
+ }
+ else if (p === 7) {
+ flags |= 8;
+ }
+ else if (p === 8) {
+ flags |= 16;
+ }
+ else if (p === 2) {
+ flags |= 32;
+ }
+ else if (p === 22) {
+ flags &= ~1;
+ flags &= ~32;
+ }
+ else if (p === 24) {
+ flags &= ~2;
+ }
+ else if (p === 25) {
+ flags &= ~4;
+ }
+ else if (p === 27) {
+ flags &= ~8;
+ }
+ else if (p === 28) {
+ flags &= ~16;
+ }
+ else if (p === 39) {
+ fg = (Buffer_1.DEFAULT_ATTR >> 9) & 0x1ff;
+ }
+ else if (p === 49) {
+ bg = Buffer_1.DEFAULT_ATTR & 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 = (Buffer_1.DEFAULT_ATTR >> 9) & 0x1ff;
+ bg = Buffer_1.DEFAULT_ATTR & 0x1ff;
+ }
+ else {
+ this._terminal.error('Unknown SGR attribute: %d.', p);
+ }
+ }
+ this._terminal.curAttr = (flags << 18) | (fg << 9) | bg;
+ };
+ InputHandler.prototype.deviceStatus = function (params, collect) {
+ if (!collect) {
+ switch (params[0]) {
+ case 5:
+ this._terminal.emit('data', EscapeSequences_1.C0.ESC + "[0n");
+ break;
+ case 6:
+ var y = this._terminal.buffer.y + 1;
+ var x = this._terminal.buffer.x + 1;
+ this._terminal.emit('data', EscapeSequences_1.C0.ESC + "[" + y + ";" + x + "R");
+ break;
+ }
+ }
+ else if (collect === '?') {
+ switch (params[0]) {
+ case 6:
+ var y = this._terminal.buffer.y + 1;
+ var x = this._terminal.buffer.x + 1;
+ this._terminal.emit('data', EscapeSequences_1.C0.ESC + "[?" + y + ";" + x + "R");
+ break;
+ case 15:
+ break;
+ case 25:
+ break;
+ case 26:
+ break;
+ case 53:
+ break;
+ }
+ }
+ };
+ InputHandler.prototype.softReset = function (params, collect) {
+ if (collect === '!') {
+ 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 = Buffer_1.DEFAULT_ATTR;
+ 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, collect) {
+ if (collect === ' ') {
+ 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, collect) {
+ if (collect)
+ 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;
+ this._terminal.savedCurAttr = this._terminal.curAttr;
+ };
+ InputHandler.prototype.restoreCursor = function (params) {
+ this._terminal.buffer.x = this._terminal.buffer.savedX || 0;
+ this._terminal.buffer.y = this._terminal.buffer.savedY || 0;
+ this._terminal.curAttr = this._terminal.savedCurAttr || Buffer_1.DEFAULT_ATTR;
+ };
+ InputHandler.prototype.setTitle = function (data) {
+ this._terminal.handleTitle(data);
+ };
+ InputHandler.prototype.nextLine = function () {
+ this._terminal.buffer.x = 0;
+ this.index();
+ };
+ InputHandler.prototype.keypadApplicationMode = function () {
+ this._terminal.log('Serial port requested application keypad.');
+ this._terminal.applicationKeypad = true;
+ if (this._terminal.viewport) {
+ this._terminal.viewport.syncScrollArea();
+ }
+ };
+ InputHandler.prototype.keypadNumericMode = function () {
+ this._terminal.log('Switching back to normal keypad.');
+ this._terminal.applicationKeypad = false;
+ if (this._terminal.viewport) {
+ this._terminal.viewport.syncScrollArea();
+ }
+ };
+ InputHandler.prototype.selectDefaultCharset = function () {
+ this._terminal.setgLevel(0);
+ this._terminal.setgCharset(0, Charsets_1.DEFAULT_CHARSET);
+ };
+ InputHandler.prototype.selectCharset = function (collectAndFlag) {
+ if (collectAndFlag.length !== 2)
+ return this.selectDefaultCharset();
+ if (collectAndFlag[0] === '/')
+ return;
+ this._terminal.setgCharset(GLEVEL[collectAndFlag[0]], Charsets_1.CHARSETS[collectAndFlag[1]] || Charsets_1.DEFAULT_CHARSET);
+ };
+ InputHandler.prototype.index = function () {
+ this._terminal.index();
+ };
+ InputHandler.prototype.tabSet = function () {
+ this._terminal.tabSet();
+ };
+ InputHandler.prototype.reverseIndex = function () {
+ this._terminal.reverseIndex();
+ };
+ InputHandler.prototype.reset = function () {
+ this._parser.reset();
+ this._terminal.reset();
+ };
+ InputHandler.prototype.setgLevel = function (level) {
+ this._terminal.setgLevel(level);
+ };
+ return InputHandler;
+}(Lifecycle_1.Disposable));
+exports.InputHandler = InputHandler;
+
+},{"./Buffer":2,"./CharWidth":4,"./EscapeSequenceParser":6,"./common/Lifecycle":17,"./common/data/EscapeSequences":18,"./core/data/Charsets":19}],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 MouseZoneManager_1 = require("./ui/MouseZoneManager");
+var EventEmitter_1 = require("./EventEmitter");
+var Linkifier = (function (_super) {
+ __extends(Linkifier, _super);
+ function Linkifier(_terminal) {
+ var _this = _super.call(this) || this;
+ _this._terminal = _terminal;
+ _this._linkMatchers = [];
+ _this._nextLinkMatcherId = 0;
+ _this._rowsToLinkify = {
+ start: null,
+ end: null
+ };
+ 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 === null) {
+ this._rowsToLinkify.start = start;
+ this._rowsToLinkify.end = end;
+ }
+ else {
+ this._rowsToLinkify.start = Math.min(this._rowsToLinkify.start, start);
+ this._rowsToLinkify.end = Math.max(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.registerLinkMatcher = function (regex, handler, options) {
+ if (options === void 0) { options = {}; }
+ if (!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,
+ willLinkActivate: options.willLinkActivate,
+ 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 = 0; 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;
+ }
+ if (this._terminal.buffer.lines.get(absoluteRowIndex).isWrapped) {
+ if (rowIndex !== 0) {
+ return;
+ }
+ var line = void 0;
+ do {
+ rowIndex--;
+ absoluteRowIndex--;
+ line = this._terminal.buffer.lines.get(absoluteRowIndex);
+ if (!line) {
+ break;
+ }
+ } while (line.isWrapped);
+ }
+ var text = this._terminal.buffer.translateBufferLineToString(absoluteRowIndex, false);
+ var currentIndex = absoluteRowIndex + 1;
+ while (currentIndex < this._terminal.buffer.lines.length &&
+ this._terminal.buffer.lines.get(currentIndex).isWrapped) {
+ text += this._terminal.buffer.translateBufferLineToString(currentIndex++, 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 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;
+ var x1 = x % this._terminal.cols;
+ var y1 = y + Math.floor(x / this._terminal.cols);
+ var x2 = (x1 + uri.length) % this._terminal.cols;
+ var y2 = y1 + Math.floor((x1 + uri.length) / this._terminal.cols);
+ if (x2 === 0) {
+ x2 = this._terminal.cols;
+ y2--;
+ }
+ this._mouseZoneManager.add(new MouseZoneManager_1.MouseZone(x1 + 1, y1 + 1, x2 + 1, y2 + 1, function (e) {
+ if (matcher.handler) {
+ return matcher.handler(e, uri);
+ }
+ window.open(uri, '_blank');
+ }, function (e) {
+ _this.emit("linkhover", _this._createLinkHoverEvent(x1, y1, x2, y2));
+ _this._terminal.element.classList.add('xterm-cursor-pointer');
+ }, function (e) {
+ _this.emit("linktooltip", _this._createLinkHoverEvent(x1, y1, x2, y2));
+ if (matcher.hoverTooltipCallback) {
+ matcher.hoverTooltipCallback(e, uri);
+ }
+ }, function () {
+ _this.emit("linkleave", _this._createLinkHoverEvent(x1, y1, x2, y2));
+ _this._terminal.element.classList.remove('xterm-cursor-pointer');
+ if (matcher.hoverLeaveCallback) {
+ matcher.hoverLeaveCallback();
+ }
+ }, function (e) {
+ if (matcher.willLinkActivate) {
+ return matcher.willLinkActivate(e, uri);
+ }
+ return true;
+ }));
+ };
+ Linkifier.prototype._createLinkHoverEvent = function (x1, y1, x2, y2) {
+ return { x1: x1, y1: y1, x2: x2, y2: y2, cols: this._terminal.cols };
+ };
+ Linkifier.TIME_BEFORE_LINKIFY = 200;
+ return Linkifier;
+}(EventEmitter_1.EventEmitter));
+exports.Linkifier = Linkifier;
+
+},{"./EventEmitter":7,"./ui/MouseZoneManager":48}],10:[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("./shared/utils/Browser");
+var EventEmitter_1 = require("./EventEmitter");
+var SelectionModel_1 = require("./SelectionModel");
+var Buffer_1 = require("./Buffer");
+var AltClickHandler_1 = require("./handlers/AltClickHandler");
+var DRAG_SCROLL_MAX_THRESHOLD = 50;
+var DRAG_SCROLL_MAX_SPEED = 15;
+var DRAG_SCROLL_INTERVAL = 50;
+var ALT_CLICK_MOVE_CURSOR_TIME = 500;
+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 SelectionManager = (function (_super) {
+ __extends(SelectionManager, _super);
+ function SelectionManager(_terminal, _charMeasure) {
+ var _this = _super.call(this) || this;
+ _this._terminal = _terminal;
+ _this._charMeasure = _charMeasure;
+ _this._enabled = true;
+ _this._initListeners();
+ _this.enable();
+ _this._model = new SelectionModel_1.SelectionModel(_terminal);
+ _this._activeSelectionMode = 0;
+ return _this;
+ }
+ SelectionManager.prototype.dispose = function () {
+ _super.prototype.dispose.call(this);
+ this._removeMouseDownListeners();
+ };
+ Object.defineProperty(SelectionManager.prototype, "_buffer", {
+ get: function () {
+ return this._terminal.buffers.active;
+ },
+ enumerable: true,
+ configurable: true
+ });
+ SelectionManager.prototype._initListeners = function () {
+ var _this = this;
+ this._mouseMoveListener = function (event) { return _this._onMouseMove(event); };
+ this._mouseUpListener = function (event) { return _this._onMouseUp(event); };
+ this._trimListener = function (amount) { return _this._onTrim(amount); };
+ this.initBuffersListeners();
+ };
+ SelectionManager.prototype.initBuffersListeners = function () {
+ var _this = this;
+ this._terminal.buffer.lines.on('trim', this._trimListener);
+ this._terminal.buffers.on('activate', function (e) { return _this._onBufferActivate(e); });
+ };
+ SelectionManager.prototype.disable = function () {
+ this.clearSelection();
+ this._enabled = false;
+ };
+ SelectionManager.prototype.enable = function () {
+ this._enabled = true;
+ };
+ 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 result = [];
+ if (this._activeSelectionMode === 3) {
+ if (start[0] === end[0]) {
+ return '';
+ }
+ for (var i = start[1]; i <= end[1]; i++) {
+ var lineText = this._buffer.translateBufferLineToString(i, true, start[0], end[0]);
+ result.push(lineText);
+ }
+ }
+ else {
+ var startRowEndCol = start[1] === end[1] ? end[0] : null;
+ 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,
+ columnSelectMode: this._activeSelectionMode === 3
+ });
+ };
+ SelectionManager.prototype.isClickInSelection = function (event) {
+ var coords = this._getMouseBufferCoords(event);
+ var start = this._model.finalSelectionStart;
+ var end = this._model.finalSelectionEnd;
+ if (!start || !end) {
+ return false;
+ }
+ return (coords[1] > start[1] && coords[1] < end[1]) ||
+ (start[1] === end[1] && coords[1] === start[1] && coords[0] > start[0] && coords[0] < end[0]) ||
+ (start[1] < end[1] && coords[1] === end[1] && coords[0] < end[0]);
+ };
+ SelectionManager.prototype.selectWordAtCursor = function (event) {
+ var coords = this._getMouseBufferCoords(event);
+ if (coords) {
+ this._selectWordAt(coords, false);
+ this._model.selectionEnd = null;
+ this.refresh(true);
+ }
+ };
+ SelectionManager.prototype.selectAll = function () {
+ this._model.isSelectAllActive = true;
+ this.refresh();
+ this._terminal.emit('selection');
+ };
+ SelectionManager.prototype.selectLines = function (start, end) {
+ this._model.clearSelection();
+ start = Math.max(start, 0);
+ end = Math.min(end, this._terminal.buffer.lines.length - 1);
+ this._model.selectionStart = [0, start];
+ this._model.selectionEnd = [this._terminal.cols, end];
+ this.refresh();
+ this._terminal.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.screenElement, 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.screenElement)[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) {
+ if (Browser.isMac) {
+ return event.altKey && this._terminal.options.macOptionClickForcesSelection;
+ }
+ return event.shiftKey;
+ };
+ SelectionManager.prototype.onMouseDown = function (event) {
+ this._mouseDownTimeStamp = event.timeStamp;
+ 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 () {
+ if (this._terminal.element.ownerDocument) {
+ 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 = this.shouldColumnSelect(event) ? 3 : 0;
+ 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 = 1;
+ this._selectWordAt(coords, true);
+ }
+ };
+ SelectionManager.prototype._onTripleClick = function (event) {
+ var coords = this._getMouseBufferCoords(event);
+ if (coords) {
+ this._activeSelectionMode = 2;
+ this._selectLineAt(coords[1]);
+ }
+ };
+ SelectionManager.prototype.shouldColumnSelect = function (event) {
+ return event.altKey && !(Browser.isMac && this._terminal.options.macOptionClickForcesSelection);
+ };
+ 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 === 2) {
+ 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 === 1) {
+ this._selectToWordAt(this._model.selectionEnd);
+ }
+ this._dragScrollAmount = this._getMouseEventScrollAmount(event);
+ if (this._activeSelectionMode !== 3) {
+ 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) {
+ if (this._activeSelectionMode !== 3) {
+ this._model.selectionEnd[0] = this._terminal.cols;
+ }
+ this._model.selectionEnd[1] = Math.min(this._terminal.buffer.ydisp + this._terminal.rows, this._terminal.buffer.lines.length - 1);
+ }
+ else {
+ if (this._activeSelectionMode !== 3) {
+ this._model.selectionEnd[0] = 0;
+ }
+ this._model.selectionEnd[1] = this._terminal.buffer.ydisp;
+ }
+ this.refresh();
+ }
+ };
+ SelectionManager.prototype._onMouseUp = function (event) {
+ var timeElapsed = event.timeStamp - this._mouseDownTimeStamp;
+ this._removeMouseDownListeners();
+ if (this.selectionText.length <= 1 && timeElapsed < ALT_CLICK_MOVE_CURSOR_TIME) {
+ (new AltClickHandler_1.AltClickHandler(event, this._terminal)).move();
+ }
+ else if (this.hasSelection) {
+ this._terminal.emit('selection');
+ }
+ };
+ SelectionManager.prototype._onBufferActivate = function (e) {
+ this.clearSelection();
+ e.inactiveBuffer.lines.off('trim', this._trimListener);
+ e.activeBuffer.lines.on('trim', this._trimListener);
+ };
+ 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, allowWhitespaceOnlySelection, followWrappedLinesAbove, followWrappedLinesBelow) {
+ if (followWrappedLinesAbove === void 0) { followWrappedLinesAbove = true; }
+ if (followWrappedLinesBelow === void 0) { followWrappedLinesBelow = true; }
+ if (coords[0] >= this._terminal.cols) {
+ return null;
+ }
+ 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);
+ if (!allowWhitespaceOnlySelection && line.slice(startIndex, endIndex).trim() === '') {
+ return null;
+ }
+ if (followWrappedLinesAbove) {
+ if (start === 0 && bufferLine[0][Buffer_1.CHAR_DATA_CODE_INDEX] !== 32) {
+ var previousBufferLine = this._buffer.lines.get(coords[1] - 1);
+ if (previousBufferLine && bufferLine.isWrapped && previousBufferLine[this._terminal.cols - 1][Buffer_1.CHAR_DATA_CODE_INDEX] !== 32) {
+ var previousLineWordPosition = this._getWordAt([this._terminal.cols - 1, coords[1] - 1], false, true, false);
+ if (previousLineWordPosition) {
+ var offset = this._terminal.cols - previousLineWordPosition.start;
+ start -= offset;
+ length += offset;
+ }
+ }
+ }
+ }
+ if (followWrappedLinesBelow) {
+ if (start + length === this._terminal.cols && bufferLine[this._terminal.cols - 1][Buffer_1.CHAR_DATA_CODE_INDEX] !== 32) {
+ var nextBufferLine = this._buffer.lines.get(coords[1] + 1);
+ if (nextBufferLine && nextBufferLine.isWrapped && nextBufferLine[0][Buffer_1.CHAR_DATA_CODE_INDEX] !== 32) {
+ var nextLineWordPosition = this._getWordAt([0, coords[1] + 1], false, false, true);
+ if (nextLineWordPosition) {
+ length += nextLineWordPosition.length;
+ }
+ }
+ }
+ }
+ return { start: start, length: length };
+ };
+ SelectionManager.prototype._selectWordAt = function (coords, allowWhitespaceOnlySelection) {
+ var wordPosition = this._getWordAt(coords, allowWhitespaceOnlySelection);
+ if (wordPosition) {
+ while (wordPosition.start < 0) {
+ wordPosition.start += this._terminal.cols;
+ coords[1]--;
+ }
+ this._model.selectionStart = [wordPosition.start, coords[1]];
+ this._model.selectionStartLength = wordPosition.length;
+ }
+ };
+ SelectionManager.prototype._selectToWordAt = function (coords) {
+ var wordPosition = this._getWordAt(coords, true);
+ if (wordPosition) {
+ var endRow = coords[1];
+ while (wordPosition.start < 0) {
+ wordPosition.start += this._terminal.cols;
+ endRow--;
+ }
+ if (!this._model.areSelectionValuesReversed()) {
+ while (wordPosition.start + wordPosition.length > this._terminal.cols) {
+ wordPosition.length -= this._terminal.cols;
+ endRow++;
+ }
+ }
+ this._model.selectionEnd = [this._model.areSelectionValuesReversed() ? wordPosition.start : wordPosition.start + wordPosition.length, endRow];
+ }
+ };
+ 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) {
+ var wrappedRange = this._buffer.getWrappedRangeForLine(line);
+ this._model.selectionStart = [0, wrappedRange.first];
+ this._model.selectionEnd = [this._terminal.cols, wrappedRange.last];
+ this._model.selectionStartLength = 0;
+ };
+ return SelectionManager;
+}(EventEmitter_1.EventEmitter));
+exports.SelectionManager = SelectionManager;
+
+},{"./Buffer":2,"./EventEmitter":7,"./SelectionModel":11,"./handlers/AltClickHandler":21,"./shared/utils/Browser":45,"./utils/MouseHelper":52}],11:[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()) {
+ var startPlusLength = this.selectionStart[0] + this.selectionStartLength;
+ if (startPlusLength > this._terminal.cols) {
+ return [startPlusLength % this._terminal.cols, this.selectionStart[1] + Math.floor(startPlusLength / this._terminal.cols)];
+ }
+ return [startPlusLength, 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;
+
+},{}],12:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.DEFAULT_BELL_SOUND = 'data:audio/wav;base64,UklGRigBAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQQBAADpAFgCwAMlBZoG/wdmCcoKRAypDQ8PbRDBEQQTOxRtFYcWlBePGIUZXhoiG88bcBz7HHIdzh0WHlMeZx51HmkeUx4WHs8dah0AHXwc3hs9G4saxRnyGBIYGBcQFv8U4RPAEoYRQBACD70NWwwHC6gJOwjWBloF7gOBAhABkf8b/qv8R/ve+Xf4Ife79W/0JfPZ8Z/wde9N7ijtE+wU6xvqM+lb6H7nw+YX5mrlxuQz5Mzje+Ma49fioeKD4nXiYeJy4pHitOL04j/jn+MN5IPkFOWs5U3mDefM55/ogOl36m7rdOyE7abuyu8D8Unyj/Pg9D/2qfcb+Yn6/vuK/Qj/lAAlAg==';
+var SoundManager = (function () {
+ function SoundManager(_terminal) {
+ this._terminal = _terminal;
+ }
+ SoundManager.prototype.playBellSound = function () {
+ var audioContextCtor = window.AudioContext || window.webkitAudioContext;
+ if (!this._audioContext && audioContextCtor) {
+ this._audioContext = new audioContextCtor();
+ }
+ if (this._audioContext) {
+ var bellAudioSource_1 = this._audioContext.createBufferSource();
+ var context_1 = this._audioContext;
+ this._audioContext.decodeAudioData(this._base64ToArrayBuffer(this._removeMimeType(this._terminal.options.bellSound)), function (buffer) {
+ bellAudioSource_1.buffer = buffer;
+ bellAudioSource_1.connect(context_1.destination);
+ bellAudioSource_1.start(0);
+ });
+ }
+ else {
+ console.warn('Sorry, but the Web Audio API is not supported by your browser. Please, consider upgrading to the latest version');
+ }
+ };
+ SoundManager.prototype._base64ToArrayBuffer = function (base64) {
+ var binaryString = window.atob(base64);
+ var len = binaryString.length;
+ var bytes = new Uint8Array(len);
+ for (var i = 0; i < len; i++) {
+ bytes[i] = binaryString.charCodeAt(i);
+ }
+ return bytes.buffer;
+ };
+ SoundManager.prototype._removeMimeType = function (dataURI) {
+ var splitUri = dataURI.split(',');
+ return splitUri[1];
+ };
+ return SoundManager;
+}());
+exports.SoundManager = SoundManager;
+
+},{}],13:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.blankLine = 'Blank line';
+exports.promptLabel = 'Terminal input';
+exports.tooMuchOutput = 'Too much output to announce, navigate to rows manually to read';
+
+},{}],14:[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("./common/data/EscapeSequences");
+var InputHandler_1 = require("./InputHandler");
+var Renderer_1 = require("./renderer/Renderer");
+var Linkifier_1 = require("./Linkifier");
+var SelectionManager_1 = require("./SelectionManager");
+var CharMeasure_1 = require("./ui/CharMeasure");
+var Browser = require("./shared/utils/Browser");
+var Lifecycle_1 = require("./ui/Lifecycle");
+var Strings = require("./Strings");
+var MouseHelper_1 = require("./utils/MouseHelper");
+var Clone_1 = require("./utils/Clone");
+var SoundManager_1 = require("./SoundManager");
+var ColorManager_1 = require("./renderer/ColorManager");
+var MouseZoneManager_1 = require("./ui/MouseZoneManager");
+var AccessibilityManager_1 = require("./AccessibilityManager");
+var ScreenDprMonitor_1 = require("./ui/ScreenDprMonitor");
+var CharAtlasCache_1 = require("./renderer/atlas/CharAtlasCache");
+var DomRenderer_1 = require("./renderer/dom/DomRenderer");
+var Keyboard_1 = require("./core/input/Keyboard");
+var document = (typeof window !== 'undefined') ? window.document : null;
+var WRITE_BUFFER_PAUSE_THRESHOLD = 5;
+var WRITE_BATCH_SIZE = 300;
+var CONSTRUCTOR_ONLY_OPTIONS = ['cols', 'rows'];
+var DEFAULT_OPTIONS = {
+ cols: 80,
+ rows: 24,
+ convertEol: false,
+ termName: 'xterm',
+ cursorBlink: false,
+ cursorStyle: 'block',
+ bellSound: SoundManager_1.DEFAULT_BELL_SOUND,
+ bellStyle: 'none',
+ drawBoldTextInBrightColors: true,
+ enableBold: true,
+ experimentalCharAtlas: 'static',
+ fontFamily: 'courier-new, courier, monospace',
+ fontSize: 15,
+ fontWeight: 'normal',
+ fontWeightBold: 'bold',
+ lineHeight: 1.0,
+ letterSpacing: 0,
+ scrollback: 1000,
+ screenKeys: false,
+ screenReaderMode: false,
+ debug: false,
+ macOptionIsMeta: false,
+ macOptionClickForcesSelection: false,
+ cancelEvents: false,
+ disableStdin: false,
+ useFlowControl: false,
+ allowTransparency: false,
+ tabStopWidth: 8,
+ theme: null,
+ rightClickSelectsWord: Browser.isMac,
+ rendererType: 'canvas'
+};
+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 = Clone_1.clone(options);
+ _this._setup();
+ return _this;
+ }
+ Terminal.prototype.dispose = function () {
+ _super.prototype.dispose.call(this);
+ this._customKeyEventHandler = null;
+ CharAtlasCache_1.removeTerminalFromCache(this);
+ this.handler = function () { };
+ this.write = function () { };
+ if (this.element && this.element.parentNode) {
+ this.element.parentNode.removeChild(this.element);
+ }
+ };
+ Terminal.prototype.destroy = function () {
+ this.dispose();
+ };
+ 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._parent = document ? document.body : null;
+ this.cols = this.options.cols;
+ this.rows = this.options.rows;
+ if (this.options.handler) {
+ this.on('data', this.options.handler);
+ }
+ this.cursorState = 0;
+ this.cursorHidden = false;
+ 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.curAttr = Buffer_1.DEFAULT_ATTR;
+ this.params = [];
+ this.currentParam = 0;
+ this.writeBuffer = [];
+ this._writeInProgress = false;
+ this._xoffSentToCatchUp = false;
+ this._userScrolling = false;
+ this._inputHandler = new InputHandler_1.InputHandler(this);
+ this.register(this._inputHandler);
+ 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.soundManager = this.soundManager || new SoundManager_1.SoundManager(this);
+ this.buffers = new BufferSet_1.BufferSet(this);
+ if (this.selectionManager) {
+ this.selectionManager.clearSelection();
+ this.selectionManager.initBuffersListeners();
+ }
+ };
+ Object.defineProperty(Terminal.prototype, "buffer", {
+ get: function () {
+ return this.buffers.active;
+ },
+ enumerable: true,
+ configurable: true
+ });
+ Terminal.prototype.eraseAttr = function () {
+ return (Buffer_1.DEFAULT_ATTR & ~0x1ff) | (this.curAttr & 0x1ff);
+ };
+ Terminal.prototype.focus = function () {
+ if (this.textarea) {
+ 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 + '"');
+ }
+ return this.options[key];
+ };
+ Terminal.prototype.setOption = function (key, value) {
+ if (!(key in DEFAULT_OPTIONS)) {
+ throw new Error('No option with key "' + key + '"');
+ }
+ if (CONSTRUCTOR_ONLY_OPTIONS.indexOf(key) !== -1) {
+ console.error("Option \"" + key + "\" can only be set in the constructor");
+ }
+ if (this.options[key] === value) {
+ return;
+ }
+ switch (key) {
+ case 'bellStyle':
+ if (!value) {
+ value = 'none';
+ }
+ break;
+ case 'cursorStyle':
+ if (!value) {
+ value = 'block';
+ }
+ break;
+ case 'fontWeight':
+ if (!value) {
+ value = 'normal';
+ }
+ break;
+ case 'fontWeightBold':
+ if (!value) {
+ value = 'bold';
+ }
+ break;
+ case 'lineHeight':
+ if (value < 1) {
+ console.warn(key + " cannot be less than 1, value: " + value);
+ return;
+ }
+ case 'rendererType':
+ if (!value) {
+ value = 'canvas';
+ }
+ break;
+ 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.options[key] = value;
+ switch (key) {
+ case 'fontFamily':
+ case 'fontSize':
+ if (this.renderer) {
+ this.renderer.clear();
+ this.charMeasure.measure(this.options);
+ }
+ break;
+ case 'drawBoldTextInBrightColors':
+ case 'experimentalCharAtlas':
+ case 'enableBold':
+ case 'letterSpacing':
+ case 'lineHeight':
+ case 'fontWeight':
+ case 'fontWeightBold':
+ if (this.renderer) {
+ this.renderer.clear();
+ this.renderer.onResize(this.cols, this.rows);
+ this.refresh(0, this.rows - 1);
+ }
+ case 'rendererType':
+ if (this.renderer) {
+ this.unregister(this.renderer);
+ this.renderer.dispose();
+ this.renderer = null;
+ }
+ this._setupRenderer();
+ this.renderer.onCharSizeChanged();
+ if (this._theme) {
+ this.renderer.setTheme(this._theme);
+ }
+ break;
+ case 'scrollback':
+ this.buffers.resize(this.cols, this.rows);
+ if (this.viewport) {
+ this.viewport.syncScrollArea();
+ }
+ break;
+ case 'screenReaderMode':
+ if (value) {
+ if (!this._accessibilityManager) {
+ this._accessibilityManager = new AccessibilityManager_1.AccessibilityManager(this);
+ }
+ }
+ else {
+ if (this._accessibilityManager) {
+ this._accessibilityManager.dispose();
+ this._accessibilityManager = null;
+ }
+ }
+ break;
+ case 'tabStopWidth':
+ this.buffers.setupTabStops();
+ break;
+ }
+ if (this.renderer) {
+ this.renderer.onOptionsChanged();
+ }
+ };
+ Terminal.prototype._onTextAreaFocus = function () {
+ if (this.sendFocus) {
+ this.handler(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.textarea.value = '';
+ this.refresh(this.buffer.y, this.buffer.y);
+ if (this.sendFocus) {
+ this.handler(EscapeSequences_1.C0.ESC + '[O');
+ }
+ this.element.classList.remove('focus');
+ this.emit('blur');
+ };
+ Terminal.prototype._initGlobal = function () {
+ var _this = this;
+ this._bindKeys();
+ this.register(Lifecycle_1.addDisposableDomListener(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); };
+ this.register(Lifecycle_1.addDisposableDomListener(this.textarea, 'paste', pasteHandlerWrapper));
+ this.register(Lifecycle_1.addDisposableDomListener(this.element, 'paste', pasteHandlerWrapper));
+ if (Browser.isFirefox) {
+ this.register(Lifecycle_1.addDisposableDomListener(this.element, 'mousedown', function (event) {
+ if (event.button === 2) {
+ Clipboard_1.rightClickHandler(event, _this.textarea, _this.selectionManager, _this.options.rightClickSelectsWord);
+ }
+ }));
+ }
+ else {
+ this.register(Lifecycle_1.addDisposableDomListener(this.element, 'contextmenu', function (event) {
+ Clipboard_1.rightClickHandler(event, _this.textarea, _this.selectionManager, _this.options.rightClickSelectsWord);
+ }));
+ }
+ if (Browser.isLinux) {
+ this.register(Lifecycle_1.addDisposableDomListener(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;
+ this.register(Lifecycle_1.addDisposableDomListener(this.element, 'keydown', function (ev) {
+ if (document.activeElement !== this) {
+ return;
+ }
+ self._keyDown(ev);
+ }, true));
+ this.register(Lifecycle_1.addDisposableDomListener(this.element, 'keypress', function (ev) {
+ if (document.activeElement !== this) {
+ return;
+ }
+ self._keyPress(ev);
+ }, true));
+ this.register(Lifecycle_1.addDisposableDomListener(this.element, 'keyup', function (ev) {
+ if (!wasModifierKeyOnlyEvent(ev)) {
+ _this.focus();
+ }
+ self._keyUp(ev);
+ }, true));
+ this.register(Lifecycle_1.addDisposableDomListener(this.textarea, 'keydown', function (ev) { return _this._keyDown(ev); }, true));
+ this.register(Lifecycle_1.addDisposableDomListener(this.textarea, 'keypress', function (ev) { return _this._keyPress(ev); }, true));
+ this.register(Lifecycle_1.addDisposableDomListener(this.textarea, 'compositionstart', function () { return _this._compositionHelper.compositionstart(); }));
+ this.register(Lifecycle_1.addDisposableDomListener(this.textarea, 'compositionupdate', function (e) { return _this._compositionHelper.compositionupdate(e); }));
+ this.register(Lifecycle_1.addDisposableDomListener(this.textarea, 'compositionend', function () { return _this._compositionHelper.compositionend(); }));
+ this.register(this.addDisposableListener('refresh', function () { return _this._compositionHelper.updateCompositionElements(); }));
+ this.register(this.addDisposableListener('refresh', function (data) { return _this._queueLinkification(data.start, data.end); }));
+ };
+ Terminal.prototype.open = function (parent) {
+ var _this = this;
+ 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._screenDprMonitor = new ScreenDprMonitor_1.ScreenDprMonitor();
+ this._screenDprMonitor.setListener(function () { return _this.emit('dprchange', window.devicePixelRatio); });
+ this.register(this._screenDprMonitor);
+ this.element = this._document.createElement('div');
+ this.element.dir = 'ltr';
+ this.element.classList.add('terminal');
+ this.element.classList.add('xterm');
+ this.element.setAttribute('tabindex', '0');
+ this._parent.appendChild(this.element);
+ var fragment = document.createDocumentFragment();
+ this._viewportElement = document.createElement('div');
+ this._viewportElement.classList.add('xterm-viewport');
+ fragment.appendChild(this._viewportElement);
+ this._viewportScrollArea = document.createElement('div');
+ this._viewportScrollArea.classList.add('xterm-scroll-area');
+ this._viewportElement.appendChild(this._viewportScrollArea);
+ this.screenElement = document.createElement('div');
+ this.screenElement.classList.add('xterm-screen');
+ this._helperContainer = document.createElement('div');
+ this._helperContainer.classList.add('xterm-helpers');
+ this.screenElement.appendChild(this._helperContainer);
+ fragment.appendChild(this.screenElement);
+ this._mouseZoneManager = new MouseZoneManager_1.MouseZoneManager(this);
+ this.register(this._mouseZoneManager);
+ this.register(this.addDisposableListener('scroll', function () { return _this._mouseZoneManager.clearAll(); }));
+ this.linkifier.attachToDom(this._mouseZoneManager);
+ this.textarea = document.createElement('textarea');
+ this.textarea.classList.add('xterm-helper-textarea');
+ this.textarea.setAttribute('aria-label', Strings.promptLabel);
+ this.textarea.setAttribute('aria-multiline', 'false');
+ this.textarea.setAttribute('autocorrect', 'off');
+ this.textarea.setAttribute('autocapitalize', 'off');
+ this.textarea.setAttribute('spellcheck', 'false');
+ this.textarea.tabIndex = 0;
+ this.register(Lifecycle_1.addDisposableDomListener(this.textarea, 'focus', function () { return _this._onTextAreaFocus(); }));
+ this.register(Lifecycle_1.addDisposableDomListener(this.textarea, '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.charMeasure = new CharMeasure_1.CharMeasure(document, this._helperContainer);
+ this.element.appendChild(fragment);
+ this._setupRenderer();
+ this._theme = 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.register(this.viewport);
+ this.register(this.addDisposableListener('cursormove', function () { return _this.renderer.onCursorMove(); }));
+ this.register(this.addDisposableListener('resize', function () { return _this.renderer.onResize(_this.cols, _this.rows); }));
+ this.register(this.addDisposableListener('blur', function () { return _this.renderer.onBlur(); }));
+ this.register(this.addDisposableListener('focus', function () { return _this.renderer.onFocus(); }));
+ this.register(this.addDisposableListener('dprchange', function () { return _this.renderer.onWindowResize(window.devicePixelRatio); }));
+ this.register(Lifecycle_1.addDisposableDomListener(window, 'resize', function () { return _this.renderer.onWindowResize(window.devicePixelRatio); }));
+ this.register(this.charMeasure.addDisposableListener('charsizechanged', function () { return _this.renderer.onCharSizeChanged(); }));
+ this.register(this.renderer.addDisposableListener('resize', function (dimensions) { return _this.viewport.syncScrollArea(); }));
+ this.selectionManager = new SelectionManager_1.SelectionManager(this, this.charMeasure);
+ this.register(Lifecycle_1.addDisposableDomListener(this.element, 'mousedown', function (e) { return _this.selectionManager.onMouseDown(e); }));
+ this.register(this.selectionManager.addDisposableListener('refresh', function (data) { return _this.renderer.onSelectionChanged(data.start, data.end, data.columnSelectMode); }));
+ this.register(this.selectionManager.addDisposableListener('newselection', function (text) {
+ _this.textarea.value = text;
+ _this.textarea.focus();
+ _this.textarea.select();
+ }));
+ this.register(this.addDisposableListener('scroll', function () {
+ _this.viewport.syncScrollArea();
+ _this.selectionManager.refresh();
+ }));
+ this.register(Lifecycle_1.addDisposableDomListener(this._viewportElement, 'scroll', function () { return _this.selectionManager.refresh(); }));
+ this.mouseHelper = new MouseHelper_1.MouseHelper(this.renderer);
+ if (this.options.screenReaderMode) {
+ this._accessibilityManager = new AccessibilityManager_1.AccessibilityManager(this);
+ }
+ this.charMeasure.measure(this.options);
+ this.refresh(0, this.rows - 1);
+ this._initGlobal();
+ this.bindMouse();
+ };
+ Terminal.prototype._setupRenderer = function () {
+ switch (this.options.rendererType) {
+ case 'canvas':
+ this.renderer = new Renderer_1.Renderer(this, this.options.theme);
+ break;
+ case 'dom':
+ this.renderer = new DomRenderer_1.DomRenderer(this, this.options.theme);
+ break;
+ default: throw new Error("Unrecognized rendererType \"" + this.options.rendererType + "\"");
+ }
+ this.register(this.renderer);
+ };
+ Terminal.prototype._setTheme = function (theme) {
+ this._theme = theme;
+ var colors = this.renderer.setTheme(theme);
+ if (this.viewport) {
+ this.viewport.onThemeChanged(colors);
+ }
+ };
+ 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.screenElement, 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.screenElement, 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.handler(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.handler(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.handler(EscapeSequences_1.C0.ESC + '[' + button + ';' + pos.x + ';' + pos.y + 'M');
+ return;
+ }
+ if (self.sgrMouse) {
+ pos.x -= 32;
+ pos.y -= 32;
+ self.handler(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.handler(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;
+ }
+ this.register(Lifecycle_1.addDisposableDomListener(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);
+ }
+ var moveHandler;
+ if (_this.normalMouse) {
+ moveHandler = function (event) {
+ if (!_this.normalMouse) {
+ return;
+ }
+ sendMove(event);
+ };
+ _this._document.addEventListener('mousemove', moveHandler);
+ }
+ var handler = function (ev) {
+ if (_this.normalMouse && !_this.x10Mouse) {
+ sendButton(ev);
+ }
+ if (moveHandler) {
+ _this._document.removeEventListener('mousemove', moveHandler);
+ moveHandler = null;
+ }
+ _this._document.removeEventListener('mouseup', handler);
+ return _this.cancel(ev);
+ };
+ _this._document.addEventListener('mouseup', handler);
+ return _this.cancel(ev);
+ }));
+ this.register(Lifecycle_1.addDisposableDomListener(el, 'wheel', function (ev) {
+ if (!_this.mouseEvents) {
+ if (!_this.buffer.hasScrollback) {
+ var amount = _this.viewport.getLinesScrolled(ev);
+ if (amount === 0) {
+ return;
+ }
+ var sequence = EscapeSequences_1.C0.ESC + (_this.applicationCursor ? 'O' : '[') + (ev.deltaY < 0 ? 'A' : 'B');
+ var data = '';
+ for (var i = 0; i < Math.abs(amount); i++) {
+ data += sequence;
+ }
+ _this.handler(data);
+ }
+ return;
+ }
+ if (_this.x10Mouse || _this._vt300Mouse || _this._decLocator)
+ return;
+ sendButton(ev);
+ ev.preventDefault();
+ }));
+ this.register(Lifecycle_1.addDisposableDomListener(el, 'wheel', function (ev) {
+ if (_this.mouseEvents)
+ return;
+ _this.viewport.onWheel(ev);
+ return _this.cancel(ev);
+ }));
+ this.register(Lifecycle_1.addDisposableDomListener(el, 'touchstart', function (ev) {
+ if (_this.mouseEvents)
+ return;
+ _this.viewport.onTouchStart(ev);
+ return _this.cancel(ev);
+ }));
+ this.register(Lifecycle_1.addDisposableDomListener(el, 'touchmove', function (ev) {
+ if (_this.mouseEvents)
+ return;
+ _this.viewport.onTouchMove(ev);
+ return _this.cancel(ev);
+ }));
+ };
+ Terminal.prototype.refresh = function (start, end) {
+ if (this.renderer) {
+ this.renderer.refreshRows(start, end);
+ }
+ };
+ Terminal.prototype._queueLinkification = function (start, end) {
+ if (this.linkifier) {
+ this.linkifier.linkifyRows(start, end);
+ }
+ };
+ Terminal.prototype.updateCursorStyle = function (ev) {
+ if (this.selectionManager && this.selectionManager.shouldColumnSelect(ev)) {
+ this.element.classList.add('xterm-cursor-crosshair');
+ }
+ else {
+ this.element.classList.remove('xterm-cursor-crosshair');
+ }
+ };
+ 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.scrollToLine = function (line) {
+ var scrollAmount = line - this.buffer.ydisp;
+ if (scrollAmount !== 0) {
+ this.scrollLines(scrollAmount);
+ }
+ };
+ Terminal.prototype.write = function (data) {
+ var _this = this;
+ if (this._isDisposed) {
+ return;
+ }
+ if (!data) {
+ return;
+ }
+ this.writeBuffer.push(data);
+ if (this.options.useFlowControl && !this._xoffSentToCatchUp && this.writeBuffer.length >= WRITE_BUFFER_PAUSE_THRESHOLD) {
+ this.handler(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;
+ if (this._isDisposed) {
+ this.writeBuffer = [];
+ }
+ 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.handler(EscapeSequences_1.C0.DC1);
+ this._xoffSentToCatchUp = false;
+ }
+ this._refreshStart = this.buffer.y;
+ this._refreshEnd = this.buffer.y;
+ this._inputHandler.parse(data);
+ 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.registerLinkMatcher = function (regex, handler, options) {
+ var matcherId = this.linkifier.registerLinkMatcher(regex, handler, options);
+ this.refresh(0, this.rows - 1);
+ return matcherId;
+ };
+ Terminal.prototype.deregisterLinkMatcher = function (matcherId) {
+ if (this.linkifier.deregisterLinkMatcher(matcherId)) {
+ this.refresh(0, this.rows - 1);
+ }
+ };
+ Terminal.prototype.registerCharacterJoiner = function (handler) {
+ var joinerId = this.renderer.registerCharacterJoiner(handler);
+ this.refresh(0, this.rows - 1);
+ return joinerId;
+ };
+ Terminal.prototype.deregisterCharacterJoiner = function (joinerId) {
+ if (this.renderer.deregisterCharacterJoiner(joinerId)) {
+ this.refresh(0, this.rows - 1);
+ }
+ };
+ Object.defineProperty(Terminal.prototype, "markers", {
+ get: function () {
+ return this.buffer.markers;
+ },
+ enumerable: true,
+ configurable: true
+ });
+ Terminal.prototype.addMarker = function (cursorYOffset) {
+ if (this.buffer !== this.buffers.normal) {
+ return;
+ }
+ return this.buffer.addMarker(this.buffer.ybase + this.buffer.y + cursorYOffset);
+ };
+ 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.selectLines = function (start, end) {
+ if (this.selectionManager) {
+ this.selectionManager.selectLines(start, end);
+ }
+ };
+ Terminal.prototype._keyDown = function (event) {
+ if (this._customKeyEventHandler && this._customKeyEventHandler(event) === false) {
+ return false;
+ }
+ if (!this._compositionHelper.keydown(event)) {
+ if (this.buffer.ybase !== this.buffer.ydisp) {
+ this.scrollToBottom();
+ }
+ return false;
+ }
+ var result = Keyboard_1.evaluateKeyboardEvent(event, this.applicationCursor, this.browser.isMac, this.options.macOptionIsMeta);
+ this.updateCursorStyle(event);
+ if (result.type === 3 || result.type === 2) {
+ var scrollCount = this.rows - 1;
+ this.scrollLines(result.type === 2 ? -scrollCount : scrollCount);
+ return this.cancel(event, true);
+ }
+ if (result.type === 1) {
+ this.selectAll();
+ }
+ if (this._isThirdLevelShift(this.browser, event)) {
+ return true;
+ }
+ if (result.cancel) {
+ this.cancel(event, true);
+ }
+ if (!result.key) {
+ return true;
+ }
+ this.emit('keydown', event);
+ this.emit('key', result.key, event);
+ this.showCursor();
+ this.handler(result.key);
+ return this.cancel(event, true);
+ };
+ Terminal.prototype._isThirdLevelShift = function (browser, ev) {
+ var thirdLevelKey = (browser.isMac && !this.options.macOptionIsMeta && 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);
+ };
+ 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._keyUp = function (ev) {
+ this.updateCursorStyle(ev);
+ };
+ 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) && !this._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.bell = function () {
+ var _this = this;
+ this.emit('bell');
+ if (this._soundBell()) {
+ this.soundManager.playBellSound();
+ }
+ 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 && (!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);
+ if (this.charMeasure) {
+ this.charMeasure.measure(this.options);
+ }
+ this.refresh(0, this.rows - 1);
+ 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(), Buffer_1.NULL_CELL_CHAR, Buffer_1.NULL_CELL_WIDTH, Buffer_1.NULL_CELL_CODE];
+ 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(), Buffer_1.NULL_CELL_CHAR, Buffer_1.NULL_CELL_WIDTH, Buffer_1.NULL_CELL_CODE];
+ 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() : Buffer_1.DEFAULT_ATTR;
+ var ch = [attr, Buffer_1.NULL_CELL_CHAR, Buffer_1.NULL_CELL_WIDTH, Buffer_1.NULL_CELL_CODE];
+ 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(), Buffer_1.NULL_CELL_CHAR, Buffer_1.NULL_CELL_WIDTH, Buffer_1.NULL_CELL_CODE];
+ }
+ return [Buffer_1.DEFAULT_ATTR, Buffer_1.NULL_CELL_CHAR, Buffer_1.NULL_CELL_WIDTH, Buffer_1.NULL_CELL_CODE];
+ };
+ 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 cursorState = this.cursorState;
+ this._setup();
+ this._customKeyEventHandler = customKeyEventHandler;
+ this._inputHandler = inputHandler;
+ this.cursorState = cursorState;
+ this.refresh(0, this.rows - 1);
+ if (this.viewport) {
+ 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) {
+ 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 < ColorManager_1.DEFAULT_ANSI_COLORS.length; i++) {
+ c = ColorManager_1.DEFAULT_ANSI_COLORS[i].rgba;
+ r2 = c >>> 24;
+ g2 = c >>> 16 & 0xFF;
+ b2 = c >>> 8 & 0xFF;
+ 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;
+ };
+ Terminal.prototype._visualBell = function () {
+ return false;
+ };
+ Terminal.prototype._soundBell = function () {
+ return this.options.bellStyle === 'sound';
+ };
+ return Terminal;
+}(EventEmitter_1.EventEmitter));
+exports.Terminal = Terminal;
+function wasModifierKeyOnlyEvent(ev) {
+ return ev.keyCode === 16 ||
+ ev.keyCode === 17 ||
+ ev.keyCode === 18;
+}
+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);
+}
+
+},{"./AccessibilityManager":1,"./Buffer":2,"./BufferSet":3,"./CompositionHelper":5,"./EventEmitter":7,"./InputHandler":8,"./Linkifier":9,"./SelectionManager":10,"./SoundManager":12,"./Strings":13,"./Viewport":15,"./common/data/EscapeSequences":18,"./core/input/Keyboard":20,"./handlers/Clipboard":22,"./renderer/ColorManager":26,"./renderer/Renderer":30,"./renderer/atlas/CharAtlasCache":34,"./renderer/dom/DomRenderer":41,"./shared/utils/Browser":45,"./ui/CharMeasure":46,"./ui/Lifecycle":47,"./ui/MouseZoneManager":48,"./ui/ScreenDprMonitor":50,"./utils/Clone":51,"./utils/MouseHelper":52}],15:[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 Lifecycle_1 = require("./common/Lifecycle");
+var Lifecycle_2 = require("./ui/Lifecycle");
+var FALLBACK_SCROLL_BAR_WIDTH = 15;
+var Viewport = (function (_super) {
+ __extends(Viewport, _super);
+ function Viewport(_terminal, _viewportElement, _scrollArea, _charMeasure) {
+ var _this = _super.call(this) || this;
+ _this._terminal = _terminal;
+ _this._viewportElement = _viewportElement;
+ _this._scrollArea = _scrollArea;
+ _this._charMeasure = _charMeasure;
+ _this.scrollBarWidth = 0;
+ _this._currentRowHeight = 0;
+ _this._lastRecordedBufferLength = 0;
+ _this._lastRecordedViewportHeight = 0;
+ _this._lastRecordedBufferHeight = 0;
+ _this._wheelPartialScroll = 0;
+ _this.scrollBarWidth = (_this._viewportElement.offsetWidth - _this._scrollArea.offsetWidth) || FALLBACK_SCROLL_BAR_WIDTH;
+ _this.register(Lifecycle_2.addDisposableDomListener(_this._viewportElement, 'scroll', _this._onScroll.bind(_this)));
+ setTimeout(function () { return _this.syncScrollArea(); }, 0);
+ return _this;
+ }
+ Viewport.prototype.onThemeChanged = function (colors) {
+ this._viewportElement.style.backgroundColor = colors.background.css;
+ };
+ Viewport.prototype._refresh = function () {
+ if (this._charMeasure.height > 0) {
+ this._currentRowHeight = this._terminal.renderer.dimensions.scaledCellHeight / window.devicePixelRatio;
+ this._lastRecordedViewportHeight = this._viewportElement.offsetHeight;
+ var newBufferHeight = Math.round(this._currentRowHeight * this._lastRecordedBufferLength) + (this._lastRecordedViewportHeight - this._terminal.renderer.dimensions.canvasHeight);
+ 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) {
+ if (!this._viewportElement.offsetParent) {
+ return;
+ }
+ 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) {
+ var amount = this._getPixelsScrolled(ev);
+ if (amount === 0) {
+ return;
+ }
+ this._viewportElement.scrollTop += amount;
+ ev.preventDefault();
+ };
+ Viewport.prototype._getPixelsScrolled = function (ev) {
+ if (ev.deltaY === 0) {
+ return 0;
+ }
+ var amount = ev.deltaY;
+ if (ev.deltaMode === WheelEvent.DOM_DELTA_LINE) {
+ amount *= this._currentRowHeight;
+ }
+ else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) {
+ amount *= this._currentRowHeight * this._terminal.rows;
+ }
+ return amount;
+ };
+ Viewport.prototype.getLinesScrolled = function (ev) {
+ if (ev.deltaY === 0) {
+ return 0;
+ }
+ var amount = ev.deltaY;
+ if (ev.deltaMode === WheelEvent.DOM_DELTA_PIXEL) {
+ amount /= this._currentRowHeight + 0.0;
+ this._wheelPartialScroll += amount;
+ amount = Math.floor(Math.abs(this._wheelPartialScroll)) * (this._wheelPartialScroll > 0 ? 1 : -1);
+ this._wheelPartialScroll %= 1;
+ }
+ else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) {
+ amount *= this._terminal.rows;
+ }
+ return amount;
+ };
+ 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;
+}(Lifecycle_1.Disposable));
+exports.Viewport = Viewport;
+
+},{"./common/Lifecycle":17,"./ui/Lifecycle":47}],16:[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
+ });
+ 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}],17:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Disposable = (function () {
+ function Disposable() {
+ this._disposables = [];
+ this._isDisposed = false;
+ }
+ Disposable.prototype.dispose = function () {
+ this._isDisposed = true;
+ this._disposables.forEach(function (d) { return d.dispose(); });
+ this._disposables.length = 0;
+ };
+ Disposable.prototype.register = function (d) {
+ this._disposables.push(d);
+ };
+ Disposable.prototype.unregister = function (d) {
+ var index = this._disposables.indexOf(d);
+ if (index !== -1) {
+ this._disposables.splice(index, 1);
+ }
+ };
+ return Disposable;
+}());
+exports.Disposable = Disposable;
+
+},{}],18:[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 = {}));
+var C1;
+(function (C1) {
+ C1.PAD = '\x80';
+ C1.HOP = '\x81';
+ C1.BPH = '\x82';
+ C1.NBH = '\x83';
+ C1.IND = '\x84';
+ C1.NEL = '\x85';
+ C1.SSA = '\x86';
+ C1.ESA = '\x87';
+ C1.HTS = '\x88';
+ C1.HTJ = '\x89';
+ C1.VTS = '\x8a';
+ C1.PLD = '\x8b';
+ C1.PLU = '\x8c';
+ C1.RI = '\x8d';
+ C1.SS2 = '\x8e';
+ C1.SS3 = '\x8f';
+ C1.DCS = '\x90';
+ C1.PU1 = '\x91';
+ C1.PU2 = '\x92';
+ C1.STS = '\x93';
+ C1.CCH = '\x94';
+ C1.MW = '\x95';
+ C1.SPA = '\x96';
+ C1.EPA = '\x97';
+ C1.SOS = '\x98';
+ C1.SGCI = '\x99';
+ C1.SCI = '\x9a';
+ C1.CSI = '\x9b';
+ C1.ST = '\x9c';
+ C1.OSC = '\x9d';
+ C1.PM = '\x9e';
+ C1.APC = '\x9f';
+})(C1 = exports.C1 || (exports.C1 = {}));
+
+},{}],19:[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['='] = {
+ '#': 'ù',
+ '@': 'à',
+ '[': 'é',
+ '\\': 'ç',
+ ']': 'ê',
+ '^': 'î',
+ '_': 'è',
+ '`': 'ô',
+ '{': 'ä',
+ '|': 'ö',
+ '}': 'ü',
+ '~': 'û'
+};
+
+},{}],20:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var EscapeSequences_1 = require("../../common/data/EscapeSequences");
+var KEYCODE_KEY_MAPPINGS = {
+ 48: ['0', ')'],
+ 49: ['1', '!'],
+ 50: ['2', '@'],
+ 51: ['3', '#'],
+ 52: ['4', '$'],
+ 53: ['5', '%'],
+ 54: ['6', '^'],
+ 55: ['7', '&'],
+ 56: ['8', '*'],
+ 57: ['9', '('],
+ 186: [';', ':'],
+ 187: ['=', '+'],
+ 188: [',', '<'],
+ 189: ['-', '_'],
+ 190: ['.', '>'],
+ 191: ['/', '?'],
+ 192: ['`', '~'],
+ 219: ['[', '{'],
+ 220: ['\\', '|'],
+ 221: [']', '}'],
+ 222: ['\'', '"']
+};
+function evaluateKeyboardEvent(ev, applicationCursorMode, isMac, macOptionIsMeta) {
+ var result = {
+ type: 0,
+ cancel: false,
+ key: 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 (applicationCursorMode) {
+ result.key = EscapeSequences_1.C0.ESC + 'OA';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[A';
+ }
+ }
+ else if (ev.key === 'UIKeyInputLeftArrow') {
+ if (applicationCursorMode) {
+ result.key = EscapeSequences_1.C0.ESC + 'OD';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[D';
+ }
+ }
+ else if (ev.key === 'UIKeyInputRightArrow') {
+ if (applicationCursorMode) {
+ result.key = EscapeSequences_1.C0.ESC + 'OC';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[C';
+ }
+ }
+ else if (ev.key === 'UIKeyInputDownArrow') {
+ if (applicationCursorMode) {
+ 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;
+ }
+ else if (ev.altKey) {
+ result.key = EscapeSequences_1.C0.ESC + EscapeSequences_1.C0.DEL;
+ 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 = isMac ? EscapeSequences_1.C0.ESC + 'b' : EscapeSequences_1.C0.ESC + '[1;5D';
+ }
+ }
+ else if (applicationCursorMode) {
+ 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 = isMac ? EscapeSequences_1.C0.ESC + 'f' : EscapeSequences_1.C0.ESC + '[1;5C';
+ }
+ }
+ else if (applicationCursorMode) {
+ 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 (applicationCursorMode) {
+ 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 (applicationCursorMode) {
+ 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 (applicationCursorMode) {
+ 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 (applicationCursorMode) {
+ result.key = EscapeSequences_1.C0.ESC + 'OF';
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[F';
+ }
+ break;
+ case 33:
+ if (ev.shiftKey) {
+ result.type = 2;
+ }
+ else {
+ result.key = EscapeSequences_1.C0.ESC + '[5~';
+ }
+ break;
+ case 34:
+ if (ev.shiftKey) {
+ result.type = 3;
+ }
+ 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 ((!isMac || macOptionIsMeta) && ev.altKey && !ev.metaKey) {
+ var keyMapping = KEYCODE_KEY_MAPPINGS[ev.keyCode];
+ var key = keyMapping && keyMapping[!ev.shiftKey ? 0 : 1];
+ if (key) {
+ result.key = EscapeSequences_1.C0.ESC + key;
+ }
+ else if (ev.keyCode >= 65 && ev.keyCode <= 90) {
+ var keyCode = ev.ctrlKey ? ev.keyCode - 64 : ev.keyCode + 32;
+ result.key = EscapeSequences_1.C0.ESC + String.fromCharCode(keyCode);
+ }
+ }
+ else if (isMac && !ev.altKey && !ev.ctrlKey && ev.metaKey) {
+ if (ev.keyCode === 65) {
+ result.type = 1;
+ }
+ }
+ break;
+ }
+ return result;
+}
+exports.evaluateKeyboardEvent = evaluateKeyboardEvent;
+
+},{"../../common/data/EscapeSequences":18}],21:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var EscapeSequences_1 = require("../common/data/EscapeSequences");
+var AltClickHandler = (function () {
+ function AltClickHandler(_mouseEvent, _terminal) {
+ this._mouseEvent = _mouseEvent;
+ this._terminal = _terminal;
+ this._lines = this._terminal.buffer.lines;
+ this._startCol = this._terminal.buffer.x;
+ this._startRow = this._terminal.buffer.y;
+ var coordinates = this._terminal.mouseHelper.getCoords(this._mouseEvent, this._terminal.element, this._terminal.charMeasure, this._terminal.options.lineHeight, this._terminal.cols, this._terminal.rows, false);
+ if (coordinates) {
+ _a = coordinates.map(function (coordinate) {
+ return coordinate - 1;
+ }), this._endCol = _a[0], this._endRow = _a[1];
+ }
+ var _a;
+ }
+ AltClickHandler.prototype.move = function () {
+ if (this._mouseEvent.altKey && this._endCol !== undefined && this._endRow !== undefined) {
+ this._terminal.handler(this._arrowSequences());
+ }
+ };
+ AltClickHandler.prototype._arrowSequences = function () {
+ if (!this._terminal.buffer.hasScrollback) {
+ return this._resetStartingRow() + this._moveToRequestedRow() + this._moveToRequestedCol();
+ }
+ return this._moveHorizontallyOnly();
+ };
+ AltClickHandler.prototype._resetStartingRow = function () {
+ if (this._moveToRequestedRow().length === 0) {
+ return '';
+ }
+ return repeat(this._bufferLine(this._startCol, this._startRow, this._startCol, this._startRow - this._wrappedRowsForRow(this._startRow), false).length, this._sequence("D"));
+ };
+ AltClickHandler.prototype._moveToRequestedRow = function () {
+ var startRow = this._startRow - this._wrappedRowsForRow(this._startRow);
+ var endRow = this._endRow - this._wrappedRowsForRow(this._endRow);
+ var rowsToMove = Math.abs(startRow - endRow) - this._wrappedRowsCount();
+ return repeat(rowsToMove, this._sequence(this._verticalDirection()));
+ };
+ AltClickHandler.prototype._moveToRequestedCol = function () {
+ var startRow;
+ if (this._moveToRequestedRow().length > 0) {
+ startRow = this._endRow - this._wrappedRowsForRow(this._endRow);
+ }
+ else {
+ startRow = this._startRow;
+ }
+ var endRow = this._endRow;
+ var direction = this._horizontalDirection();
+ return repeat(this._bufferLine(this._startCol, startRow, this._endCol, endRow, direction === "C").length, this._sequence(direction));
+ };
+ AltClickHandler.prototype._moveHorizontallyOnly = function () {
+ var direction = this._horizontalDirection();
+ return repeat(Math.abs(this._startCol - this._endCol), this._sequence(direction));
+ };
+ AltClickHandler.prototype._wrappedRowsCount = function () {
+ var wrappedRows = 0;
+ var startRow = this._startRow - this._wrappedRowsForRow(this._startRow);
+ var endRow = this._endRow - this._wrappedRowsForRow(this._endRow);
+ for (var i = 0; i < Math.abs(startRow - endRow); i++) {
+ var direction = this._verticalDirection() === "A" ? -1 : 1;
+ if (this._lines.get(startRow + (direction * i)).isWrapped) {
+ wrappedRows++;
+ }
+ }
+ return wrappedRows;
+ };
+ AltClickHandler.prototype._wrappedRowsForRow = function (currentRow) {
+ var rowCount = 0;
+ var lineWraps = this._lines.get(currentRow).isWrapped;
+ while (lineWraps && currentRow >= 0 && currentRow < this._terminal.rows) {
+ rowCount++;
+ currentRow--;
+ lineWraps = this._lines.get(currentRow).isWrapped;
+ }
+ return rowCount;
+ };
+ AltClickHandler.prototype._horizontalDirection = function () {
+ var startRow;
+ if (this._moveToRequestedRow().length > 0) {
+ startRow = this._endRow - this._wrappedRowsForRow(this._endRow);
+ }
+ else {
+ startRow = this._startRow;
+ }
+ if ((this._startCol < this._endCol &&
+ startRow <= this._endRow) ||
+ (this._startCol >= this._endCol &&
+ startRow < this._endRow)) {
+ return "C";
+ }
+ return "D";
+ };
+ AltClickHandler.prototype._verticalDirection = function () {
+ if (this._startRow > this._endRow) {
+ return "A";
+ }
+ return "B";
+ };
+ AltClickHandler.prototype._bufferLine = function (startCol, startRow, endCol, endRow, forward) {
+ var currentCol = startCol;
+ var currentRow = startRow;
+ var bufferStr = '';
+ while (currentCol !== endCol || currentRow !== endRow) {
+ currentCol += forward ? 1 : -1;
+ if (forward && currentCol > this._terminal.cols - 1) {
+ bufferStr += this._terminal.buffer.translateBufferLineToString(currentRow, false, startCol, currentCol);
+ currentCol = 0;
+ startCol = 0;
+ currentRow++;
+ }
+ else if (!forward && currentCol < 0) {
+ bufferStr += this._terminal.buffer.translateBufferLineToString(currentRow, false, 0, startCol + 1);
+ currentCol = this._terminal.cols - 1;
+ startCol = currentCol;
+ currentRow--;
+ }
+ }
+ return bufferStr + this._terminal.buffer.translateBufferLineToString(currentRow, false, startCol, currentCol);
+ };
+ AltClickHandler.prototype._sequence = function (direction) {
+ var mod = this._terminal.applicationCursor ? 'O' : '[';
+ return EscapeSequences_1.C0.ESC + mod + direction;
+ };
+ return AltClickHandler;
+}());
+exports.AltClickHandler = AltClickHandler;
+function repeat(count, str) {
+ count = Math.floor(count);
+ var rpt = '';
+ for (var i = 0; i < count; i++) {
+ rpt += str;
+ }
+ return rpt;
+}
+
+},{"../common/data/EscapeSequences":18}],22:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+function prepareTextForTerminal(text) {
+ return text.replace(/\r?\n/g, '\r');
+}
+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);
+ 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;
+ }, 200);
+}
+exports.moveTextAreaUnderMouseCursor = moveTextAreaUnderMouseCursor;
+function rightClickHandler(ev, textarea, selectionManager, shouldSelectWord) {
+ moveTextAreaUnderMouseCursor(ev, textarea);
+ if (shouldSelectWord && !selectionManager.isClickInSelection(ev)) {
+ selectionManager.selectWordAtCursor(ev);
+ }
+ textarea.value = selectionManager.selectionText;
+ textarea.select();
+}
+exports.rightClickHandler = rightClickHandler;
+
+},{}],23:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Terminal_1 = require("../Terminal");
+var Strings = require("../Strings");
+var Terminal = (function () {
+ function Terminal(options) {
+ this._core = new Terminal_1.Terminal(options);
+ }
+ Object.defineProperty(Terminal.prototype, "element", {
+ get: function () { return this._core.element; },
+ enumerable: true,
+ configurable: true
+ });
+ Object.defineProperty(Terminal.prototype, "textarea", {
+ get: function () { return this._core.textarea; },
+ enumerable: true,
+ configurable: true
+ });
+ Object.defineProperty(Terminal.prototype, "rows", {
+ get: function () { return this._core.rows; },
+ enumerable: true,
+ configurable: true
+ });
+ Object.defineProperty(Terminal.prototype, "cols", {
+ get: function () { return this._core.cols; },
+ enumerable: true,
+ configurable: true
+ });
+ Object.defineProperty(Terminal.prototype, "markers", {
+ get: function () { return this._core.markers; },
+ enumerable: true,
+ configurable: true
+ });
+ Terminal.prototype.blur = function () {
+ this._core.blur();
+ };
+ Terminal.prototype.focus = function () {
+ this._core.focus();
+ };
+ Terminal.prototype.on = function (type, listener) {
+ this._core.on(type, listener);
+ };
+ Terminal.prototype.off = function (type, listener) {
+ this._core.off(type, listener);
+ };
+ Terminal.prototype.emit = function (type, data) {
+ this._core.emit(type, data);
+ };
+ Terminal.prototype.addDisposableListener = function (type, handler) {
+ return this._core.addDisposableListener(type, handler);
+ };
+ Terminal.prototype.resize = function (columns, rows) {
+ this._core.resize(columns, rows);
+ };
+ Terminal.prototype.writeln = function (data) {
+ this._core.writeln(data);
+ };
+ Terminal.prototype.open = function (parent) {
+ this._core.open(parent);
+ };
+ Terminal.prototype.attachCustomKeyEventHandler = function (customKeyEventHandler) {
+ this._core.attachCustomKeyEventHandler(customKeyEventHandler);
+ };
+ Terminal.prototype.registerLinkMatcher = function (regex, handler, options) {
+ return this._core.registerLinkMatcher(regex, handler, options);
+ };
+ Terminal.prototype.deregisterLinkMatcher = function (matcherId) {
+ this._core.deregisterLinkMatcher(matcherId);
+ };
+ Terminal.prototype.registerCharacterJoiner = function (handler) {
+ return this._core.registerCharacterJoiner(handler);
+ };
+ Terminal.prototype.deregisterCharacterJoiner = function (joinerId) {
+ this._core.deregisterCharacterJoiner(joinerId);
+ };
+ Terminal.prototype.addMarker = function (cursorYOffset) {
+ return this._core.addMarker(cursorYOffset);
+ };
+ Terminal.prototype.hasSelection = function () {
+ return this._core.hasSelection();
+ };
+ Terminal.prototype.getSelection = function () {
+ return this._core.getSelection();
+ };
+ Terminal.prototype.clearSelection = function () {
+ this._core.clearSelection();
+ };
+ Terminal.prototype.selectAll = function () {
+ this._core.selectAll();
+ };
+ Terminal.prototype.selectLines = function (start, end) {
+ this._core.selectLines(start, end);
+ };
+ Terminal.prototype.dispose = function () {
+ this._core.dispose();
+ };
+ Terminal.prototype.destroy = function () {
+ this._core.destroy();
+ };
+ Terminal.prototype.scrollLines = function (amount) {
+ this._core.scrollLines(amount);
+ };
+ Terminal.prototype.scrollPages = function (pageCount) {
+ this._core.scrollPages(pageCount);
+ };
+ Terminal.prototype.scrollToTop = function () {
+ this._core.scrollToTop();
+ };
+ Terminal.prototype.scrollToBottom = function () {
+ this._core.scrollToBottom();
+ };
+ Terminal.prototype.scrollToLine = function (line) {
+ this._core.scrollToLine(line);
+ };
+ Terminal.prototype.clear = function () {
+ this._core.clear();
+ };
+ Terminal.prototype.write = function (data) {
+ this._core.write(data);
+ };
+ Terminal.prototype.getOption = function (key) {
+ return this._core.getOption(key);
+ };
+ Terminal.prototype.setOption = function (key, value) {
+ this._core.setOption(key, value);
+ };
+ Terminal.prototype.refresh = function (start, end) {
+ this._core.refresh(start, end);
+ };
+ Terminal.prototype.reset = function () {
+ this._core.reset();
+ };
+ Terminal.applyAddon = function (addon) {
+ addon.apply(Terminal);
+ };
+ Object.defineProperty(Terminal, "strings", {
+ get: function () {
+ return Strings;
+ },
+ enumerable: true,
+ configurable: true
+ });
+ return Terminal;
+}());
+exports.Terminal = Terminal;
+
+},{"../Strings":13,"../Terminal":14}],24:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Types_1 = require("./atlas/Types");
+var CharAtlasCache_1 = require("./atlas/CharAtlasCache");
+var Buffer_1 = require("../Buffer");
+var BaseRenderLayer = (function () {
+ function BaseRenderLayer(_container, id, zIndex, _alpha, _colors) {
+ this._container = _container;
+ 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.classList.add("xterm-" + id + "-layer");
+ this._canvas.style.zIndex = zIndex.toString();
+ this._initCanvas();
+ this._container.appendChild(this._canvas);
+ }
+ BaseRenderLayer.prototype.dispose = function () {
+ this._container.removeChild(this._canvas);
+ };
+ BaseRenderLayer.prototype._initCanvas = function () {
+ this._ctx = this._canvas.getContext('2d', { alpha: this._alpha });
+ if (!this._alpha) {
+ this.clearAll();
+ }
+ };
+ 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, columnSelectMode) {
+ if (columnSelectMode === void 0) { columnSelectMode = false; }
+ };
+ BaseRenderLayer.prototype.onThemeChanged = function (terminal, colorSet) {
+ this._refreshCharAtlas(terminal, colorSet);
+ };
+ BaseRenderLayer.prototype.setTransparency = function (terminal, alpha) {
+ if (alpha === this._alpha) {
+ return;
+ }
+ var oldCanvas = this._canvas;
+ this._alpha = alpha;
+ this._canvas = this._canvas.cloneNode();
+ this._initCanvas();
+ this._container.replaceChild(this._canvas, oldCanvas);
+ this._refreshCharAtlas(terminal, this._colors);
+ this.onGridChanged(terminal, 0, terminal.rows - 1);
+ };
+ BaseRenderLayer.prototype._refreshCharAtlas = function (terminal, colorSet) {
+ if (this._scaledCharWidth <= 0 && this._scaledCharHeight <= 0) {
+ return;
+ }
+ this._charAtlas = CharAtlasCache_1.acquireCharAtlas(terminal, colorSet, this._scaledCharWidth, this._scaledCharHeight);
+ this._charAtlas.warmUp();
+ };
+ BaseRenderLayer.prototype.resize = function (terminal, dim) {
+ 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();
+ }
+ 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.css;
+ 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.css;
+ 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 = this._getFont(terminal, false, false);
+ 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.drawChars = function (terminal, chars, code, width, x, y, fg, bg, bold, dim, italic) {
+ var drawInBrightColor = terminal.options.drawBoldTextInBrightColors && bold && fg < 8 && fg !== Types_1.INVERTED_DEFAULT_COLOR;
+ fg += drawInBrightColor ? 8 : 0;
+ var atlasDidDraw = this._charAtlas && this._charAtlas.draw(this._ctx, { chars: chars, code: code, bg: bg, fg: fg, bold: bold && terminal.options.enableBold, dim: dim, italic: italic }, x * this._scaledCellWidth + this._scaledCharLeft, y * this._scaledCellHeight + this._scaledCharTop);
+ if (!atlasDidDraw) {
+ this._drawUncachedChars(terminal, chars, width, fg, x, y, bold && terminal.options.enableBold, dim, italic);
+ }
+ };
+ BaseRenderLayer.prototype._drawUncachedChars = function (terminal, chars, width, fg, x, y, bold, dim, italic) {
+ this._ctx.save();
+ this._ctx.font = this._getFont(terminal, bold, italic);
+ this._ctx.textBaseline = 'top';
+ if (fg === Types_1.INVERTED_DEFAULT_COLOR) {
+ this._ctx.fillStyle = this._colors.background.css;
+ }
+ else if (fg < 256) {
+ this._ctx.fillStyle = this._colors.ansi[fg].css;
+ }
+ else {
+ this._ctx.fillStyle = this._colors.foreground.css;
+ }
+ this._clipRow(terminal, y);
+ if (dim) {
+ this._ctx.globalAlpha = Types_1.DIM_OPACITY;
+ }
+ this._ctx.fillText(chars, 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();
+ };
+ BaseRenderLayer.prototype._getFont = function (terminal, isBold, isItalic) {
+ var fontWeight = isBold ? terminal.options.fontWeightBold : terminal.options.fontWeight;
+ var fontStyle = isItalic ? 'italic' : '';
+ return fontStyle + " " + fontWeight + " " + terminal.options.fontSize * window.devicePixelRatio + "px " + terminal.options.fontFamily;
+ };
+ return BaseRenderLayer;
+}());
+exports.BaseRenderLayer = BaseRenderLayer;
+
+},{"../Buffer":2,"./atlas/CharAtlasCache":34,"./atlas/Types":40}],25:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Buffer_1 = require("../Buffer");
+var CharacterJoinerRegistry = (function () {
+ function CharacterJoinerRegistry(_terminal) {
+ this._terminal = _terminal;
+ this._characterJoiners = [];
+ this._nextCharacterJoinerId = 0;
+ }
+ CharacterJoinerRegistry.prototype.registerCharacterJoiner = function (handler) {
+ var joiner = {
+ id: this._nextCharacterJoinerId++,
+ handler: handler
+ };
+ this._characterJoiners.push(joiner);
+ return joiner.id;
+ };
+ CharacterJoinerRegistry.prototype.deregisterCharacterJoiner = function (joinerId) {
+ for (var i = 0; i < this._characterJoiners.length; i++) {
+ if (this._characterJoiners[i].id === joinerId) {
+ this._characterJoiners.splice(i, 1);
+ return true;
+ }
+ }
+ return false;
+ };
+ CharacterJoinerRegistry.prototype.getJoinedCharacters = function (row) {
+ if (this._characterJoiners.length === 0) {
+ return [];
+ }
+ var line = this._terminal.buffer.lines.get(row);
+ if (line.length === 0) {
+ return [];
+ }
+ var ranges = [];
+ var lineStr = this._terminal.buffer.translateBufferLineToString(row, true);
+ var rangeStartColumn = 0;
+ var currentStringIndex = 0;
+ var rangeStartStringIndex = 0;
+ var rangeAttr = line[0][Buffer_1.CHAR_DATA_ATTR_INDEX] >> 9;
+ for (var x = 0; x < this._terminal.cols; x++) {
+ var charData = line[x];
+ var chars = charData[Buffer_1.CHAR_DATA_CHAR_INDEX];
+ var width = charData[Buffer_1.CHAR_DATA_WIDTH_INDEX];
+ var attr = charData[Buffer_1.CHAR_DATA_ATTR_INDEX] >> 9;
+ if (width === 0) {
+ continue;
+ }
+ if (attr !== rangeAttr) {
+ if (x - rangeStartColumn > 1) {
+ var joinedRanges = this._getJoinedRanges(lineStr, rangeStartStringIndex, currentStringIndex, line, rangeStartColumn);
+ for (var i = 0; i < joinedRanges.length; i++) {
+ ranges.push(joinedRanges[i]);
+ }
+ }
+ rangeStartColumn = x;
+ rangeStartStringIndex = currentStringIndex;
+ rangeAttr = attr;
+ }
+ currentStringIndex += chars.length;
+ }
+ if (this._terminal.cols - rangeStartColumn > 1) {
+ var joinedRanges = this._getJoinedRanges(lineStr, rangeStartStringIndex, currentStringIndex, line, rangeStartColumn);
+ for (var i = 0; i < joinedRanges.length; i++) {
+ ranges.push(joinedRanges[i]);
+ }
+ }
+ return ranges;
+ };
+ CharacterJoinerRegistry.prototype._getJoinedRanges = function (line, startIndex, endIndex, lineData, startCol) {
+ var text = line.substring(startIndex, endIndex);
+ var joinedRanges = this._characterJoiners[0].handler(text);
+ for (var i = 1; i < this._characterJoiners.length; i++) {
+ var joinerRanges = this._characterJoiners[i].handler(text);
+ for (var j = 0; j < joinerRanges.length; j++) {
+ CharacterJoinerRegistry._mergeRanges(joinedRanges, joinerRanges[j]);
+ }
+ }
+ this._stringRangesToCellRanges(joinedRanges, lineData, startCol);
+ return joinedRanges;
+ };
+ CharacterJoinerRegistry.prototype._stringRangesToCellRanges = function (ranges, line, startCol) {
+ var currentRangeIndex = 0;
+ var currentRangeStarted = false;
+ var currentStringIndex = 0;
+ var currentRange = ranges[currentRangeIndex];
+ if (!currentRange) {
+ return;
+ }
+ for (var x = startCol; x < this._terminal.cols; x++) {
+ var charData = line[x];
+ var width = charData[Buffer_1.CHAR_DATA_WIDTH_INDEX];
+ var length_1 = charData[Buffer_1.CHAR_DATA_CHAR_INDEX].length;
+ if (width === 0) {
+ continue;
+ }
+ if (!currentRangeStarted && currentRange[0] <= currentStringIndex) {
+ currentRange[0] = x;
+ currentRangeStarted = true;
+ }
+ if (currentRange[1] <= currentStringIndex) {
+ currentRange[1] = x;
+ currentRange = ranges[++currentRangeIndex];
+ if (!currentRange) {
+ break;
+ }
+ if (currentRange[0] <= currentStringIndex) {
+ currentRange[0] = x;
+ currentRangeStarted = true;
+ }
+ else {
+ currentRangeStarted = false;
+ }
+ }
+ currentStringIndex += length_1;
+ }
+ if (currentRange) {
+ currentRange[1] = this._terminal.cols;
+ }
+ };
+ CharacterJoinerRegistry._mergeRanges = function (ranges, newRange) {
+ var inRange = false;
+ for (var i = 0; i < ranges.length; i++) {
+ var range = ranges[i];
+ if (!inRange) {
+ if (newRange[1] <= range[0]) {
+ ranges.splice(i, 0, newRange);
+ return ranges;
+ }
+ if (newRange[1] <= range[1]) {
+ range[0] = Math.min(newRange[0], range[0]);
+ return ranges;
+ }
+ if (newRange[0] < range[1]) {
+ range[0] = Math.min(newRange[0], range[0]);
+ inRange = true;
+ }
+ continue;
+ }
+ else {
+ if (newRange[1] <= range[0]) {
+ ranges[i - 1][1] = newRange[1];
+ return ranges;
+ }
+ if (newRange[1] <= range[1]) {
+ ranges[i - 1][1] = Math.max(newRange[1], range[1]);
+ ranges.splice(i, 1);
+ inRange = false;
+ return ranges;
+ }
+ ranges.splice(i, 1);
+ i--;
+ }
+ }
+ if (inRange) {
+ ranges[ranges.length - 1][1] = newRange[1];
+ }
+ else {
+ ranges.push(newRange);
+ }
+ return ranges;
+ };
+ return CharacterJoinerRegistry;
+}());
+exports.CharacterJoinerRegistry = CharacterJoinerRegistry;
+
+},{"../Buffer":2}],26:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var DEFAULT_FOREGROUND = fromHex('#ffffff');
+var DEFAULT_BACKGROUND = fromHex('#000000');
+var DEFAULT_CURSOR = fromHex('#ffffff');
+var DEFAULT_CURSOR_ACCENT = fromHex('#000000');
+var DEFAULT_SELECTION = {
+ css: 'rgba(255, 255, 255, 0.3)',
+ rgba: 0xFFFFFF77
+};
+exports.DEFAULT_ANSI_COLORS = (function () {
+ var colors = [
+ fromHex('#2e3436'),
+ fromHex('#cc0000'),
+ fromHex('#4e9a06'),
+ fromHex('#c4a000'),
+ fromHex('#3465a4'),
+ fromHex('#75507b'),
+ fromHex('#06989a'),
+ fromHex('#d3d7cf'),
+ fromHex('#555753'),
+ fromHex('#ef2929'),
+ fromHex('#8ae234'),
+ fromHex('#fce94f'),
+ fromHex('#729fcf'),
+ fromHex('#ad7fa8'),
+ fromHex('#34e2e2'),
+ fromHex('#eeeeec')
+ ];
+ var v = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff];
+ for (var i = 0; i < 216; i++) {
+ var r = v[(i / 36) % 6 | 0];
+ var g = v[(i / 6) % 6 | 0];
+ var b = v[i % 6];
+ colors.push({
+ css: "#" + toPaddedHex(r) + toPaddedHex(g) + toPaddedHex(b),
+ rgba: ((r << 24) | (g << 16) | (b << 8) | 0xFF) >>> 0
+ });
+ }
+ for (var i = 0; i < 24; i++) {
+ var c = 8 + i * 10;
+ var ch = toPaddedHex(c);
+ colors.push({
+ css: "#" + ch + ch + ch,
+ rgba: ((c << 24) | (c << 16) | (c << 8) | 0xFF) >>> 0
+ });
+ }
+ return colors;
+})();
+function fromHex(css) {
+ return {
+ css: css,
+ rgba: parseInt(css.slice(1), 16) << 8 | 0xFF
+ };
+}
+function toPaddedHex(c) {
+ var s = c.toString(16);
+ return s.length < 2 ? '0' + s : s;
+}
+var ColorManager = (function () {
+ function ColorManager(document, allowTransparency) {
+ this.allowTransparency = allowTransparency;
+ var canvas = document.createElement('canvas');
+ canvas.width = 1;
+ canvas.height = 1;
+ this._ctx = canvas.getContext('2d');
+ this._ctx.globalCompositeOperation = 'copy';
+ this._litmusColor = this._ctx.createLinearGradient(0, 0, 1, 1);
+ this.colors = {
+ foreground: DEFAULT_FOREGROUND,
+ background: DEFAULT_BACKGROUND,
+ cursor: DEFAULT_CURSOR,
+ cursorAccent: DEFAULT_CURSOR_ACCENT,
+ selection: DEFAULT_SELECTION,
+ ansi: exports.DEFAULT_ANSI_COLORS.slice()
+ };
+ }
+ ColorManager.prototype.setTheme = function (theme) {
+ this.colors.foreground = this._parseColor(theme.foreground, DEFAULT_FOREGROUND);
+ this.colors.background = this._parseColor(theme.background, DEFAULT_BACKGROUND);
+ this.colors.cursor = this._parseColor(theme.cursor, DEFAULT_CURSOR, true);
+ this.colors.cursorAccent = this._parseColor(theme.cursorAccent, DEFAULT_CURSOR_ACCENT, true);
+ this.colors.selection = this._parseColor(theme.selection, DEFAULT_SELECTION, true);
+ this.colors.ansi[0] = this._parseColor(theme.black, exports.DEFAULT_ANSI_COLORS[0]);
+ this.colors.ansi[1] = this._parseColor(theme.red, exports.DEFAULT_ANSI_COLORS[1]);
+ this.colors.ansi[2] = this._parseColor(theme.green, exports.DEFAULT_ANSI_COLORS[2]);
+ this.colors.ansi[3] = this._parseColor(theme.yellow, exports.DEFAULT_ANSI_COLORS[3]);
+ this.colors.ansi[4] = this._parseColor(theme.blue, exports.DEFAULT_ANSI_COLORS[4]);
+ this.colors.ansi[5] = this._parseColor(theme.magenta, exports.DEFAULT_ANSI_COLORS[5]);
+ this.colors.ansi[6] = this._parseColor(theme.cyan, exports.DEFAULT_ANSI_COLORS[6]);
+ this.colors.ansi[7] = this._parseColor(theme.white, exports.DEFAULT_ANSI_COLORS[7]);
+ this.colors.ansi[8] = this._parseColor(theme.brightBlack, exports.DEFAULT_ANSI_COLORS[8]);
+ this.colors.ansi[9] = this._parseColor(theme.brightRed, exports.DEFAULT_ANSI_COLORS[9]);
+ this.colors.ansi[10] = this._parseColor(theme.brightGreen, exports.DEFAULT_ANSI_COLORS[10]);
+ this.colors.ansi[11] = this._parseColor(theme.brightYellow, exports.DEFAULT_ANSI_COLORS[11]);
+ this.colors.ansi[12] = this._parseColor(theme.brightBlue, exports.DEFAULT_ANSI_COLORS[12]);
+ this.colors.ansi[13] = this._parseColor(theme.brightMagenta, exports.DEFAULT_ANSI_COLORS[13]);
+ this.colors.ansi[14] = this._parseColor(theme.brightCyan, exports.DEFAULT_ANSI_COLORS[14]);
+ this.colors.ansi[15] = this._parseColor(theme.brightWhite, exports.DEFAULT_ANSI_COLORS[15]);
+ };
+ ColorManager.prototype._parseColor = function (css, fallback, allowTransparency) {
+ if (allowTransparency === void 0) { allowTransparency = this.allowTransparency; }
+ if (!css) {
+ return fallback;
+ }
+ this._ctx.fillStyle = this._litmusColor;
+ this._ctx.fillStyle = css;
+ if (typeof this._ctx.fillStyle !== 'string') {
+ console.warn("Color: " + css + " is invalid using fallback " + fallback.css);
+ return fallback;
+ }
+ this._ctx.fillRect(0, 0, 1, 1);
+ var data = this._ctx.getImageData(0, 0, 1, 1).data;
+ if (!allowTransparency && data[3] !== 0xFF) {
+ console.warn("Color: " + css + " is using transparency, but allowTransparency is false. " +
+ ("Using fallback " + fallback.css + "."));
+ return fallback;
+ }
+ return {
+ css: css,
+ rgba: (data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]) >>> 0
+ };
+ };
+ return ColorManager;
+}());
+exports.ColorManager = ColorManager;
+
+},{}],27:[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) {
+ _super.prototype.resize.call(this, terminal, dim);
+ 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);
+ }
+ else {
+ this._cursorBlinkStateManager.restartBlinkAnimation(terminal);
+ }
+ };
+ 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.css;
+ 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.css;
+ this.fillLeftLineAtCell(x, y);
+ this._ctx.restore();
+ };
+ CursorRenderLayer.prototype._renderBlockCursor = function (terminal, x, y, charData) {
+ this._ctx.save();
+ this._ctx.fillStyle = this._colors.cursor.css;
+ this.fillCells(x, y, charData[Buffer_1.CHAR_DATA_WIDTH_INDEX], 1);
+ this._ctx.fillStyle = this._colors.cursorAccent.css;
+ 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.css;
+ this.fillBottomLineAtCells(x, y);
+ this._ctx.restore();
+ };
+ CursorRenderLayer.prototype._renderBlurCursor = function (terminal, x, y, charData) {
+ this._ctx.save();
+ this._ctx.strokeStyle = this._colors.cursor.css;
+ 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":2,"./BaseRenderLayer":24}],28:[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;
+
+},{}],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 BaseRenderLayer_1 = require("./BaseRenderLayer");
+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("linkhover", function (e) { return _this._onLinkHover(e); });
+ terminal.linkifier.on("linkleave", function (e) { return _this._onLinkLeave(e); });
+ return _this;
+ }
+ LinkRenderLayer.prototype.resize = function (terminal, dim) {
+ _super.prototype.resize.call(this, terminal, dim);
+ this._state = null;
+ };
+ LinkRenderLayer.prototype.reset = function (terminal) {
+ this._clearCurrentLink();
+ };
+ LinkRenderLayer.prototype._clearCurrentLink = function () {
+ if (this._state) {
+ this.clearCells(this._state.x1, this._state.y1, this._state.cols - this._state.x1, 1);
+ var middleRowCount = this._state.y2 - this._state.y1 - 1;
+ if (middleRowCount > 0) {
+ this.clearCells(0, this._state.y1 + 1, this._state.cols, middleRowCount);
+ }
+ this.clearCells(0, this._state.y2, this._state.x2, 1);
+ this._state = null;
+ }
+ };
+ LinkRenderLayer.prototype._onLinkHover = function (e) {
+ this._ctx.fillStyle = this._colors.foreground.css;
+ if (e.y1 === e.y2) {
+ this.fillBottomLineAtCells(e.x1, e.y1, e.x2 - e.x1);
+ }
+ else {
+ this.fillBottomLineAtCells(e.x1, e.y1, e.cols - e.x1);
+ for (var y = e.y1 + 1; y < e.y2; y++) {
+ this.fillBottomLineAtCells(0, y, e.cols);
+ }
+ this.fillBottomLineAtCells(0, e.y2, e.x2);
+ }
+ this._state = e;
+ };
+ LinkRenderLayer.prototype._onLinkLeave = function (e) {
+ this._clearCurrentLink();
+ };
+ return LinkRenderLayer;
+}(BaseRenderLayer_1.BaseRenderLayer));
+exports.LinkRenderLayer = LinkRenderLayer;
+
+},{"./BaseRenderLayer":24}],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 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 RenderDebouncer_1 = require("../ui/RenderDebouncer");
+var ScreenDprMonitor_1 = require("../ui/ScreenDprMonitor");
+var CharacterJoinerRegistry_1 = require("../renderer/CharacterJoinerRegistry");
+var Renderer = (function (_super) {
+ __extends(Renderer, _super);
+ function Renderer(_terminal, theme) {
+ var _this = _super.call(this) || this;
+ _this._terminal = _terminal;
+ _this._isPaused = false;
+ _this._needsFullRefresh = false;
+ var allowTransparency = _this._terminal.options.allowTransparency;
+ _this.colorManager = new ColorManager_1.ColorManager(document, allowTransparency);
+ _this._characterJoinerRegistry = new CharacterJoinerRegistry_1.CharacterJoinerRegistry(_terminal);
+ if (theme) {
+ _this.colorManager.setTheme(theme);
+ }
+ _this._renderLayers = [
+ new TextRenderLayer_1.TextRenderLayer(_this._terminal.screenElement, 0, _this.colorManager.colors, _this._characterJoinerRegistry, allowTransparency),
+ new SelectionRenderLayer_1.SelectionRenderLayer(_this._terminal.screenElement, 1, _this.colorManager.colors),
+ new LinkRenderLayer_1.LinkRenderLayer(_this._terminal.screenElement, 2, _this.colorManager.colors, _this._terminal),
+ new CursorRenderLayer_1.CursorRenderLayer(_this._terminal.screenElement, 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;
+ _this._updateDimensions();
+ _this.onOptionsChanged();
+ _this._renderDebouncer = new RenderDebouncer_1.RenderDebouncer(_this._terminal, _this._renderRows.bind(_this));
+ _this._screenDprMonitor = new ScreenDprMonitor_1.ScreenDprMonitor();
+ _this._screenDprMonitor.setListener(function () { return _this.onWindowResize(window.devicePixelRatio); });
+ _this.register(_this._screenDprMonitor);
+ if ('IntersectionObserver' in window) {
+ var observer_1 = new IntersectionObserver(function (e) { return _this.onIntersectionChange(e[0]); }, { threshold: 0 });
+ observer_1.observe(_this._terminal.element);
+ _this.register({ dispose: function () { return observer_1.disconnect(); } });
+ }
+ return _this;
+ }
+ Renderer.prototype.dispose = function () {
+ _super.prototype.dispose.call(this);
+ this._renderLayers.forEach(function (l) { return l.dispose(); });
+ };
+ Renderer.prototype.onIntersectionChange = function (entry) {
+ this._isPaused = entry.intersectionRatio === 0;
+ if (!this._isPaused && this._needsFullRefresh) {
+ this._terminal.refresh(0, this._terminal.rows - 1);
+ }
+ };
+ Renderer.prototype.onWindowResize = function (devicePixelRatio) {
+ if (this._devicePixelRatio !== devicePixelRatio) {
+ this._devicePixelRatio = devicePixelRatio;
+ this.onResize(this._terminal.cols, this._terminal.rows);
+ }
+ };
+ 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);
+ });
+ if (this._isPaused) {
+ this._needsFullRefresh = true;
+ }
+ else {
+ this._terminal.refresh(0, this._terminal.rows - 1);
+ }
+ return this.colorManager.colors;
+ };
+ Renderer.prototype.onResize = function (cols, rows) {
+ var _this = this;
+ this._updateDimensions();
+ this._renderLayers.forEach(function (l) { return l.resize(_this._terminal, _this.dimensions); });
+ if (this._isPaused) {
+ this._needsFullRefresh = true;
+ }
+ else {
+ this._terminal.refresh(0, this._terminal.rows - 1);
+ }
+ this._terminal.screenElement.style.width = this.dimensions.canvasWidth + "px";
+ this._terminal.screenElement.style.height = this.dimensions.canvasHeight + "px";
+ this.emit('resize', {
+ width: this.dimensions.canvasWidth,
+ height: this.dimensions.canvasHeight
+ });
+ };
+ Renderer.prototype.onCharSizeChanged = function () {
+ this.onResize(this._terminal.cols, this._terminal.rows);
+ };
+ Renderer.prototype.onBlur = function () {
+ var _this = this;
+ this._runOperation(function (l) { return l.onBlur(_this._terminal); });
+ };
+ Renderer.prototype.onFocus = function () {
+ var _this = this;
+ this._runOperation(function (l) { return l.onFocus(_this._terminal); });
+ };
+ Renderer.prototype.onSelectionChanged = function (start, end, columnSelectMode) {
+ var _this = this;
+ if (columnSelectMode === void 0) { columnSelectMode = false; }
+ this._runOperation(function (l) { return l.onSelectionChanged(_this._terminal, start, end, columnSelectMode); });
+ };
+ Renderer.prototype.onCursorMove = function () {
+ var _this = this;
+ this._runOperation(function (l) { return l.onCursorMove(_this._terminal); });
+ };
+ Renderer.prototype.onOptionsChanged = function () {
+ var _this = this;
+ this.colorManager.allowTransparency = this._terminal.options.allowTransparency;
+ this._runOperation(function (l) { return l.onOptionsChanged(_this._terminal); });
+ };
+ Renderer.prototype.clear = function () {
+ var _this = this;
+ this._runOperation(function (l) { return l.reset(_this._terminal); });
+ };
+ Renderer.prototype._runOperation = function (operation) {
+ if (this._isPaused) {
+ this._needsFullRefresh = true;
+ }
+ else {
+ this._renderLayers.forEach(function (l) { return operation(l); });
+ }
+ };
+ Renderer.prototype.refreshRows = function (start, end) {
+ if (this._isPaused) {
+ this._needsFullRefresh = true;
+ return;
+ }
+ this._renderDebouncer.refresh(start, end);
+ };
+ Renderer.prototype._renderRows = function (start, end) {
+ var _this = this;
+ this._renderLayers.forEach(function (l) { return l.onGridChanged(_this._terminal, start, end); });
+ this._terminal.emit('refresh', { start: start, end: end });
+ };
+ Renderer.prototype._updateDimensions = function () {
+ 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;
+ };
+ Renderer.prototype.registerCharacterJoiner = function (handler) {
+ return this._characterJoinerRegistry.registerCharacterJoiner(handler);
+ };
+ Renderer.prototype.deregisterCharacterJoiner = function (joinerId) {
+ return this._characterJoinerRegistry.deregisterCharacterJoiner(joinerId);
+ };
+ return Renderer;
+}(EventEmitter_1.EventEmitter));
+exports.Renderer = Renderer;
+
+},{"../EventEmitter":7,"../renderer/CharacterJoinerRegistry":25,"../ui/RenderDebouncer":49,"../ui/ScreenDprMonitor":50,"./ColorManager":26,"./CursorRenderLayer":27,"./LinkRenderLayer":29,"./SelectionRenderLayer":31,"./TextRenderLayer":32}],31:[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._clearState();
+ return _this;
+ }
+ SelectionRenderLayer.prototype._clearState = function () {
+ this._state = {
+ start: null,
+ end: null,
+ columnSelectMode: null,
+ ydisp: null
+ };
+ };
+ SelectionRenderLayer.prototype.resize = function (terminal, dim) {
+ _super.prototype.resize.call(this, terminal, dim);
+ this._clearState();
+ };
+ SelectionRenderLayer.prototype.reset = function (terminal) {
+ if (this._state.start && this._state.end) {
+ this._clearState();
+ this.clearAll();
+ }
+ };
+ SelectionRenderLayer.prototype.onSelectionChanged = function (terminal, start, end, columnSelectMode) {
+ if (!this._didStateChange(start, end, columnSelectMode, terminal.buffer.ydisp)) {
+ 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;
+ }
+ this._ctx.fillStyle = this._colors.selection.css;
+ if (columnSelectMode) {
+ var startCol = start[0];
+ var width = end[0] - startCol;
+ var height = viewportCappedEndRow - viewportCappedStartRow + 1;
+ this.fillCells(startCol, viewportCappedStartRow, width, height);
+ }
+ else {
+ var startCol = viewportStartRow === viewportCappedStartRow ? start[0] : 0;
+ var startRowEndCol = viewportCappedStartRow === viewportCappedEndRow ? end[0] : terminal.cols;
+ 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]];
+ this._state.columnSelectMode = columnSelectMode;
+ this._state.ydisp = terminal.buffer.ydisp;
+ };
+ SelectionRenderLayer.prototype._didStateChange = function (start, end, columnSelectMode, ydisp) {
+ return !this._areCoordinatesEqual(start, this._state.start) ||
+ !this._areCoordinatesEqual(end, this._state.end) ||
+ columnSelectMode !== this._state.columnSelectMode ||
+ ydisp !== this._state.ydisp;
+ };
+ SelectionRenderLayer.prototype._areCoordinatesEqual = function (coord1, coord2) {
+ if (!coord1 || !coord2) {
+ return false;
+ }
+ return coord1[0] === coord2[0] && coord1[1] === coord2[1];
+ };
+ return SelectionRenderLayer;
+}(BaseRenderLayer_1.BaseRenderLayer));
+exports.SelectionRenderLayer = SelectionRenderLayer;
+
+},{"./BaseRenderLayer":24}],32:[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("./atlas/Types");
+var GridCache_1 = require("./GridCache");
+var BaseRenderLayer_1 = require("./BaseRenderLayer");
+var TextRenderLayer = (function (_super) {
+ __extends(TextRenderLayer, _super);
+ function TextRenderLayer(container, zIndex, colors, characterJoinerRegistry, alpha) {
+ var _this = _super.call(this, container, 'text', zIndex, alpha, colors) || this;
+ _this._characterOverlapCache = {};
+ _this._state = new GridCache_1.GridCache();
+ _this._characterJoinerRegistry = characterJoinerRegistry;
+ return _this;
+ }
+ TextRenderLayer.prototype.resize = function (terminal, dim) {
+ _super.prototype.resize.call(this, terminal, dim);
+ var terminalFont = this._getFont(terminal, false, false);
+ 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._forEachCell = function (terminal, firstRow, lastRow, joinerRegistry, callback) {
+ for (var y = firstRow; y <= lastRow; y++) {
+ var row = y + terminal.buffer.ydisp;
+ var line = terminal.buffer.lines.get(row);
+ var joinedRanges = joinerRegistry ? joinerRegistry.getJoinedCharacters(row) : [];
+ for (var x = 0; x < terminal.cols; x++) {
+ var charData = line[x];
+ var code = charData[Buffer_1.CHAR_DATA_CODE_INDEX];
+ var chars = 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];
+ var isJoined = false;
+ var lastCharX = x;
+ if (width === 0) {
+ continue;
+ }
+ if (joinedRanges.length > 0 && x === joinedRanges[0][0]) {
+ isJoined = true;
+ var range = joinedRanges.shift();
+ chars = terminal.buffer.translateBufferLineToString(row, true, range[0], range[1]);
+ width = range[1] - range[0];
+ code = Infinity;
+ lastCharX = range[1] - 1;
+ }
+ if (!isJoined && this._isOverlapping(charData)) {
+ if (lastCharX < line.length - 1 && line[lastCharX + 1][Buffer_1.CHAR_DATA_CODE_INDEX] === Buffer_1.NULL_CELL_CODE) {
+ width = 2;
+ }
+ }
+ var flags = attr >> 18;
+ var bg = attr & 0x1ff;
+ var fg = (attr >> 9) & 0x1ff;
+ if (flags & 8) {
+ var temp = bg;
+ bg = fg;
+ fg = temp;
+ if (fg === 256) {
+ fg = Types_1.INVERTED_DEFAULT_COLOR;
+ }
+ if (bg === 257) {
+ bg = Types_1.INVERTED_DEFAULT_COLOR;
+ }
+ }
+ callback(code, chars, width, x, y, fg, bg, flags);
+ x = lastCharX;
+ }
+ }
+ };
+ TextRenderLayer.prototype._drawBackground = function (terminal, firstRow, lastRow) {
+ var _this = this;
+ var ctx = this._ctx;
+ var cols = terminal.cols;
+ var startX = 0;
+ var startY = 0;
+ var prevFillStyle = null;
+ ctx.save();
+ this._forEachCell(terminal, firstRow, lastRow, null, function (code, chars, width, x, y, fg, bg, flags) {
+ var nextFillStyle = null;
+ if (bg === Types_1.INVERTED_DEFAULT_COLOR) {
+ nextFillStyle = _this._colors.foreground.css;
+ }
+ else if (bg < 256) {
+ nextFillStyle = _this._colors.ansi[bg].css;
+ }
+ if (prevFillStyle === null) {
+ startX = x;
+ startY = y;
+ }
+ if (y !== startY) {
+ ctx.fillStyle = prevFillStyle;
+ _this.fillCells(startX, startY, cols - startX, 1);
+ startX = x;
+ startY = y;
+ }
+ else if (prevFillStyle !== nextFillStyle) {
+ ctx.fillStyle = prevFillStyle;
+ _this.fillCells(startX, startY, x - startX, 1);
+ startX = x;
+ startY = y;
+ }
+ prevFillStyle = nextFillStyle;
+ });
+ if (prevFillStyle !== null) {
+ ctx.fillStyle = prevFillStyle;
+ this.fillCells(startX, startY, cols - startX, 1);
+ }
+ ctx.restore();
+ };
+ TextRenderLayer.prototype._drawForeground = function (terminal, firstRow, lastRow) {
+ var _this = this;
+ this._forEachCell(terminal, firstRow, lastRow, this._characterJoinerRegistry, function (code, chars, width, x, y, fg, bg, flags) {
+ if (flags & 16) {
+ return;
+ }
+ if (flags & 2) {
+ _this._ctx.save();
+ if (fg === Types_1.INVERTED_DEFAULT_COLOR) {
+ _this._ctx.fillStyle = _this._colors.background.css;
+ }
+ else if (fg < 256) {
+ _this._ctx.fillStyle = _this._colors.ansi[fg].css;
+ }
+ else {
+ _this._ctx.fillStyle = _this._colors.foreground.css;
+ }
+ _this.fillBottomLineAtCells(x, y, width);
+ _this._ctx.restore();
+ }
+ _this.drawChars(terminal, chars, code, width, x, y, fg, bg, !!(flags & 1), !!(flags & 32), !!(flags & 64));
+ });
+ };
+ TextRenderLayer.prototype.onGridChanged = function (terminal, firstRow, lastRow) {
+ if (this._state.cache.length === 0) {
+ return;
+ }
+ if (this._charAtlas) {
+ this._charAtlas.beginFrame();
+ }
+ this.clearCells(0, firstRow, terminal.cols, lastRow - firstRow + 1);
+ this._drawBackground(terminal, firstRow, lastRow);
+ this._drawForeground(terminal, firstRow, lastRow);
+ };
+ TextRenderLayer.prototype.onOptionsChanged = function (terminal) {
+ this.setTransparency(terminal, terminal.options.allowTransparency);
+ };
+ 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;
+ };
+ return TextRenderLayer;
+}(BaseRenderLayer_1.BaseRenderLayer));
+exports.TextRenderLayer = TextRenderLayer;
+
+},{"../Buffer":2,"./BaseRenderLayer":24,"./GridCache":28,"./atlas/Types":40}],33:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var BaseCharAtlas = (function () {
+ function BaseCharAtlas() {
+ this._didWarmUp = false;
+ }
+ BaseCharAtlas.prototype.warmUp = function () {
+ if (!this._didWarmUp) {
+ this._doWarmUp();
+ this._didWarmUp = true;
+ }
+ };
+ BaseCharAtlas.prototype._doWarmUp = function () { };
+ BaseCharAtlas.prototype.beginFrame = function () { };
+ return BaseCharAtlas;
+}());
+exports.default = BaseCharAtlas;
+
+},{}],34:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var CharAtlasUtils_1 = require("./CharAtlasUtils");
+var DynamicCharAtlas_1 = require("./DynamicCharAtlas");
+var NoneCharAtlas_1 = require("./NoneCharAtlas");
+var StaticCharAtlas_1 = require("./StaticCharAtlas");
+var charAtlasImplementations = {
+ 'none': NoneCharAtlas_1.default,
+ 'static': StaticCharAtlas_1.default,
+ 'dynamic': DynamicCharAtlas_1.default
+};
+var charAtlasCache = [];
+function acquireCharAtlas(terminal, colors, scaledCharWidth, scaledCharHeight) {
+ var newConfig = CharAtlasUtils_1.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 (CharAtlasUtils_1.configEquals(entry.config, newConfig)) {
+ return entry.atlas;
+ }
+ 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 (CharAtlasUtils_1.configEquals(entry.config, newConfig)) {
+ entry.ownedBy.push(terminal);
+ return entry.atlas;
+ }
+ }
+ var newEntry = {
+ atlas: new charAtlasImplementations[terminal.options.experimentalCharAtlas](document, newConfig),
+ config: newConfig,
+ ownedBy: [terminal]
+ };
+ charAtlasCache.push(newEntry);
+ return newEntry.atlas;
+}
+exports.acquireCharAtlas = acquireCharAtlas;
+function removeTerminalFromCache(terminal) {
+ for (var i = 0; i < charAtlasCache.length; i++) {
+ var index = charAtlasCache[i].ownedBy.indexOf(terminal);
+ if (index !== -1) {
+ if (charAtlasCache[i].ownedBy.length === 1) {
+ charAtlasCache.splice(i, 1);
+ }
+ else {
+ charAtlasCache[i].ownedBy.splice(index, 1);
+ }
+ break;
+ }
+ }
+}
+exports.removeTerminalFromCache = removeTerminalFromCache;
+
+},{"./CharAtlasUtils":35,"./DynamicCharAtlas":36,"./NoneCharAtlas":38,"./StaticCharAtlas":39}],35:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+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 {
+ type: terminal.options.experimentalCharAtlas,
+ devicePixelRatio: window.devicePixelRatio,
+ scaledCharWidth: scaledCharWidth,
+ scaledCharHeight: scaledCharHeight,
+ fontFamily: terminal.options.fontFamily,
+ fontSize: terminal.options.fontSize,
+ fontWeight: terminal.options.fontWeight,
+ fontWeightBold: terminal.options.fontWeightBold,
+ allowTransparency: terminal.options.allowTransparency,
+ colors: clonedColors
+ };
+}
+exports.generateConfig = generateConfig;
+function configEquals(a, b) {
+ for (var i = 0; i < a.colors.ansi.length; i++) {
+ if (a.colors.ansi[i].rgba !== b.colors.ansi[i].rgba) {
+ return false;
+ }
+ }
+ return a.type === b.type &&
+ a.devicePixelRatio === b.devicePixelRatio &&
+ a.fontFamily === b.fontFamily &&
+ a.fontSize === b.fontSize &&
+ a.fontWeight === b.fontWeight &&
+ a.fontWeightBold === b.fontWeightBold &&
+ a.allowTransparency === b.allowTransparency &&
+ a.scaledCharWidth === b.scaledCharWidth &&
+ a.scaledCharHeight === b.scaledCharHeight &&
+ a.colors.foreground === b.colors.foreground &&
+ a.colors.background === b.colors.background;
+}
+exports.configEquals = configEquals;
+
+},{}],36:[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 BaseCharAtlas_1 = require("./BaseCharAtlas");
+var ColorManager_1 = require("../ColorManager");
+var CharAtlasGenerator_1 = require("../../shared/atlas/CharAtlasGenerator");
+var LRUMap_1 = require("./LRUMap");
+var TEXTURE_WIDTH = 1024;
+var TEXTURE_HEIGHT = 1024;
+var TRANSPARENT_COLOR = {
+ css: 'rgba(0, 0, 0, 0)',
+ rgba: 0
+};
+var FRAME_CACHE_DRAW_LIMIT = 100;
+function getGlyphCacheKey(glyph) {
+ var styleFlags = (glyph.bold ? 0 : 4) + (glyph.dim ? 0 : 2) + (glyph.italic ? 0 : 1);
+ return glyph.bg + "_" + glyph.fg + "_" + styleFlags + glyph.chars;
+}
+var DynamicCharAtlas = (function (_super) {
+ __extends(DynamicCharAtlas, _super);
+ function DynamicCharAtlas(document, _config) {
+ var _this = _super.call(this) || this;
+ _this._config = _config;
+ _this._drawToCacheCount = 0;
+ _this._cacheCanvas = document.createElement('canvas');
+ _this._cacheCanvas.width = TEXTURE_WIDTH;
+ _this._cacheCanvas.height = TEXTURE_HEIGHT;
+ _this._cacheCtx = _this._cacheCanvas.getContext('2d', { alpha: true });
+ var tmpCanvas = document.createElement('canvas');
+ tmpCanvas.width = _this._config.scaledCharWidth;
+ tmpCanvas.height = _this._config.scaledCharHeight;
+ _this._tmpCtx = tmpCanvas.getContext('2d', { alpha: _this._config.allowTransparency });
+ _this._width = Math.floor(TEXTURE_WIDTH / _this._config.scaledCharWidth);
+ _this._height = Math.floor(TEXTURE_HEIGHT / _this._config.scaledCharHeight);
+ var capacity = _this._width * _this._height;
+ _this._cacheMap = new LRUMap_1.default(capacity);
+ _this._cacheMap.prealloc(capacity);
+ return _this;
+ }
+ DynamicCharAtlas.prototype.beginFrame = function () {
+ this._drawToCacheCount = 0;
+ };
+ DynamicCharAtlas.prototype.draw = function (ctx, glyph, x, y) {
+ var glyphKey = getGlyphCacheKey(glyph);
+ var cacheValue = this._cacheMap.get(glyphKey);
+ if (cacheValue != null) {
+ this._drawFromCache(ctx, cacheValue, x, y);
+ return true;
+ }
+ else if (this._canCache(glyph) && this._drawToCacheCount < FRAME_CACHE_DRAW_LIMIT) {
+ var index = void 0;
+ if (this._cacheMap.size < this._cacheMap.capacity) {
+ index = this._cacheMap.size;
+ }
+ else {
+ index = this._cacheMap.peek().index;
+ }
+ var cacheValue_1 = this._drawToCache(glyph, index);
+ this._cacheMap.set(glyphKey, cacheValue_1);
+ this._drawFromCache(ctx, cacheValue_1, x, y);
+ return true;
+ }
+ return false;
+ };
+ DynamicCharAtlas.prototype._canCache = function (glyph) {
+ return glyph.code < 256;
+ };
+ DynamicCharAtlas.prototype._toCoordinates = function (index) {
+ return [
+ (index % this._width) * this._config.scaledCharWidth,
+ Math.floor(index / this._width) * this._config.scaledCharHeight
+ ];
+ };
+ DynamicCharAtlas.prototype._drawFromCache = function (ctx, cacheValue, x, y) {
+ if (cacheValue.isEmpty) {
+ return;
+ }
+ var _a = this._toCoordinates(cacheValue.index), cacheX = _a[0], cacheY = _a[1];
+ ctx.drawImage(this._cacheCanvas, cacheX, cacheY, this._config.scaledCharWidth, this._config.scaledCharHeight, x, y, this._config.scaledCharWidth, this._config.scaledCharHeight);
+ };
+ DynamicCharAtlas.prototype._getColorFromAnsiIndex = function (idx) {
+ if (idx < this._config.colors.ansi.length) {
+ return this._config.colors.ansi[idx];
+ }
+ return ColorManager_1.DEFAULT_ANSI_COLORS[idx];
+ };
+ DynamicCharAtlas.prototype._getBackgroundColor = function (glyph) {
+ if (this._config.allowTransparency) {
+ return TRANSPARENT_COLOR;
+ }
+ else if (glyph.bg === Types_1.INVERTED_DEFAULT_COLOR) {
+ return this._config.colors.foreground;
+ }
+ else if (glyph.bg < 256) {
+ return this._getColorFromAnsiIndex(glyph.bg);
+ }
+ return this._config.colors.background;
+ };
+ DynamicCharAtlas.prototype._getForegroundColor = function (glyph) {
+ if (glyph.fg === Types_1.INVERTED_DEFAULT_COLOR) {
+ return this._config.colors.background;
+ }
+ else if (glyph.fg < 256) {
+ return this._getColorFromAnsiIndex(glyph.fg);
+ }
+ return this._config.colors.foreground;
+ };
+ DynamicCharAtlas.prototype._drawToCache = function (glyph, index) {
+ this._drawToCacheCount++;
+ this._tmpCtx.save();
+ var backgroundColor = this._getBackgroundColor(glyph);
+ this._tmpCtx.globalCompositeOperation = 'copy';
+ this._tmpCtx.fillStyle = backgroundColor.css;
+ this._tmpCtx.fillRect(0, 0, this._config.scaledCharWidth, this._config.scaledCharHeight);
+ this._tmpCtx.globalCompositeOperation = 'source-over';
+ var fontWeight = glyph.bold ? this._config.fontWeightBold : this._config.fontWeight;
+ var fontStyle = glyph.italic ? 'italic' : '';
+ this._tmpCtx.font =
+ fontStyle + " " + fontWeight + " " + this._config.fontSize * this._config.devicePixelRatio + "px " + this._config.fontFamily;
+ this._tmpCtx.textBaseline = 'top';
+ this._tmpCtx.fillStyle = this._getForegroundColor(glyph).css;
+ if (glyph.dim) {
+ this._tmpCtx.globalAlpha = Types_1.DIM_OPACITY;
+ }
+ this._tmpCtx.fillText(glyph.chars, 0, 0);
+ this._tmpCtx.restore();
+ var imageData = this._tmpCtx.getImageData(0, 0, this._config.scaledCharWidth, this._config.scaledCharHeight);
+ var isEmpty = false;
+ if (!this._config.allowTransparency) {
+ isEmpty = CharAtlasGenerator_1.clearColor(imageData, backgroundColor);
+ }
+ var _a = this._toCoordinates(index), x = _a[0], y = _a[1];
+ this._cacheCtx.putImageData(imageData, x, y);
+ return {
+ index: index,
+ isEmpty: isEmpty
+ };
+ };
+ return DynamicCharAtlas;
+}(BaseCharAtlas_1.default));
+exports.default = DynamicCharAtlas;
+
+},{"../../shared/atlas/CharAtlasGenerator":43,"../ColorManager":26,"./BaseCharAtlas":33,"./LRUMap":37,"./Types":40}],37:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var LRUMap = (function () {
+ function LRUMap(capacity) {
+ this.capacity = capacity;
+ this._map = {};
+ this._head = null;
+ this._tail = null;
+ this._nodePool = [];
+ this.size = 0;
+ }
+ LRUMap.prototype._unlinkNode = function (node) {
+ var prev = node.prev;
+ var next = node.next;
+ if (node === this._head) {
+ this._head = next;
+ }
+ if (node === this._tail) {
+ this._tail = prev;
+ }
+ if (prev !== null) {
+ prev.next = next;
+ }
+ if (next !== null) {
+ next.prev = prev;
+ }
+ };
+ LRUMap.prototype._appendNode = function (node) {
+ var tail = this._tail;
+ if (tail !== null) {
+ tail.next = node;
+ }
+ node.prev = tail;
+ node.next = null;
+ this._tail = node;
+ if (this._head === null) {
+ this._head = node;
+ }
+ };
+ LRUMap.prototype.prealloc = function (count) {
+ var nodePool = this._nodePool;
+ for (var i = 0; i < count; i++) {
+ nodePool.push({
+ prev: null,
+ next: null,
+ key: null,
+ value: null
+ });
+ }
+ };
+ LRUMap.prototype.get = function (key) {
+ var node = this._map[key];
+ if (node !== undefined) {
+ this._unlinkNode(node);
+ this._appendNode(node);
+ return node.value;
+ }
+ return null;
+ };
+ LRUMap.prototype.peek = function () {
+ var head = this._head;
+ return head === null ? null : head.value;
+ };
+ LRUMap.prototype.set = function (key, value) {
+ var node = this._map[key];
+ if (node !== undefined) {
+ node = this._map[key];
+ this._unlinkNode(node);
+ node.value = value;
+ }
+ else if (this.size >= this.capacity) {
+ node = this._head;
+ this._unlinkNode(node);
+ delete this._map[node.key];
+ node.key = key;
+ node.value = value;
+ this._map[key] = node;
+ }
+ else {
+ var nodePool = this._nodePool;
+ if (nodePool.length > 0) {
+ node = nodePool.pop();
+ node.key = key;
+ node.value = value;
+ }
+ else {
+ node = {
+ prev: null,
+ next: null,
+ key: key,
+ value: value
+ };
+ }
+ this._map[key] = node;
+ this.size++;
+ }
+ this._appendNode(node);
+ };
+ return LRUMap;
+}());
+exports.default = LRUMap;
+
+},{}],38:[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 BaseCharAtlas_1 = require("./BaseCharAtlas");
+var NoneCharAtlas = (function (_super) {
+ __extends(NoneCharAtlas, _super);
+ function NoneCharAtlas(document, config) {
+ return _super.call(this) || this;
+ }
+ NoneCharAtlas.prototype.draw = function (ctx, glyph, x, y) {
+ return false;
+ };
+ return NoneCharAtlas;
+}(BaseCharAtlas_1.default));
+exports.default = NoneCharAtlas;
+
+},{"./BaseCharAtlas":33}],39:[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 Types_2 = require("../../shared/atlas/Types");
+var CharAtlasGenerator_1 = require("../../shared/atlas/CharAtlasGenerator");
+var BaseCharAtlas_1 = require("./BaseCharAtlas");
+var StaticCharAtlas = (function (_super) {
+ __extends(StaticCharAtlas, _super);
+ function StaticCharAtlas(_document, _config) {
+ var _this = _super.call(this) || this;
+ _this._document = _document;
+ _this._config = _config;
+ _this._canvasFactory = function (width, height) {
+ var canvas = _this._document.createElement('canvas');
+ canvas.width = width;
+ canvas.height = height;
+ return canvas;
+ };
+ return _this;
+ }
+ StaticCharAtlas.prototype._doWarmUp = function () {
+ var _this = this;
+ var result = CharAtlasGenerator_1.generateStaticCharAtlasTexture(window, this._canvasFactory, this._config);
+ if (result instanceof HTMLCanvasElement) {
+ this._texture = result;
+ }
+ else {
+ result.then(function (texture) {
+ _this._texture = texture;
+ });
+ }
+ };
+ StaticCharAtlas.prototype._isCached = function (glyph, colorIndex) {
+ var isAscii = glyph.code < 256;
+ var isBasicColor = glyph.fg < 16;
+ var isDefaultColor = glyph.fg >= 256;
+ var isDefaultBackground = glyph.bg >= 256;
+ return isAscii && (isBasicColor || isDefaultColor) && isDefaultBackground && !glyph.italic;
+ };
+ StaticCharAtlas.prototype.draw = function (ctx, glyph, x, y) {
+ if (this._texture == null) {
+ return false;
+ }
+ var colorIndex = 0;
+ if (glyph.fg < 256) {
+ colorIndex = 2 + glyph.fg + (glyph.bold ? 16 : 0);
+ }
+ else {
+ if (glyph.bold) {
+ colorIndex = 1;
+ }
+ }
+ if (!this._isCached(glyph, colorIndex)) {
+ return false;
+ }
+ ctx.save();
+ var charAtlasCellWidth = this._config.scaledCharWidth + Types_2.CHAR_ATLAS_CELL_SPACING;
+ var charAtlasCellHeight = this._config.scaledCharHeight + Types_2.CHAR_ATLAS_CELL_SPACING;
+ if (glyph.dim) {
+ ctx.globalAlpha = Types_1.DIM_OPACITY;
+ }
+ ctx.drawImage(this._texture, glyph.code * charAtlasCellWidth, colorIndex * charAtlasCellHeight, charAtlasCellWidth, this._config.scaledCharHeight, x, y, charAtlasCellWidth, this._config.scaledCharHeight);
+ ctx.restore();
+ return true;
+ };
+ return StaticCharAtlas;
+}(BaseCharAtlas_1.default));
+exports.default = StaticCharAtlas;
+
+},{"../../shared/atlas/CharAtlasGenerator":43,"../../shared/atlas/Types":44,"./BaseCharAtlas":33,"./Types":40}],40:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.INVERTED_DEFAULT_COLOR = -1;
+exports.DIM_OPACITY = 0.5;
+
+},{}],41:[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 ColorManager_1 = require("../ColorManager");
+var RenderDebouncer_1 = require("../../ui/RenderDebouncer");
+var DomRendererRowFactory_1 = require("./DomRendererRowFactory");
+var TERMINAL_CLASS_PREFIX = 'xterm-dom-renderer-owner-';
+var ROW_CONTAINER_CLASS = 'xterm-rows';
+var FG_CLASS_PREFIX = 'xterm-fg-';
+var BG_CLASS_PREFIX = 'xterm-bg-';
+var FOCUS_CLASS = 'xterm-focus';
+var SELECTION_CLASS = 'xterm-selection';
+var nextTerminalId = 1;
+var DomRenderer = (function (_super) {
+ __extends(DomRenderer, _super);
+ function DomRenderer(_terminal, theme) {
+ var _this = _super.call(this) || this;
+ _this._terminal = _terminal;
+ _this._terminalClass = nextTerminalId++;
+ _this._rowElements = [];
+ var allowTransparency = _this._terminal.options.allowTransparency;
+ _this.colorManager = new ColorManager_1.ColorManager(document, allowTransparency);
+ _this.setTheme(theme);
+ _this._rowContainer = document.createElement('div');
+ _this._rowContainer.classList.add(ROW_CONTAINER_CLASS);
+ _this._rowContainer.style.lineHeight = 'normal';
+ _this._rowContainer.setAttribute('aria-hidden', 'true');
+ _this._refreshRowElements(_this._terminal.cols, _this._terminal.rows);
+ _this._selectionContainer = document.createElement('div');
+ _this._selectionContainer.classList.add(SELECTION_CLASS);
+ _this._selectionContainer.setAttribute('aria-hidden', 'true');
+ _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._updateDimensions();
+ _this._renderDebouncer = new RenderDebouncer_1.RenderDebouncer(_this._terminal, _this._renderRows.bind(_this));
+ _this._rowFactory = new DomRendererRowFactory_1.DomRendererRowFactory(document);
+ _this._terminal.element.classList.add(TERMINAL_CLASS_PREFIX + _this._terminalClass);
+ _this._terminal.screenElement.appendChild(_this._rowContainer);
+ _this._terminal.screenElement.appendChild(_this._selectionContainer);
+ return _this;
+ }
+ DomRenderer.prototype.dispose = function () {
+ this._terminal.element.classList.remove(TERMINAL_CLASS_PREFIX + this._terminalClass);
+ this._terminal.screenElement.removeChild(this._rowContainer);
+ this._terminal.screenElement.removeChild(this._selectionContainer);
+ this._terminal.screenElement.removeChild(this._themeStyleElement);
+ this._terminal.screenElement.removeChild(this._dimensionsStyleElement);
+ _super.prototype.dispose.call(this);
+ };
+ DomRenderer.prototype._updateDimensions = function () {
+ var _this = this;
+ this.dimensions.scaledCharWidth = this._terminal.charMeasure.width * window.devicePixelRatio;
+ this.dimensions.scaledCharHeight = this._terminal.charMeasure.height * window.devicePixelRatio;
+ this.dimensions.scaledCellWidth = this.dimensions.scaledCharWidth;
+ this.dimensions.scaledCellHeight = this.dimensions.scaledCharHeight;
+ this.dimensions.scaledCharLeft = 0;
+ this.dimensions.scaledCharTop = 0;
+ this.dimensions.scaledCanvasWidth = this.dimensions.scaledCellWidth * this._terminal.cols;
+ this.dimensions.scaledCanvasHeight = this.dimensions.scaledCellHeight * this._terminal.rows;
+ this.dimensions.canvasWidth = this._terminal.charMeasure.width * this._terminal.cols;
+ this.dimensions.canvasHeight = this._terminal.charMeasure.height * this._terminal.rows;
+ this.dimensions.actualCellWidth = this._terminal.charMeasure.width;
+ this.dimensions.actualCellHeight = this._terminal.charMeasure.height;
+ this._rowElements.forEach(function (element) {
+ element.style.width = _this.dimensions.canvasWidth + "px";
+ element.style.height = _this._terminal.charMeasure.height + "px";
+ });
+ if (!this._dimensionsStyleElement) {
+ this._dimensionsStyleElement = document.createElement('style');
+ this._terminal.screenElement.appendChild(this._dimensionsStyleElement);
+ }
+ var styles = this._terminalSelector + " ." + ROW_CONTAINER_CLASS + " span {" +
+ " display: inline-block;" +
+ " height: 100%;" +
+ " vertical-align: top;" +
+ (" width: " + this._terminal.charMeasure.width + "px") +
+ "}";
+ this._dimensionsStyleElement.innerHTML = styles;
+ this._selectionContainer.style.height = this._terminal._viewportElement.style.height;
+ this._rowContainer.style.width = this.dimensions.canvasWidth + "px";
+ this._rowContainer.style.height = this.dimensions.canvasHeight + "px";
+ };
+ DomRenderer.prototype.setTheme = function (theme) {
+ var _this = this;
+ if (theme) {
+ this.colorManager.setTheme(theme);
+ }
+ if (!this._themeStyleElement) {
+ this._themeStyleElement = document.createElement('style');
+ this._terminal.screenElement.appendChild(this._themeStyleElement);
+ }
+ var styles = this._terminalSelector + " ." + ROW_CONTAINER_CLASS + " {" +
+ (" color: " + this.colorManager.colors.foreground.css + ";") +
+ (" background-color: " + this.colorManager.colors.background.css + ";") +
+ (" font-family: " + this._terminal.getOption('fontFamily') + ";") +
+ (" font-size: " + this._terminal.getOption('fontSize') + "px;") +
+ "}";
+ styles +=
+ this._terminalSelector + " span:not(." + DomRendererRowFactory_1.BOLD_CLASS + ") {" +
+ (" font-weight: " + this._terminal.options.fontWeight + ";") +
+ "}" +
+ (this._terminalSelector + " span." + DomRendererRowFactory_1.BOLD_CLASS + " {") +
+ (" font-weight: " + this._terminal.options.fontWeightBold + ";") +
+ "}" +
+ (this._terminalSelector + " span." + DomRendererRowFactory_1.ITALIC_CLASS + " {") +
+ " font-style: italic;" +
+ "}";
+ styles +=
+ this._terminalSelector + " ." + ROW_CONTAINER_CLASS + "." + FOCUS_CLASS + " ." + DomRendererRowFactory_1.CURSOR_CLASS + " {" +
+ (" background-color: " + this.colorManager.colors.cursor.css + ";") +
+ (" color: " + this.colorManager.colors.cursorAccent.css + ";") +
+ "}" +
+ (this._terminalSelector + " ." + ROW_CONTAINER_CLASS + ":not(." + FOCUS_CLASS + ") ." + DomRendererRowFactory_1.CURSOR_CLASS + " {") +
+ " outline: 1px solid #fff;" +
+ " outline-offset: -1px;" +
+ "}";
+ styles +=
+ this._terminalSelector + " ." + SELECTION_CLASS + " {" +
+ " position: absolute;" +
+ " top: 0;" +
+ " left: 0;" +
+ " z-index: 1;" +
+ " pointer-events: none;" +
+ "}" +
+ (this._terminalSelector + " ." + SELECTION_CLASS + " div {") +
+ " position: absolute;" +
+ (" background-color: " + this.colorManager.colors.selection.css + ";") +
+ "}";
+ this.colorManager.colors.ansi.forEach(function (c, i) {
+ styles +=
+ _this._terminalSelector + " ." + FG_CLASS_PREFIX + i + " { color: " + c.css + "; }" +
+ (_this._terminalSelector + " ." + BG_CLASS_PREFIX + i + " { background-color: " + c.css + "; }");
+ });
+ this._themeStyleElement.innerHTML = styles;
+ return this.colorManager.colors;
+ };
+ DomRenderer.prototype.onWindowResize = function (devicePixelRatio) {
+ this._updateDimensions();
+ };
+ DomRenderer.prototype._refreshRowElements = function (cols, rows) {
+ for (var i = this._rowElements.length; i <= rows; i++) {
+ var row = document.createElement('div');
+ this._rowContainer.appendChild(row);
+ this._rowElements.push(row);
+ }
+ while (this._rowElements.length > rows) {
+ this._rowContainer.removeChild(this._rowElements.pop());
+ }
+ };
+ DomRenderer.prototype.onResize = function (cols, rows) {
+ this._refreshRowElements(cols, rows);
+ this._updateDimensions();
+ };
+ DomRenderer.prototype.onCharSizeChanged = function () {
+ this._updateDimensions();
+ };
+ DomRenderer.prototype.onBlur = function () {
+ this._rowContainer.classList.remove(FOCUS_CLASS);
+ };
+ DomRenderer.prototype.onFocus = function () {
+ this._rowContainer.classList.add(FOCUS_CLASS);
+ };
+ DomRenderer.prototype.onSelectionChanged = function (start, end, columnSelectMode) {
+ while (this._selectionContainer.children.length) {
+ this._selectionContainer.removeChild(this._selectionContainer.children[0]);
+ }
+ if (!start || !end) {
+ return;
+ }
+ var viewportStartRow = start[1] - this._terminal.buffer.ydisp;
+ var viewportEndRow = end[1] - this._terminal.buffer.ydisp;
+ var viewportCappedStartRow = Math.max(viewportStartRow, 0);
+ var viewportCappedEndRow = Math.min(viewportEndRow, this._terminal.rows - 1);
+ if (viewportCappedStartRow >= this._terminal.rows || viewportCappedEndRow < 0) {
+ return;
+ }
+ var documentFragment = document.createDocumentFragment();
+ if (columnSelectMode) {
+ documentFragment.appendChild(this._createSelectionElement(viewportCappedStartRow, start[0], end[0], viewportCappedEndRow - viewportCappedStartRow + 1));
+ }
+ else {
+ var startCol = viewportStartRow === viewportCappedStartRow ? start[0] : 0;
+ var endCol = viewportCappedStartRow === viewportCappedEndRow ? end[0] : this._terminal.cols;
+ documentFragment.appendChild(this._createSelectionElement(viewportCappedStartRow, startCol, endCol));
+ var middleRowsCount = viewportCappedEndRow - viewportCappedStartRow - 1;
+ documentFragment.appendChild(this._createSelectionElement(viewportCappedStartRow + 1, 0, this._terminal.cols, middleRowsCount));
+ if (viewportCappedStartRow !== viewportCappedEndRow) {
+ var endCol_1 = viewportEndRow === viewportCappedEndRow ? end[0] : this._terminal.cols;
+ documentFragment.appendChild(this._createSelectionElement(viewportCappedEndRow, 0, endCol_1));
+ }
+ }
+ this._selectionContainer.appendChild(documentFragment);
+ };
+ DomRenderer.prototype._createSelectionElement = function (row, colStart, colEnd, rowCount) {
+ if (rowCount === void 0) { rowCount = 1; }
+ var element = document.createElement('div');
+ element.style.height = rowCount * this._terminal.charMeasure.height + "px";
+ element.style.top = row * this._terminal.charMeasure.height + "px";
+ element.style.left = colStart * this._terminal.charMeasure.width + "px";
+ element.style.width = this._terminal.charMeasure.width * (colEnd - colStart) + "px";
+ return element;
+ };
+ DomRenderer.prototype.onCursorMove = function () {
+ };
+ DomRenderer.prototype.onOptionsChanged = function () {
+ this._updateDimensions();
+ this.setTheme(undefined);
+ this._terminal.refresh(0, this._terminal.rows - 1);
+ };
+ DomRenderer.prototype.clear = function () {
+ this._rowElements.forEach(function (e) { return e.innerHTML = ''; });
+ };
+ DomRenderer.prototype.refreshRows = function (start, end) {
+ this._renderDebouncer.refresh(start, end);
+ };
+ DomRenderer.prototype._renderRows = function (start, end) {
+ var terminal = this._terminal;
+ var cursorAbsoluteY = terminal.buffer.ybase + terminal.buffer.y;
+ var cursorX = this._terminal.buffer.x;
+ for (var y = start; y <= end; y++) {
+ var rowElement = this._rowElements[y];
+ rowElement.innerHTML = '';
+ var row = y + terminal.buffer.ydisp;
+ var lineData = terminal.buffer.lines.get(row);
+ rowElement.appendChild(this._rowFactory.createRow(lineData, row === cursorAbsoluteY, cursorX, terminal.charMeasure.width, terminal.cols));
+ }
+ this._terminal.emit('refresh', { start: start, end: end });
+ };
+ Object.defineProperty(DomRenderer.prototype, "_terminalSelector", {
+ get: function () {
+ return "." + TERMINAL_CLASS_PREFIX + this._terminalClass;
+ },
+ enumerable: true,
+ configurable: true
+ });
+ DomRenderer.prototype.registerCharacterJoiner = function (handler) { return -1; };
+ DomRenderer.prototype.deregisterCharacterJoiner = function (joinerId) { return false; };
+ return DomRenderer;
+}(EventEmitter_1.EventEmitter));
+exports.DomRenderer = DomRenderer;
+
+},{"../../EventEmitter":7,"../../ui/RenderDebouncer":49,"../ColorManager":26,"./DomRendererRowFactory":42}],42:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Buffer_1 = require("../../Buffer");
+exports.BOLD_CLASS = 'xterm-bold';
+exports.ITALIC_CLASS = 'xterm-italic';
+exports.CURSOR_CLASS = 'xterm-cursor';
+var DomRendererRowFactory = (function () {
+ function DomRendererRowFactory(_document) {
+ this._document = _document;
+ }
+ DomRendererRowFactory.prototype.createRow = function (lineData, isCursorRow, cursorX, cellWidth, cols) {
+ var fragment = this._document.createDocumentFragment();
+ var colCount = 0;
+ for (var x = 0; x < lineData.length; x++) {
+ if (colCount >= cols) {
+ continue;
+ }
+ var charData = lineData[x];
+ 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;
+ }
+ var charElement = this._document.createElement('span');
+ if (width > 1) {
+ charElement.style.width = cellWidth * width + "px";
+ }
+ var flags = attr >> 18;
+ var bg = attr & 0x1ff;
+ var fg = (attr >> 9) & 0x1ff;
+ if (isCursorRow && x === cursorX) {
+ charElement.classList.add(exports.CURSOR_CLASS);
+ }
+ if (flags & 8) {
+ var temp = bg;
+ bg = fg;
+ fg = temp;
+ if (fg === 256) {
+ fg = 0;
+ }
+ if (bg === 257) {
+ bg = 15;
+ }
+ }
+ if (flags & 1) {
+ if (fg < 8) {
+ fg += 8;
+ }
+ charElement.classList.add(exports.BOLD_CLASS);
+ }
+ if (flags & 64) {
+ charElement.classList.add(exports.ITALIC_CLASS);
+ }
+ charElement.textContent = char;
+ if (fg !== 257) {
+ charElement.classList.add("xterm-fg-" + fg);
+ }
+ if (bg !== 256) {
+ charElement.classList.add("xterm-bg-" + bg);
+ }
+ fragment.appendChild(charElement);
+ colCount += width;
+ }
+ return fragment;
+ };
+ return DomRendererRowFactory;
+}());
+exports.DomRendererRowFactory = DomRendererRowFactory;
+
+},{"../../Buffer":2}],43:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Types_1 = require("./Types");
+var Browser_1 = require("../utils/Browser");
+function generateStaticCharAtlasTexture(context, canvasFactory, config) {
+ var cellWidth = config.scaledCharWidth + Types_1.CHAR_ATLAS_CELL_SPACING;
+ var cellHeight = config.scaledCharHeight + Types_1.CHAR_ATLAS_CELL_SPACING;
+ var canvas = canvasFactory(255 * cellWidth, (2 + 16 + 16) * cellHeight);
+ var ctx = canvas.getContext('2d', { alpha: config.allowTransparency });
+ ctx.fillStyle = config.colors.background.css;
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
+ ctx.save();
+ ctx.fillStyle = config.colors.foreground.css;
+ ctx.font = getFont(config.fontWeight, config);
+ ctx.textBaseline = 'top';
+ for (var i = 0; i < 256; i++) {
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(i * cellWidth, 0, cellWidth, cellHeight);
+ ctx.clip();
+ ctx.fillText(String.fromCharCode(i), i * cellWidth, 0);
+ ctx.restore();
+ }
+ ctx.save();
+ ctx.font = getFont(config.fontWeightBold, config);
+ for (var i = 0; i < 256; i++) {
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(i * cellWidth, cellHeight, cellWidth, cellHeight);
+ ctx.clip();
+ ctx.fillText(String.fromCharCode(i), i * cellWidth, cellHeight);
+ ctx.restore();
+ }
+ ctx.restore();
+ ctx.font = getFont(config.fontWeight, config);
+ for (var colorIndex = 0; colorIndex < 16; colorIndex++) {
+ var y = (colorIndex + 2) * cellHeight;
+ for (var i = 0; i < 256; i++) {
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(i * cellWidth, y, cellWidth, cellHeight);
+ ctx.clip();
+ ctx.fillStyle = config.colors.ansi[colorIndex].css;
+ ctx.fillText(String.fromCharCode(i), i * cellWidth, y);
+ ctx.restore();
+ }
+ }
+ ctx.font = getFont(config.fontWeightBold, config);
+ for (var colorIndex = 0; colorIndex < 16; colorIndex++) {
+ var y = (colorIndex + 2 + 16) * cellHeight;
+ for (var i = 0; i < 256; i++) {
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(i * cellWidth, y, cellWidth, cellHeight);
+ ctx.clip();
+ ctx.fillStyle = config.colors.ansi[colorIndex].css;
+ ctx.fillText(String.fromCharCode(i), i * cellWidth, y);
+ ctx.restore();
+ }
+ }
+ ctx.restore();
+ if (!('createImageBitmap' in context) || Browser_1.isFirefox || Browser_1.isSafari) {
+ if (canvas instanceof HTMLCanvasElement) {
+ return canvas;
+ }
+ return new Promise(function (r) { return r(canvas.transferToImageBitmap()); });
+ }
+ var charAtlasImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
+ clearColor(charAtlasImageData, config.colors.background);
+ return context.createImageBitmap(charAtlasImageData);
+}
+exports.generateStaticCharAtlasTexture = generateStaticCharAtlasTexture;
+function clearColor(imageData, color) {
+ var isEmpty = true;
+ var r = color.rgba >>> 24;
+ var g = color.rgba >>> 16 & 0xFF;
+ var b = color.rgba >>> 8 & 0xFF;
+ 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;
+ }
+ else {
+ isEmpty = false;
+ }
+ }
+ return isEmpty;
+}
+exports.clearColor = clearColor;
+function getFont(fontWeight, config) {
+ return fontWeight + " " + config.fontSize * config.devicePixelRatio + "px " + config.fontFamily;
+}
+
+},{"../utils/Browser":45,"./Types":44}],44:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.CHAR_ATLAS_CELL_SPACING = 1;
+
+},{}],45:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+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.isSafari = /^((?!chrome|android).)*safari/i.test(userAgent);
+exports.isMSIE = !!~userAgent.indexOf('MSIE') || !!~userAgent.indexOf('Trident');
+exports.isMac = contains(['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'], platform);
+exports.isIpad = platform === 'iPad';
+exports.isIphone = platform === 'iPhone';
+exports.isMSWindows = contains(['Windows', 'Win16', 'Win32', 'WinCE'], platform);
+exports.isLinux = platform.indexOf('Linux') >= 0;
+function contains(arr, el) {
+ return arr.indexOf(el) >= 0;
+}
+
+},{}],46:[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;
+ _this._measureElement = _this._document.createElement('span');
+ _this._measureElement.classList.add('xterm-char-measure-element');
+ _this._measureElement.textContent = 'W';
+ _this._measureElement.setAttribute('aria-hidden', 'true');
+ _this._parentElement.appendChild(_this._measureElement);
+ 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) {
+ 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}],47:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+function addDisposableDomListener(node, type, handler, useCapture) {
+ node.addEventListener(type, handler, useCapture);
+ return {
+ dispose: function () {
+ if (!handler) {
+ return;
+ }
+ node.removeEventListener(type, handler, useCapture);
+ node = null;
+ handler = null;
+ }
+ };
+}
+exports.addDisposableDomListener = addDisposableDomListener;
+
+},{}],48:[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 Lifecycle_1 = require("../common/Lifecycle");
+var Lifecycle_2 = require("./Lifecycle");
+var HOVER_DURATION = 500;
+var MouseZoneManager = (function (_super) {
+ __extends(MouseZoneManager, _super);
+ function MouseZoneManager(_terminal) {
+ var _this = _super.call(this) || this;
+ _this._terminal = _terminal;
+ _this._zones = [];
+ _this._areZonesActive = false;
+ _this._tooltipTimeout = null;
+ _this._currentZone = null;
+ _this._lastHoverCoords = [null, null];
+ _this.register(Lifecycle_2.addDisposableDomListener(_this._terminal.element, 'mousedown', function (e) { return _this._onMouseDown(e); }));
+ _this._mouseMoveListener = function (e) { return _this._onMouseMove(e); };
+ _this._clickListener = function (e) { return _this._onClick(e); };
+ return _this;
+ }
+ MouseZoneManager.prototype.dispose = function () {
+ _super.prototype.dispose.call(this);
+ this._deactivate();
+ };
+ 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.y1 > start && zone.y1 <= end + 1) ||
+ (zone.y2 > start && zone.y2 <= end + 1) ||
+ (zone.y1 < start && zone.y2 > 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) {
+ if (zone.willLinkActivate(e)) {
+ 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.screenElement, this._terminal.charMeasure, this._terminal.options.lineHeight, this._terminal.cols, this._terminal.rows);
+ if (!coords) {
+ return null;
+ }
+ var x = coords[0];
+ var y = coords[1];
+ for (var i = 0; i < this._zones.length; i++) {
+ var zone = this._zones[i];
+ if (zone.y1 === zone.y2) {
+ if (y === zone.y1 && x >= zone.x1 && x < zone.x2) {
+ return zone;
+ }
+ }
+ else {
+ if ((y === zone.y1 && x >= zone.x1) ||
+ (y === zone.y2 && x < zone.x2) ||
+ (y > zone.y1 && y < zone.y2)) {
+ return zone;
+ }
+ }
+ }
+ return null;
+ };
+ return MouseZoneManager;
+}(Lifecycle_1.Disposable));
+exports.MouseZoneManager = MouseZoneManager;
+var MouseZone = (function () {
+ function MouseZone(x1, y1, x2, y2, clickCallback, hoverCallback, tooltipCallback, leaveCallback, willLinkActivate) {
+ this.x1 = x1;
+ this.y1 = y1;
+ this.x2 = x2;
+ this.y2 = y2;
+ this.clickCallback = clickCallback;
+ this.hoverCallback = hoverCallback;
+ this.tooltipCallback = tooltipCallback;
+ this.leaveCallback = leaveCallback;
+ this.willLinkActivate = willLinkActivate;
+ }
+ return MouseZone;
+}());
+exports.MouseZone = MouseZone;
+
+},{"../common/Lifecycle":17,"./Lifecycle":47}],49:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var RenderDebouncer = (function () {
+ function RenderDebouncer(_terminal, _callback) {
+ this._terminal = _terminal;
+ this._callback = _callback;
+ this._animationFrame = null;
+ }
+ RenderDebouncer.prototype.dispose = function () {
+ if (this._animationFrame) {
+ window.cancelAnimationFrame(this._animationFrame);
+ this._animationFrame = null;
+ }
+ };
+ RenderDebouncer.prototype.refresh = function (rowStart, rowEnd) {
+ var _this = this;
+ rowStart = rowStart || 0;
+ rowEnd = rowEnd || this._terminal.rows - 1;
+ this._rowStart = this._rowStart !== undefined ? Math.min(this._rowStart, rowStart) : rowStart;
+ this._rowEnd = this._rowEnd !== undefined ? Math.max(this._rowEnd, rowEnd) : rowEnd;
+ if (this._animationFrame) {
+ return;
+ }
+ this._animationFrame = window.requestAnimationFrame(function () { return _this._innerRefresh(); });
+ };
+ RenderDebouncer.prototype._innerRefresh = function () {
+ this._rowStart = Math.max(this._rowStart, 0);
+ this._rowEnd = Math.min(this._rowEnd, this._terminal.rows - 1);
+ this._callback(this._rowStart, this._rowEnd);
+ this._rowStart = null;
+ this._rowEnd = null;
+ this._animationFrame = null;
+ };
+ return RenderDebouncer;
+}());
+exports.RenderDebouncer = RenderDebouncer;
+
+},{}],50:[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 Lifecycle_1 = require("../common/Lifecycle");
+var ScreenDprMonitor = (function (_super) {
+ __extends(ScreenDprMonitor, _super);
+ function ScreenDprMonitor() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ ScreenDprMonitor.prototype.setListener = function (listener) {
+ var _this = this;
+ if (this._listener) {
+ this.clearListener();
+ }
+ this._listener = listener;
+ this._outerListener = function () {
+ _this._listener(window.devicePixelRatio, _this._currentDevicePixelRatio);
+ _this._updateDpr();
+ };
+ this._updateDpr();
+ };
+ ScreenDprMonitor.prototype.dispose = function () {
+ _super.prototype.dispose.call(this);
+ this.clearListener();
+ };
+ ScreenDprMonitor.prototype._updateDpr = function () {
+ if (this._resolutionMediaMatchList) {
+ this._resolutionMediaMatchList.removeListener(this._outerListener);
+ }
+ this._currentDevicePixelRatio = window.devicePixelRatio;
+ this._resolutionMediaMatchList = window.matchMedia("screen and (resolution: " + window.devicePixelRatio + "dppx)");
+ this._resolutionMediaMatchList.addListener(this._outerListener);
+ };
+ ScreenDprMonitor.prototype.clearListener = function () {
+ if (!this._listener) {
+ return;
+ }
+ this._resolutionMediaMatchList.removeListener(this._outerListener);
+ this._listener = null;
+ this._outerListener = null;
+ };
+ return ScreenDprMonitor;
+}(Lifecycle_1.Disposable));
+exports.ScreenDprMonitor = ScreenDprMonitor;
+
+},{"../common/Lifecycle":17}],51:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.clone = function (val, depth) {
+ if (depth === void 0) { depth = 5; }
+ if (typeof val !== 'object') {
+ return val;
+ }
+ if (val === null) {
+ return null;
+ }
+ var clonedObject = Array.isArray(val) ? [] : {};
+ for (var key in val) {
+ clonedObject[key] = depth <= 1 ? val[key] : exports.clone(val[key], depth - 1);
+ }
+ return clonedObject;
+};
+
+},{}],52:[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 = element.offsetParent;
+ }
+ 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;
+
+},{}],53:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Terminal_1 = require("./public/Terminal");
+module.exports = Terminal_1.Terminal;
+
+},{"./public/Terminal":23}]},{},[53])(53)
+});
+//# sourceMappingURL=xterm.js.map
diff --git a/static/js/xterm@3.6.0/xterm.js.map b/static/js/xterm@3.6.0/xterm.js.map
new file mode 100644
index 0000000..5ad18f9
--- /dev/null
+++ b/static/js/xterm@3.6.0/xterm.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"xterm.js","sources":["../src/xterm.ts","../src/utils/MouseHelper.ts","../src/utils/Clone.ts","../src/ui/ScreenDprMonitor.ts","../src/ui/RenderDebouncer.ts","../src/ui/MouseZoneManager.ts","../src/ui/Lifecycle.ts","../src/ui/CharMeasure.ts","../src/shared/utils/Browser.ts","../src/shared/atlas/Types.ts","../src/shared/atlas/CharAtlasGenerator.ts","../src/renderer/dom/DomRendererRowFactory.ts","../src/renderer/dom/DomRenderer.ts","../src/renderer/atlas/Types.ts","../src/renderer/atlas/StaticCharAtlas.ts","../src/renderer/atlas/NoneCharAtlas.ts","../src/renderer/atlas/LRUMap.ts","../src/renderer/atlas/DynamicCharAtlas.ts","../src/renderer/atlas/CharAtlasUtils.ts","../src/renderer/atlas/CharAtlasCache.ts","../src/renderer/atlas/BaseCharAtlas.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/CharacterJoinerRegistry.ts","../src/renderer/BaseRenderLayer.ts","../src/public/Terminal.ts","../src/handlers/Clipboard.ts","../src/handlers/AltClickHandler.ts","../src/core/input/Keyboard.ts","../src/core/data/Charsets.ts","../src/common/data/EscapeSequences.ts","../src/common/Lifecycle.ts","../src/common/CircularList.ts","../src/Viewport.ts","../src/Terminal.ts","../src/Strings.ts","../src/SoundManager.ts","../src/SelectionModel.ts","../src/SelectionManager.ts","../src/Linkifier.ts","../src/InputHandler.ts","../src/EventEmitter.ts","../src/EscapeSequenceParser.ts","../src/CompositionHelper.ts","../src/CharWidth.ts","../src/BufferSet.ts","../src/Buffer.ts","../src/AccessibilityManager.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 './public/Terminal';\n\nmodule.exports = Terminal;\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ICharMeasure } from '../Types';\nimport { IRenderer } from '../renderer/Types';\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 = element.offsetParent;\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 * A simple utility for cloning values\n */\nexport const clone = (val: T, depth: number = 5): T => {\n if (typeof val !== 'object') {\n return val;\n }\n\n // cloning null always returns null\n if (val === null) {\n return null;\n }\n\n // If we're cloning an array, use an array as the base, otherwise use an object\n const clonedObject: any = Array.isArray(val) ? [] : {};\n\n for (const key in val) {\n // Recursively clone eack item unless we're at the maximum depth\n clonedObject[key] = depth <= 1 ? val[key] : clone(val[key], depth - 1);\n }\n\n return clonedObject as T;\n};\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { Disposable } from '../common/Lifecycle';\n\nexport type ScreenDprListener = (newDevicePixelRatio?: number, oldDevicePixelRatio?: number) => void;\n\n/**\n * The screen device pixel ratio monitor allows listening for when the\n * window.devicePixelRatio value changes. This is done not with polling but with\n * the use of window.matchMedia to watch media queries. When the event fires,\n * the listener will be reattached using a different media query to ensure that\n * any further changes will register.\n *\n * The listener should fire on both window zoom changes and switching to a\n * monitor with a different DPI.\n */\nexport class ScreenDprMonitor extends Disposable {\n private _currentDevicePixelRatio: number;\n private _outerListener: MediaQueryListListener;\n private _listener: ScreenDprListener;\n private _resolutionMediaMatchList: MediaQueryList;\n\n public setListener(listener: ScreenDprListener): void {\n if (this._listener) {\n this.clearListener();\n }\n this._listener = listener;\n this._outerListener = () => {\n this._listener(window.devicePixelRatio, this._currentDevicePixelRatio);\n this._updateDpr();\n };\n this._updateDpr();\n }\n\n public dispose(): void {\n super.dispose();\n this.clearListener();\n }\n\n private _updateDpr(): void {\n // Clear listeners for old DPR\n if (this._resolutionMediaMatchList) {\n this._resolutionMediaMatchList.removeListener(this._outerListener);\n }\n // Add listeners for new DPR\n this._currentDevicePixelRatio = window.devicePixelRatio;\n this._resolutionMediaMatchList = window.matchMedia(`screen and (resolution: ${window.devicePixelRatio}dppx)`);\n this._resolutionMediaMatchList.addListener(this._outerListener);\n }\n\n public clearListener(): void {\n if (!this._listener) {\n return;\n }\n this._resolutionMediaMatchList.removeListener(this._outerListener);\n this._listener = null;\n this._outerListener = null;\n }\n}\n","import { ITerminal } from '../Types';\nimport { IDisposable } from 'xterm';\n\n/**\n * Debounces calls to render terminal rows using animation frames.\n */\nexport class RenderDebouncer implements IDisposable {\n private _rowStart: number;\n private _rowEnd: number;\n private _animationFrame: number = null;\n\n constructor(\n private _terminal: ITerminal,\n private _callback: (start: number, end: number) => void\n ) {\n }\n\n public dispose(): void {\n if (this._animationFrame) {\n window.cancelAnimationFrame(this._animationFrame);\n this._animationFrame = null;\n }\n }\n\n public refresh(rowStart?: number, rowEnd?: number): void {\n rowStart = rowStart || 0;\n rowEnd = rowEnd || this._terminal.rows - 1;\n this._rowStart = this._rowStart !== undefined ? Math.min(this._rowStart, rowStart) : rowStart;\n this._rowEnd = this._rowEnd !== undefined ? Math.max(this._rowEnd, rowEnd) : rowEnd;\n\n if (this._animationFrame) {\n return;\n }\n\n this._animationFrame = window.requestAnimationFrame(() => this._innerRefresh());\n }\n\n private _innerRefresh(): void {\n // Clamp values\n this._rowStart = Math.max(this._rowStart, 0);\n this._rowEnd = Math.min(this._rowEnd, this._terminal.rows - 1);\n\n // Run render callback\n this._callback(this._rowStart, this._rowEnd);\n\n // Reset debouncer\n this._rowStart = null;\n this._rowEnd = null;\n this._animationFrame = null;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ITerminal } from '../Types';\nimport { IMouseZoneManager, IMouseZone } from './Types';\nimport { Disposable } from '../common/Lifecycle';\nimport { addDisposableDomListener } from './Lifecycle';\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 extends Disposable 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 super();\n\n this.register(addDisposableDomListener(this._terminal.element, '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 dispose(): void {\n super.dispose();\n this._deactivate();\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.y1 > start && zone.y1 <= end + 1) ||\n (zone.y2 > start && zone.y2 <= end + 1) ||\n (zone.y1 < start && zone.y2 > 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 if (zone.willLinkActivate(e)) {\n e.preventDefault();\n e.stopImmediatePropagation();\n }\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.screenElement, this._terminal.charMeasure, this._terminal.options.lineHeight, this._terminal.cols, this._terminal.rows);\n if (!coords) {\n return null;\n }\n const x = coords[0];\n const y = coords[1];\n for (let i = 0; i < this._zones.length; i++) {\n const zone = this._zones[i];\n if (zone.y1 === zone.y2) {\n // Single line link\n if (y === zone.y1 && x >= zone.x1 && x < zone.x2) {\n return zone;\n }\n } else {\n // Multi-line link\n if ((y === zone.y1 && x >= zone.x1) ||\n (y === zone.y2 && x < zone.x2) ||\n (y > zone.y1 && y < zone.y2)) {\n return zone;\n }\n }\n }\n return null;\n }\n}\n\nexport class MouseZone implements IMouseZone {\n constructor(\n public x1: number,\n public y1: number,\n public x2: number,\n public y2: number,\n public clickCallback: (e: MouseEvent) => any,\n public hoverCallback: (e: MouseEvent) => any,\n public tooltipCallback: (e: MouseEvent) => any,\n public leaveCallback: () => void,\n public willLinkActivate: (e: MouseEvent) => boolean\n ) {\n }\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IDisposable } from 'xterm';\n\n/**\n * Adds a disposabe listener to a node in the DOM, returning the disposable.\n * @param type The event type.\n * @param handler The handler for the listener.\n */\nexport function addDisposableDomListener(\n node: Element | Window | Document,\n type: string,\n handler: (e: any) => void,\n useCapture?: boolean\n): IDisposable {\n node.addEventListener(type, handler, useCapture);\n return {\n dispose: () => {\n if (!handler) {\n // Already disposed\n return;\n }\n node.removeEventListener(type, handler, useCapture);\n node = null;\n handler = null;\n }\n };\n}\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ICharMeasure, ITerminalOptions } from '../Types';\nimport { EventEmitter } from '../EventEmitter';\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 this._measureElement = this._document.createElement('span');\n this._measureElement.classList.add('xterm-char-measure-element');\n this._measureElement.textContent = 'W';\n this._measureElement.setAttribute('aria-hidden', 'true');\n this._parentElement.appendChild(this._measureElement);\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 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\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 isSafari = /^((?!chrome|android).)*safari/i.test(userAgent);\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/**\n * Return if the given array contains the given element\n * @param arr The array to search for the given element.\n * @param el The element to look for into the array\n */\nfunction contains(arr: any[], el: any): boolean {\n return arr.indexOf(el) >= 0;\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { FontWeight } from 'xterm';\nimport { IColorSet } from '../Types';\n\nexport const CHAR_ATLAS_CELL_SPACING = 1;\n\nexport interface ICharAtlasConfig {\n type: 'none' | 'static' | 'dynamic';\n devicePixelRatio: number;\n fontSize: number;\n fontFamily: string;\n fontWeight: FontWeight;\n fontWeightBold: FontWeight;\n scaledCharWidth: number;\n scaledCharHeight: number;\n allowTransparency: boolean;\n colors: IColorSet;\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { FontWeight } from 'xterm';\nimport { CHAR_ATLAS_CELL_SPACING, ICharAtlasConfig } from './Types';\nimport { IColor } from '../Types';\nimport { isFirefox, isSafari } from '../utils/Browser';\n\ndeclare const Promise: any;\n\nexport interface IOffscreenCanvas {\n width: number;\n height: number;\n getContext(type: '2d', config?: Canvas2DContextAttributes): CanvasRenderingContext2D;\n transferToImageBitmap(): ImageBitmap;\n}\n\n/**\n * Generates a char atlas.\n * @param context The window or worker context.\n * @param canvasFactory A function to generate a canvas with a width or height.\n * @param config The config for the new char atlas.\n */\nexport function generateStaticCharAtlasTexture(context: Window, canvasFactory: (width: number, height: number) => HTMLCanvasElement | IOffscreenCanvas, config: ICharAtlasConfig): HTMLCanvasElement | Promise {\n const cellWidth = config.scaledCharWidth + CHAR_ATLAS_CELL_SPACING;\n const cellHeight = config.scaledCharHeight + CHAR_ATLAS_CELL_SPACING;\n const canvas = canvasFactory(\n /*255 ascii chars*/255 * cellWidth,\n (/*default+default bold*/2 + /*0-15*/16 + /*0-15 bold*/16) * cellHeight\n );\n const ctx = canvas.getContext('2d', {alpha: config.allowTransparency});\n\n ctx.fillStyle = config.colors.background.css;\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n\n ctx.save();\n ctx.fillStyle = config.colors.foreground.css;\n ctx.font = getFont(config.fontWeight, config);\n ctx.textBaseline = 'top';\n\n // Default color\n for (let i = 0; i < 256; i++) {\n ctx.save();\n ctx.beginPath();\n ctx.rect(i * cellWidth, 0, cellWidth, cellHeight);\n ctx.clip();\n ctx.fillText(String.fromCharCode(i), i * cellWidth, 0);\n ctx.restore();\n }\n // Default color bold\n ctx.save();\n ctx.font = getFont(config.fontWeightBold, config);\n for (let i = 0; i < 256; i++) {\n ctx.save();\n ctx.beginPath();\n ctx.rect(i * cellWidth, cellHeight, cellWidth, cellHeight);\n ctx.clip();\n ctx.fillText(String.fromCharCode(i), i * cellWidth, cellHeight);\n ctx.restore();\n }\n ctx.restore();\n\n // Colors 0-15\n ctx.font = getFont(config.fontWeight, config);\n for (let colorIndex = 0; colorIndex < 16; colorIndex++) {\n const y = (colorIndex + 2) * cellHeight;\n // Draw ascii characters\n for (let i = 0; i < 256; i++) {\n ctx.save();\n ctx.beginPath();\n ctx.rect(i * cellWidth, y, cellWidth, cellHeight);\n ctx.clip();\n ctx.fillStyle = config.colors.ansi[colorIndex].css;\n ctx.fillText(String.fromCharCode(i), i * cellWidth, y);\n ctx.restore();\n }\n }\n\n // Colors 0-15 bold\n ctx.font = getFont(config.fontWeightBold, config);\n for (let colorIndex = 0; colorIndex < 16; colorIndex++) {\n const y = (colorIndex + 2 + 16) * cellHeight;\n // Draw ascii characters\n for (let i = 0; i < 256; i++) {\n ctx.save();\n ctx.beginPath();\n ctx.rect(i * cellWidth, y, cellWidth, cellHeight);\n ctx.clip();\n ctx.fillStyle = config.colors.ansi[colorIndex].css;\n ctx.fillText(String.fromCharCode(i), i * cellWidth, y);\n ctx.restore();\n }\n }\n 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 context) || isFirefox || isSafari) {\n // Don't attempt to clear background colors if createImageBitmap is not supported\n if (canvas instanceof HTMLCanvasElement) {\n // Just return the HTMLCanvas if it's a HTMLCanvasElement\n return canvas;\n }\n // Transfer to an ImageBitmap is this is an OffscreenCanvas\n return new Promise((r: (bitmap: ImageBitmap) => void) => r(canvas.transferToImageBitmap()));\n }\n\n const charAtlasImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);\n\n // Remove the background color from the image so characters may overlap\n clearColor(charAtlasImageData, config.colors.background);\n\n return context.createImageBitmap(charAtlasImageData);\n}\n\n/**\n * Makes a partiicular rgb color in an ImageData completely transparent.\n * @returns True if the result is \"empty\", meaning all pixels are fully transparent.\n */\nexport function clearColor(imageData: ImageData, color: IColor): boolean {\n let isEmpty = true;\n const r = color.rgba >>> 24;\n const g = color.rgba >>> 16 & 0xFF;\n const b = color.rgba >>> 8 & 0xFF;\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 } else {\n isEmpty = false;\n }\n }\n return isEmpty;\n}\n\nfunction getFont(fontWeight: FontWeight, config: ICharAtlasConfig): string {\n return `${fontWeight} ${config.fontSize * config.devicePixelRatio}px ${config.fontFamily}`;\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { LineData } from '../../Types';\nimport { CHAR_DATA_CHAR_INDEX, CHAR_DATA_ATTR_INDEX, CHAR_DATA_WIDTH_INDEX } from '../../Buffer';\nimport { FLAGS } from '../Types';\n\nexport const BOLD_CLASS = 'xterm-bold';\nexport const ITALIC_CLASS = 'xterm-italic';\nexport const CURSOR_CLASS = 'xterm-cursor';\n\nexport class DomRendererRowFactory {\n constructor(\n private _document: Document\n ) {\n }\n\n public createRow(lineData: LineData, isCursorRow: boolean, cursorX: number, cellWidth: number, cols: number): DocumentFragment {\n const fragment = this._document.createDocumentFragment();\n let colCount = 0;\n\n for (let x = 0; x < lineData.length; x++) {\n // Don't allow any buffer to the right to be displayed\n if (colCount >= cols) {\n continue;\n }\n\n const charData = lineData[x];\n const char: string = charData[CHAR_DATA_CHAR_INDEX];\n const attr: number = charData[CHAR_DATA_ATTR_INDEX];\n const width: number = charData[CHAR_DATA_WIDTH_INDEX];\n\n // The character to the left is a wide character, drawing is owned by the char at x-1\n if (width === 0) {\n continue;\n }\n\n const charElement = this._document.createElement('span');\n if (width > 1) {\n charElement.style.width = `${cellWidth * width}px`;\n }\n\n const flags = attr >> 18;\n let bg = attr & 0x1ff;\n let fg = (attr >> 9) & 0x1ff;\n\n if (isCursorRow && x === cursorX) {\n charElement.classList.add(CURSOR_CLASS);\n }\n\n // If inverse flag is on, the foreground should become the background.\n if (flags & FLAGS.INVERSE) {\n const temp = bg;\n bg = fg;\n fg = temp;\n if (fg === 256) {\n fg = 0;\n }\n if (bg === 257) {\n bg = 15;\n }\n }\n\n if (flags & FLAGS.BOLD) {\n // Convert the FG color to the bold variant\n if (fg < 8) {\n fg += 8;\n }\n charElement.classList.add(BOLD_CLASS);\n }\n\n if (flags & FLAGS.ITALIC) {\n charElement.classList.add(ITALIC_CLASS);\n }\n\n charElement.textContent = char;\n if (fg !== 257) {\n charElement.classList.add(`xterm-fg-${fg}`);\n }\n if (bg !== 256) {\n charElement.classList.add(`xterm-bg-${bg}`);\n }\n fragment.appendChild(charElement);\n colCount += width;\n }\n return fragment;\n }\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IRenderer, IRenderDimensions, IColorSet } from '../Types';\nimport { ITerminal, CharacterJoinerHandler } from '../../Types';\nimport { ITheme } from 'xterm';\nimport { EventEmitter } from '../../EventEmitter';\nimport { ColorManager } from '../ColorManager';\nimport { RenderDebouncer } from '../../ui/RenderDebouncer';\nimport { BOLD_CLASS, ITALIC_CLASS, CURSOR_CLASS, DomRendererRowFactory } from './DomRendererRowFactory';\n\nconst TERMINAL_CLASS_PREFIX = 'xterm-dom-renderer-owner-';\nconst ROW_CONTAINER_CLASS = 'xterm-rows';\nconst FG_CLASS_PREFIX = 'xterm-fg-';\nconst BG_CLASS_PREFIX = 'xterm-bg-';\nconst FOCUS_CLASS = 'xterm-focus';\nconst SELECTION_CLASS = 'xterm-selection';\n\nlet nextTerminalId = 1;\n\n// TODO: Pull into an addon when TS composite projects allow easier sharing of code (not just\n// interfaces) between core and addons\n\n/**\n * A fallback renderer for when canvas is slow. This is not meant to be\n * particularly fast or feature complete, more just stable and usable for when\n * canvas is not an option.\n */\nexport class DomRenderer extends EventEmitter implements IRenderer {\n private _renderDebouncer: RenderDebouncer;\n private _rowFactory: DomRendererRowFactory;\n private _terminalClass: number = nextTerminalId++;\n\n private _themeStyleElement: HTMLStyleElement;\n private _dimensionsStyleElement: HTMLStyleElement;\n private _rowContainer: HTMLElement;\n private _rowElements: HTMLElement[] = [];\n private _selectionContainer: HTMLElement;\n\n public dimensions: IRenderDimensions;\n public colorManager: ColorManager;\n\n constructor(private _terminal: ITerminal, theme: ITheme | undefined) {\n super();\n const allowTransparency = this._terminal.options.allowTransparency;\n this.colorManager = new ColorManager(document, allowTransparency);\n this.setTheme(theme);\n\n this._rowContainer = document.createElement('div');\n this._rowContainer.classList.add(ROW_CONTAINER_CLASS);\n this._rowContainer.style.lineHeight = 'normal';\n this._rowContainer.setAttribute('aria-hidden', 'true');\n this._refreshRowElements(this._terminal.cols, this._terminal.rows);\n this._selectionContainer = document.createElement('div');\n this._selectionContainer.classList.add(SELECTION_CLASS);\n this._selectionContainer.setAttribute('aria-hidden', 'true');\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._updateDimensions();\n\n this._renderDebouncer = new RenderDebouncer(this._terminal, this._renderRows.bind(this));\n this._rowFactory = new DomRendererRowFactory(document);\n\n this._terminal.element.classList.add(TERMINAL_CLASS_PREFIX + this._terminalClass);\n this._terminal.screenElement.appendChild(this._rowContainer);\n this._terminal.screenElement.appendChild(this._selectionContainer);\n }\n\n public dispose(): void {\n this._terminal.element.classList.remove(TERMINAL_CLASS_PREFIX + this._terminalClass);\n this._terminal.screenElement.removeChild(this._rowContainer);\n this._terminal.screenElement.removeChild(this._selectionContainer);\n this._terminal.screenElement.removeChild(this._themeStyleElement);\n this._terminal.screenElement.removeChild(this._dimensionsStyleElement);\n super.dispose();\n }\n\n private _updateDimensions(): void {\n this.dimensions.scaledCharWidth = this._terminal.charMeasure.width * window.devicePixelRatio;\n this.dimensions.scaledCharHeight = this._terminal.charMeasure.height * window.devicePixelRatio;\n this.dimensions.scaledCellWidth = this.dimensions.scaledCharWidth;\n this.dimensions.scaledCellHeight = this.dimensions.scaledCharHeight;\n this.dimensions.scaledCharLeft = 0;\n this.dimensions.scaledCharTop = 0;\n this.dimensions.scaledCanvasWidth = this.dimensions.scaledCellWidth * this._terminal.cols;\n this.dimensions.scaledCanvasHeight = this.dimensions.scaledCellHeight * this._terminal.rows;\n this.dimensions.canvasWidth = this._terminal.charMeasure.width * this._terminal.cols;\n this.dimensions.canvasHeight = this._terminal.charMeasure.height * this._terminal.rows;\n this.dimensions.actualCellWidth = this._terminal.charMeasure.width;\n this.dimensions.actualCellHeight = this._terminal.charMeasure.height;\n\n this._rowElements.forEach(element => {\n element.style.width = `${this.dimensions.canvasWidth}px`;\n element.style.height = `${this._terminal.charMeasure.height}px`;\n });\n\n if (!this._dimensionsStyleElement) {\n this._dimensionsStyleElement = document.createElement('style');\n this._terminal.screenElement.appendChild(this._dimensionsStyleElement);\n }\n\n const styles =\n `${this._terminalSelector} .${ROW_CONTAINER_CLASS} span {` +\n ` display: inline-block;` +\n ` height: 100%;` +\n ` vertical-align: top;` +\n ` width: ${this._terminal.charMeasure.width}px` +\n `}`;\n\n this._dimensionsStyleElement.innerHTML = styles;\n\n this._selectionContainer.style.height = (this._terminal)._viewportElement.style.height;\n this._rowContainer.style.width = `${this.dimensions.canvasWidth}px`;\n this._rowContainer.style.height = `${this.dimensions.canvasHeight}px`;\n }\n\n public setTheme(theme: ITheme | undefined): IColorSet {\n if (theme) {\n this.colorManager.setTheme(theme);\n }\n\n if (!this._themeStyleElement) {\n this._themeStyleElement = document.createElement('style');\n this._terminal.screenElement.appendChild(this._themeStyleElement);\n }\n\n // Base CSS\n let styles =\n `${this._terminalSelector} .${ROW_CONTAINER_CLASS} {` +\n ` color: ${this.colorManager.colors.foreground.css};` +\n ` background-color: ${this.colorManager.colors.background.css};` +\n ` font-family: ${this._terminal.getOption('fontFamily')};` +\n ` font-size: ${this._terminal.getOption('fontSize')}px;` +\n `}`;\n // Text styles\n styles +=\n `${this._terminalSelector} span:not(.${BOLD_CLASS}) {` +\n ` font-weight: ${this._terminal.options.fontWeight};` +\n `}` +\n `${this._terminalSelector} span.${BOLD_CLASS} {` +\n ` font-weight: ${this._terminal.options.fontWeightBold};` +\n `}` +\n `${this._terminalSelector} span.${ITALIC_CLASS} {` +\n ` font-style: italic;` +\n `}`;\n // Cursor\n styles +=\n `${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${CURSOR_CLASS} {` +\n ` background-color: ${this.colorManager.colors.cursor.css};` +\n ` color: ${this.colorManager.colors.cursorAccent.css};` +\n `}` +\n `${this._terminalSelector} .${ROW_CONTAINER_CLASS}:not(.${FOCUS_CLASS}) .${CURSOR_CLASS} {` +\n ` outline: 1px solid #fff;` +\n ` outline-offset: -1px;` +\n `}`;\n // Selection\n styles +=\n `${this._terminalSelector} .${SELECTION_CLASS} {` +\n ` position: absolute;` +\n ` top: 0;` +\n ` left: 0;` +\n ` z-index: 1;` +\n ` pointer-events: none;` +\n `}` +\n `${this._terminalSelector} .${SELECTION_CLASS} div {` +\n ` position: absolute;` +\n ` background-color: ${this.colorManager.colors.selection.css};` +\n `}`;\n // Colors\n this.colorManager.colors.ansi.forEach((c, i) => {\n styles +=\n `${this._terminalSelector} .${FG_CLASS_PREFIX}${i} { color: ${c.css}; }` +\n `${this._terminalSelector} .${BG_CLASS_PREFIX}${i} { background-color: ${c.css}; }`;\n });\n\n this._themeStyleElement.innerHTML = styles;\n return this.colorManager.colors;\n }\n\n public onWindowResize(devicePixelRatio: number): void {\n this._updateDimensions();\n }\n\n private _refreshRowElements(cols: number, rows: number): void {\n // Add missing elements\n for (let i = this._rowElements.length; i <= rows; i++) {\n const row = document.createElement('div');\n this._rowContainer.appendChild(row);\n this._rowElements.push(row);\n }\n // Remove excess elements\n while (this._rowElements.length > rows) {\n this._rowContainer.removeChild(this._rowElements.pop());\n }\n }\n\n public onResize(cols: number, rows: number): void {\n this._refreshRowElements(cols, rows);\n this._updateDimensions();\n }\n\n public onCharSizeChanged(): void {\n this._updateDimensions();\n }\n\n public onBlur(): void {\n this._rowContainer.classList.remove(FOCUS_CLASS);\n }\n\n public onFocus(): void {\n this._rowContainer.classList.add(FOCUS_CLASS);\n }\n\n public onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean): void {\n // Remove all selections\n while (this._selectionContainer.children.length) {\n this._selectionContainer.removeChild(this._selectionContainer.children[0]);\n }\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] - this._terminal.buffer.ydisp;\n const viewportEndRow = end[1] - this._terminal.buffer.ydisp;\n const viewportCappedStartRow = Math.max(viewportStartRow, 0);\n const viewportCappedEndRow = Math.min(viewportEndRow, this._terminal.rows - 1);\n\n // No need to draw the selection\n if (viewportCappedStartRow >= this._terminal.rows || viewportCappedEndRow < 0) {\n return;\n }\n\n // Create the selections\n const documentFragment = document.createDocumentFragment();\n\n if (columnSelectMode) {\n documentFragment.appendChild(\n this._createSelectionElement(viewportCappedStartRow, start[0], end[0], viewportCappedEndRow - viewportCappedStartRow + 1)\n );\n } else {\n // Draw first row\n const startCol = viewportStartRow === viewportCappedStartRow ? start[0] : 0;\n const endCol = viewportCappedStartRow === viewportCappedEndRow ? end[0] : this._terminal.cols;\n documentFragment.appendChild(this._createSelectionElement(viewportCappedStartRow, startCol, endCol));\n // Draw middle rows\n const middleRowsCount = viewportCappedEndRow - viewportCappedStartRow - 1;\n documentFragment.appendChild(this._createSelectionElement(viewportCappedStartRow + 1, 0, this._terminal.cols, middleRowsCount));\n // Draw final row\n if (viewportCappedStartRow !== viewportCappedEndRow) {\n // Only draw viewportEndRow if it's not the same as viewporttartRow\n const endCol = viewportEndRow === viewportCappedEndRow ? end[0] : this._terminal.cols;\n documentFragment.appendChild(this._createSelectionElement(viewportCappedEndRow, 0, endCol));\n }\n }\n this._selectionContainer.appendChild(documentFragment);\n }\n\n /**\n * Creates a selection element at the specified position.\n * @param row The row of the selection.\n * @param colStart The start column.\n * @param colEnd The end columns.\n */\n private _createSelectionElement(row: number, colStart: number, colEnd: number, rowCount: number = 1): HTMLElement {\n const element = document.createElement('div');\n element.style.height = `${rowCount * this._terminal.charMeasure.height}px`;\n element.style.top = `${row * this._terminal.charMeasure.height}px`;\n element.style.left = `${colStart * this._terminal.charMeasure.width}px`;\n element.style.width = `${this._terminal.charMeasure.width * (colEnd - colStart)}px`;\n return element;\n }\n\n public onCursorMove(): void {\n // No-op, the cursor is drawn when rows are drawn\n }\n\n public onOptionsChanged(): void {\n // Force a refresh\n this._updateDimensions();\n this.setTheme(undefined);\n this._terminal.refresh(0, this._terminal.rows - 1);\n }\n\n public clear(): void {\n this._rowElements.forEach(e => e.innerHTML = '');\n }\n\n public refreshRows(start: number, end: number): void {\n this._renderDebouncer.refresh(start, end);\n }\n\n private _renderRows(start: number, end: number): void {\n const terminal = this._terminal;\n\n const cursorAbsoluteY = terminal.buffer.ybase + terminal.buffer.y;\n const cursorX = this._terminal.buffer.x;\n\n for (let y = start; y <= end; y++) {\n const rowElement = this._rowElements[y];\n rowElement.innerHTML = '';\n\n const row = y + terminal.buffer.ydisp;\n const lineData = terminal.buffer.lines.get(row);\n rowElement.appendChild(this._rowFactory.createRow(lineData, row === cursorAbsoluteY, cursorX, terminal.charMeasure.width, terminal.cols));\n }\n\n this._terminal.emit('refresh', {start, end});\n }\n\n private get _terminalSelector(): string {\n return `.${TERMINAL_CLASS_PREFIX}${this._terminalClass}`;\n }\n\n public registerCharacterJoiner(handler: CharacterJoinerHandler): number { return -1; }\n public deregisterCharacterJoiner(joinerId: number): boolean { return false; }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nexport const INVERTED_DEFAULT_COLOR = -1;\nexport const DIM_OPACITY = 0.5;\n\nexport interface IGlyphIdentifier {\n chars: string;\n code: number;\n bg: number;\n fg: number;\n bold: boolean;\n dim: boolean;\n italic: boolean;\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { DIM_OPACITY, IGlyphIdentifier } from './Types';\nimport { CHAR_ATLAS_CELL_SPACING, ICharAtlasConfig } from '../../shared/atlas/Types';\nimport { generateStaticCharAtlasTexture } from '../../shared/atlas/CharAtlasGenerator';\nimport BaseCharAtlas from './BaseCharAtlas';\n\nexport default class StaticCharAtlas extends BaseCharAtlas {\n private _texture: HTMLCanvasElement | ImageBitmap;\n\n constructor(private _document: Document, private _config: ICharAtlasConfig) {\n super();\n }\n\n private _canvasFactory = (width: number, height: number) => {\n const canvas = this._document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n\n // This is useful for debugging\n // document.body.appendChild(canvas);\n\n return canvas;\n }\n\n protected _doWarmUp(): void {\n const result = generateStaticCharAtlasTexture(window, this._canvasFactory, this._config);\n if (result instanceof HTMLCanvasElement) {\n this._texture = result;\n } else {\n result.then(texture => {\n this._texture = texture;\n });\n }\n }\n\n private _isCached(glyph: IGlyphIdentifier, colorIndex: number): boolean {\n const isAscii = glyph.code < 256;\n // A color is basic if it is one of the 4 bit ANSI colors.\n const isBasicColor = glyph.fg < 16;\n const isDefaultColor = glyph.fg >= 256;\n const isDefaultBackground = glyph.bg >= 256;\n return isAscii && (isBasicColor || isDefaultColor) && isDefaultBackground && !glyph.italic;\n }\n\n public draw(\n ctx: CanvasRenderingContext2D,\n glyph: IGlyphIdentifier,\n x: number,\n y: number\n ): boolean {\n // we're not warmed up yet\n if (this._texture == null) {\n return false;\n }\n\n let colorIndex = 0;\n if (glyph.fg < 256) {\n colorIndex = 2 + glyph.fg + (glyph.bold ? 16 : 0);\n } else {\n // If default color and bold\n if (glyph.bold) {\n colorIndex = 1;\n }\n }\n if (!this._isCached(glyph, colorIndex)) {\n return false;\n }\n\n ctx.save();\n\n // ImageBitmap's draw about twice as fast as from a canvas\n const charAtlasCellWidth = this._config.scaledCharWidth + CHAR_ATLAS_CELL_SPACING;\n const charAtlasCellHeight = this._config.scaledCharHeight + CHAR_ATLAS_CELL_SPACING;\n\n // Apply alpha to dim the character\n if (glyph.dim) {\n ctx.globalAlpha = DIM_OPACITY;\n }\n\n ctx.drawImage(\n this._texture,\n glyph.code * charAtlasCellWidth,\n colorIndex * charAtlasCellHeight,\n charAtlasCellWidth,\n this._config.scaledCharHeight,\n x,\n y,\n charAtlasCellWidth,\n this._config.scaledCharHeight\n );\n\n ctx.restore();\n\n return true;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * A dummy CharAtlas implementation that always fails to draw characters.\n */\n\nimport { IGlyphIdentifier } from './Types';\nimport { ICharAtlasConfig } from '../../shared/atlas/Types';\nimport BaseCharAtlas from './BaseCharAtlas';\n\nexport default class NoneCharAtlas extends BaseCharAtlas {\n constructor(document: Document, config: ICharAtlasConfig) {\n super();\n }\n\n public draw(\n ctx: CanvasRenderingContext2D,\n glyph: IGlyphIdentifier,\n x: number,\n y: number\n ): boolean {\n return false;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\ninterface ILinkedListNode {\n prev: ILinkedListNode;\n next: ILinkedListNode;\n key: string;\n value: T;\n}\n\nexport default class LRUMap {\n private _map: { [key: string]: ILinkedListNode } = {};\n private _head: ILinkedListNode = null;\n private _tail: ILinkedListNode = null;\n private _nodePool: ILinkedListNode[] = [];\n public size: number = 0;\n\n constructor(public capacity: number) { }\n\n private _unlinkNode(node: ILinkedListNode): void {\n const prev = node.prev;\n const next = node.next;\n if (node === this._head) {\n this._head = next;\n }\n if (node === this._tail) {\n this._tail = prev;\n }\n if (prev !== null) {\n prev.next = next;\n }\n if (next !== null) {\n next.prev = prev;\n }\n }\n\n private _appendNode(node: ILinkedListNode): void {\n const tail = this._tail;\n if (tail !== null) {\n tail.next = node;\n }\n node.prev = tail;\n node.next = null;\n this._tail = node;\n if (this._head === null) {\n this._head = node;\n }\n }\n\n /**\n * Preallocate a bunch of linked-list nodes. Allocating these nodes ahead of time means that\n * they're more likely to live next to each other in memory, which seems to improve performance.\n *\n * Each empty object only consumes about 60 bytes of memory, so this is pretty cheap, even for\n * large maps.\n */\n public prealloc(count: number): void {\n const nodePool = this._nodePool;\n for (let i = 0; i < count; i++) {\n nodePool.push({\n prev: null,\n next: null,\n key: null,\n value: null\n });\n }\n }\n\n public get(key: string): T | null {\n // This is unsafe: We're assuming our keyspace doesn't overlap with Object.prototype. However,\n // it's faster than calling hasOwnProperty, and in our case, it would never overlap.\n const node = this._map[key];\n if (node !== undefined) {\n this._unlinkNode(node);\n this._appendNode(node);\n return node.value;\n }\n return null;\n }\n\n public peek(): T | null {\n const head = this._head;\n return head === null ? null : head.value;\n }\n\n public set(key: string, value: T): void {\n // This is unsafe: See note above.\n let node = this._map[key];\n if (node !== undefined) {\n // already exists, we just need to mutate it and move it to the end of the list\n node = this._map[key];\n this._unlinkNode(node);\n node.value = value;\n } else if (this.size >= this.capacity) {\n // we're out of space: recycle the head node, move it to the tail\n node = this._head;\n this._unlinkNode(node);\n delete this._map[node.key];\n node.key = key;\n node.value = value;\n this._map[key] = node;\n } else {\n // make a new element\n const nodePool = this._nodePool;\n if (nodePool.length > 0) {\n // use a preallocated node if we can\n node = nodePool.pop();\n node.key = key;\n node.value = value;\n } else {\n node = {\n prev: null,\n next: null,\n key,\n value\n };\n }\n this._map[key] = node;\n this.size++;\n }\n this._appendNode(node);\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { DIM_OPACITY, IGlyphIdentifier, INVERTED_DEFAULT_COLOR } from './Types';\nimport { ICharAtlasConfig } from '../../shared/atlas/Types';\nimport { IColor } from '../../shared/Types';\nimport BaseCharAtlas from './BaseCharAtlas';\nimport { DEFAULT_ANSI_COLORS } from '../ColorManager';\nimport { clearColor } from '../../shared/atlas/CharAtlasGenerator';\nimport LRUMap from './LRUMap';\n\n// In practice we're probably never going to exhaust a texture this large. For debugging purposes,\n// however, it can be useful to set this to a really tiny value, to verify that LRU eviction works.\nconst TEXTURE_WIDTH = 1024;\nconst TEXTURE_HEIGHT = 1024;\n\nconst TRANSPARENT_COLOR = {\n css: 'rgba(0, 0, 0, 0)',\n rgba: 0\n};\n\n// Drawing to the cache is expensive: If we have to draw more than this number of glyphs to the\n// cache in a single frame, give up on trying to cache anything else, and try to finish the current\n// frame ASAP.\n//\n// This helps to limit the amount of damage a program can do when it would otherwise thrash the\n// cache.\nconst FRAME_CACHE_DRAW_LIMIT = 100;\n\ninterface IGlyphCacheValue {\n index: number;\n isEmpty: boolean;\n}\n\nfunction getGlyphCacheKey(glyph: IGlyphIdentifier): string {\n const styleFlags = (glyph.bold ? 0 : 4) + (glyph.dim ? 0 : 2) + (glyph.italic ? 0 : 1);\n return `${glyph.bg}_${glyph.fg}_${styleFlags}${glyph.chars}`;\n}\n\nexport default class DynamicCharAtlas extends BaseCharAtlas {\n // An ordered map that we're using to keep track of where each glyph is in the atlas texture.\n // It's ordered so that we can determine when to remove the old entries.\n private _cacheMap: LRUMap;\n\n // The texture that the atlas is drawn to\n private _cacheCanvas: HTMLCanvasElement;\n private _cacheCtx: CanvasRenderingContext2D;\n\n // A temporary context that glyphs are drawn to before being transfered to the atlas.\n private _tmpCtx: CanvasRenderingContext2D;\n\n // The number of characters stored in the atlas by width/height\n private _width: number;\n private _height: number;\n\n private _drawToCacheCount: number = 0;\n\n constructor(document: Document, private _config: ICharAtlasConfig) {\n super();\n this._cacheCanvas = document.createElement('canvas');\n this._cacheCanvas.width = TEXTURE_WIDTH;\n this._cacheCanvas.height = TEXTURE_HEIGHT;\n // The canvas needs alpha because we use clearColor to convert the background color to alpha.\n // It might also contain some characters with transparent backgrounds if allowTransparency is\n // set.\n this._cacheCtx = this._cacheCanvas.getContext('2d', {alpha: true});\n\n const tmpCanvas = document.createElement('canvas');\n tmpCanvas.width = this._config.scaledCharWidth;\n tmpCanvas.height = this._config.scaledCharHeight;\n this._tmpCtx = tmpCanvas.getContext('2d', {alpha: this._config.allowTransparency});\n\n this._width = Math.floor(TEXTURE_WIDTH / this._config.scaledCharWidth);\n this._height = Math.floor(TEXTURE_HEIGHT / this._config.scaledCharHeight);\n const capacity = this._width * this._height;\n this._cacheMap = new LRUMap(capacity);\n this._cacheMap.prealloc(capacity);\n\n // This is useful for debugging\n // document.body.appendChild(this._cacheCanvas);\n }\n\n public beginFrame(): void {\n this._drawToCacheCount = 0;\n }\n\n public draw(\n ctx: CanvasRenderingContext2D,\n glyph: IGlyphIdentifier,\n x: number,\n y: number\n ): boolean {\n const glyphKey = getGlyphCacheKey(glyph);\n const cacheValue = this._cacheMap.get(glyphKey);\n if (cacheValue != null) {\n this._drawFromCache(ctx, cacheValue, x, y);\n return true;\n } else if (this._canCache(glyph) && this._drawToCacheCount < FRAME_CACHE_DRAW_LIMIT) {\n let index;\n if (this._cacheMap.size < this._cacheMap.capacity) {\n index = this._cacheMap.size;\n } else {\n // we're out of space, so our call to set will delete this item\n index = this._cacheMap.peek().index;\n }\n const cacheValue = this._drawToCache(glyph, index);\n this._cacheMap.set(glyphKey, cacheValue);\n this._drawFromCache(ctx, cacheValue, x, y);\n return true;\n }\n return false;\n }\n\n private _canCache(glyph: IGlyphIdentifier): boolean {\n // Only cache ascii and extended characters for now, to be safe. In the future, we could do\n // something more complicated to determine the expected width of a character.\n //\n // If we switch the renderer over to webgl at some point, we may be able to use blending modes\n // to draw overlapping glyphs from the atlas:\n // https://github.com/servo/webrender/issues/464#issuecomment-255632875\n // https://webglfundamentals.org/webgl/lessons/webgl-text-texture.html\n return glyph.code < 256;\n }\n\n private _toCoordinates(index: number): [number, number] {\n return [\n (index % this._width) * this._config.scaledCharWidth,\n Math.floor(index / this._width) * this._config.scaledCharHeight\n ];\n }\n\n private _drawFromCache(\n ctx: CanvasRenderingContext2D,\n cacheValue: IGlyphCacheValue,\n x: number,\n y: number\n ): void {\n // We don't actually need to do anything if this is whitespace.\n if (cacheValue.isEmpty) {\n return;\n }\n const [cacheX, cacheY] = this._toCoordinates(cacheValue.index);\n ctx.drawImage(\n this._cacheCanvas,\n cacheX,\n cacheY,\n this._config.scaledCharWidth,\n this._config.scaledCharHeight,\n x,\n y,\n this._config.scaledCharWidth,\n this._config.scaledCharHeight\n );\n }\n\n private _getColorFromAnsiIndex(idx: number): IColor {\n if (idx < this._config.colors.ansi.length) {\n return this._config.colors.ansi[idx];\n }\n return DEFAULT_ANSI_COLORS[idx];\n }\n\n private _getBackgroundColor(glyph: IGlyphIdentifier): IColor {\n if (this._config.allowTransparency) {\n // The background color might have some transparency, so we need to render it as fully\n // transparent in the atlas. Otherwise we'd end up drawing the transparent background twice\n // around the anti-aliased edges of the glyph, and it would look too dark.\n return TRANSPARENT_COLOR;\n } else if (glyph.bg === INVERTED_DEFAULT_COLOR) {\n return this._config.colors.foreground;\n } else if (glyph.bg < 256) {\n return this._getColorFromAnsiIndex(glyph.bg);\n }\n return this._config.colors.background;\n }\n\n private _getForegroundColor(glyph: IGlyphIdentifier): IColor {\n if (glyph.fg === INVERTED_DEFAULT_COLOR) {\n return this._config.colors.background;\n } else if (glyph.fg < 256) {\n // 256 color support\n return this._getColorFromAnsiIndex(glyph.fg);\n }\n return this._config.colors.foreground;\n }\n\n // TODO: We do this (or something similar) in multiple places. We should split this off\n // into a shared function.\n private _drawToCache(glyph: IGlyphIdentifier, index: number): IGlyphCacheValue {\n this._drawToCacheCount++;\n\n this._tmpCtx.save();\n\n // draw the background\n const backgroundColor = this._getBackgroundColor(glyph);\n // Use a 'copy' composite operation to clear any existing glyph out of _tmpCtxWithAlpha, regardless of\n // transparency in backgroundColor\n this._tmpCtx.globalCompositeOperation = 'copy';\n this._tmpCtx.fillStyle = backgroundColor.css;\n this._tmpCtx.fillRect(0, 0, this._config.scaledCharWidth, this._config.scaledCharHeight);\n this._tmpCtx.globalCompositeOperation = 'source-over';\n\n // draw the foreground/glyph\n const fontWeight = glyph.bold ? this._config.fontWeightBold : this._config.fontWeight;\n const fontStyle = glyph.italic ? 'italic' : '';\n this._tmpCtx.font =\n `${fontStyle} ${fontWeight} ${this._config.fontSize * this._config.devicePixelRatio}px ${this._config.fontFamily}`;\n this._tmpCtx.textBaseline = 'top';\n\n this._tmpCtx.fillStyle = this._getForegroundColor(glyph).css;\n\n // Apply alpha to dim the character\n if (glyph.dim) {\n this._tmpCtx.globalAlpha = DIM_OPACITY;\n }\n // Draw the character\n this._tmpCtx.fillText(glyph.chars, 0, 0);\n this._tmpCtx.restore();\n\n // clear the background from the character to avoid issues with drawing over the previous\n // character if it extends past it's bounds\n const imageData = this._tmpCtx.getImageData(\n 0, 0, this._config.scaledCharWidth, this._config.scaledCharHeight\n );\n let isEmpty = false;\n if (!this._config.allowTransparency) {\n isEmpty = clearColor(imageData, backgroundColor);\n }\n\n // copy the data from imageData to _cacheCanvas\n const [x, y] = this._toCoordinates(index);\n // putImageData doesn't do any blending, so it will overwrite any existing cache entry for us\n this._cacheCtx.putImageData(imageData, x, y);\n\n return {\n index,\n isEmpty\n };\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ITerminal } from '../../Types';\nimport { IColorSet } from '../Types';\nimport { ICharAtlasConfig } from '../../shared/atlas/Types';\n\nexport function generateConfig(scaledCharWidth: number, scaledCharHeight: number, terminal: ITerminal, colors: IColorSet): ICharAtlasConfig {\n // null out some fields that don't matter\n const clonedColors = {\n foreground: colors.foreground,\n background: colors.background,\n cursor: null,\n cursorAccent: null,\n selection: null,\n // For the static char atlas, we only use the first 16 colors, but we need all 256 for the\n // dynamic character atlas.\n ansi: colors.ansi.slice(0, 16)\n };\n return {\n type: terminal.options.experimentalCharAtlas,\n devicePixelRatio: window.devicePixelRatio,\n scaledCharWidth,\n scaledCharHeight,\n fontFamily: terminal.options.fontFamily,\n fontSize: terminal.options.fontSize,\n fontWeight: terminal.options.fontWeight,\n fontWeightBold: terminal.options.fontWeightBold,\n allowTransparency: terminal.options.allowTransparency,\n colors: clonedColors\n };\n}\n\nexport function configEquals(a: ICharAtlasConfig, b: ICharAtlasConfig): boolean {\n for (let i = 0; i < a.colors.ansi.length; i++) {\n if (a.colors.ansi[i].rgba !== b.colors.ansi[i].rgba) {\n return false;\n }\n }\n return a.type === b.type &&\n a.devicePixelRatio === b.devicePixelRatio &&\n a.fontFamily === b.fontFamily &&\n a.fontSize === b.fontSize &&\n a.fontWeight === b.fontWeight &&\n a.fontWeightBold === b.fontWeightBold &&\n a.allowTransparency === b.allowTransparency &&\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","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ITerminal } from '../../Types';\nimport { IColorSet } from '../Types';\nimport { ICharAtlasConfig } from '../../shared/atlas/Types';\nimport { generateConfig, configEquals } from './CharAtlasUtils';\nimport BaseCharAtlas from './BaseCharAtlas';\nimport DynamicCharAtlas from './DynamicCharAtlas';\nimport NoneCharAtlas from './NoneCharAtlas';\nimport StaticCharAtlas from './StaticCharAtlas';\n\nconst charAtlasImplementations = {\n 'none': NoneCharAtlas,\n 'static': StaticCharAtlas,\n 'dynamic': DynamicCharAtlas\n};\n\ninterface ICharAtlasCacheEntry {\n atlas: BaseCharAtlas;\n config: ICharAtlasConfig;\n // N.B. This implementation potentially holds onto copies of the terminal forever, so\n // this may cause memory leaks.\n ownedBy: ITerminal[];\n}\n\nconst 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(\n terminal: ITerminal,\n colors: IColorSet,\n scaledCharWidth: number,\n scaledCharHeight: number\n): BaseCharAtlas {\n const newConfig = generateConfig(scaledCharWidth, scaledCharHeight, terminal, colors);\n\n // TODO: Currently if a terminal changes configs it will not free the entry reference (until it's disposed)\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.atlas;\n }\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 // 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.atlas;\n }\n }\n\n const newEntry: ICharAtlasCacheEntry = {\n atlas: new charAtlasImplementations[terminal.options.experimentalCharAtlas](\n document,\n newConfig\n ),\n config: newConfig,\n ownedBy: [terminal]\n };\n charAtlasCache.push(newEntry);\n return newEntry.atlas;\n}\n\n/**\n * Removes a terminal reference from the cache, allowing its memory to be freed.\n * @param terminal The terminal to remove.\n */\nexport function removeTerminalFromCache(terminal: ITerminal): void {\n for (let i = 0; i < charAtlasCache.length; i++) {\n const index = charAtlasCache[i].ownedBy.indexOf(terminal);\n if (index !== -1) {\n if (charAtlasCache[i].ownedBy.length === 1) {\n // Remove the cache entry if it's the only terminal\n charAtlasCache.splice(i, 1);\n } else {\n // Remove the reference from the cache entry\n charAtlasCache[i].ownedBy.splice(index, 1);\n }\n break;\n }\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IGlyphIdentifier } from './Types';\n\nexport default abstract class BaseCharAtlas {\n private _didWarmUp: boolean = false;\n\n /**\n * Perform any work needed to warm the cache before it can be used. May be called multiple times.\n * Implement _doWarmUp instead if you only want to get called once.\n */\n public warmUp(): void {\n if (!this._didWarmUp) {\n this._doWarmUp();\n this._didWarmUp = true;\n }\n }\n\n /**\n * Perform any work needed to warm the cache before it can be used. Used by the default\n * implementation of warmUp(), and will only be called once.\n */\n protected _doWarmUp(): void { }\n\n /**\n * Called when we start drawing a new frame.\n *\n * TODO: We rely on this getting called by TextRenderLayer. This should really be called by\n * Renderer instead, but we need to make Renderer the source-of-truth for the char atlas, instead\n * of BaseRenderLayer.\n */\n public beginFrame(): void { }\n\n /**\n * May be called before warmUp finishes, however it is okay for the implementation to\n * do nothing and return false in that case.\n *\n * @param ctx Where to draw the character onto.\n * @param glyph Information about what to draw\n * @param x The position on the context to start drawing at\n * @param y The position on the context to start drawing at\n * @returns The success state. True if we drew the character.\n */\n public abstract draw(\n ctx: CanvasRenderingContext2D,\n glyph: IGlyphIdentifier,\n x: number,\n y: number\n ): boolean;\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { CHAR_DATA_ATTR_INDEX, CHAR_DATA_CODE_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, NULL_CELL_CODE } from '../Buffer';\nimport { FLAGS, IColorSet, IRenderDimensions, ICharacterJoinerRegistry } from './Types';\nimport { CharData, ITerminal } from '../Types';\nimport { INVERTED_DEFAULT_COLOR } from './atlas/Types';\nimport { GridCache } from './GridCache';\nimport { BaseRenderLayer } 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 */\n// const 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 private _characterJoinerRegistry: ICharacterJoinerRegistry;\n\n constructor(container: HTMLElement, zIndex: number, colors: IColorSet, characterJoinerRegistry: ICharacterJoinerRegistry, alpha: boolean) {\n super(container, 'text', zIndex, alpha, colors);\n this._state = new GridCache();\n this._characterJoinerRegistry = characterJoinerRegistry;\n }\n\n public resize(terminal: ITerminal, dim: IRenderDimensions): void {\n super.resize(terminal, dim);\n\n // Clear the character width cache if the font or width has changed\n const terminalFont = this._getFont(terminal, false, false);\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 private _forEachCell(\n terminal: ITerminal,\n firstRow: number,\n lastRow: number,\n joinerRegistry: ICharacterJoinerRegistry | null,\n callback: (\n code: number,\n chars: string,\n width: number,\n x: number,\n y: number,\n fg: number,\n bg: number,\n flags: number\n ) => void\n ): void {\n for (let y = firstRow; y <= lastRow; y++) {\n const row = y + terminal.buffer.ydisp;\n const line = terminal.buffer.lines.get(row);\n const joinedRanges = joinerRegistry ? joinerRegistry.getJoinedCharacters(row) : [];\n for (let x = 0; x < terminal.cols; x++) {\n const charData = line[x];\n let code: number = charData[CHAR_DATA_CODE_INDEX];\n\n // Can either represent character(s) for a single cell or multiple cells\n // if indicated by a character joiner.\n let chars: 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 // If true, indicates that the current character(s) to draw were joined.\n let isJoined = false;\n let lastCharX = x;\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 continue;\n }\n\n // Process any joined character ranges as needed. Because of how the\n // ranges are produced, we know that they are valid for the characters\n // and attributes of our input.\n if (joinedRanges.length > 0 && x === joinedRanges[0][0]) {\n isJoined = true;\n const range = joinedRanges.shift();\n\n // We already know the exact start and end column of the joined range,\n // so we get the string and width representing it directly\n chars = terminal.buffer.translateBufferLineToString(\n row,\n true,\n range[0],\n range[1]\n );\n width = range[1] - range[0];\n code = Infinity;\n\n // Skip over the cells occupied by this range in the loop\n lastCharX = range[1] - 1;\n }\n\n // If the character is an overlapping char and the character to the\n // right is a space, take ownership of the cell to the right. We skip\n // this check for joined characters because their rendering likely won't\n // yield the same result as rendering the last character individually.\n if (!isJoined && 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 (lastCharX < line.length - 1 && line[lastCharX + 1][CHAR_DATA_CODE_INDEX] === NULL_CELL_CODE) {\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 const flags = attr >> 18;\n let bg = attr & 0x1ff;\n let fg = (attr >> 9) & 0x1ff;\n\n // If inverse flag is on, the foreground should become the background.\n if (flags & FLAGS.INVERSE) {\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 callback(\n code,\n chars,\n width,\n x,\n y,\n fg,\n bg,\n flags\n );\n\n x = lastCharX;\n }\n }\n }\n\n /**\n * Draws the background for a specified range of columns. Tries to batch adjacent cells of the\n * same color together to reduce draw calls.\n */\n private _drawBackground(terminal: ITerminal, firstRow: number, lastRow: number): void {\n const ctx = this._ctx;\n const cols = terminal.cols;\n let startX: number = 0;\n let startY: number = 0;\n let prevFillStyle: string | null = null;\n\n ctx.save();\n\n this._forEachCell(terminal, firstRow, lastRow, null, (code, chars, width, x, y, fg, bg, flags) => {\n // libvte and xterm both draw the background (but not foreground) of invisible characters,\n // so we should too.\n let nextFillStyle = null; // null represents default background color\n if (bg === INVERTED_DEFAULT_COLOR) {\n nextFillStyle = this._colors.foreground.css;\n } else if (bg < 256) {\n nextFillStyle = this._colors.ansi[bg].css;\n }\n\n if (prevFillStyle === null) {\n // This is either the first iteration, or the default background was set. Either way, we\n // don't need to draw anything.\n startX = x;\n startY = y;\n } if (y !== startY) {\n // our row changed, draw the previous row\n ctx.fillStyle = prevFillStyle;\n this.fillCells(startX, startY, cols - startX, 1);\n startX = x;\n startY = y;\n } else if (prevFillStyle !== nextFillStyle) {\n // our color changed, draw the previous characters in this row\n ctx.fillStyle = prevFillStyle;\n this.fillCells(startX, startY, x - startX, 1);\n startX = x;\n startY = y;\n }\n\n prevFillStyle = nextFillStyle;\n });\n\n // flush the last color we encountered\n if (prevFillStyle !== null) {\n ctx.fillStyle = prevFillStyle;\n this.fillCells(startX, startY, cols - startX, 1);\n }\n\n ctx.restore();\n }\n\n private _drawForeground(terminal: ITerminal, firstRow: number, lastRow: number): void {\n this._forEachCell(terminal, firstRow, lastRow, this._characterJoinerRegistry, (code, chars, width, x, y, fg, bg, flags) => {\n if (flags & FLAGS.INVISIBLE) {\n return;\n }\n if (flags & FLAGS.UNDERLINE) {\n this._ctx.save();\n if (fg === INVERTED_DEFAULT_COLOR) {\n this._ctx.fillStyle = this._colors.background.css;\n } else if (fg < 256) {\n // 256 color support\n this._ctx.fillStyle = this._colors.ansi[fg].css;\n } else {\n this._ctx.fillStyle = this._colors.foreground.css;\n }\n this.fillBottomLineAtCells(x, y, width);\n this._ctx.restore();\n }\n this.drawChars(\n terminal, chars, code,\n width, x, y,\n fg, bg,\n !!(flags & FLAGS.BOLD), !!(flags & FLAGS.DIM), !!(flags & FLAGS.ITALIC)\n );\n });\n }\n\n public onGridChanged(terminal: ITerminal, firstRow: number, lastRow: number): void {\n // Resize has not been called yet\n if (this._state.cache.length === 0) {\n return;\n }\n\n if (this._charAtlas) {\n this._charAtlas.beginFrame();\n }\n\n this.clearCells(0, firstRow, terminal.cols, lastRow - firstRow + 1);\n this._drawBackground(terminal, firstRow, lastRow);\n this._drawForeground(terminal, firstRow, lastRow);\n }\n\n public onOptionsChanged(terminal: ITerminal): void {\n this.setTransparency(terminal, terminal.options.allowTransparency);\n }\n\n /**\n * Whether a character is overlapping to the next cell.\n */\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 { ITerminal } from '../Types';\nimport { IColorSet, IRenderDimensions } from './Types';\nimport { BaseRenderLayer } from './BaseRenderLayer';\n\ninterface ISelectionState {\n start: [number, number];\n end: [number, number];\n columnSelectMode: boolean;\n ydisp: number;\n}\n\nexport class SelectionRenderLayer extends BaseRenderLayer {\n private _state: ISelectionState;\n\n constructor(container: HTMLElement, zIndex: number, colors: IColorSet) {\n super(container, 'selection', zIndex, true, colors);\n this._clearState();\n }\n\n private _clearState(): void {\n this._state = {\n start: null,\n end: null,\n columnSelectMode: null,\n ydisp: null\n };\n }\n\n public resize(terminal: ITerminal, dim: IRenderDimensions): void {\n super.resize(terminal, dim);\n // Resizing the canvas discards the contents of the canvas so clear state\n this._clearState();\n }\n\n public reset(terminal: ITerminal): void {\n if (this._state.start && this._state.end) {\n this._clearState();\n this.clearAll();\n }\n }\n\n public onSelectionChanged(terminal: ITerminal, start: [number, number], end: [number, number], columnSelectMode: boolean): void {\n // Selection has not changed\n if (!this._didStateChange(start, end, columnSelectMode, terminal.buffer.ydisp)) {\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 this._ctx.fillStyle = this._colors.selection.css;\n\n if (columnSelectMode) {\n const startCol = start[0];\n const width = end[0] - startCol;\n const height = viewportCappedEndRow - viewportCappedStartRow + 1;\n this.fillCells(startCol, viewportCappedStartRow, width, height);\n } else {\n // Draw first row\n const startCol = viewportStartRow === viewportCappedStartRow ? start[0] : 0;\n const startRowEndCol = viewportCappedStartRow === viewportCappedEndRow ? end[0] : terminal.cols;\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\n // Save state for next render\n this._state.start = [start[0], start[1]];\n this._state.end = [end[0], end[1]];\n this._state.columnSelectMode = columnSelectMode;\n this._state.ydisp = terminal.buffer.ydisp;\n }\n\n private _didStateChange(start: [number, number], end: [number, number], columnSelectMode: boolean, ydisp: number): boolean {\n return !this._areCoordinatesEqual(start, this._state.start) ||\n !this._areCoordinatesEqual(end, this._state.end) ||\n columnSelectMode !== this._state.columnSelectMode ||\n ydisp !== this._state.ydisp;\n }\n\n private _areCoordinatesEqual(coord1: [number, number], coord2: [number, number]): boolean {\n if (!coord1 || !coord2) {\n return false;\n }\n\n return coord1[0] === coord2[0] && coord1[1] === coord2[1];\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { TextRenderLayer } from './TextRenderLayer';\nimport { SelectionRenderLayer } from './SelectionRenderLayer';\nimport { CursorRenderLayer } from './CursorRenderLayer';\nimport { ColorManager } from './ColorManager';\nimport { IRenderLayer, IColorSet, IRenderer, IRenderDimensions, ICharacterJoinerRegistry } from './Types';\nimport { ITerminal, CharacterJoinerHandler } from '../Types';\nimport { LinkRenderLayer } from './LinkRenderLayer';\nimport { EventEmitter } from '../EventEmitter';\nimport { RenderDebouncer } from '../ui/RenderDebouncer';\nimport { ScreenDprMonitor } from '../ui/ScreenDprMonitor';\nimport { ITheme } from 'xterm';\nimport { CharacterJoinerRegistry } from '../renderer/CharacterJoinerRegistry';\n\nexport class Renderer extends EventEmitter implements IRenderer {\n private _renderDebouncer: RenderDebouncer;\n\n private _renderLayers: IRenderLayer[];\n private _devicePixelRatio: number;\n private _screenDprMonitor: ScreenDprMonitor;\n private _isPaused: boolean = false;\n private _needsFullRefresh: boolean = false;\n private _characterJoinerRegistry: ICharacterJoinerRegistry;\n\n public colorManager: ColorManager;\n public dimensions: IRenderDimensions;\n\n constructor(private _terminal: ITerminal, theme: ITheme) {\n super();\n const allowTransparency = this._terminal.options.allowTransparency;\n this.colorManager = new ColorManager(document, allowTransparency);\n this._characterJoinerRegistry = new CharacterJoinerRegistry(_terminal);\n if (theme) {\n this.colorManager.setTheme(theme);\n }\n\n this._renderLayers = [\n new TextRenderLayer(this._terminal.screenElement, 0, this.colorManager.colors, this._characterJoinerRegistry, allowTransparency),\n new SelectionRenderLayer(this._terminal.screenElement, 1, this.colorManager.colors),\n new LinkRenderLayer(this._terminal.screenElement, 2, this.colorManager.colors, this._terminal),\n new CursorRenderLayer(this._terminal.screenElement, 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 this._updateDimensions();\n this.onOptionsChanged();\n\n this._renderDebouncer = new RenderDebouncer(this._terminal, this._renderRows.bind(this));\n this._screenDprMonitor = new ScreenDprMonitor();\n this._screenDprMonitor.setListener(() => this.onWindowResize(window.devicePixelRatio));\n this.register(this._screenDprMonitor);\n\n // Detect whether IntersectionObserver is detected and enable renderer pause\n // and resume based on terminal visibility if so\n if ('IntersectionObserver' in window) {\n const observer = new IntersectionObserver(e => this.onIntersectionChange(e[0]), { threshold: 0 });\n observer.observe(this._terminal.element);\n this.register({ dispose: () => observer.disconnect() });\n }\n }\n\n public dispose(): void {\n super.dispose();\n this._renderLayers.forEach(l => l.dispose());\n }\n\n public onIntersectionChange(entry: IntersectionObserverEntry): void {\n this._isPaused = entry.intersectionRatio === 0;\n if (!this._isPaused && this._needsFullRefresh) {\n this._terminal.refresh(0, this._terminal.rows - 1);\n }\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);\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 if (this._isPaused) {\n this._needsFullRefresh = true;\n } else {\n this._terminal.refresh(0, this._terminal.rows - 1);\n }\n\n return this.colorManager.colors;\n }\n\n public onResize(cols: number, rows: number): void {\n // Update character and canvas dimensions\n this._updateDimensions();\n\n // Resize all render layers\n this._renderLayers.forEach(l => l.resize(this._terminal, this.dimensions));\n\n // Force a refresh\n if (this._isPaused) {\n this._needsFullRefresh = true;\n } else {\n this._terminal.refresh(0, this._terminal.rows - 1);\n }\n\n // Resize the screen\n this._terminal.screenElement.style.width = `${this.dimensions.canvasWidth}px`;\n this._terminal.screenElement.style.height = `${this.dimensions.canvasHeight}px`;\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);\n }\n\n public onBlur(): void {\n this._runOperation(l => l.onBlur(this._terminal));\n }\n\n public onFocus(): void {\n this._runOperation(l => l.onFocus(this._terminal));\n }\n\n public onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean = false): void {\n this._runOperation(l => l.onSelectionChanged(this._terminal, start, end, columnSelectMode));\n }\n\n public onCursorMove(): void {\n this._runOperation(l => l.onCursorMove(this._terminal));\n }\n\n public onOptionsChanged(): void {\n this.colorManager.allowTransparency = this._terminal.options.allowTransparency;\n this._runOperation(l => l.onOptionsChanged(this._terminal));\n }\n\n public clear(): void {\n this._runOperation(l => l.reset(this._terminal));\n }\n\n private _runOperation(operation: (layer: IRenderLayer) => void): void {\n if (this._isPaused) {\n this._needsFullRefresh = true;\n } else {\n this._renderLayers.forEach(l => operation(l));\n }\n }\n\n /**\n * Queues a refresh between two rows (inclusive), to be done on next animation\n * frame.\n * @param start The start row.\n * @param end The end row.\n */\n public refreshRows(start: number, end: number): void {\n if (this._isPaused) {\n this._needsFullRefresh = true;\n return;\n }\n this._renderDebouncer.refresh(start, end);\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 _renderRows(start: number, end: number): void {\n this._renderLayers.forEach(l => l.onGridChanged(this._terminal, start, end));\n this._terminal.emit('refresh', { start, end });\n }\n\n /**\n * Recalculates the character and canvas dimensions.\n */\n private _updateDimensions(): void {\n // Perform a new measure if the CharMeasure dimensions are not yet available\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\n public registerCharacterJoiner(handler: CharacterJoinerHandler): number {\n return this._characterJoinerRegistry.registerCharacterJoiner(handler);\n }\n\n public deregisterCharacterJoiner(joinerId: number): boolean {\n return this._characterJoinerRegistry.deregisterCharacterJoiner(joinerId);\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ILinkHoverEvent, ITerminal, ILinkifierAccessor, LinkHoverEventTypes } from '../Types';\nimport { IColorSet, IRenderDimensions } from './Types';\nimport { BaseRenderLayer } from './BaseRenderLayer';\n\nexport class LinkRenderLayer extends BaseRenderLayer {\n private _state: ILinkHoverEvent = 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: ILinkHoverEvent) => this._onLinkHover(e));\n terminal.linkifier.on(LinkHoverEventTypes.LEAVE, (e: ILinkHoverEvent) => this._onLinkLeave(e));\n }\n\n public resize(terminal: ITerminal, dim: IRenderDimensions): void {\n super.resize(terminal, dim);\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.x1, this._state.y1, this._state.cols - this._state.x1, 1);\n const middleRowCount = this._state.y2 - this._state.y1 - 1;\n if (middleRowCount > 0) {\n this.clearCells(0, this._state.y1 + 1, this._state.cols, middleRowCount);\n }\n this.clearCells(0, this._state.y2, this._state.x2, 1);\n this._state = null;\n }\n }\n\n private _onLinkHover(e: ILinkHoverEvent): void {\n this._ctx.fillStyle = this._colors.foreground.css;\n if (e.y1 === e.y2) {\n // Single line link\n this.fillBottomLineAtCells(e.x1, e.y1, e.x2 - e.x1);\n } else {\n // Multi-line link\n this.fillBottomLineAtCells(e.x1, e.y1, e.cols - e.x1);\n for (let y = e.y1 + 1; y < e.y2; y++) {\n this.fillBottomLineAtCells(0, y, e.cols);\n }\n this.fillBottomLineAtCells(0, e.y2, e.x2);\n }\n this._state = e;\n }\n\n private _onLinkLeave(e: ILinkHoverEvent): 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 { CHAR_DATA_WIDTH_INDEX } from '../Buffer';\nimport { IColorSet, IRenderDimensions } from './Types';\nimport { BaseRenderLayer } from './BaseRenderLayer';\nimport { CharData, ITerminal } from '../Types';\n\ninterface ICursorState {\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: ICursorState;\n private _cursorRenderers: {[key: string]: (terminal: ITerminal, x: number, y: number, charData: CharData) => void};\n private _cursorBlinkStateManager: CursorBlinkStateManager;\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): void {\n super.resize(terminal, dim);\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 if (!this._cursorBlinkStateManager || this._cursorBlinkStateManager.isPaused) {\n this._render(terminal, false);\n } else {\n this._cursorBlinkStateManager.restartBlinkAnimation(terminal);\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.css;\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.css;\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.css;\n this.fillCells(x, y, charData[CHAR_DATA_WIDTH_INDEX], 1);\n this._ctx.fillStyle = this._colors.cursorAccent.css;\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.css;\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.css;\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 { IColorManager } from './Types';\nimport { IColor, IColorSet } from '../shared/Types';\nimport { ITheme } from 'xterm';\n\nconst DEFAULT_FOREGROUND = fromHex('#ffffff');\nconst DEFAULT_BACKGROUND = fromHex('#000000');\nconst DEFAULT_CURSOR = fromHex('#ffffff');\nconst DEFAULT_CURSOR_ACCENT = fromHex('#000000');\nconst DEFAULT_SELECTION = {\n css: 'rgba(255, 255, 255, 0.3)',\n rgba: 0xFFFFFF77\n};\n\n// An IIFE to generate DEFAULT_ANSI_COLORS. Do not mutate DEFAULT_ANSI_COLORS, instead make a copy\n// and mutate that.\nexport const DEFAULT_ANSI_COLORS = (() => {\n const colors = [\n // dark:\n fromHex('#2e3436'),\n fromHex('#cc0000'),\n fromHex('#4e9a06'),\n fromHex('#c4a000'),\n fromHex('#3465a4'),\n fromHex('#75507b'),\n fromHex('#06989a'),\n fromHex('#d3d7cf'),\n // bright:\n fromHex('#555753'),\n fromHex('#ef2929'),\n fromHex('#8ae234'),\n fromHex('#fce94f'),\n fromHex('#729fcf'),\n fromHex('#ad7fa8'),\n fromHex('#34e2e2'),\n fromHex('#eeeeec')\n ];\n\n // Fill in the remaining 240 ANSI colors.\n // Generate colors (16-231)\n const v = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff];\n for (let i = 0; i < 216; i++) {\n const r = v[(i / 36) % 6 | 0];\n const g = v[(i / 6) % 6 | 0];\n const b = v[i % 6];\n colors.push({\n css: `#${toPaddedHex(r)}${toPaddedHex(g)}${toPaddedHex(b)}`,\n // Use >>> 0 to force a conversion to an unsigned int\n rgba: ((r << 24) | (g << 16) | (b << 8) | 0xFF) >>> 0\n });\n }\n\n // Generate greys (232-255)\n for (let i = 0; i < 24; i++) {\n const c = 8 + i * 10;\n const ch = toPaddedHex(c);\n colors.push({\n css: `#${ch}${ch}${ch}`,\n rgba: ((c << 24) | (c << 16) | (c << 8) | 0xFF) >>> 0\n });\n }\n\n return colors;\n})();\n\nfunction fromHex(css: string): IColor {\n return {\n css,\n rgba: parseInt(css.slice(1), 16) << 8 | 0xFF\n };\n}\n\nfunction toPaddedHex(c: number): string {\n const 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 private _ctx: CanvasRenderingContext2D;\n private _litmusColor: CanvasGradient;\n\n constructor(document: Document, public allowTransparency: boolean) {\n const canvas = document.createElement('canvas');\n canvas.width = 1;\n canvas.height = 1;\n this._ctx = canvas.getContext('2d');\n this._ctx.globalCompositeOperation = 'copy';\n this._litmusColor = this._ctx.createLinearGradient(0, 0, 1, 1);\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: DEFAULT_ANSI_COLORS.slice()\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 = this._parseColor(theme.foreground, DEFAULT_FOREGROUND);\n this.colors.background = this._parseColor(theme.background, DEFAULT_BACKGROUND);\n this.colors.cursor = this._parseColor(theme.cursor, DEFAULT_CURSOR, true);\n this.colors.cursorAccent = this._parseColor(theme.cursorAccent, DEFAULT_CURSOR_ACCENT, true);\n this.colors.selection = this._parseColor(theme.selection, DEFAULT_SELECTION, true);\n this.colors.ansi[0] = this._parseColor(theme.black, DEFAULT_ANSI_COLORS[0]);\n this.colors.ansi[1] = this._parseColor(theme.red, DEFAULT_ANSI_COLORS[1]);\n this.colors.ansi[2] = this._parseColor(theme.green, DEFAULT_ANSI_COLORS[2]);\n this.colors.ansi[3] = this._parseColor(theme.yellow, DEFAULT_ANSI_COLORS[3]);\n this.colors.ansi[4] = this._parseColor(theme.blue, DEFAULT_ANSI_COLORS[4]);\n this.colors.ansi[5] = this._parseColor(theme.magenta, DEFAULT_ANSI_COLORS[5]);\n this.colors.ansi[6] = this._parseColor(theme.cyan, DEFAULT_ANSI_COLORS[6]);\n this.colors.ansi[7] = this._parseColor(theme.white, DEFAULT_ANSI_COLORS[7]);\n this.colors.ansi[8] = this._parseColor(theme.brightBlack, DEFAULT_ANSI_COLORS[8]);\n this.colors.ansi[9] = this._parseColor(theme.brightRed, DEFAULT_ANSI_COLORS[9]);\n this.colors.ansi[10] = this._parseColor(theme.brightGreen, DEFAULT_ANSI_COLORS[10]);\n this.colors.ansi[11] = this._parseColor(theme.brightYellow, DEFAULT_ANSI_COLORS[11]);\n this.colors.ansi[12] = this._parseColor(theme.brightBlue, DEFAULT_ANSI_COLORS[12]);\n this.colors.ansi[13] = this._parseColor(theme.brightMagenta, DEFAULT_ANSI_COLORS[13]);\n this.colors.ansi[14] = this._parseColor(theme.brightCyan, DEFAULT_ANSI_COLORS[14]);\n this.colors.ansi[15] = this._parseColor(theme.brightWhite, DEFAULT_ANSI_COLORS[15]);\n }\n\n private _parseColor(\n css: string,\n fallback: IColor,\n allowTransparency: boolean = this.allowTransparency\n ): IColor {\n if (!css) {\n return fallback;\n }\n\n // If parsing the value results in failure, then it must be ignored, and the attribute must\n // retain its previous value.\n // -- https://html.spec.whatwg.org/multipage/canvas.html#fill-and-stroke-styles\n this._ctx.fillStyle = this._litmusColor;\n this._ctx.fillStyle = css;\n if (typeof this._ctx.fillStyle !== 'string') {\n console.warn(`Color: ${css} is invalid using fallback ${fallback.css}`);\n return fallback;\n }\n\n this._ctx.fillRect(0, 0, 1, 1);\n const data = this._ctx.getImageData(0, 0, 1, 1).data;\n\n if (!allowTransparency && data[3] !== 0xFF) {\n // Ideally we'd just ignore the alpha channel, but...\n //\n // Browsers may not give back exactly the same RGB values we put in, because most/all\n // convert the color to a pre-multiplied representation. getImageData converts that back to\n // a un-premultipled representation, but the precision loss may make the RGB channels unuable\n // on their own.\n //\n // E.g. In Chrome #12345610 turns into #10305010, and in the extreme case, 0xFFFFFF00 turns\n // into 0x00000000.\n //\n // \"Note: Due to the lossy nature of converting to and from premultiplied alpha color values,\n // pixels that have just been set using putImageData() might be returned to an equivalent\n // getImageData() as different values.\"\n // -- https://html.spec.whatwg.org/multipage/canvas.html#pixel-manipulation\n //\n // So let's just use the fallback color in this case instead.\n console.warn(\n `Color: ${css} is using transparency, but allowTransparency is false. ` +\n `Using fallback ${fallback.css}.`\n );\n return fallback;\n }\n\n return {\n css,\n rgba: (data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]) >>> 0\n };\n }\n}\n","import { CHAR_DATA_ATTR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from '../Buffer';\nimport { ITerminal, LineData } from '../Types';\nimport { ICharacterJoinerRegistry, ICharacterJoiner } from './Types';\n\nexport class CharacterJoinerRegistry implements ICharacterJoinerRegistry {\n\n private _characterJoiners: ICharacterJoiner[] = [];\n private _nextCharacterJoinerId: number = 0;\n\n constructor(private _terminal: ITerminal) {\n }\n\n public registerCharacterJoiner(handler: (text: string) => [number, number][]): number {\n const joiner: ICharacterJoiner = {\n id: this._nextCharacterJoinerId++,\n handler\n };\n\n this._characterJoiners.push(joiner);\n return joiner.id;\n }\n\n public deregisterCharacterJoiner(joinerId: number): boolean {\n for (let i = 0; i < this._characterJoiners.length; i++) {\n if (this._characterJoiners[i].id === joinerId) {\n this._characterJoiners.splice(i, 1);\n return true;\n }\n }\n\n return false;\n }\n\n public getJoinedCharacters(row: number): [number, number][] {\n if (this._characterJoiners.length === 0) {\n return [];\n }\n\n const line = this._terminal.buffer.lines.get(row);\n if (line.length === 0) {\n return [];\n }\n\n const ranges: [number, number][] = [];\n const lineStr = this._terminal.buffer.translateBufferLineToString(row, true);\n\n // Because some cells can be represented by multiple javascript characters,\n // we track the cell and the string indexes separately. This allows us to\n // translate the string ranges we get from the joiners back into cell ranges\n // for use when rendering\n let rangeStartColumn = 0;\n let currentStringIndex = 0;\n let rangeStartStringIndex = 0;\n let rangeAttr = line[0][CHAR_DATA_ATTR_INDEX] >> 9;\n\n for (let x = 0; x < this._terminal.cols; x++) {\n const charData = line[x];\n const chars = charData[CHAR_DATA_CHAR_INDEX];\n const width = charData[CHAR_DATA_WIDTH_INDEX];\n const attr = charData[CHAR_DATA_ATTR_INDEX] >> 9;\n\n if (width === 0) {\n // If this character is of width 0, skip it.\n continue;\n }\n\n // End of range\n if (attr !== rangeAttr) {\n // If we ended up with a sequence of more than one character,\n // look for ranges to join.\n if (x - rangeStartColumn > 1) {\n const joinedRanges = this._getJoinedRanges(\n lineStr,\n rangeStartStringIndex,\n currentStringIndex,\n line,\n rangeStartColumn\n );\n for (let i = 0; i < joinedRanges.length; i++) {\n ranges.push(joinedRanges[i]);\n }\n }\n\n // Reset our markers for a new range.\n rangeStartColumn = x;\n rangeStartStringIndex = currentStringIndex;\n rangeAttr = attr;\n }\n\n currentStringIndex += chars.length;\n }\n\n // Process any trailing ranges.\n if (this._terminal.cols - rangeStartColumn > 1) {\n const joinedRanges = this._getJoinedRanges(\n lineStr,\n rangeStartStringIndex,\n currentStringIndex,\n line,\n rangeStartColumn\n );\n for (let i = 0; i < joinedRanges.length; i++) {\n ranges.push(joinedRanges[i]);\n }\n }\n\n return ranges;\n }\n\n /**\n * Given a segment of a line of text, find all ranges of text that should be\n * joined in a single rendering unit. Ranges are internally converted to\n * column ranges, rather than string ranges.\n * @param line String representation of the full line of text\n * @param startIndex Start position of the range to search in the string (inclusive)\n * @param endIndex End position of the range to search in the string (exclusive)\n */\n private _getJoinedRanges(line: string, startIndex: number, endIndex: number, lineData: LineData, startCol: number): [number, number][] {\n const text = line.substring(startIndex, endIndex);\n // At this point we already know that there is at least one joiner so\n // we can just pull its value and assign it directly rather than\n // merging it into an empty array, which incurs unnecessary writes.\n const joinedRanges: [number, number][] = this._characterJoiners[0].handler(text);\n for (let i = 1; i < this._characterJoiners.length; i++) {\n // We merge any overlapping ranges across the different joiners\n const joinerRanges = this._characterJoiners[i].handler(text);\n for (let j = 0; j < joinerRanges.length; j++) {\n CharacterJoinerRegistry._mergeRanges(joinedRanges, joinerRanges[j]);\n }\n }\n this._stringRangesToCellRanges(joinedRanges, lineData, startCol);\n return joinedRanges;\n }\n\n /**\n * Modifies the provided ranges in-place to adjust for variations between\n * string length and cell width so that the range represents a cell range,\n * rather than the string range the joiner provides.\n * @param ranges String ranges containing start (inclusive) and end (exclusive) index\n * @param line Cell data for the relevant line in the terminal\n * @param startCol Offset within the line to start from\n */\n private _stringRangesToCellRanges(ranges: [number, number][], line: LineData, startCol: number): void {\n let currentRangeIndex = 0;\n let currentRangeStarted = false;\n let currentStringIndex = 0;\n let currentRange = ranges[currentRangeIndex];\n\n // If we got through all of the ranges, stop searching\n if (!currentRange) {\n return;\n }\n\n for (let x = startCol; x < this._terminal.cols; x++) {\n const charData = line[x];\n const width = charData[CHAR_DATA_WIDTH_INDEX];\n const length = charData[CHAR_DATA_CHAR_INDEX].length;\n\n // We skip zero-width characters when creating the string to join the text\n // so we do the same here\n if (width === 0) {\n continue;\n }\n\n // Adjust the start of the range\n if (!currentRangeStarted && currentRange[0] <= currentStringIndex) {\n currentRange[0] = x;\n currentRangeStarted = true;\n }\n\n // Adjust the end of the range\n if (currentRange[1] <= currentStringIndex) {\n currentRange[1] = x;\n\n // We're finished with this range, so we move to the next one\n currentRange = ranges[++currentRangeIndex];\n\n // If there are no more ranges left, stop searching\n if (!currentRange) {\n break;\n }\n\n // Ranges can be on adjacent characters. Because the end index of the\n // ranges are exclusive, this means that the index for the start of a\n // range can be the same as the end index of the previous range. To\n // account for the start of the next range, we check here just in case.\n if (currentRange[0] <= currentStringIndex) {\n currentRange[0] = x;\n currentRangeStarted = true;\n } else {\n currentRangeStarted = false;\n }\n }\n\n // Adjust the string index based on the character length to line up with\n // the column adjustment\n currentStringIndex += length;\n }\n\n // If there is still a range left at the end, it must extend all the way to\n // the end of the line.\n if (currentRange) {\n currentRange[1] = this._terminal.cols;\n }\n }\n\n /**\n * Merges the range defined by the provided start and end into the list of\n * existing ranges. The merge is done in place on the existing range for\n * performance and is also returned.\n * @param ranges Existing range list\n * @param newRange Tuple of two numbers representing the new range to merge in.\n * @returns The ranges input with the new range merged in place\n */\n private static _mergeRanges(ranges: [number, number][], newRange: [number, number]): [number, number][] {\n let inRange = false;\n for (let i = 0; i < ranges.length; i++) {\n const range = ranges[i];\n if (!inRange) {\n if (newRange[1] <= range[0]) {\n // Case 1: New range is before the search range\n ranges.splice(i, 0, newRange);\n return ranges;\n }\n\n if (newRange[1] <= range[1]) {\n // Case 2: New range is either wholly contained within the\n // search range or overlaps with the front of it\n range[0] = Math.min(newRange[0], range[0]);\n return ranges;\n }\n\n if (newRange[0] < range[1]) {\n // Case 3: New range either wholly contains the search range\n // or overlaps with the end of it\n range[0] = Math.min(newRange[0], range[0]);\n inRange = true;\n }\n\n // Case 4: New range starts after the search range\n continue;\n } else {\n if (newRange[1] <= range[0]) {\n // Case 5: New range extends from previous range but doesn't\n // reach the current one\n ranges[i - 1][1] = newRange[1];\n return ranges;\n }\n\n if (newRange[1] <= range[1]) {\n // Case 6: New range extends from prvious range into the\n // current range\n ranges[i - 1][1] = Math.max(newRange[1], range[1]);\n ranges.splice(i, 1);\n inRange = false;\n return ranges;\n }\n\n // Case 7: New range extends from previous range past the\n // end of the current range\n ranges.splice(i, 1);\n i--;\n }\n }\n\n if (inRange) {\n // Case 8: New range extends past the last existing range\n ranges[ranges.length - 1][1] = newRange[1];\n } else {\n // Case 9: New range starts after the last existing range\n ranges.push(newRange);\n }\n\n return ranges;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IRenderLayer, IColorSet, IRenderDimensions } from './Types';\nimport { CharData, ITerminal } from '../Types';\nimport { DIM_OPACITY, INVERTED_DEFAULT_COLOR } from './atlas/Types';\nimport BaseCharAtlas from './atlas/BaseCharAtlas';\nimport { acquireCharAtlas } from './atlas/CharAtlasCache';\nimport { CHAR_DATA_CHAR_INDEX } from '../Buffer';\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 protected _charAtlas: BaseCharAtlas;\n\n constructor(\n private _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.classList.add(`xterm-${id}-layer`);\n this._canvas.style.zIndex = zIndex.toString();\n this._initCanvas();\n this._container.appendChild(this._canvas);\n }\n\n public dispose(): void {\n this._container.removeChild(this._canvas);\n }\n\n private _initCanvas(): void {\n this._ctx = this._canvas.getContext('2d', {alpha: this._alpha});\n // Draw the background if this is an opaque layer\n if (!this._alpha) {\n this.clearAll();\n }\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], columnSelectMode: boolean = false): void {}\n\n public onThemeChanged(terminal: ITerminal, colorSet: IColorSet): void {\n this._refreshCharAtlas(terminal, colorSet);\n }\n\n protected setTransparency(terminal: ITerminal, alpha: boolean): void {\n // Do nothing when alpha doesn't change\n if (alpha === this._alpha) {\n return;\n }\n\n // Create new canvas and replace old one\n const oldCanvas = this._canvas;\n this._alpha = alpha;\n // Cloning preserves properties\n this._canvas = this._canvas.cloneNode();\n this._initCanvas();\n this._container.replaceChild(this._canvas, oldCanvas);\n\n // Regenerate char atlas and force a full redraw\n this._refreshCharAtlas(terminal, this._colors);\n this.onGridChanged(terminal, 0, terminal.rows - 1);\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 = acquireCharAtlas(terminal, colorSet, this._scaledCharWidth, this._scaledCharHeight);\n this._charAtlas.warmUp();\n }\n\n public resize(terminal: ITerminal, dim: IRenderDimensions): 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 this._refreshCharAtlas(terminal, this._colors);\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.css;\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.css;\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 = this._getFont(terminal, false, false);\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 one or more characters at a cell. If possible this will draw using\n * the character atlas to reduce draw time.\n * @param terminal The terminal.\n * @param chars The character or characters.\n * @param code The character code.\n * @param width The width of the characters.\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 drawChars(terminal: ITerminal, chars: string, code: number, width: number, x: number, y: number, fg: number, bg: number, bold: boolean, dim: boolean, italic: boolean): void {\n const drawInBrightColor = terminal.options.drawBoldTextInBrightColors && bold && fg < 8 && fg !== INVERTED_DEFAULT_COLOR;\n\n fg += drawInBrightColor ? 8 : 0;\n const atlasDidDraw = this._charAtlas && this._charAtlas.draw(\n this._ctx,\n {chars, code, bg, fg, bold: bold && terminal.options.enableBold, dim, italic},\n x * this._scaledCellWidth + this._scaledCharLeft,\n y * this._scaledCellHeight + this._scaledCharTop\n );\n\n if (!atlasDidDraw) {\n this._drawUncachedChars(terminal, chars, width, fg, x, y, bold && terminal.options.enableBold, dim, italic);\n }\n }\n\n /**\n * Draws one or more characters at one or more cells. The character(s) will be\n * clipped to ensure that they fit with the cell(s), including the cell to the\n * right if the last character is a wide character.\n * @param terminal The terminal.\n * @param chars 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 _drawUncachedChars(terminal: ITerminal, chars: string, width: number, fg: number, x: number, y: number, bold: boolean, dim: boolean, italic: boolean): void {\n this._ctx.save();\n this._ctx.font = this._getFont(terminal, bold, italic);\n this._ctx.textBaseline = 'top';\n\n if (fg === INVERTED_DEFAULT_COLOR) {\n this._ctx.fillStyle = this._colors.background.css;\n } else if (fg < 256) {\n // 256 color support\n this._ctx.fillStyle = this._colors.ansi[fg].css;\n } else {\n this._ctx.fillStyle = this._colors.foreground.css;\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 chars,\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 * Gets the current font.\n * @param terminal The terminal.\n * @param isBold If we should use the bold fontWeight.\n */\n protected _getFont(terminal: ITerminal, isBold: boolean, isItalic: boolean): string {\n const fontWeight = isBold ? terminal.options.fontWeightBold : terminal.options.fontWeight;\n const fontStyle = isItalic ? 'italic' : '';\n\n return `${fontStyle} ${fontWeight} ${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`;\n }\n}\n\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings } from 'xterm';\nimport { ITerminal } from '../Types';\nimport { Terminal as TerminalCore } from '../Terminal';\nimport * as Strings from '../Strings';\n\nexport class Terminal implements ITerminalApi {\n private _core: ITerminal;\n\n constructor(options?: ITerminalOptions) {\n this._core = new TerminalCore(options);\n }\n\n public get element(): HTMLElement { return this._core.element; }\n public get textarea(): HTMLTextAreaElement { return this._core.textarea; }\n public get rows(): number { return this._core.rows; }\n public get cols(): number { return this._core.cols; }\n public get markers(): IMarker[] { return this._core.markers; }\n public blur(): void {\n this._core.blur();\n }\n public focus(): void {\n this._core.focus();\n }\n public on(type: 'blur' | 'focus' | 'linefeed' | 'selection', listener: () => void): void;\n public on(type: 'data', listener: (...args: any[]) => void): void;\n public on(type: 'key', listener: (key?: string, event?: KeyboardEvent) => void): void;\n public on(type: 'keypress' | 'keydown', listener: (event?: KeyboardEvent) => void): void;\n public on(type: 'refresh', listener: (data?: { start: number; end: number; }) => void): void;\n public on(type: 'resize', listener: (data?: { cols: number; rows: number; }) => void): void;\n public on(type: 'scroll', listener: (ydisp?: number) => void): void;\n public on(type: 'title', listener: (title?: string) => void): void;\n public on(type: string, listener: (...args: any[]) => void): void;\n public on(type: any, listener: any): void {\n this._core.on(type, listener);\n }\n public off(type: string, listener: (...args: any[]) => void): void {\n this._core.off(type, listener);\n }\n public emit(type: string, data?: any): void {\n this._core.emit(type, data);\n }\n public addDisposableListener(type: string, handler: (...args: any[]) => void): IDisposable {\n return this._core.addDisposableListener(type, handler);\n }\n public resize(columns: number, rows: number): void {\n this._core.resize(columns, rows);\n }\n public writeln(data: string): void {\n this._core.writeln(data);\n }\n public open(parent: HTMLElement): void {\n this._core.open(parent);\n }\n public attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void {\n this._core.attachCustomKeyEventHandler(customKeyEventHandler);\n }\n public registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => void, options?: ILinkMatcherOptions): number {\n return this._core.registerLinkMatcher(regex, handler, options);\n }\n public deregisterLinkMatcher(matcherId: number): void {\n this._core.deregisterLinkMatcher(matcherId);\n }\n public registerCharacterJoiner(handler: (text: string) => [number, number][]): number {\n return this._core.registerCharacterJoiner(handler);\n }\n public deregisterCharacterJoiner(joinerId: number): void {\n this._core.deregisterCharacterJoiner(joinerId);\n }\n public addMarker(cursorYOffset: number): IMarker {\n return this._core.addMarker(cursorYOffset);\n }\n public hasSelection(): boolean {\n return this._core.hasSelection();\n }\n public getSelection(): string {\n return this._core.getSelection();\n }\n public clearSelection(): void {\n this._core.clearSelection();\n }\n public selectAll(): void {\n this._core.selectAll();\n }\n public selectLines(start: number, end: number): void {\n this._core.selectLines(start, end);\n }\n public dispose(): void {\n this._core.dispose();\n }\n public destroy(): void {\n this._core.destroy();\n }\n public scrollLines(amount: number): void {\n this._core.scrollLines(amount);\n }\n public scrollPages(pageCount: number): void {\n this._core.scrollPages(pageCount);\n }\n public scrollToTop(): void {\n this._core.scrollToTop();\n }\n public scrollToBottom(): void {\n this._core.scrollToBottom();\n }\n public scrollToLine(line: number): void {\n this._core.scrollToLine(line);\n }\n public clear(): void {\n this._core.clear();\n }\n public write(data: string): void {\n this._core.write(data);\n }\n public getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'fontWeight' | 'fontWeightBold' | 'rendererType' | 'termName'): string;\n public getOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell'): boolean;\n public getOption(key: 'colors'): string[];\n public getOption(key: 'cols' | 'fontSize' | 'letterSpacing' | 'lineHeight' | 'rows' | 'tabStopWidth' | 'scrollback'): number;\n public getOption(key: 'handler'): (data: string) => void;\n public getOption(key: string): any;\n public getOption(key: any): any {\n return this._core.getOption(key);\n }\n public setOption(key: 'bellSound' | 'fontFamily' | 'termName', value: string): void;\n public setOption(key: 'fontWeight' | 'fontWeightBold', value: 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'): void;\n public setOption(key: 'bellStyle', value: 'none' | 'visual' | 'sound' | 'both'): void;\n public setOption(key: 'cursorStyle', value: 'block' | 'underline' | 'bar'): void;\n public setOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell', value: boolean): void;\n public setOption(key: 'colors', value: string[]): void;\n public setOption(key: 'fontSize' | 'letterSpacing' | 'lineHeight' | 'tabStopWidth' | 'scrollback', value: number): void;\n public setOption(key: 'handler', value: (data: string) => void): void;\n public setOption(key: 'theme', value: ITheme): void;\n public setOption(key: 'cols' | 'rows', value: number): void;\n public setOption(key: string, value: any): void;\n public setOption(key: any, value: any): void {\n this._core.setOption(key, value);\n }\n public refresh(start: number, end: number): void {\n this._core.refresh(start, end);\n }\n public reset(): void {\n this._core.reset();\n }\n public static applyAddon(addon: any): void {\n addon.apply(Terminal);\n }\n public static get strings(): ILocalizableStrings {\n return Strings;\n }\n}\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ITerminal, ISelectionManager } from '../Types';\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): string {\n return text.replace(/\\r?\\n/g, '\\r');\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 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 ev The original paste event to be handled\n * @param 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 const dispatchPaste = function(text: string): void {\n text = prepareTextForTerminal(text);\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 // Timeout needs to be long enough for click event to be handled.\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 }, 200);\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 * @param shouldSelectWord If true and there is no selection the current word will be selected\n */\nexport function rightClickHandler(ev: MouseEvent, textarea: HTMLTextAreaElement, selectionManager: ISelectionManager, shouldSelectWord: boolean): void {\n moveTextAreaUnderMouseCursor(ev, textarea);\n\n if (shouldSelectWord && !selectionManager.isClickInSelection(ev)) {\n selectionManager.selectWordAtCursor(ev);\n }\n\n // Get textarea ready to copy from the context menu\n textarea.value = selectionManager.selectionText;\n textarea.select();\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ITerminal, ICircularList, LineData } from '../Types';\nimport { C0 } from '../common/data/EscapeSequences';\n\nconst enum Direction {\n UP = 'A',\n DOWN = 'B',\n RIGHT = 'C',\n LEFT = 'D'\n}\n\nexport class AltClickHandler {\n private _startRow: number;\n private _startCol: number;\n private _endRow: number;\n private _endCol: number;\n private _lines: ICircularList;\n\n constructor(\n private _mouseEvent: MouseEvent,\n private _terminal: ITerminal\n ) {\n this._lines = this._terminal.buffer.lines;\n this._startCol = this._terminal.buffer.x;\n this._startRow = this._terminal.buffer.y;\n\n const coordinates = this._terminal.mouseHelper.getCoords(\n this._mouseEvent,\n this._terminal.element,\n this._terminal.charMeasure,\n this._terminal.options.lineHeight,\n this._terminal.cols,\n this._terminal.rows,\n false\n );\n\n if (coordinates) {\n [this._endCol, this._endRow] = coordinates.map((coordinate: number) => {\n return coordinate - 1;\n });\n }\n }\n\n /**\n * Writes the escape sequences of arrows to the terminal\n */\n public move(): void {\n if (this._mouseEvent.altKey && this._endCol !== undefined && this._endRow !== undefined) {\n this._terminal.handler(this._arrowSequences());\n }\n }\n\n /**\n * Concatenates all the arrow sequences together.\n * Resets the starting row to an unwrapped row, moves to the requested row,\n * then moves to requested col.\n */\n private _arrowSequences(): string {\n // The alt buffer should try to navigate between rows\n if (!this._terminal.buffer.hasScrollback) {\n return this._resetStartingRow() + this._moveToRequestedRow() + this._moveToRequestedCol();\n }\n\n // Only move horizontally for the normal buffer\n return this._moveHorizontallyOnly();\n }\n\n /**\n * If the initial position of the cursor is on a row that is wrapped, move the\n * cursor up to the first row that is not wrapped to have accurate vertical\n * positioning.\n */\n private _resetStartingRow(): string {\n if (this._moveToRequestedRow().length === 0) {\n return '';\n }\n return repeat(this._bufferLine(\n this._startCol, this._startRow, this._startCol,\n this._startRow - this._wrappedRowsForRow(this._startRow), false\n ).length, this._sequence(Direction.LEFT));\n }\n\n /**\n * Using the reset starting and ending row, move to the requested row,\n * ignoring wrapped rows\n */\n private _moveToRequestedRow(): string {\n const startRow = this._startRow - this._wrappedRowsForRow(this._startRow);\n const endRow = this._endRow - this._wrappedRowsForRow(this._endRow);\n\n const rowsToMove = Math.abs(startRow - endRow) - this._wrappedRowsCount();\n\n return repeat(rowsToMove, this._sequence(this._verticalDirection()));\n }\n\n /**\n * Move to the requested col on the ending row\n */\n private _moveToRequestedCol(): string {\n let startRow;\n if (this._moveToRequestedRow().length > 0) {\n startRow = this._endRow - this._wrappedRowsForRow(this._endRow);\n } else {\n startRow = this._startRow;\n }\n\n const endRow = this._endRow;\n const direction = this._horizontalDirection();\n\n return repeat(this._bufferLine(\n this._startCol, startRow, this._endCol, endRow,\n direction === Direction.RIGHT\n ).length, this._sequence(direction));\n }\n\n private _moveHorizontallyOnly(): string {\n const direction = this._horizontalDirection();\n return repeat(Math.abs(this._startCol - this._endCol), this._sequence(direction));\n }\n\n /**\n * Utility functions\n */\n\n /**\n * Calculates the number of wrapped rows between the unwrapped starting and\n * ending rows. These rows need to ignored since the cursor skips over them.\n */\n private _wrappedRowsCount(): number {\n let wrappedRows = 0;\n const startRow = this._startRow - this._wrappedRowsForRow(this._startRow);\n const endRow = this._endRow - this._wrappedRowsForRow(this._endRow);\n\n for (let i = 0; i < Math.abs(startRow - endRow); i++) {\n const direction = this._verticalDirection() === Direction.UP ? -1 : 1;\n\n if ((this._lines.get(startRow + (direction * i))).isWrapped) {\n wrappedRows++;\n }\n }\n\n return wrappedRows;\n }\n\n /**\n * Calculates the number of wrapped rows that make up a given row.\n * @param currentRow The row to determine how many wrapped rows make it up\n */\n private _wrappedRowsForRow(currentRow: number): number {\n let rowCount = 0;\n let lineWraps = (this._lines.get(currentRow)).isWrapped;\n\n while (lineWraps && currentRow >= 0 && currentRow < this._terminal.rows) {\n rowCount++;\n currentRow--;\n lineWraps = (this._lines.get(currentRow)).isWrapped;\n }\n\n return rowCount;\n }\n\n /**\n * Direction determiners\n */\n\n /**\n * Determines if the right or left arrow is needed\n */\n private _horizontalDirection(): Direction {\n let startRow;\n if (this._moveToRequestedRow().length > 0) {\n startRow = this._endRow - this._wrappedRowsForRow(this._endRow);\n } else {\n startRow = this._startRow;\n }\n\n if ((this._startCol < this._endCol &&\n startRow <= this._endRow) || // down/right or same y/right\n (this._startCol >= this._endCol &&\n startRow < this._endRow)) { // down/left or same y/left\n return Direction.RIGHT;\n }\n return Direction.LEFT;\n }\n\n /**\n * Determines if the up or down arrow is needed\n */\n private _verticalDirection(): Direction {\n if (this._startRow > this._endRow) {\n return Direction.UP;\n }\n return Direction.DOWN;\n }\n\n /**\n * Constructs the string of chars in the buffer from a starting row and col\n * to an ending row and col\n * @param startCol The starting column position\n * @param startRow The starting row position\n * @param endCol The ending column position\n * @param endRow The ending row position\n * @param forward Direction to move\n */\n private _bufferLine(\n startCol: number,\n startRow: number,\n endCol: number,\n endRow: number,\n forward: boolean\n ): string {\n let currentCol = startCol;\n let currentRow = startRow;\n let bufferStr = '';\n\n while (currentCol !== endCol || currentRow !== endRow) {\n currentCol += forward ? 1 : -1;\n\n if (forward && currentCol > this._terminal.cols - 1) {\n bufferStr += this._terminal.buffer.translateBufferLineToString(\n currentRow, false, startCol, currentCol\n );\n currentCol = 0;\n startCol = 0;\n currentRow++;\n } else if (!forward && currentCol < 0) {\n bufferStr += this._terminal.buffer.translateBufferLineToString(\n currentRow, false, 0, startCol + 1\n );\n currentCol = this._terminal.cols - 1;\n startCol = currentCol;\n currentRow--;\n }\n }\n\n return bufferStr + this._terminal.buffer.translateBufferLineToString(\n currentRow, false, startCol, currentCol\n );\n }\n\n /**\n * Constructs the escape sequence for clicking an arrow\n * @param direction The direction to move\n */\n private _sequence(direction: Direction): string {\n const mod = this._terminal.applicationCursor ? 'O' : '[';\n return C0.ESC + mod + direction;\n }\n}\n\n/**\n * Returns a string repeated a given number of times\n * Polyfill from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat\n * @param count The number of times to repeat the string\n * @param string The string that is to be repeated\n */\nfunction repeat(count: number, str: string): string {\n count = Math.floor(count);\n let rpt = '';\n for (let i = 0; i < count; i++) {\n rpt += str;\n }\n return rpt;\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 { IKeyboardEvent } from '../../common/Types';\nimport { IKeyboardResult, KeyboardResultType } from '../Types';\nimport { C0 } from '../../common/data/EscapeSequences';\n\n// reg + shift key mappings for digits and special chars\nconst KEYCODE_KEY_MAPPINGS: { [key: number]: [string, string]} = {\n // digits 0-9\n 48: ['0', ')'],\n 49: ['1', '!'],\n 50: ['2', '@'],\n 51: ['3', '#'],\n 52: ['4', '$'],\n 53: ['5', '%'],\n 54: ['6', '^'],\n 55: ['7', '&'],\n 56: ['8', '*'],\n 57: ['9', '('],\n\n // special chars\n 186: [';', ':'],\n 187: ['=', '+'],\n 188: [',', '<'],\n 189: ['-', '_'],\n 190: ['.', '>'],\n 191: ['/', '?'],\n 192: ['`', '~'],\n 219: ['[', '{'],\n 220: ['\\\\', '|'],\n 221: [']', '}'],\n 222: ['\\'', '\"']\n};\n\nexport function evaluateKeyboardEvent(\n ev: IKeyboardEvent,\n applicationCursorMode: boolean,\n isMac: boolean,\n macOptionIsMeta: boolean\n): IKeyboardResult {\n const result: IKeyboardResult = {\n type: KeyboardResultType.SEND_KEY,\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 };\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 (applicationCursorMode) {\n result.key = C0.ESC + 'OA';\n } else {\n result.key = C0.ESC + '[A';\n }\n }\n else if (ev.key === 'UIKeyInputLeftArrow') {\n if (applicationCursorMode) {\n result.key = C0.ESC + 'OD';\n } else {\n result.key = C0.ESC + '[D';\n }\n }\n else if (ev.key === 'UIKeyInputRightArrow') {\n if (applicationCursorMode) {\n result.key = C0.ESC + 'OC';\n } else {\n result.key = C0.ESC + '[C';\n }\n }\n else if (ev.key === 'UIKeyInputDownArrow') {\n if (applicationCursorMode) {\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 } else if (ev.altKey) {\n result.key = C0.ESC + C0.DEL; // \\e ^?\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 = isMac ? C0.ESC + 'b' : C0.ESC + '[1;5D';\n }\n } else if (applicationCursorMode) {\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 = isMac ? C0.ESC + 'f' : C0.ESC + '[1;5C';\n }\n } else if (applicationCursorMode) {\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 (applicationCursorMode) {\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 (applicationCursorMode) {\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 (applicationCursorMode) {\n result.key = C0.ESC + 'OH';\n } else {\n result.key = C0.ESC + '[H';\n }\n break;\n case 35:\n // end\n if (modifiers) {\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'F';\n } else if (applicationCursorMode) {\n result.key = C0.ESC + 'OF';\n } else {\n result.key = C0.ESC + '[F';\n }\n break;\n case 33:\n // page up\n if (ev.shiftKey) {\n result.type = KeyboardResultType.PAGE_UP;\n } else {\n result.key = C0.ESC + '[5~';\n }\n break;\n case 34:\n // page down\n if (ev.shiftKey) {\n result.type = KeyboardResultType.PAGE_DOWN;\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 ((!isMac || macOptionIsMeta) && ev.altKey && !ev.metaKey) {\n // On macOS this is a third level shift when !macOptionIsMeta. Use instead.\n const keyMapping = KEYCODE_KEY_MAPPINGS[ev.keyCode];\n const key = keyMapping && keyMapping[!ev.shiftKey ? 0 : 1];\n if (key) {\n result.key = C0.ESC + key;\n } else if (ev.keyCode >= 65 && ev.keyCode <= 90) {\n const keyCode = ev.ctrlKey ? ev.keyCode - 64 : ev.keyCode + 32;\n result.key = C0.ESC + String.fromCharCode(keyCode);\n }\n } else if (isMac && !ev.altKey && !ev.ctrlKey && ev.metaKey) {\n if (ev.keyCode === 65) { // cmd + a\n result.type = KeyboardResultType.SELECT_ALL;\n }\n }\n break;\n }\n\n return result;\n}\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ICharset } 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]: ICharset } = {};\n\n/**\n * The default character set, US.\n */\nexport const DEFAULT_CHARSET: ICharset = 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) 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/**\n * C1 control codes\n * See = https://en.wikipedia.org/wiki/C0_and_C1_control_codes\n */\nexport namespace C1 {\n /** padding character */\n export const PAD = '\\x80';\n /** High Octet Preset */\n export const HOP = '\\x81';\n /** Break Permitted Here */\n export const BPH = '\\x82';\n /** No Break Here */\n export const NBH = '\\x83';\n /** Index */\n export const IND = '\\x84';\n /** Next Line */\n export const NEL = '\\x85';\n /** Start of Selected Area */\n export const SSA = '\\x86';\n /** End of Selected Area */\n export const ESA = '\\x87';\n /** Horizontal Tabulation Set */\n export const HTS = '\\x88';\n /** Horizontal Tabulation With Justification */\n export const HTJ = '\\x89';\n /** Vertical Tabulation Set */\n export const VTS = '\\x8a';\n /** Partial Line Down */\n export const PLD = '\\x8b';\n /** Partial Line Up */\n export const PLU = '\\x8c';\n /** Reverse Index */\n export const RI = '\\x8d';\n /** Single-Shift 2 */\n export const SS2 = '\\x8e';\n /** Single-Shift 3 */\n export const SS3 = '\\x8f';\n /** Device Control String */\n export const DCS = '\\x90';\n /** Private Use 1 */\n export const PU1 = '\\x91';\n /** Private Use 2 */\n export const PU2 = '\\x92';\n /** Set Transmit State */\n export const STS = '\\x93';\n /** Destructive backspace, intended to eliminate ambiguity about meaning of BS. */\n export const CCH = '\\x94';\n /** Message Waiting */\n export const MW = '\\x95';\n /** Start of Protected Area */\n export const SPA = '\\x96';\n /** End of Protected Area */\n export const EPA = '\\x97';\n /** Start of String */\n export const SOS = '\\x98';\n /** Single Graphic Character Introducer */\n export const SGCI = '\\x99';\n /** Single Character Introducer */\n export const SCI = '\\x9a';\n /** Control Sequence Introducer */\n export const CSI = '\\x9b';\n /** String Terminator */\n export const ST = '\\x9c';\n /** Operating System Command */\n export const OSC = '\\x9d';\n /** Privacy Message */\n export const PM = '\\x9e';\n /** Application Program Command */\n export const APC = '\\x9f';\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IDisposable } from 'xterm';\n\n/**\n * A base class that can be extended to provide convenience methods for managing the lifecycle of an\n * object and its components.\n */\nexport abstract class Disposable implements IDisposable {\n protected _disposables: IDisposable[] = [];\n protected _isDisposed: boolean = false;\n\n constructor() {\n }\n\n /**\n * Disposes the object, triggering the `dispose` method on all registered IDisposables.\n */\n public dispose(): void {\n this._isDisposed = true;\n this._disposables.forEach(d => d.dispose());\n this._disposables.length = 0;\n }\n\n /**\n * Registers a disposable object.\n * @param d The disposable to register.\n */\n public register(d: T): void {\n this._disposables.push(d);\n }\n\n /**\n * Unregisters a disposable object if it has been registered, if not do\n * nothing.\n * @param d The disposable to unregister.\n */\n public unregister(d: T): void {\n const index = this._disposables.indexOf(d);\n if (index !== -1) {\n this._disposables.splice(index, 1);\n }\n }\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 '../Types';\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 const 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 /**\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 { IColorSet } from './renderer/Types';\nimport { ITerminal, IViewport } from './Types';\nimport { CharMeasure } from './ui/CharMeasure';\nimport { Disposable } from './common/Lifecycle';\nimport { addDisposableDomListener } from './ui/Lifecycle';\n\nconst FALLBACK_SCROLL_BAR_WIDTH = 15;\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 extends Disposable implements IViewport {\n public scrollBarWidth: number = 0;\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 // Stores a partial line amount when scrolling, this is used to keep track of how much of a line\n // is scrolled so we can \"scroll\" over partial lines and feel natural on touchpads. This is a\n // quick fix and could have a more robust solution in place that reset the value when needed.\n private _wheelPartialScroll: number = 0;\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 super();\n\n // Measure the width of the scrollbar. If it is 0 we can assume it's an OSX overlay scrollbar.\n // Unfortunately the overlay scrollbar would be hidden underneath the screen element in that case,\n // therefore we account for a standard amount to make it visible\n this.scrollBarWidth = (this._viewportElement.offsetWidth - this._scrollArea.offsetWidth) || FALLBACK_SCROLL_BAR_WIDTH;\n this.register(addDisposableDomListener(this._viewportElement, '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.css;\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 this._lastRecordedViewportHeight = this._viewportElement.offsetHeight;\n const newBufferHeight = Math.round(this._currentRowHeight * this._lastRecordedBufferLength) + (this._lastRecordedViewportHeight - this._terminal.renderer.dimensions.canvasHeight);\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 // Don't attempt to scroll if the element is not visible, otherwise scrollTop will be corrupt\n // which causes the terminal to scroll the buffer to the top\n if (!this._viewportElement.offsetParent) {\n return;\n }\n\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 const amount = this._getPixelsScrolled(ev);\n if (amount === 0) {\n return;\n }\n this._viewportElement.scrollTop += amount;\n // Prevent the page from scrolling when the terminal scrolls\n ev.preventDefault();\n }\n\n private _getPixelsScrolled(ev: WheelEvent): number {\n // Do nothing if it's not a vertical scroll event\n if (ev.deltaY === 0) {\n return 0;\n }\n\n // Fallback to WheelEvent.DOM_DELTA_PIXEL\n let amount = ev.deltaY;\n if (ev.deltaMode === WheelEvent.DOM_DELTA_LINE) {\n amount *= this._currentRowHeight;\n } else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) {\n amount *= this._currentRowHeight * this._terminal.rows;\n }\n return amount;\n }\n\n /**\n * Gets the number of pixels scrolled by the mouse event taking into account what type of delta\n * is being used.\n * @param ev The mouse wheel event.\n */\n public getLinesScrolled(ev: WheelEvent): number {\n // Do nothing if it's not a vertical scroll event\n if (ev.deltaY === 0) {\n return 0;\n }\n\n // Fallback to WheelEvent.DOM_DELTA_LINE\n let amount = ev.deltaY;\n if (ev.deltaMode === WheelEvent.DOM_DELTA_PIXEL) {\n amount /= this._currentRowHeight + 0.0; // Prevent integer division\n this._wheelPartialScroll += amount;\n amount = Math.floor(Math.abs(this._wheelPartialScroll)) * (this._wheelPartialScroll > 0 ? 1 : -1);\n this._wheelPartialScroll %= 1;\n } else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) {\n amount *= this._terminal.rows;\n }\n return amount;\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 const 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) 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 { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminalOptions, ITerminal, IBrowser, ILinkifier, ILinkMatcherOptions, CustomKeyEventHandler, LinkMatcherHandler, CharData, LineData, CharacterJoinerHandler } from './Types';\nimport { IMouseZoneManager } from './ui/Types';\nimport { IRenderer } from './renderer/Types';\nimport { BufferSet } from './BufferSet';\nimport { Buffer, MAX_BUFFER_SIZE, DEFAULT_ATTR, NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR } from './Buffer';\nimport { CompositionHelper } from './CompositionHelper';\nimport { EventEmitter } from './EventEmitter';\nimport { Viewport } from './Viewport';\nimport { rightClickHandler, moveTextAreaUnderMouseCursor, pasteHandler, copyHandler } from './handlers/Clipboard';\nimport { C0 } from './common/data/EscapeSequences';\nimport { InputHandler } from './InputHandler';\nimport { Renderer } from './renderer/Renderer';\nimport { Linkifier } from './Linkifier';\nimport { SelectionManager } from './SelectionManager';\nimport { CharMeasure } from './ui/CharMeasure';\nimport * as Browser from './shared/utils/Browser';\nimport { addDisposableDomListener } from './ui/Lifecycle';\nimport * as Strings from './Strings';\nimport { MouseHelper } from './utils/MouseHelper';\nimport { clone } from './utils/Clone';\nimport { DEFAULT_BELL_SOUND, SoundManager } from './SoundManager';\nimport { DEFAULT_ANSI_COLORS } from './renderer/ColorManager';\nimport { MouseZoneManager } from './ui/MouseZoneManager';\nimport { AccessibilityManager } from './AccessibilityManager';\nimport { ScreenDprMonitor } from './ui/ScreenDprMonitor';\nimport { ITheme, IMarker, IDisposable } from 'xterm';\nimport { removeTerminalFromCache } from './renderer/atlas/CharAtlasCache';\nimport { DomRenderer } from './renderer/dom/DomRenderer';\nimport { IKeyboardEvent } from './common/Types';\nimport { evaluateKeyboardEvent } from './core/input/Keyboard';\nimport { KeyboardResultType, ICharset } from './core/Types';\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\n/**\n * The set of options that only have an effect when set in the Terminal constructor.\n */\nconst CONSTRUCTOR_ONLY_OPTIONS = ['cols', 'rows'];\n\nconst DEFAULT_OPTIONS: ITerminalOptions = {\n cols: 80,\n rows: 24,\n convertEol: false,\n termName: 'xterm',\n cursorBlink: false,\n cursorStyle: 'block',\n bellSound: DEFAULT_BELL_SOUND,\n bellStyle: 'none',\n drawBoldTextInBrightColors: true,\n enableBold: true,\n experimentalCharAtlas: 'static',\n fontFamily: 'courier-new, courier, monospace',\n fontSize: 15,\n fontWeight: 'normal',\n fontWeightBold: 'bold',\n lineHeight: 1.0,\n letterSpacing: 0,\n scrollback: 1000,\n screenKeys: false,\n screenReaderMode: false,\n debug: false,\n macOptionIsMeta: false,\n macOptionClickForcesSelection: false,\n cancelEvents: false,\n disableStdin: false,\n useFlowControl: false,\n allowTransparency: false,\n tabStopWidth: 8,\n theme: null,\n rightClickSelectsWord: Browser.isMac,\n rendererType: 'canvas'\n};\n\nexport class Terminal extends EventEmitter implements ITerminal, IDisposable, IInputHandlingTerminal {\n public textarea: HTMLTextAreaElement;\n public element: HTMLElement;\n public screenElement: 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 _viewportScrollArea: HTMLElement;\n private _viewportElement: HTMLElement;\n private _helperContainer: HTMLElement;\n private _compositionView: HTMLElement;\n\n private _visualBellTimer: number;\n\n public browser: IBrowser = Browser;\n\n public options: ITerminalOptions;\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 _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: ICharset;\n public gcharset: number;\n public glevel: number;\n public charsets: ICharset[];\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 public curAttr: number;\n public savedCurAttr: number;\n\n public params: (string | number)[];\n public currentParam: string | number;\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 // Store if user went browsing history in scrollback\n private _userScrolling: boolean;\n\n private _inputHandler: InputHandler;\n public soundManager: SoundManager;\n public renderer: IRenderer;\n public selectionManager: SelectionManager;\n public linkifier: ILinkifier;\n public buffers: BufferSet;\n public viewport: IViewport;\n private _compositionHelper: ICompositionHelper;\n public charMeasure: CharMeasure;\n private _mouseZoneManager: IMouseZoneManager;\n public mouseHelper: MouseHelper;\n private _accessibilityManager: AccessibilityManager;\n private _screenDprMonitor: ScreenDprMonitor;\n private _theme: ITheme;\n\n public cols: number;\n public rows: number;\n\n /**\n * Creates a new `Terminal` object.\n *\n * @param 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 = clone(options);\n this._setup();\n }\n\n public dispose(): void {\n super.dispose();\n this._customKeyEventHandler = null;\n removeTerminalFromCache(this);\n this.handler = () => {};\n this.write = () => {};\n if (this.element && this.element.parentNode) {\n this.element.parentNode.removeChild(this.element);\n }\n }\n\n /**\n * @deprecated Use dispose instead.\n */\n public destroy(): void {\n this.dispose();\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 });\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;\n this.rows = this.options.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._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.curAttr = DEFAULT_ATTR;\n\n this.params = [];\n this.currentParam = 0;\n\n // user input states\n this.writeBuffer = [];\n this._writeInProgress = false;\n\n this._xoffSentToCatchUp = false;\n // this._writeStopped = false;\n this._userScrolling = false;\n\n this._inputHandler = new InputHandler(this);\n this.register(this._inputHandler);\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 this.soundManager = this.soundManager || new SoundManager(this);\n\n // Create the terminal's buffers and set the current buffer\n this.buffers = new BufferSet(this);\n if (this.selectionManager) {\n this.selectionManager.clearSelection();\n this.selectionManager.initBuffersListeners();\n }\n }\n\n /**\n * Convenience property to active buffer.\n */\n public get buffer(): Buffer {\n return this.buffers.active;\n }\n\n /**\n * back_color_erase feature for xterm.\n */\n public eraseAttr(): number {\n // if (this.is('screen')) return DEFAULT_ATTR;\n return (DEFAULT_ATTR & ~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 if (this.textarea) {\n this.textarea.focus();\n }\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 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 return this.options[key];\n }\n\n /**\n * Sets an option on the terminal.\n * @param key The option key.\n * @param 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 if (CONSTRUCTOR_ONLY_OPTIONS.indexOf(key) !== -1) {\n console.error(`Option \"${key}\" can only be set in the constructor`);\n }\n if (this.options[key] === value) {\n return;\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 'fontWeight':\n if (!value) {\n value = 'normal';\n }\n break;\n case 'fontWeightBold':\n if (!value) {\n value = 'bold';\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 'rendererType':\n if (!value) {\n value = 'canvas';\n }\n break;\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.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 if (this.renderer) {\n this.renderer.clear();\n this.charMeasure.measure(this.options);\n }\n break;\n case 'drawBoldTextInBrightColors':\n case 'experimentalCharAtlas':\n case 'enableBold':\n case 'letterSpacing':\n case 'lineHeight':\n case 'fontWeight':\n case 'fontWeightBold':\n // When the font changes the size of the cells may change which requires a renderer clear\n if (this.renderer) {\n this.renderer.clear();\n this.renderer.onResize(this.cols, this.rows);\n this.refresh(0, this.rows - 1);\n }\n case 'rendererType':\n if (this.renderer) {\n this.unregister(this.renderer);\n this.renderer.dispose();\n this.renderer = null;\n }\n this._setupRenderer();\n this.renderer.onCharSizeChanged();\n if (this._theme) {\n this.renderer.setTheme(this._theme);\n }\n break;\n case 'scrollback':\n this.buffers.resize(this.cols, this.rows);\n if (this.viewport) {\n this.viewport.syncScrollArea();\n }\n break;\n case 'screenReaderMode':\n if (value) {\n if (!this._accessibilityManager) {\n this._accessibilityManager = new AccessibilityManager(this);\n }\n } else {\n if (this._accessibilityManager) {\n this._accessibilityManager.dispose();\n this._accessibilityManager = null;\n }\n }\n break;\n case 'tabStopWidth': this.buffers.setupTabStops(); 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.handler(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 // Text can safely be removed on blur. Doing it earlier could interfere with\n // screen readers reading it out.\n this.textarea.value = '';\n this.refresh(this.buffer.y, this.buffer.y);\n if (this.sendFocus) {\n this.handler(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 this.register(addDisposableDomListener(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: ClipboardEvent) => pasteHandler(event, this);\n this.register(addDisposableDomListener(this.textarea, 'paste', pasteHandlerWrapper));\n this.register(addDisposableDomListener(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 this.register(addDisposableDomListener(this.element, 'mousedown', (event: MouseEvent) => {\n if (event.button === 2) {\n rightClickHandler(event, this.textarea, this.selectionManager, this.options.rightClickSelectsWord);\n }\n }));\n } else {\n this.register(addDisposableDomListener(this.element, 'contextmenu', (event: MouseEvent) => {\n rightClickHandler(event, this.textarea, this.selectionManager, this.options.rightClickSelectsWord);\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 this.register(addDisposableDomListener(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 this.register(addDisposableDomListener(this.element, 'keydown', function (ev: KeyboardEvent): void {\n if (document.activeElement !== this) {\n return;\n }\n self._keyDown(ev);\n }, true));\n\n this.register(addDisposableDomListener(this.element, 'keypress', function (ev: KeyboardEvent): void {\n if (document.activeElement !== this) {\n return;\n }\n self._keyPress(ev);\n }, true));\n\n this.register(addDisposableDomListener(this.element, 'keyup', (ev: KeyboardEvent) => {\n if (!wasModifierKeyOnlyEvent(ev)) {\n this.focus();\n }\n\n self._keyUp(ev);\n }, true));\n\n this.register(addDisposableDomListener(this.textarea, 'keydown', (ev: KeyboardEvent) => this._keyDown(ev), true));\n this.register(addDisposableDomListener(this.textarea, 'keypress', (ev: KeyboardEvent) => this._keyPress(ev), true));\n this.register(addDisposableDomListener(this.textarea, 'compositionstart', () => this._compositionHelper.compositionstart()));\n this.register(addDisposableDomListener(this.textarea, 'compositionupdate', (e: CompositionEvent) => this._compositionHelper.compositionupdate(e)));\n this.register(addDisposableDomListener(this.textarea, 'compositionend', () => this._compositionHelper.compositionend()));\n this.register(this.addDisposableListener('refresh', () => this._compositionHelper.updateCompositionElements()));\n this.register(this.addDisposableListener('refresh', (data) => this._queueLinkification(data.start, data.end)));\n }\n\n /**\n * Opens the terminal within an element.\n *\n * @param parent The element to create the terminal within.\n */\n public open(parent: HTMLElement): void {\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\n this._screenDprMonitor = new ScreenDprMonitor();\n this._screenDprMonitor.setListener(() => this.emit('dprchange', window.devicePixelRatio));\n this.register(this._screenDprMonitor);\n\n // Create main element container\n this.element = this._document.createElement('div');\n this.element.dir = 'ltr'; // xterm.css assumes LTR\n this.element.classList.add('terminal');\n this.element.classList.add('xterm');\n this.element.setAttribute('tabindex', '0');\n this._parent.appendChild(this.element);\n\n // Performance: Use a document fragment to build the terminal\n // viewport and helper elements detached from the DOM\n const fragment = document.createDocumentFragment();\n this._viewportElement = document.createElement('div');\n this._viewportElement.classList.add('xterm-viewport');\n fragment.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 this.screenElement = document.createElement('div');\n this.screenElement.classList.add('xterm-screen');\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 this.screenElement.appendChild(this._helperContainer);\n fragment.appendChild(this.screenElement);\n\n this._mouseZoneManager = new MouseZoneManager(this);\n this.register(this._mouseZoneManager);\n this.register(this.addDisposableListener('scroll', () => this._mouseZoneManager.clearAll()));\n this.linkifier.attachToDom(this._mouseZoneManager);\n\n this.textarea = document.createElement('textarea');\n this.textarea.classList.add('xterm-helper-textarea');\n // TODO: New API to set title? This could say \"Terminal bash input\", etc.\n this.textarea.setAttribute('aria-label', Strings.promptLabel);\n this.textarea.setAttribute('aria-multiline', 'false');\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.register(addDisposableDomListener(this.textarea, 'focus', () => this._onTextAreaFocus()));\n this.register(addDisposableDomListener(this.textarea, '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.charMeasure = new CharMeasure(document, this._helperContainer);\n\n // Performance: Add viewport and helper elements from the fragment\n this.element.appendChild(fragment);\n\n this._setupRenderer();\n this._theme = 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 this.register(this.viewport);\n\n this.register(this.addDisposableListener('cursormove', () => this.renderer.onCursorMove()));\n this.register(this.addDisposableListener('resize', () => this.renderer.onResize(this.cols, this.rows)));\n this.register(this.addDisposableListener('blur', () => this.renderer.onBlur()));\n this.register(this.addDisposableListener('focus', () => this.renderer.onFocus()));\n this.register(this.addDisposableListener('dprchange', () => this.renderer.onWindowResize(window.devicePixelRatio)));\n // dprchange should handle this case, we need this as well for browsers that don't support the\n // matchMedia query.\n this.register(addDisposableDomListener(window, 'resize', () => this.renderer.onWindowResize(window.devicePixelRatio)));\n this.register(this.charMeasure.addDisposableListener('charsizechanged', () => this.renderer.onCharSizeChanged()));\n this.register(this.renderer.addDisposableListener('resize', (dimensions) => this.viewport.syncScrollArea()));\n\n this.selectionManager = new SelectionManager(this, this.charMeasure);\n this.register(addDisposableDomListener(this.element, 'mousedown', (e: MouseEvent) => this.selectionManager.onMouseDown(e)));\n this.register(this.selectionManager.addDisposableListener('refresh', data => this.renderer.onSelectionChanged(data.start, data.end, data.columnSelectMode)));\n this.register(this.selectionManager.addDisposableListener('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.register(this.addDisposableListener('scroll', () => {\n this.viewport.syncScrollArea();\n this.selectionManager.refresh();\n }));\n this.register(addDisposableDomListener(this._viewportElement, 'scroll', () => this.selectionManager.refresh()));\n\n this.mouseHelper = new MouseHelper(this.renderer);\n\n if (this.options.screenReaderMode) {\n // Note that this must be done *after* the renderer is created in order to\n // ensure the correct order of the dprchange event\n this._accessibilityManager = new AccessibilityManager(this);\n }\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 private _setupRenderer(): void {\n switch (this.options.rendererType) {\n case 'canvas': this.renderer = new Renderer(this, this.options.theme); break;\n case 'dom': this.renderer = new DomRenderer(this, this.options.theme); break;\n default: throw new Error(`Unrecognized rendererType \"${this.options.rendererType}\"`);\n }\n this.register(this.renderer);\n }\n\n /**\n * Sets the theme on the renderer. The renderer must have been initialized.\n * @param theme The theme to set.\n */\n private _setTheme(theme: ITheme): void {\n this._theme = theme;\n const colors = this.renderer.setTheme(theme);\n if (this.viewport) {\n this.viewport.onThemeChanged(colors);\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.screenElement, 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 const pos = self.mouseHelper.getRawByteCoords(ev, self.screenElement, 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.handler(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.handler(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.handler(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.handler(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 const data: number[] = [];\n\n encode(data, button);\n encode(data, pos.x);\n encode(data, pos.y);\n\n self.handler(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 this.register(addDisposableDomListener(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 // TODO: All mouse handling should be pulled into its own file.\n\n // bind events\n let moveHandler: (event: MouseEvent) => void;\n if (this.normalMouse) {\n moveHandler = (event: MouseEvent) => {\n // Do nothing if normal mouse mode is on. This can happen if the mouse is held down when the\n // terminal exits normalMouse mode.\n if (!this.normalMouse) {\n return;\n }\n sendMove(event);\n };\n // TODO: these event listeners should be managed by the disposable, the Terminal reference may\n // be kept aroud if Terminal.dispose is fired when the mouse is down\n this._document.addEventListener('mousemove', moveHandler);\n }\n\n // x10 compatibility mode can't send button releases\n const handler = (ev: MouseEvent) => {\n if (this.normalMouse && !this.x10Mouse) {\n sendButton(ev);\n }\n if (moveHandler) {\n // Even though this should only be attached when this.normalMouse is true, holding the\n // mouse button down when normalMouse changes can happen. Just always try to remove it.\n this._document.removeEventListener('mousemove', moveHandler);\n moveHandler = null;\n }\n this._document.removeEventListener('mouseup', handler);\n return this.cancel(ev);\n };\n this._document.addEventListener('mouseup', handler);\n\n return this.cancel(ev);\n }));\n\n // if (this.normalMouse) {\n // on(this.document, 'mousemove', sendMove);\n // }\n\n this.register(addDisposableDomListener(el, 'wheel', (ev: WheelEvent) => {\n if (!this.mouseEvents) {\n // Convert wheel events into up/down events when the buffer does not have scrollback, this\n // enables scrolling in apps hosted in the alt buffer such as vim or tmux.\n if (!this.buffer.hasScrollback) {\n const amount = this.viewport.getLinesScrolled(ev);\n\n // Do nothing if there's no vertical scroll\n if (amount === 0) {\n return;\n }\n\n // Construct and send sequences\n const sequence = C0.ESC + (this.applicationCursor ? 'O' : '[') + ( ev.deltaY < 0 ? 'A' : 'B');\n let data = '';\n for (let i = 0; i < Math.abs(amount); i++) {\n data += sequence;\n }\n this.handler(data);\n }\n return;\n }\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 this.register(addDisposableDomListener(el, 'wheel', (ev: WheelEvent) => {\n if (this.mouseEvents) return;\n this.viewport.onWheel(ev);\n return this.cancel(ev);\n }));\n\n this.register(addDisposableDomListener(el, 'touchstart', (ev: TouchEvent) => {\n if (this.mouseEvents) return;\n this.viewport.onTouchStart(ev);\n return this.cancel(ev);\n }));\n\n this.register(addDisposableDomListener(el, 'touchmove', (ev: TouchEvent) => {\n if (this.mouseEvents) return;\n this.viewport.onTouchMove(ev);\n return this.cancel(ev);\n }));\n }\n\n /**\n * Tells the renderer to refresh terminal content between two rows (inclusive) at the next\n * opportunity.\n * @param start The row to start from (between 0 and this.rows - 1).\n * @param 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.refreshRows(start, end);\n }\n }\n\n /**\n * Queues linkification for the specified rows.\n * @param start The row to start from (between 0 and this.rows - 1).\n * @param 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 * Change the cursor style for different selection modes\n */\n public updateCursorStyle(ev: KeyboardEvent): void {\n if (this.selectionManager && this.selectionManager.shouldColumnSelect(ev)) {\n this.element.classList.add('xterm-cursor-crosshair');\n } else {\n this.element.classList.remove('xterm-cursor-crosshair');\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 const 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 disp The number of lines to scroll down (negative scroll up).\n * @param 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 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 public scrollToLine(line: number): void {\n const scrollAmount = line - this.buffer.ydisp;\n if (scrollAmount !== 0) {\n this.scrollLines(scrollAmount);\n }\n }\n\n /**\n * Writes text to the terminal.\n * @param data The text to write to the terminal.\n */\n public write(data: string): void {\n // Ensure the terminal isn't disposed\n if (this._isDisposed) {\n return;\n }\n\n // Ignore falsy data values (including the empty string)\n if (!data) {\n return;\n }\n\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.handler(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 protected _innerWrite(): void {\n // Ensure the terminal isn't disposed\n if (this._isDisposed) {\n this.writeBuffer = [];\n }\n\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.handler(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\n this._inputHandler.parse(data);\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 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 * 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 const matcherId = this.linkifier.registerLinkMatcher(regex, handler, options);\n this.refresh(0, this.rows - 1);\n return matcherId;\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.deregisterLinkMatcher(matcherId)) {\n this.refresh(0, this.rows - 1);\n }\n }\n\n public registerCharacterJoiner(handler: CharacterJoinerHandler): number {\n const joinerId = this.renderer.registerCharacterJoiner(handler);\n this.refresh(0, this.rows - 1);\n return joinerId;\n }\n\n public deregisterCharacterJoiner(joinerId: number): void {\n if (this.renderer.deregisterCharacterJoiner(joinerId)) {\n this.refresh(0, this.rows - 1);\n }\n }\n\n public get markers(): IMarker[] {\n return this.buffer.markers;\n }\n\n public addMarker(cursorYOffset: number): IMarker {\n // Disallow markers on the alt buffer\n if (this.buffer !== this.buffers.normal) {\n return;\n }\n\n return this.buffer.addMarker(this.buffer.ybase + this.buffer.y + cursorYOffset);\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 public selectLines(start: number, end: number): void {\n if (this.selectionManager) {\n this.selectionManager.selectLines(start, end);\n }\n }\n\n /**\n * Handle a keydown event\n * Key Resources:\n * - https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent\n * @param ev The keydown event to be handled.\n */\n protected _keyDown(event: KeyboardEvent): boolean {\n if (this._customKeyEventHandler && this._customKeyEventHandler(event) === false) {\n return false;\n }\n\n if (!this._compositionHelper.keydown(event)) {\n if (this.buffer.ybase !== this.buffer.ydisp) {\n this.scrollToBottom();\n }\n return false;\n }\n\n const result = evaluateKeyboardEvent(event, this.applicationCursor, this.browser.isMac, this.options.macOptionIsMeta);\n\n this.updateCursorStyle(event);\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.type === KeyboardResultType.PAGE_DOWN || result.type === KeyboardResultType.PAGE_UP) {\n const scrollCount = this.rows - 1;\n this.scrollLines(result.type === KeyboardResultType.PAGE_UP ? -scrollCount : scrollCount);\n return this.cancel(event, true);\n }\n\n if (result.type === KeyboardResultType.SELECT_ALL) {\n this.selectAll();\n }\n\n if (this._isThirdLevelShift(this.browser, event)) {\n return true;\n }\n\n if (result.cancel) {\n // The event is canceled at the end already, is this necessary?\n this.cancel(event, true);\n }\n\n if (!result.key) {\n return true;\n }\n\n this.emit('keydown', event);\n this.emit('key', result.key, event);\n this.showCursor();\n this.handler(result.key);\n\n return this.cancel(event, true);\n }\n\n private _isThirdLevelShift(browser: IBrowser, ev: IKeyboardEvent): boolean {\n const thirdLevelKey =\n (browser.isMac && !this.options.macOptionIsMeta && 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\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: ICharset): void {\n this.charsets[g] = charset;\n if (this.glevel === g) {\n this.charset = charset;\n }\n }\n\n protected _keyUp(ev: KeyboardEvent): void {\n this.updateCursorStyle(ev);\n }\n\n /**\n * Handle a keypress event.\n * Key Resources:\n * - https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent\n * @param 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) && !this._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 * 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()) {\n this.soundManager.playBellSound();\n }\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 x The number of columns to resize to.\n * @param 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 && (!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 if (this.charMeasure) {\n this.charMeasure.measure(this.options);\n }\n\n this.refresh(0, this.rows - 1);\n this.emit('resize', {cols: x, rows: y});\n }\n\n /**\n * Updates the range of rows to refresh\n * @param 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 x The column from which to start erasing to the end of the line.\n * @param 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(), NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]; // 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 x The column from which to start erasing to the start of the line.\n * @param 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(), NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]; // 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 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 cur First bunch of data for each \"blank\" character.\n * @param isWrapped Whether the new line is wrapped from the previous line.\n * @param 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() : DEFAULT_ATTR;\n\n const ch: CharData = [attr, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]; // 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 default attribute.\n * @param cur\n */\n public ch(cur?: boolean): CharData {\n if (cur) {\n return [this.eraseAttr(), NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE];\n }\n return [DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE];\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 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 title The title to populate in the event.\n */\n public 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 cursorState = this.cursorState;\n this._setup();\n this._customKeyEventHandler = customKeyEventHandler;\n this._inputHandler = inputHandler;\n this.cursorState = cursorState;\n this.refresh(0, this.rows - 1);\n if (this.viewport) {\n this.viewport.syncScrollArea();\n }\n }\n\n\n /**\n * ESC H Tab Set (HTS is 0x88).\n */\n public 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 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 < DEFAULT_ANSI_COLORS.length; i++) {\n c = DEFAULT_ANSI_COLORS[i].rgba;\n r2 = c >>> 24;\n g2 = c >>> 16 & 0xFF;\n b2 = c >>> 8 & 0xFF;\n // assume that alpha is 0xFF\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 private _visualBell(): boolean {\n return false;\n // return this.options.bellStyle === 'visual' ||\n // this.options.bellStyle === 'both';\n }\n\n private _soundBell(): boolean {\n return this.options.bellStyle === 'sound';\n // return this.options.bellStyle === 'sound' ||\n // this.options.bellStyle === 'both';\n }\n}\n\n/**\n * Helpers\n */\n\nfunction wasModifierKeyOnlyEvent(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\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 * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nexport let blankLine = 'Blank line';\nexport let promptLabel = 'Terminal input';\nexport let tooMuchOutput = 'Too much output to announce, navigate to rows manually to read';\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ITerminal, ISoundManager } from './Types';\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 DEFAULT_BELL_SOUND = '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\nexport class SoundManager implements ISoundManager {\n private _audioContext: AudioContext;\n\n constructor(\n private _terminal: ITerminal\n ) {\n }\n\n public playBellSound(): void {\n const audioContextCtor: typeof AudioContext = (window).AudioContext || (window).webkitAudioContext;\n if (!this._audioContext && audioContextCtor) {\n this._audioContext = new audioContextCtor();\n }\n\n if (this._audioContext) {\n const bellAudioSource = this._audioContext.createBufferSource();\n const context = this._audioContext;\n this._audioContext.decodeAudioData(this._base64ToArrayBuffer(this._removeMimeType(this._terminal.options.bellSound)), (buffer) => {\n bellAudioSource.buffer = buffer;\n bellAudioSource.connect(context.destination);\n bellAudioSource.start(0);\n });\n } else {\n console.warn('Sorry, but the Web Audio API is not supported by your browser. Please, consider upgrading to the latest version');\n }\n }\n\n private _base64ToArrayBuffer(base64: string): ArrayBuffer {\n const binaryString = window.atob(base64);\n const len = binaryString.length;\n const bytes = new Uint8Array(len);\n\n for (let i = 0; i < len; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n\n return bytes.buffer;\n }\n\n private _removeMimeType(dataURI: string): string {\n // Split the input to get the mime-type and the data itself\n const splitUri = dataURI.split(',');\n\n // Return only the data\n return splitUri[1];\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ITerminal } from './Types';\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 + length if the end doesn't exist or they're reversed\n if (!this.selectionEnd || this.areSelectionValuesReversed()) {\n const startPlusLength = this.selectionStart[0] + this.selectionStartLength;\n if (startPlusLength > this._terminal.cols) {\n return [startPlusLength % this._terminal.cols, this.selectionStart[1] + Math.floor(startPlusLength / this._terminal.cols)];\n }\n return [startPlusLength, 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 { ITerminal, ISelectionManager, IBuffer, CharData, XtermListener } from './Types';\nimport { MouseHelper } from './utils/MouseHelper';\nimport * as Browser from './shared/utils/Browser';\nimport { CharMeasure } from './ui/CharMeasure';\nimport { EventEmitter } from './EventEmitter';\nimport { SelectionModel } from './SelectionModel';\nimport { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_CODE_INDEX } from './Buffer';\nimport { AltClickHandler } from './handlers/AltClickHandler';\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 * The maximum amount of time that can have elapsed for an alt click to move the\n * cursor.\n */\nconst ALT_CLICK_MOVE_CURSOR_TIME = 500;\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 */\nexport const enum SelectionMode {\n NORMAL,\n WORD,\n LINE,\n COLUMN\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 protected _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 private _trimListener: XtermListener;\n\n private _mouseDownTimeStamp: number;\n\n constructor(\n private _terminal: ITerminal,\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 public dispose(): void {\n super.dispose();\n this._removeMouseDownListeners();\n }\n\n private get _buffer(): IBuffer {\n return this._terminal.buffers.active;\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 this._trimListener = (amount: number) => this._onTrim(amount);\n\n this.initBuffersListeners();\n }\n\n public initBuffersListeners(): void {\n this._terminal.buffer.lines.on('trim', this._trimListener);\n this._terminal.buffers.on('activate', e => this._onBufferActivate(e));\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 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 const result: string[] = [];\n\n if (this._activeSelectionMode === SelectionMode.COLUMN) {\n // Ignore zero width selections\n if (start[0] === end[0]) {\n return '';\n }\n\n for (let i = start[1]; i <= end[1]; i++) {\n const lineText = this._buffer.translateBufferLineToString(i, true, start[0], end[0]);\n result.push(lineText);\n }\n } else {\n // Get first row\n const startRowEndCol = start[1] === end[1] ? end[0] : null;\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\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', {\n start: this._model.finalSelectionStart,\n end: this._model.finalSelectionEnd,\n columnSelectMode: this._activeSelectionMode === SelectionMode.COLUMN\n });\n }\n\n /**\n * Checks if the current click was inside the current selection\n * @param event The mouse event\n */\n public isClickInSelection(event: MouseEvent): boolean {\n const coords = this._getMouseBufferCoords(event);\n const start = this._model.finalSelectionStart;\n const end = this._model.finalSelectionEnd;\n\n if (!start || !end) {\n return false;\n }\n\n return (coords[1] > start[1] && coords[1] < end[1]) ||\n (start[1] === end[1] && coords[1] === start[1] && coords[0] > start[0] && coords[0] < end[0]) ||\n (start[1] < end[1] && coords[1] === end[1] && coords[0] < end[0]);\n }\n\n /**\n * Selects word at the current mouse event coordinates.\n * @param event The mouse event.\n */\n public selectWordAtCursor(event: MouseEvent): void {\n const coords = this._getMouseBufferCoords(event);\n if (coords) {\n this._selectWordAt(coords, false);\n this._model.selectionEnd = null;\n this.refresh(true);\n }\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._terminal.emit('selection');\n }\n\n public selectLines(start: number, end: number): void {\n this._model.clearSelection();\n start = Math.max(start, 0);\n end = Math.min(end, this._terminal.buffer.lines.length - 1);\n this._model.selectionStart = [0, start];\n this._model.selectionEnd = [this._terminal.cols, end];\n this.refresh();\n this._terminal.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.screenElement, 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.screenElement)[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 if (Browser.isMac) {\n return event.altKey && this._terminal.options.macOptionClickForcesSelection;\n }\n\n return 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 this._mouseDownTimeStamp = event.timeStamp;\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 if (this._terminal.element.ownerDocument) {\n this._terminal.element.ownerDocument.removeEventListener('mousemove', this._mouseMoveListener);\n this._terminal.element.ownerDocument.removeEventListener('mouseup', this._mouseUpListener);\n }\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 = this.shouldColumnSelect(event) ? SelectionMode.COLUMN : 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, true);\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 * Returns whether the selection manager should operate in column select mode\n * @param event the mouse or keyboard event\n */\n public shouldColumnSelect(event: KeyboardEvent | MouseEvent): boolean {\n return event.altKey && !(Browser.isMac && this._terminal.options.macOptionClickForcesSelection);\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. This should only happen when\n // NOT in column select mode.\n if (this._activeSelectionMode !== SelectionMode.COLUMN) {\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\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 the cursor was above or below the viewport, make sure it's at the\n // start or end of the viewport respectively. This should only happen when\n // NOT in column select mode.\n if (this._dragScrollAmount > 0) {\n if (this._activeSelectionMode !== SelectionMode.COLUMN) {\n this._model.selectionEnd[0] = this._terminal.cols;\n }\n this._model.selectionEnd[1] = Math.min(this._terminal.buffer.ydisp + this._terminal.rows, this._terminal.buffer.lines.length - 1);\n } else {\n if (this._activeSelectionMode !== SelectionMode.COLUMN) {\n this._model.selectionEnd[0] = 0;\n }\n this._model.selectionEnd[1] = 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 const timeElapsed = event.timeStamp - this._mouseDownTimeStamp;\n\n this._removeMouseDownListeners();\n\n if (this.selectionText.length <= 1 && timeElapsed < ALT_CLICK_MOVE_CURSOR_TIME) {\n (new AltClickHandler(event, this._terminal)).move();\n } else if (this.hasSelection) {\n this._terminal.emit('selection');\n }\n }\n\n private _onBufferActivate(e: {activeBuffer: IBuffer, inactiveBuffer: IBuffer}): void {\n this.clearSelection();\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 e.inactiveBuffer.lines.off('trim', this._trimListener);\n e.activeBuffer.lines.on('trim', this._trimListener);\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], allowWhitespaceOnlySelection: boolean, followWrappedLinesAbove: boolean = true, followWrappedLinesBelow: boolean = true): IWordPosition {\n // Ensure coords are within viewport (eg. not within scroll bar)\n if (coords[0] >= this._terminal.cols) {\n return null;\n }\n\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 let 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 let 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 if (!allowWhitespaceOnlySelection && line.slice(startIndex, endIndex).trim() === '') {\n return null;\n }\n\n // Recurse upwards if the line is wrapped and the word wraps to the above line\n if (followWrappedLinesAbove) {\n if (start === 0 && bufferLine[0][CHAR_DATA_CODE_INDEX] !== 32 /*' '*/) {\n const previousBufferLine = this._buffer.lines.get(coords[1] - 1);\n if (previousBufferLine && (bufferLine).isWrapped && previousBufferLine[this._terminal.cols - 1][CHAR_DATA_CODE_INDEX] !== 32 /*' '*/) {\n const previousLineWordPosition = this._getWordAt([this._terminal.cols - 1, coords[1] - 1], false, true, false);\n if (previousLineWordPosition) {\n const offset = this._terminal.cols - previousLineWordPosition.start;\n start -= offset;\n length += offset;\n }\n }\n }\n }\n\n // Recurse downwards if the line is wrapped and the word wraps to the next line\n if (followWrappedLinesBelow) {\n if (start + length === this._terminal.cols && bufferLine[this._terminal.cols - 1][CHAR_DATA_CODE_INDEX] !== 32 /*' '*/) {\n const nextBufferLine = this._buffer.lines.get(coords[1] + 1);\n if (nextBufferLine && (nextBufferLine).isWrapped && nextBufferLine[0][CHAR_DATA_CODE_INDEX] !== 32 /*' '*/) {\n const nextLineWordPosition = this._getWordAt([0, coords[1] + 1], false, false, true);\n if (nextLineWordPosition) {\n length += nextLineWordPosition.length;\n }\n }\n }\n }\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 * @param allowWhitespaceOnlySelection If whitespace should be selected\n */\n protected _selectWordAt(coords: [number, number], allowWhitespaceOnlySelection: boolean): void {\n const wordPosition = this._getWordAt(coords, allowWhitespaceOnlySelection);\n if (wordPosition) {\n // Adjust negative start value\n while (wordPosition.start < 0) {\n wordPosition.start += this._terminal.cols;\n coords[1]--;\n }\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, true);\n if (wordPosition) {\n let endRow = coords[1];\n\n // Adjust negative start value\n while (wordPosition.start < 0) {\n wordPosition.start += this._terminal.cols;\n endRow--;\n }\n\n // Adjust wrapped length value, this only needs to happen when values are reversed as in that\n // case we're interested in the start of the word, not the end\n if (!this._model.areSelectionValuesReversed()) {\n while (wordPosition.start + wordPosition.length > this._terminal.cols) {\n wordPosition.length -= this._terminal.cols;\n endRow++;\n }\n }\n\n this._model.selectionEnd = [this._model.areSelectionValuesReversed() ? wordPosition.start : wordPosition.start + wordPosition.length, endRow];\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 const wrappedRange = this._buffer.getWrappedRangeForLine(line);\n this._model.selectionStart = [0, wrappedRange.first];\n this._model.selectionEnd = [this._terminal.cols, wrappedRange.last];\n this._model.selectionStartLength = 0;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IMouseZoneManager } from './ui/Types';\nimport { ILinkHoverEvent, ILinkMatcher, LinkMatcherHandler, LinkHoverEventTypes, ILinkMatcherOptions, ILinkifier, ITerminal, LineData } from './Types';\nimport { MouseZone } from './ui/MouseZoneManager';\nimport { EventEmitter } from './EventEmitter';\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 readonly TIME_BEFORE_LINKIFY = 200;\n\n protected _linkMatchers: ILinkMatcher[] = [];\n\n private _mouseZoneManager: IMouseZoneManager;\n private _rowsTimeoutId: number;\n private _nextLinkMatcherId = 0;\n private _rowsToLinkify: {start: number, end: number};\n\n constructor(\n protected _terminal: ITerminal\n ) {\n super();\n this._rowsToLinkify = {\n start: null,\n end: null\n };\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 === null) {\n this._rowsToLinkify.start = start;\n this._rowsToLinkify.end = end;\n } else {\n this._rowsToLinkify.start = Math.min(this._rowsToLinkify.start, start);\n this._rowsToLinkify.end = Math.max(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 * 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 (!handler) {\n throw new Error('handler must be defined');\n }\n const matcher: ILinkMatcher = {\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 willLinkActivate: options.willLinkActivate,\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: ILinkMatcher): 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 for (let i = 0; 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 // Ensure the row exists\n let absoluteRowIndex = this._terminal.buffer.ydisp + rowIndex;\n if (absoluteRowIndex >= this._terminal.buffer.lines.length) {\n return;\n }\n\n if ((this._terminal.buffer.lines.get(absoluteRowIndex)).isWrapped) {\n // Only attempt to linkify rows that start in the viewport\n if (rowIndex !== 0) {\n return;\n }\n // If the first row is wrapped, backtrack to find the origin row and linkify that\n let line: LineData;\n\n do {\n rowIndex--;\n absoluteRowIndex--;\n line = this._terminal.buffer.lines.get(absoluteRowIndex);\n\n if (!line) {\n break;\n }\n\n } while ((line).isWrapped);\n }\n\n // Construct full unwrapped line text\n let text = this._terminal.buffer.translateBufferLineToString(absoluteRowIndex, false);\n let currentIndex = absoluteRowIndex + 1;\n while (currentIndex < this._terminal.buffer.lines.length &&\n (this._terminal.buffer.lines.get(currentIndex)).isWrapped) {\n text += this._terminal.buffer.translateBufferLineToString(currentIndex++, false);\n }\n\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: ILinkMatcher, offset: number = 0): void {\n // Find the first match\n const match = text.match(matcher.regex);\n if (!match || match.length === 0) {\n return;\n }\n const 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: ILinkMatcher): void {\n const x1 = x % this._terminal.cols;\n const y1 = y + Math.floor(x / this._terminal.cols);\n let x2 = (x1 + uri.length) % this._terminal.cols;\n let y2 = y1 + Math.floor((x1 + uri.length) / this._terminal.cols);\n if (x2 === 0) {\n x2 = this._terminal.cols;\n y2--;\n }\n\n this._mouseZoneManager.add(new MouseZone(\n x1 + 1,\n y1 + 1,\n x2 + 1,\n y2 + 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, this._createLinkHoverEvent(x1, y1, x2, y2));\n this._terminal.element.classList.add('xterm-cursor-pointer');\n },\n e => {\n this.emit(LinkHoverEventTypes.TOOLTIP, this._createLinkHoverEvent(x1, y1, x2, y2));\n if (matcher.hoverTooltipCallback) {\n matcher.hoverTooltipCallback(e, uri);\n }\n },\n () => {\n this.emit(LinkHoverEventTypes.LEAVE, this._createLinkHoverEvent(x1, y1, x2, y2));\n this._terminal.element.classList.remove('xterm-cursor-pointer');\n if (matcher.hoverLeaveCallback) {\n matcher.hoverLeaveCallback();\n }\n },\n e => {\n if (matcher.willLinkActivate) {\n return matcher.willLinkActivate(e, uri);\n }\n return true;\n }\n ));\n }\n\n private _createLinkHoverEvent(x1: number, y1: number, x2: number, y2: number): ILinkHoverEvent {\n return { x1, y1, x2, y2, cols: 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 { CharData, IInputHandler, IDcsHandler, IEscapeSequenceParser, IBuffer, IInputHandlingTerminal } from './Types';\nimport { C0, C1 } from './common/data/EscapeSequences';\nimport { CHARSETS, DEFAULT_CHARSET } from './core/data/Charsets';\nimport { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CODE_INDEX, DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE } from './Buffer';\nimport { FLAGS } from './renderer/Types';\nimport { wcwidth } from './CharWidth';\nimport { EscapeSequenceParser } from './EscapeSequenceParser';\nimport { ICharset } from './core/Types';\nimport { Disposable } from './common/Lifecycle';\n\n/**\n * Map collect to glevel. Used in `selectCharset`.\n */\nconst GLEVEL: {[key: string]: number} = {'(': 0, ')': 1, '*': 2, '+': 3, '-': 1, '.': 2};\n\n\n/**\n * DCS subparser implementations\n */\n\n /**\n * DCS + q Pt ST (xterm)\n * Request Terminfo String\n * not supported\n */\nclass RequestTerminfo implements IDcsHandler {\n private _data: string;\n constructor(private _terminal: any) { }\n hook(collect: string, params: number[], flag: number): void {\n this._data = '';\n }\n put(data: string, start: number, end: number): void {\n this._data += data.substring(start, end);\n }\n unhook(): void {\n // invalid: DCS 0 + r Pt ST\n this._terminal.handler(`${C0.ESC}P0+r${this._data}${C0.ESC}\\\\`);\n }\n}\n\n/**\n * DCS $ q Pt ST\n * DECRQSS (https://vt100.net/docs/vt510-rm/DECRQSS.html)\n * Request Status String (DECRQSS), VT420 and up.\n * Response: DECRPSS (https://vt100.net/docs/vt510-rm/DECRPSS.html)\n */\nclass DECRQSS implements IDcsHandler {\n private _data: string;\n\n constructor(private _terminal: any) { }\n\n hook(collect: string, params: number[], flag: number): void {\n // reset data\n this._data = '';\n }\n\n put(data: string, start: number, end: number): void {\n this._data += data.substring(start, end);\n }\n\n unhook(): void {\n switch (this._data) {\n // valid: DCS 1 $ r Pt ST (xterm)\n case '\"q': // DECSCA\n return this._terminal.handler(`${C0.ESC}P1$r0\"q${C0.ESC}\\\\`);\n case '\"p': // DECSCL\n return this._terminal.handler(`${C0.ESC}P1$r61\"p${C0.ESC}\\\\`);\n case 'r': // DECSTBM\n const pt = '' + (this._terminal.buffer.scrollTop + 1) +\n ';' + (this._terminal.buffer.scrollBottom + 1) + 'r';\n return this._terminal.handler(`${C0.ESC}P1$r${pt}${C0.ESC}\\\\`);\n case 'm': // SGR\n // TODO: report real settings instead of 0m\n return this._terminal.handler(`${C0.ESC}P1$r0m${C0.ESC}\\\\`);\n case ' q': // DECSCUSR\n const STYLES: {[key: string]: number} = {'block': 2, 'underline': 4, 'bar': 6};\n let style = STYLES[this._terminal.getOption('cursorStyle')];\n style -= this._terminal.getOption('cursorBlink');\n return this._terminal.handler(`${C0.ESC}P1$r${style} q${C0.ESC}\\\\`);\n default:\n // invalid: DCS 0 $ r Pt ST (xterm)\n this._terminal.error('Unknown DCS $q %s', this._data);\n this._terminal.handler(`${C0.ESC}P0$r${this._data}${C0.ESC}\\\\`);\n }\n }\n}\n\n/**\n * DCS Ps; Ps| Pt ST\n * DECUDK (https://vt100.net/docs/vt510-rm/DECUDK.html)\n * not supported\n */\n\n /**\n * DCS + p Pt ST (xterm)\n * Set Terminfo Data\n * not supported\n */\n\n\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 extends Disposable implements IInputHandler {\n private _surrogateHigh: string;\n\n constructor(\n private _terminal: IInputHandlingTerminal,\n private _parser: IEscapeSequenceParser = new EscapeSequenceParser())\n {\n super();\n\n this.register(this._parser);\n\n this._surrogateHigh = '';\n\n /**\n * custom fallback handlers\n */\n this._parser.setCsiHandlerFallback((collect: string, params: number[], flag: number) => {\n this._terminal.error('Unknown CSI code: ', { collect, params, flag: String.fromCharCode(flag) });\n });\n this._parser.setEscHandlerFallback((collect: string, flag: number) => {\n this._terminal.error('Unknown ESC code: ', { collect, flag: String.fromCharCode(flag) });\n });\n this._parser.setExecuteHandlerFallback((code: number) => {\n this._terminal.error('Unknown EXECUTE code: ', { code });\n });\n this._parser.setOscHandlerFallback((identifier: number, data: string) => {\n this._terminal.error('Unknown OSC code: ', { identifier, data });\n });\n\n /**\n * print handler\n */\n this._parser.setPrintHandler((data, start, end): void => this.print(data, start, end));\n\n /**\n * CSI handler\n */\n this._parser.setCsiHandler('@', (params, collect) => this.insertChars(params));\n this._parser.setCsiHandler('A', (params, collect) => this.cursorUp(params));\n this._parser.setCsiHandler('B', (params, collect) => this.cursorDown(params));\n this._parser.setCsiHandler('C', (params, collect) => this.cursorForward(params));\n this._parser.setCsiHandler('D', (params, collect) => this.cursorBackward(params));\n this._parser.setCsiHandler('E', (params, collect) => this.cursorNextLine(params));\n this._parser.setCsiHandler('F', (params, collect) => this.cursorPrecedingLine(params));\n this._parser.setCsiHandler('G', (params, collect) => this.cursorCharAbsolute(params));\n this._parser.setCsiHandler('H', (params, collect) => this.cursorPosition(params));\n this._parser.setCsiHandler('I', (params, collect) => this.cursorForwardTab(params));\n this._parser.setCsiHandler('J', (params, collect) => this.eraseInDisplay(params));\n this._parser.setCsiHandler('K', (params, collect) => this.eraseInLine(params));\n this._parser.setCsiHandler('L', (params, collect) => this.insertLines(params));\n this._parser.setCsiHandler('M', (params, collect) => this.deleteLines(params));\n this._parser.setCsiHandler('P', (params, collect) => this.deleteChars(params));\n this._parser.setCsiHandler('S', (params, collect) => this.scrollUp(params));\n this._parser.setCsiHandler('T', (params, collect) => this.scrollDown(params, collect));\n this._parser.setCsiHandler('X', (params, collect) => this.eraseChars(params));\n this._parser.setCsiHandler('Z', (params, collect) => this.cursorBackwardTab(params));\n this._parser.setCsiHandler('`', (params, collect) => this.charPosAbsolute(params));\n this._parser.setCsiHandler('a', (params, collect) => this.hPositionRelative(params));\n this._parser.setCsiHandler('b', (params, collect) => this.repeatPrecedingCharacter(params));\n this._parser.setCsiHandler('c', (params, collect) => this.sendDeviceAttributes(params, collect));\n this._parser.setCsiHandler('d', (params, collect) => this.linePosAbsolute(params));\n this._parser.setCsiHandler('e', (params, collect) => this.vPositionRelative(params));\n this._parser.setCsiHandler('f', (params, collect) => this.hVPosition(params));\n this._parser.setCsiHandler('g', (params, collect) => this.tabClear(params));\n this._parser.setCsiHandler('h', (params, collect) => this.setMode(params, collect));\n this._parser.setCsiHandler('l', (params, collect) => this.resetMode(params, collect));\n this._parser.setCsiHandler('m', (params, collect) => this.charAttributes(params));\n this._parser.setCsiHandler('n', (params, collect) => this.deviceStatus(params, collect));\n this._parser.setCsiHandler('p', (params, collect) => this.softReset(params, collect));\n this._parser.setCsiHandler('q', (params, collect) => this.setCursorStyle(params, collect));\n this._parser.setCsiHandler('r', (params, collect) => this.setScrollRegion(params, collect));\n this._parser.setCsiHandler('s', (params, collect) => this.saveCursor(params));\n this._parser.setCsiHandler('u', (params, collect) => this.restoreCursor(params));\n\n /**\n * execute handler\n */\n this._parser.setExecuteHandler(C0.BEL, () => this.bell());\n this._parser.setExecuteHandler(C0.LF, () => this.lineFeed());\n this._parser.setExecuteHandler(C0.VT, () => this.lineFeed());\n this._parser.setExecuteHandler(C0.FF, () => this.lineFeed());\n this._parser.setExecuteHandler(C0.CR, () => this.carriageReturn());\n this._parser.setExecuteHandler(C0.BS, () => this.backspace());\n this._parser.setExecuteHandler(C0.HT, () => this.tab());\n this._parser.setExecuteHandler(C0.SO, () => this.shiftOut());\n this._parser.setExecuteHandler(C0.SI, () => this.shiftIn());\n // FIXME: What do to with missing? Old code just added those to print.\n\n // some C1 control codes - FIXME: should those be enabled by default?\n this._parser.setExecuteHandler(C1.IND, () => this.index());\n this._parser.setExecuteHandler(C1.NEL, () => this.nextLine());\n this._parser.setExecuteHandler(C1.HTS, () => this.tabSet());\n\n /**\n * OSC handler\n */\n // 0 - icon name + title\n this._parser.setOscHandler(0, (data) => this.setTitle(data));\n // 1 - icon name\n // 2 - title\n this._parser.setOscHandler(2, (data) => this.setTitle(data));\n // 3 - set property X in the form \"prop=value\"\n // 4 - Change Color Number\n // 5 - Change Special Color Number\n // 6 - Enable/disable Special Color Number c\n // 7 - current directory? (not in xterm spec, see https://gitlab.com/gnachman/iterm2/issues/3939)\n // 10 - Change VT100 text foreground color to Pt.\n // 11 - Change VT100 text background color to Pt.\n // 12 - Change text cursor color to Pt.\n // 13 - Change mouse foreground color to Pt.\n // 14 - Change mouse background color to Pt.\n // 15 - Change Tektronix foreground color to Pt.\n // 16 - Change Tektronix background color to Pt.\n // 17 - Change highlight background color to Pt.\n // 18 - Change Tektronix cursor color to Pt.\n // 19 - Change highlight foreground color to Pt.\n // 46 - Change Log File to Pt.\n // 50 - Set Font to Pt.\n // 51 - reserved for Emacs shell.\n // 52 - Manipulate Selection Data.\n // 104 ; c - Reset Color Number c.\n // 105 ; c - Reset Special Color Number c.\n // 106 ; c; f - Enable/disable Special Color Number c.\n // 110 - Reset VT100 text foreground color.\n // 111 - Reset VT100 text background color.\n // 112 - Reset text cursor color.\n // 113 - Reset mouse foreground color.\n // 114 - Reset mouse background color.\n // 115 - Reset Tektronix foreground color.\n // 116 - Reset Tektronix background color.\n // 117 - Reset highlight color.\n // 118 - Reset Tektronix cursor color.\n // 119 - Reset highlight foreground color.\n\n /**\n * ESC handlers\n */\n this._parser.setEscHandler('7', () => this.saveCursor([]));\n this._parser.setEscHandler('8', () => this.restoreCursor([]));\n this._parser.setEscHandler('D', () => this.index());\n this._parser.setEscHandler('E', () => this.nextLine());\n this._parser.setEscHandler('H', () => this.tabSet());\n this._parser.setEscHandler('M', () => this.reverseIndex());\n this._parser.setEscHandler('=', () => this.keypadApplicationMode());\n this._parser.setEscHandler('>', () => this.keypadNumericMode());\n this._parser.setEscHandler('c', () => this.reset());\n this._parser.setEscHandler('n', () => this.setgLevel(2));\n this._parser.setEscHandler('o', () => this.setgLevel(3));\n this._parser.setEscHandler('|', () => this.setgLevel(3));\n this._parser.setEscHandler('}', () => this.setgLevel(2));\n this._parser.setEscHandler('~', () => this.setgLevel(1));\n this._parser.setEscHandler('%@', () => this.selectDefaultCharset());\n this._parser.setEscHandler('%G', () => this.selectDefaultCharset());\n for (const flag in CHARSETS) {\n this._parser.setEscHandler('(' + flag, () => this.selectCharset('(' + flag));\n this._parser.setEscHandler(')' + flag, () => this.selectCharset(')' + flag));\n this._parser.setEscHandler('*' + flag, () => this.selectCharset('*' + flag));\n this._parser.setEscHandler('+' + flag, () => this.selectCharset('+' + flag));\n this._parser.setEscHandler('-' + flag, () => this.selectCharset('-' + flag));\n this._parser.setEscHandler('.' + flag, () => this.selectCharset('.' + flag));\n this._parser.setEscHandler('/' + flag, () => this.selectCharset('/' + flag)); // TODO: supported?\n }\n\n /**\n * error handler\n */\n this._parser.setErrorHandler((state) => {\n this._terminal.error('Parsing error: ', state);\n return state;\n });\n\n /**\n * DCS handler\n */\n this._parser.setDcsHandler('$q', new DECRQSS(this._terminal));\n this._parser.setDcsHandler('+q', new RequestTerminfo(this._terminal));\n }\n\n public dispose(): void {\n super.dispose();\n this._terminal = null;\n }\n\n public parse(data: string): void {\n // Ensure the terminal is not disposed\n if (!this._terminal) {\n return;\n }\n\n let buffer = this._terminal.buffer;\n const cursorStartX = buffer.x;\n const cursorStartY = buffer.y;\n\n // TODO: Consolidate debug/logging #1560\n if ((this._terminal).debug) {\n this._terminal.log('data: ' + data);\n }\n\n // apply leftover surrogate high from last write\n if (this._surrogateHigh) {\n data = this._surrogateHigh + data;\n this._surrogateHigh = '';\n }\n\n this._parser.parse(data);\n\n buffer = this._terminal.buffer;\n if (buffer.x !== cursorStartX || buffer.y !== cursorStartY) {\n this._terminal.emit('cursormove');\n }\n }\n\n public print(data: string, start: number, end: number): void {\n let char: string;\n let code: number;\n let low: number;\n let chWidth: number;\n const buffer: IBuffer = this._terminal.buffer;\n const charset: ICharset = this._terminal.charset;\n const screenReaderMode: boolean = this._terminal.options.screenReaderMode;\n const cols: number = this._terminal.cols;\n const wraparoundMode: boolean = this._terminal.wraparoundMode;\n const insertMode: boolean = this._terminal.insertMode;\n const curAttr: number = this._terminal.curAttr;\n let bufferRow = buffer.lines.get(buffer.y + buffer.ybase);\n\n this._terminal.updateRange(buffer.y);\n for (let stringPosition = start; stringPosition < end; ++stringPosition) {\n char = data.charAt(stringPosition);\n code = data.charCodeAt(stringPosition);\n\n // surrogate pair handling\n if (0xD800 <= code && code <= 0xDBFF) {\n // we got a surrogate high\n // get surrogate low (next 2 bytes)\n low = data.charCodeAt(stringPosition + 1);\n if (isNaN(low)) {\n // end of data stream, save surrogate high\n this._surrogateHigh = char;\n continue;\n }\n code = ((code - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;\n char += data.charAt(stringPosition + 1);\n }\n // surrogate low - already handled above\n if (0xDC00 <= code && code <= 0xDFFF) {\n continue;\n }\n\n // calculate print space\n // expensive call, therefore we save width in line buffer\n chWidth = wcwidth(code);\n\n // get charset replacement character\n if (charset) {\n char = charset[char] || char;\n code = char.charCodeAt(0);\n }\n\n if (screenReaderMode) {\n this._terminal.emit('a11y.char', char);\n }\n\n // insert combining char at last cursor position\n // FIXME: needs handling after cursor jumps\n // buffer.x should never be 0 for a combining char\n // since they always follow a cell consuming char\n // therefore we can test for buffer.x to avoid overflow left\n if (!chWidth && buffer.x) {\n if (bufferRow[buffer.x - 1]) {\n if (!bufferRow[buffer.x - 1][CHAR_DATA_WIDTH_INDEX]) {\n // found empty cell after fullwidth, need to go 2 cells back\n // it is save to step 2 cells back here\n // since an empty cell is only set by fullwidth chars\n if (bufferRow[buffer.x - 2]) {\n bufferRow[buffer.x - 2][CHAR_DATA_CHAR_INDEX] += char;\n bufferRow[buffer.x - 2][CHAR_DATA_CODE_INDEX] = code;\n }\n } else {\n bufferRow[buffer.x - 1][CHAR_DATA_CHAR_INDEX] += char;\n bufferRow[buffer.x - 1][CHAR_DATA_CODE_INDEX] = code;\n }\n }\n continue;\n }\n\n // goto next line if ch would overflow\n // TODO: needs a global min terminal width of 2\n if (buffer.x + chWidth - 1 >= cols) {\n // autowrap - DECAWM\n // automatically wraps to the beginning of the next line\n if (wraparoundMode) {\n buffer.x = 0;\n buffer.y++;\n if (buffer.y > buffer.scrollBottom) {\n 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 (buffer.lines.get(buffer.y)).isWrapped = true;\n }\n // row changed, get it again\n bufferRow = buffer.lines.get(buffer.y + buffer.ybase);\n } else {\n if (chWidth === 2) {\n // FIXME: check for xterm behavior\n // What to do here? We got a wide char that does not fit into last cell\n continue;\n }\n // FIXME: Do we have to set buffer.x to cols - 1, if not wrapping?\n }\n }\n\n // insert mode: move characters to right\n // To achieve insert, we remove cells from the right\n // and insert empty ones at cursor position\n if (insertMode) {\n // do this twice for a fullwidth char\n for (let moves = 0; moves < chWidth; ++moves) {\n // remove last cell\n // if it's width is 0, we have to adjust the second last cell as well\n const removed = bufferRow.pop();\n if (removed[CHAR_DATA_WIDTH_INDEX] === 0\n && bufferRow[this._terminal.cols - 2]\n && bufferRow[this._terminal.cols - 2][CHAR_DATA_WIDTH_INDEX] === 2) {\n bufferRow[this._terminal.cols - 2] = [curAttr, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE];\n }\n\n // insert empty cell at cursor\n bufferRow.splice(buffer.x, 0, [curAttr, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]);\n }\n }\n\n // write current char to buffer and advance cursor\n bufferRow[buffer.x++] = [curAttr, char, chWidth, code];\n\n // fullwidth char - also set next cell to placeholder stub and advance cursor\n if (chWidth === 2) {\n bufferRow[buffer.x++] = [curAttr, '', 0, undefined];\n }\n }\n this._terminal.updateRange(buffer.y);\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 // make buffer local for faster access\n const buffer = this._terminal.buffer;\n\n if (this._terminal.convertEol) {\n buffer.x = 0;\n }\n buffer.y++;\n if (buffer.y > buffer.scrollBottom) {\n 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 (buffer.x >= this._terminal.cols) {\n 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 const originalX = this._terminal.buffer.x;\n this._terminal.buffer.x = this._terminal.buffer.nextStop();\n if (this._terminal.options.screenReaderMode) {\n this._terminal.emit('a11y.tab', this._terminal.buffer.x - originalX);\n }\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 // make buffer local for faster access\n const buffer = this._terminal.buffer;\n\n const row = buffer.y + buffer.ybase;\n let j = buffer.x;\n const ch: CharData = [this._terminal.eraseAttr(), NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]; // xterm\n\n while (param-- && j < this._terminal.cols) {\n buffer.lines.get(row).splice(j++, 0, ch);\n 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\n // make buffer local for faster access\n const buffer = this._terminal.buffer;\n\n const row: number = buffer.y + buffer.ybase;\n\n const scrollBottomRowsOffset = this._terminal.rows - 1 - buffer.scrollBottom;\n const scrollBottomAbsolute = this._terminal.rows - 1 + buffer.ybase - scrollBottomRowsOffset + 1;\n while (param--) {\n // test: echo -e '\\e[44m\\e[1L\\e[0m'\n // blankLine(true) - xterm/linux behavior\n buffer.lines.splice(scrollBottomAbsolute - 1, 1);\n buffer.lines.splice(row, 0, this._terminal.blankLine(true));\n }\n\n // this.maxRange();\n this._terminal.updateRange(buffer.y);\n this._terminal.updateRange(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\n // make buffer local for faster access\n const buffer = this._terminal.buffer;\n\n const row: number = buffer.y + buffer.ybase;\n\n let j: number;\n j = this._terminal.rows - 1 - buffer.scrollBottom;\n j = this._terminal.rows - 1 + buffer.ybase - j;\n while (param--) {\n // test: echo -e '\\e[44m\\e[1M\\e[0m'\n // blankLine(true) - xterm/linux behavior\n buffer.lines.splice(row, 1);\n buffer.lines.splice(j, 0, this._terminal.blankLine(true));\n }\n\n // this.maxRange();\n this._terminal.updateRange(buffer.y);\n this._terminal.updateRange(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 // make buffer local for faster access\n const buffer = this._terminal.buffer;\n\n const row = buffer.y + buffer.ybase;\n const ch: CharData = [this._terminal.eraseAttr(), NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]; // xterm\n\n while (param--) {\n buffer.lines.get(row).splice(buffer.x, 1);\n buffer.lines.get(row).push(ch);\n }\n this._terminal.updateRange(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\n // make buffer local for faster access\n const buffer = this._terminal.buffer;\n\n while (param--) {\n buffer.lines.splice(buffer.ybase + buffer.scrollTop, 1);\n buffer.lines.splice(buffer.ybase + buffer.scrollBottom, 0, this._terminal.blankLine());\n }\n // this.maxRange();\n this._terminal.updateRange(buffer.scrollTop);\n this._terminal.updateRange(buffer.scrollBottom);\n }\n\n /**\n * CSI Ps T Scroll down Ps lines (default = 1) (SD).\n */\n public scrollDown(params: number[], collect?: string): void {\n if (params.length < 2 && !collect) {\n let param = params[0] || 1;\n\n // make buffer local for faster access\n const buffer = this._terminal.buffer;\n\n while (param--) {\n buffer.lines.splice(buffer.ybase + buffer.scrollBottom, 1);\n buffer.lines.splice(buffer.ybase + buffer.scrollTop, 0, this._terminal.blankLine());\n }\n // this.maxRange();\n this._terminal.updateRange(buffer.scrollTop);\n this._terminal.updateRange(buffer.scrollBottom);\n }\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 // make buffer local for faster access\n const buffer = this._terminal.buffer;\n\n const row = buffer.y + buffer.ybase;\n let j = buffer.x;\n const ch: CharData = [this._terminal.eraseAttr(), NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]; // xterm\n\n while (param-- && j < this._terminal.cols) {\n 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\n // make buffer local for faster access\n const buffer = this._terminal.buffer;\n\n while (param--) {\n buffer.x = 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\n // make buffer local for faster access\n const buffer = this._terminal.buffer;\n\n const line = buffer.lines.get(buffer.ybase + buffer.y);\n const ch = line[buffer.x - 1] || [DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE];\n\n while (param--) {\n line[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[], collect?: string): void {\n if (params[0] > 0) {\n return;\n }\n\n if (!collect) {\n if (this._terminal.is('xterm') || this._terminal.is('rxvt-unicode') || this._terminal.is('screen')) {\n this._terminal.handler(C0.ESC + '[?1;2c');\n } else if (this._terminal.is('linux')) {\n this._terminal.handler(C0.ESC + '[?6c');\n }\n } else if (collect === '>') {\n // xterm and urxvt\n // seem to spit this\n // out around ~370 times (?).\n if (this._terminal.is('xterm')) {\n this._terminal.handler(C0.ESC + '[>0;276;0c');\n } else if (this._terminal.is('rxvt-unicode')) {\n this._terminal.handler(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.handler(params[0] + 'c');\n } else if (this._terminal.is('screen')) {\n this._terminal.handler(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 const 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[], collect?: string): 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 (!collect) {\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 (collect === '?') {\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[], collect?: string): 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 (!collect) {\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 (collect === '?') {\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.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 = DEFAULT_ATTR;\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 = DEFAULT_ATTR >> 18;\n fg = (DEFAULT_ATTR >> 9) & 0x1ff;\n bg = DEFAULT_ATTR & 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 === 3) {\n // italic text\n flags |= FLAGS.ITALIC;\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 = (DEFAULT_ATTR >> 9) & 0x1ff;\n } else if (p === 49) {\n // reset bg\n bg = DEFAULT_ATTR & 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 = (DEFAULT_ATTR >> 9) & 0x1ff;\n bg = DEFAULT_ATTR & 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[], collect?: string): void {\n if (!collect) {\n switch (params[0]) {\n case 5:\n // status report\n this._terminal.emit('data', `${C0.ESC}[0n`);\n break;\n case 6:\n // cursor position\n const y = this._terminal.buffer.y + 1;\n const x = this._terminal.buffer.x + 1;\n this._terminal.emit('data', `${C0.ESC}[${y};${x}R`);\n break;\n }\n } else if (collect === '?') {\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 const y = this._terminal.buffer.y + 1;\n const x = this._terminal.buffer.x + 1;\n this._terminal.emit('data', `${C0.ESC}[?${y};${x}R`);\n break;\n case 15:\n // no printer\n // this.handler(C0.ESC + '[?11n');\n break;\n case 25:\n // dont support user defined keys\n // this.handler(C0.ESC + '[?21n');\n break;\n case 26:\n // north american keyboard\n // this.handler(C0.ESC + '[?27;1;0;0n');\n break;\n case 53:\n // no dec locator/mouse\n // this.handler(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[], collect?: string): void {\n if (collect === '!') {\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 = DEFAULT_ATTR;\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 /**\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[], collect?: string): void {\n if (collect === ' ') {\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 /**\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[], collect?: string): void {\n if (collect) 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 * ESC 7\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 this._terminal.savedCurAttr = this._terminal.curAttr;\n }\n\n\n /**\n * CSI u\n * ESC 8\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 this._terminal.curAttr = this._terminal.savedCurAttr || DEFAULT_ATTR;\n }\n\n\n /**\n * OSC 0; ST (set icon name + window title)\n * OSC 2; ST (set window title)\n * Proxy to set window title. Icon name is not supported.\n */\n public setTitle(data: string): void {\n this._terminal.handleTitle(data);\n }\n\n /**\n * ESC E\n * C1.NEL\n * DEC mnemonic: NEL (https://vt100.net/docs/vt510-rm/NEL)\n * Moves cursor to first position on next line.\n */\n public nextLine(): void {\n this._terminal.buffer.x = 0;\n this.index();\n }\n\n /**\n * ESC =\n * DEC mnemonic: DECKPAM (https://vt100.net/docs/vt510-rm/DECKPAM.html)\n * Enables the numeric keypad to send application sequences to the host.\n */\n public keypadApplicationMode(): void {\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 }\n\n /**\n * ESC >\n * DEC mnemonic: DECKPNM (https://vt100.net/docs/vt510-rm/DECKPNM.html)\n * Enables the keypad to send numeric characters to the host.\n */\n public keypadNumericMode(): void {\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 }\n\n /**\n * ESC % @\n * ESC % G\n * Select default character set. UTF-8 is not supported (string are unicode anyways)\n * therefore ESC % G does the same.\n */\n public selectDefaultCharset(): void {\n this._terminal.setgLevel(0);\n this._terminal.setgCharset(0, DEFAULT_CHARSET); // US (default)\n }\n\n /**\n * ESC ( C\n * Designate G0 Character Set, VT100, ISO 2022.\n * ESC ) C\n * Designate G1 Character Set (ISO 2022, VT100).\n * ESC * C\n * Designate G2 Character Set (ISO 2022, VT220).\n * ESC + C\n * Designate G3 Character Set (ISO 2022, VT220).\n * ESC - C\n * Designate G1 Character Set (VT300).\n * ESC . C\n * Designate G2 Character Set (VT300).\n * ESC / C\n * Designate G3 Character Set (VT300). C = A -> ISO Latin-1 Supplemental. - Supported?\n */\n public selectCharset(collectAndFlag: string): void {\n if (collectAndFlag.length !== 2) return this.selectDefaultCharset();\n if (collectAndFlag[0] === '/') return; // TODO: Is this supported?\n this._terminal.setgCharset(GLEVEL[collectAndFlag[0]], CHARSETS[collectAndFlag[1]] || DEFAULT_CHARSET);\n }\n\n /**\n * ESC D\n * C1.IND\n * DEC mnemonic: IND (https://vt100.net/docs/vt510-rm/IND.html)\n * Moves the cursor down one line in the same column.\n */\n public index(): void {\n this._terminal.index(); // TODO: save to move from terminal?\n }\n\n /**\n * ESC H\n * C1.HTS\n * DEC mnemonic: HTS (https://vt100.net/docs/vt510-rm/HTS.html)\n * Sets a horizontal tab stop at the column position indicated by\n * the value of the active column when the terminal receives an HTS.\n */\n public tabSet(): void {\n this._terminal.tabSet(); // TODO: save to move from terminal?\n }\n\n /**\n * ESC M\n * C1.RI\n * DEC mnemonic: HTS\n * Moves the cursor up one line in the same column. If the cursor is at the top margin,\n * the page scrolls down.\n */\n public reverseIndex(): void {\n this._terminal.reverseIndex(); // TODO: save to move from terminal?\n }\n\n /**\n * ESC c\n * DEC mnemonic: RIS (https://vt100.net/docs/vt510-rm/RIS.html)\n * Reset to initial state.\n */\n public reset(): void {\n this._parser.reset();\n this._terminal.reset(); // TODO: save to move from terminal?\n }\n\n /**\n * ESC n\n * ESC o\n * ESC |\n * ESC }\n * ESC ~\n * DEC mnemonic: LS (https://vt100.net/docs/vt510-rm/LS.html)\n * When you use a locking shift, the character set remains in GL or GR until\n * you use another locking shift. (partly supported)\n */\n public setgLevel(level: number): void {\n this._terminal.setgLevel(level); // TODO: save to move from terminal?\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { XtermListener } from './Types';\nimport { IEventEmitter, IDisposable } from 'xterm';\nimport { Disposable } from './common/Lifecycle';\n\nexport class EventEmitter extends Disposable implements IEventEmitter, IDisposable {\n private _events: {[type: string]: XtermListener[]};\n\n constructor() {\n super();\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: XtermListener): void {\n this._events[type] = this._events[type] || [];\n this._events[type].push(listener);\n }\n\n /**\n * Adds a disposabe listener to the EventEmitter, returning the disposable.\n * @param type The event type.\n * @param handler The handler for the listener.\n */\n public addDisposableListener(type: string, handler: XtermListener): IDisposable {\n // TODO: Rename addDisposableEventListener to more easily disambiguate from Dom listener\n this.on(type, handler);\n return {\n dispose: () => {\n if (!handler) {\n // Already disposed\n return;\n }\n this.off(type, handler);\n handler = null;\n }\n };\n }\n\n public off(type: string, listener: XtermListener): void {\n if (!this._events[type]) {\n return;\n }\n\n const obj = this._events[type];\n let i = obj.length;\n\n while (i--) {\n if (obj[i] === 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 emit(type: string, ...args: any[]): void {\n if (!this._events[type]) {\n return;\n }\n const 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): XtermListener[] {\n return this._events[type] || [];\n }\n\n public dispose(): void {\n super.dispose();\n this._events = {};\n }\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ParserState, ParserAction, IParsingState, IDcsHandler, IEscapeSequenceParser } from './Types';\nimport { Disposable } from './common/Lifecycle';\n\n/**\n * Returns an array filled with numbers between the low and high parameters (right exclusive).\n * @param low The low number.\n * @param high The high number.\n */\nfunction r(low: number, high: number): number[] {\n let c = high - low;\n const arr = new Array(c);\n while (c--) {\n arr[c] = --high;\n }\n return arr;\n}\n\n/**\n * Transition table for EscapeSequenceParser.\n * NOTE: data in the underlying table is packed like this:\n * currentState << 8 | characterCode --> action << 4 | nextState\n */\nexport class TransitionTable {\n public table: Uint8Array | number[];\n\n constructor(length: number) {\n this.table = (typeof Uint8Array === 'undefined')\n ? new Array(length)\n : new Uint8Array(length);\n }\n\n /**\n * Add a transition to the transition table.\n * @param code input character code\n * @param state current parser state\n * @param action parser action to be done\n * @param next next parser state\n */\n add(code: number, state: number, action: number | null, next: number | null): void {\n this.table[state << 8 | code] = ((action | 0) << 4) | ((next === undefined) ? state : next);\n }\n\n /**\n * Add transitions for multiple input character codes.\n * @param codes input character code array\n * @param state current parser state\n * @param action parser action to be done\n * @param next next parser state\n */\n addMany(codes: number[], state: number, action: number | null, next: number | null): void {\n for (let i = 0; i < codes.length; i++) {\n this.add(codes[i], state, action, next);\n }\n }\n}\n\n\n/**\n * Default definitions for the VT500_TRANSITION_TABLE.\n */\nconst PRINTABLES = r(0x20, 0x7f);\nconst EXECUTABLES = r(0x00, 0x18);\nEXECUTABLES.push(0x19);\nEXECUTABLES.concat(r(0x1c, 0x20));\nconst DEFAULT_TRANSITION = ParserAction.ERROR << 4 | ParserState.GROUND;\n\n/**\n * VT500 compatible transition table.\n * Taken from https://vt100.net/emu/dec_ansi_parser.\n */\nexport const VT500_TRANSITION_TABLE = (function (): TransitionTable {\n const table: TransitionTable = new TransitionTable(4095);\n\n const states: number[] = r(ParserState.GROUND, ParserState.DCS_PASSTHROUGH + 1);\n let state: any;\n\n // table with default transition [any] --> DEFAULT_TRANSITION\n for (state in states) {\n // NOTE: table lookup is capped at 0xa0 in parse to keep the table small\n for (let code = 0; code < 160; ++code) {\n table.add(code, state, ParserAction.ERROR, ParserState.GROUND);\n }\n }\n // printables\n table.addMany(PRINTABLES, ParserState.GROUND, ParserAction.PRINT, ParserState.GROUND);\n // global anywhere rules\n for (state in states) {\n table.addMany([0x18, 0x1a, 0x99, 0x9a], state, ParserAction.EXECUTE, ParserState.GROUND);\n table.addMany(r(0x80, 0x90), state, ParserAction.EXECUTE, ParserState.GROUND);\n table.addMany(r(0x90, 0x98), state, ParserAction.EXECUTE, ParserState.GROUND);\n table.add(0x9c, state, ParserAction.IGNORE, ParserState.GROUND); // ST as terminator\n table.add(0x1b, state, ParserAction.CLEAR, ParserState.ESCAPE); // ESC\n table.add(0x9d, state, ParserAction.OSC_START, ParserState.OSC_STRING); // OSC\n table.addMany([0x98, 0x9e, 0x9f], state, ParserAction.IGNORE, ParserState.SOS_PM_APC_STRING);\n table.add(0x9b, state, ParserAction.CLEAR, ParserState.CSI_ENTRY); // CSI\n table.add(0x90, state, ParserAction.CLEAR, ParserState.DCS_ENTRY); // DCS\n }\n // rules for executables and 7f\n table.addMany(EXECUTABLES, ParserState.GROUND, ParserAction.EXECUTE, ParserState.GROUND);\n table.addMany(EXECUTABLES, ParserState.ESCAPE, ParserAction.EXECUTE, ParserState.ESCAPE);\n table.add(0x7f, ParserState.ESCAPE, ParserAction.IGNORE, ParserState.ESCAPE);\n table.addMany(EXECUTABLES, ParserState.OSC_STRING, ParserAction.IGNORE, ParserState.OSC_STRING);\n table.addMany(EXECUTABLES, ParserState.CSI_ENTRY, ParserAction.EXECUTE, ParserState.CSI_ENTRY);\n table.add(0x7f, ParserState.CSI_ENTRY, ParserAction.IGNORE, ParserState.CSI_ENTRY);\n table.addMany(EXECUTABLES, ParserState.CSI_PARAM, ParserAction.EXECUTE, ParserState.CSI_PARAM);\n table.add(0x7f, ParserState.CSI_PARAM, ParserAction.IGNORE, ParserState.CSI_PARAM);\n table.addMany(EXECUTABLES, ParserState.CSI_IGNORE, ParserAction.EXECUTE, ParserState.CSI_IGNORE);\n table.addMany(EXECUTABLES, ParserState.CSI_INTERMEDIATE, ParserAction.EXECUTE, ParserState.CSI_INTERMEDIATE);\n table.add(0x7f, ParserState.CSI_INTERMEDIATE, ParserAction.IGNORE, ParserState.CSI_INTERMEDIATE);\n table.addMany(EXECUTABLES, ParserState.ESCAPE_INTERMEDIATE, ParserAction.EXECUTE, ParserState.ESCAPE_INTERMEDIATE);\n table.add(0x7f, ParserState.ESCAPE_INTERMEDIATE, ParserAction.IGNORE, ParserState.ESCAPE_INTERMEDIATE);\n // osc\n table.add(0x5d, ParserState.ESCAPE, ParserAction.OSC_START, ParserState.OSC_STRING);\n table.addMany(PRINTABLES, ParserState.OSC_STRING, ParserAction.OSC_PUT, ParserState.OSC_STRING);\n table.add(0x7f, ParserState.OSC_STRING, ParserAction.OSC_PUT, ParserState.OSC_STRING);\n table.addMany([0x9c, 0x1b, 0x18, 0x1a, 0x07], ParserState.OSC_STRING, ParserAction.OSC_END, ParserState.GROUND);\n table.addMany(r(0x1c, 0x20), ParserState.OSC_STRING, ParserAction.IGNORE, ParserState.OSC_STRING);\n // sos/pm/apc does nothing\n table.addMany([0x58, 0x5e, 0x5f], ParserState.ESCAPE, ParserAction.IGNORE, ParserState.SOS_PM_APC_STRING);\n table.addMany(PRINTABLES, ParserState.SOS_PM_APC_STRING, ParserAction.IGNORE, ParserState.SOS_PM_APC_STRING);\n table.addMany(EXECUTABLES, ParserState.SOS_PM_APC_STRING, ParserAction.IGNORE, ParserState.SOS_PM_APC_STRING);\n table.add(0x9c, ParserState.SOS_PM_APC_STRING, ParserAction.IGNORE, ParserState.GROUND);\n // csi entries\n table.add(0x5b, ParserState.ESCAPE, ParserAction.CLEAR, ParserState.CSI_ENTRY);\n table.addMany(r(0x40, 0x7f), ParserState.CSI_ENTRY, ParserAction.CSI_DISPATCH, ParserState.GROUND);\n table.addMany(r(0x30, 0x3a), ParserState.CSI_ENTRY, ParserAction.PARAM, ParserState.CSI_PARAM);\n table.add(0x3b, ParserState.CSI_ENTRY, ParserAction.PARAM, ParserState.CSI_PARAM);\n table.addMany([0x3c, 0x3d, 0x3e, 0x3f], ParserState.CSI_ENTRY, ParserAction.COLLECT, ParserState.CSI_PARAM);\n table.addMany(r(0x30, 0x3a), ParserState.CSI_PARAM, ParserAction.PARAM, ParserState.CSI_PARAM);\n table.add(0x3b, ParserState.CSI_PARAM, ParserAction.PARAM, ParserState.CSI_PARAM);\n table.addMany(r(0x40, 0x7f), ParserState.CSI_PARAM, ParserAction.CSI_DISPATCH, ParserState.GROUND);\n table.addMany([0x3a, 0x3c, 0x3d, 0x3e, 0x3f], ParserState.CSI_PARAM, ParserAction.IGNORE, ParserState.CSI_IGNORE);\n table.addMany(r(0x20, 0x40), ParserState.CSI_IGNORE, ParserAction.IGNORE, ParserState.CSI_IGNORE);\n table.add(0x7f, ParserState.CSI_IGNORE, ParserAction.IGNORE, ParserState.CSI_IGNORE);\n table.addMany(r(0x40, 0x7f), ParserState.CSI_IGNORE, ParserAction.IGNORE, ParserState.GROUND);\n table.add(0x3a, ParserState.CSI_ENTRY, ParserAction.IGNORE, ParserState.CSI_IGNORE);\n table.addMany(r(0x20, 0x30), ParserState.CSI_ENTRY, ParserAction.COLLECT, ParserState.CSI_INTERMEDIATE);\n table.addMany(r(0x20, 0x30), ParserState.CSI_INTERMEDIATE, ParserAction.COLLECT, ParserState.CSI_INTERMEDIATE);\n table.addMany(r(0x30, 0x40), ParserState.CSI_INTERMEDIATE, ParserAction.IGNORE, ParserState.CSI_IGNORE);\n table.addMany(r(0x40, 0x7f), ParserState.CSI_INTERMEDIATE, ParserAction.CSI_DISPATCH, ParserState.GROUND);\n table.addMany(r(0x20, 0x30), ParserState.CSI_PARAM, ParserAction.COLLECT, ParserState.CSI_INTERMEDIATE);\n // esc_intermediate\n table.addMany(r(0x20, 0x30), ParserState.ESCAPE, ParserAction.COLLECT, ParserState.ESCAPE_INTERMEDIATE);\n table.addMany(r(0x20, 0x30), ParserState.ESCAPE_INTERMEDIATE, ParserAction.COLLECT, ParserState.ESCAPE_INTERMEDIATE);\n table.addMany(r(0x30, 0x7f), ParserState.ESCAPE_INTERMEDIATE, ParserAction.ESC_DISPATCH, ParserState.GROUND);\n table.addMany(r(0x30, 0x50), ParserState.ESCAPE, ParserAction.ESC_DISPATCH, ParserState.GROUND);\n table.addMany(r(0x51, 0x58), ParserState.ESCAPE, ParserAction.ESC_DISPATCH, ParserState.GROUND);\n table.addMany([0x59, 0x5a, 0x5c], ParserState.ESCAPE, ParserAction.ESC_DISPATCH, ParserState.GROUND);\n table.addMany(r(0x60, 0x7f), ParserState.ESCAPE, ParserAction.ESC_DISPATCH, ParserState.GROUND);\n // dcs entry\n table.add(0x50, ParserState.ESCAPE, ParserAction.CLEAR, ParserState.DCS_ENTRY);\n table.addMany(EXECUTABLES, ParserState.DCS_ENTRY, ParserAction.IGNORE, ParserState.DCS_ENTRY);\n table.add(0x7f, ParserState.DCS_ENTRY, ParserAction.IGNORE, ParserState.DCS_ENTRY);\n table.addMany(r(0x1c, 0x20), ParserState.DCS_ENTRY, ParserAction.IGNORE, ParserState.DCS_ENTRY);\n table.addMany(r(0x20, 0x30), ParserState.DCS_ENTRY, ParserAction.COLLECT, ParserState.DCS_INTERMEDIATE);\n table.add(0x3a, ParserState.DCS_ENTRY, ParserAction.IGNORE, ParserState.DCS_IGNORE);\n table.addMany(r(0x30, 0x3a), ParserState.DCS_ENTRY, ParserAction.PARAM, ParserState.DCS_PARAM);\n table.add(0x3b, ParserState.DCS_ENTRY, ParserAction.PARAM, ParserState.DCS_PARAM);\n table.addMany([0x3c, 0x3d, 0x3e, 0x3f], ParserState.DCS_ENTRY, ParserAction.COLLECT, ParserState.DCS_PARAM);\n table.addMany(EXECUTABLES, ParserState.DCS_IGNORE, ParserAction.IGNORE, ParserState.DCS_IGNORE);\n table.addMany(r(0x20, 0x80), ParserState.DCS_IGNORE, ParserAction.IGNORE, ParserState.DCS_IGNORE);\n table.addMany(r(0x1c, 0x20), ParserState.DCS_IGNORE, ParserAction.IGNORE, ParserState.DCS_IGNORE);\n table.addMany(EXECUTABLES, ParserState.DCS_PARAM, ParserAction.IGNORE, ParserState.DCS_PARAM);\n table.add(0x7f, ParserState.DCS_PARAM, ParserAction.IGNORE, ParserState.DCS_PARAM);\n table.addMany(r(0x1c, 0x20), ParserState.DCS_PARAM, ParserAction.IGNORE, ParserState.DCS_PARAM);\n table.addMany(r(0x30, 0x3a), ParserState.DCS_PARAM, ParserAction.PARAM, ParserState.DCS_PARAM);\n table.add(0x3b, ParserState.DCS_PARAM, ParserAction.PARAM, ParserState.DCS_PARAM);\n table.addMany([0x3a, 0x3c, 0x3d, 0x3e, 0x3f], ParserState.DCS_PARAM, ParserAction.IGNORE, ParserState.DCS_IGNORE);\n table.addMany(r(0x20, 0x30), ParserState.DCS_PARAM, ParserAction.COLLECT, ParserState.DCS_INTERMEDIATE);\n table.addMany(EXECUTABLES, ParserState.DCS_INTERMEDIATE, ParserAction.IGNORE, ParserState.DCS_INTERMEDIATE);\n table.add(0x7f, ParserState.DCS_INTERMEDIATE, ParserAction.IGNORE, ParserState.DCS_INTERMEDIATE);\n table.addMany(r(0x1c, 0x20), ParserState.DCS_INTERMEDIATE, ParserAction.IGNORE, ParserState.DCS_INTERMEDIATE);\n table.addMany(r(0x20, 0x30), ParserState.DCS_INTERMEDIATE, ParserAction.COLLECT, ParserState.DCS_INTERMEDIATE);\n table.addMany(r(0x30, 0x40), ParserState.DCS_INTERMEDIATE, ParserAction.IGNORE, ParserState.DCS_IGNORE);\n table.addMany(r(0x40, 0x7f), ParserState.DCS_INTERMEDIATE, ParserAction.DCS_HOOK, ParserState.DCS_PASSTHROUGH);\n table.addMany(r(0x40, 0x7f), ParserState.DCS_PARAM, ParserAction.DCS_HOOK, ParserState.DCS_PASSTHROUGH);\n table.addMany(r(0x40, 0x7f), ParserState.DCS_ENTRY, ParserAction.DCS_HOOK, ParserState.DCS_PASSTHROUGH);\n table.addMany(EXECUTABLES, ParserState.DCS_PASSTHROUGH, ParserAction.DCS_PUT, ParserState.DCS_PASSTHROUGH);\n table.addMany(PRINTABLES, ParserState.DCS_PASSTHROUGH, ParserAction.DCS_PUT, ParserState.DCS_PASSTHROUGH);\n table.add(0x7f, ParserState.DCS_PASSTHROUGH, ParserAction.IGNORE, ParserState.DCS_PASSTHROUGH);\n table.addMany([0x1b, 0x9c], ParserState.DCS_PASSTHROUGH, ParserAction.DCS_UNHOOK, ParserState.GROUND);\n return table;\n})();\n\n/**\n * Dummy DCS handler as default fallback.\n */\nclass DcsDummy implements IDcsHandler {\n hook(collect: string, params: number[], flag: number): void { }\n put(data: string, start: number, end: number): void { }\n unhook(): void { }\n}\n\n/**\n * EscapeSequenceParser.\n * This class implements the ANSI/DEC compatible parser described by\n * Paul Williams (https://vt100.net/emu/dec_ansi_parser).\n * To implement custom ANSI compliant escape sequences it is not needed to\n * alter this parser, instead consider registering a custom handler.\n * For non ANSI compliant sequences change the transition table with\n * the optional `transitions` contructor argument and\n * reimplement the `parse` method.\n * NOTE: The parameter element notation is currently not supported.\n * TODO: implement error recovery hook via error handler return values\n */\nexport class EscapeSequenceParser extends Disposable implements IEscapeSequenceParser {\n public initialState: number;\n public currentState: number;\n\n // buffers over several parse calls\n protected _osc: string;\n protected _params: number[];\n protected _collect: string;\n\n // handler lookup containers\n protected _printHandler: (data: string, start: number, end: number) => void;\n protected _executeHandlers: any;\n protected _csiHandlers: any;\n protected _escHandlers: any;\n protected _oscHandlers: any;\n protected _dcsHandlers: any;\n protected _activeDcsHandler: IDcsHandler | null;\n protected _errorHandler: (state: IParsingState) => IParsingState;\n\n // fallback handlers\n protected _printHandlerFb: (data: string, start: number, end: number) => void;\n protected _executeHandlerFb: (code: number) => void;\n protected _csiHandlerFb: (collect: string, params: number[], flag: number) => void;\n protected _escHandlerFb: (collect: string, flag: number) => void;\n protected _oscHandlerFb: (identifier: number, data: string) => void;\n protected _dcsHandlerFb: IDcsHandler;\n protected _errorHandlerFb: (state: IParsingState) => IParsingState;\n\n constructor(readonly TRANSITIONS: TransitionTable = VT500_TRANSITION_TABLE) {\n super();\n\n this.initialState = ParserState.GROUND;\n this.currentState = this.initialState;\n this._osc = '';\n this._params = [0];\n this._collect = '';\n\n // set default fallback handlers and handler lookup containers\n this._printHandlerFb = (data, start, end): void => { };\n this._executeHandlerFb = (code: number): void => { };\n this._csiHandlerFb = (collect: string, params: number[], flag: number): void => { };\n this._escHandlerFb = (collect: string, flag: number): void => { };\n this._oscHandlerFb = (identifier: number, data: string): void => { };\n this._dcsHandlerFb = new DcsDummy();\n this._errorHandlerFb = (state: IParsingState): IParsingState => state;\n this._printHandler = this._printHandlerFb;\n this._executeHandlers = Object.create(null);\n this._csiHandlers = Object.create(null);\n this._escHandlers = Object.create(null);\n this._oscHandlers = Object.create(null);\n this._dcsHandlers = Object.create(null);\n this._activeDcsHandler = null;\n this._errorHandler = this._errorHandlerFb;\n }\n\n public dispose(): void {\n this._printHandlerFb = null;\n this._executeHandlerFb = null;\n this._csiHandlerFb = null;\n this._escHandlerFb = null;\n this._oscHandlerFb = null;\n this._dcsHandlerFb = null;\n this._errorHandlerFb = null;\n this._printHandler = null;\n this._executeHandlers = null;\n this._csiHandlers = null;\n this._escHandlers = null;\n this._oscHandlers = null;\n this._dcsHandlers = null;\n this._activeDcsHandler = null;\n this._errorHandler = null;\n }\n\n setPrintHandler(callback: (data: string, start: number, end: number) => void): void {\n this._printHandler = callback;\n }\n clearPrintHandler(): void {\n this._printHandler = this._printHandlerFb;\n }\n\n setExecuteHandler(flag: string, callback: () => void): void {\n this._executeHandlers[flag.charCodeAt(0)] = callback;\n }\n clearExecuteHandler(flag: string): void {\n if (this._executeHandlers[flag.charCodeAt(0)]) delete this._executeHandlers[flag.charCodeAt(0)];\n }\n setExecuteHandlerFallback(callback: (code: number) => void): void {\n this._executeHandlerFb = callback;\n }\n\n setCsiHandler(flag: string, callback: (params: number[], collect: string) => void): void {\n this._csiHandlers[flag.charCodeAt(0)] = callback;\n }\n clearCsiHandler(flag: string): void {\n if (this._csiHandlers[flag.charCodeAt(0)]) delete this._csiHandlers[flag.charCodeAt(0)];\n }\n setCsiHandlerFallback(callback: (collect: string, params: number[], flag: number) => void): void {\n this._csiHandlerFb = callback;\n }\n\n setEscHandler(collectAndFlag: string, callback: () => void): void {\n this._escHandlers[collectAndFlag] = callback;\n }\n clearEscHandler(collectAndFlag: string): void {\n if (this._escHandlers[collectAndFlag]) delete this._escHandlers[collectAndFlag];\n }\n setEscHandlerFallback(callback: (collect: string, flag: number) => void): void {\n this._escHandlerFb = callback;\n }\n\n setOscHandler(ident: number, callback: (data: string) => void): void {\n this._oscHandlers[ident] = callback;\n }\n clearOscHandler(ident: number): void {\n if (this._oscHandlers[ident]) delete this._oscHandlers[ident];\n }\n setOscHandlerFallback(callback: (identifier: number, data: string) => void): void {\n this._oscHandlerFb = callback;\n }\n\n setDcsHandler(collectAndFlag: string, handler: IDcsHandler): void {\n this._dcsHandlers[collectAndFlag] = handler;\n }\n clearDcsHandler(collectAndFlag: string): void {\n if (this._dcsHandlers[collectAndFlag]) delete this._dcsHandlers[collectAndFlag];\n }\n setDcsHandlerFallback(handler: IDcsHandler): void {\n this._dcsHandlerFb = handler;\n }\n\n setErrorHandler(callback: (state: IParsingState) => IParsingState): void {\n this._errorHandler = callback;\n }\n clearErrorHandler(): void {\n this._errorHandler = this._errorHandlerFb;\n }\n\n reset(): void {\n this.currentState = this.initialState;\n this._osc = '';\n this._params = [0];\n this._collect = '';\n this._activeDcsHandler = null;\n }\n\n parse(data: string): void {\n let code = 0;\n let transition = 0;\n let error = false;\n let currentState = this.currentState;\n let print = -1;\n let dcs = -1;\n let osc = this._osc;\n let collect = this._collect;\n let params = this._params;\n const table: Uint8Array | number[] = this.TRANSITIONS.table;\n let dcsHandler: IDcsHandler | null = this._activeDcsHandler;\n let callback: Function | null = null;\n\n // process input string\n const l = data.length;\n for (let i = 0; i < l; ++i) {\n code = data.charCodeAt(i);\n\n // shortcut for most chars (print action)\n if (currentState === ParserState.GROUND && code > 0x1f && code < 0x80) {\n print = (~print) ? print : i;\n do i++;\n while (i < l && data.charCodeAt(i) > 0x1f && data.charCodeAt(i) < 0x80);\n i--;\n continue;\n }\n\n // shortcut for CSI params\n if (currentState === ParserState.CSI_PARAM && (code > 0x2f && code < 0x39)) {\n params[params.length - 1] = params[params.length - 1] * 10 + code - 48;\n continue;\n }\n\n // normal transition & action lookup\n transition = (code < 0xa0) ? (table[currentState << 8 | code]) : DEFAULT_TRANSITION;\n switch (transition >> 4) {\n case ParserAction.PRINT:\n print = (~print) ? print : i;\n break;\n case ParserAction.EXECUTE:\n if (~print) {\n this._printHandler(data, print, i);\n print = -1;\n }\n callback = this._executeHandlers[code];\n if (callback) callback();\n else this._executeHandlerFb(code);\n break;\n case ParserAction.IGNORE:\n // handle leftover print or dcs chars\n if (~print) {\n this._printHandler(data, print, i);\n print = -1;\n } else if (~dcs) {\n dcsHandler.put(data, dcs, i);\n dcs = -1;\n }\n break;\n case ParserAction.ERROR:\n // chars higher than 0x9f are handled by this action\n // to keep the transition table small\n if (code > 0x9f) {\n switch (currentState) {\n case ParserState.GROUND:\n print = (~print) ? print : i;\n break;\n case ParserState.OSC_STRING:\n osc += String.fromCharCode(code);\n transition |= ParserState.OSC_STRING;\n break;\n case ParserState.CSI_IGNORE:\n transition |= ParserState.CSI_IGNORE;\n break;\n case ParserState.DCS_IGNORE:\n transition |= ParserState.DCS_IGNORE;\n break;\n case ParserState.DCS_PASSTHROUGH:\n dcs = (~dcs) ? dcs : i;\n transition |= ParserState.DCS_PASSTHROUGH;\n break;\n default:\n error = true;\n }\n } else {\n error = true;\n }\n // if we end up here a real error happened\n if (error) {\n const inject: IParsingState = this._errorHandler(\n {\n position: i,\n code,\n currentState,\n print,\n dcs,\n osc,\n collect,\n params,\n abort: false\n });\n if (inject.abort) return;\n // TODO: inject return values\n error = false;\n }\n break;\n case ParserAction.CSI_DISPATCH:\n callback = this._csiHandlers[code];\n if (callback) callback(params, collect);\n else this._csiHandlerFb(collect, params, code);\n break;\n case ParserAction.PARAM:\n if (code === 0x3b) params.push(0);\n else params[params.length - 1] = params[params.length - 1] * 10 + code - 48;\n break;\n case ParserAction.COLLECT:\n collect += String.fromCharCode(code);\n break;\n case ParserAction.ESC_DISPATCH:\n callback = this._escHandlers[collect + String.fromCharCode(code)];\n if (callback) callback(collect, code);\n else this._escHandlerFb(collect, code);\n break;\n case ParserAction.CLEAR:\n if (~print) {\n this._printHandler(data, print, i);\n print = -1;\n }\n osc = '';\n params = [0];\n collect = '';\n dcs = -1;\n break;\n case ParserAction.DCS_HOOK:\n dcsHandler = this._dcsHandlers[collect + String.fromCharCode(code)];\n if (!dcsHandler) dcsHandler = this._dcsHandlerFb;\n dcsHandler.hook(collect, params, code);\n break;\n case ParserAction.DCS_PUT:\n dcs = (~dcs) ? dcs : i;\n break;\n case ParserAction.DCS_UNHOOK:\n if (dcsHandler) {\n if (~dcs) dcsHandler.put(data, dcs, i);\n dcsHandler.unhook();\n dcsHandler = null;\n }\n if (code === 0x1b) transition |= ParserState.ESCAPE;\n osc = '';\n params = [0];\n collect = '';\n dcs = -1;\n break;\n case ParserAction.OSC_START:\n if (~print) {\n this._printHandler(data, print, i);\n print = -1;\n }\n osc = '';\n break;\n case ParserAction.OSC_PUT:\n osc += data.charAt(i);\n break;\n case ParserAction.OSC_END:\n if (osc && code !== 0x18 && code !== 0x1a) {\n // NOTE: OSC subparsing is not part of the original parser\n // we do basic identifier parsing here to offer a jump table for OSC as well\n const idx = osc.indexOf(';');\n if (idx === -1) {\n this._oscHandlerFb(-1, osc); // this is an error (malformed OSC)\n } else {\n // Note: NaN is not handled here\n // either catch it with the fallback handler\n // or with an explicit NaN OSC handler\n const identifier = parseInt(osc.substring(0, idx));\n const content = osc.substring(idx + 1);\n callback = this._oscHandlers[identifier];\n if (callback) callback(content);\n else this._oscHandlerFb(identifier, content);\n }\n }\n if (code === 0x1b) transition |= ParserState.ESCAPE;\n osc = '';\n params = [0];\n collect = '';\n dcs = -1;\n break;\n }\n currentState = transition & 15;\n }\n\n // push leftover pushable buffers to terminal\n if (currentState === ParserState.GROUND && ~print) {\n this._printHandler(data, print, data.length);\n } else if (currentState === ParserState.DCS_PASSTHROUGH && ~dcs && dcsHandler) {\n dcsHandler.put(data, dcs, data.length);\n }\n\n // save non pushable buffers\n this._osc = osc;\n this._collect = collect;\n this._params = params;\n\n // save active dcs handler reference\n this._activeDcsHandler = dcsHandler;\n\n // save state\n this.currentState = currentState;\n }\n}\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ITerminal } from './Types';\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 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 }\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 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\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 }\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 }\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 }\n if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) {\n return opts.control;\n }\n // binary search in table of non-spacing characters\n if (bisearch(ucs, COMBINING_BMP)) {\n return 0;\n }\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 }\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 initTable(): 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 }\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 }\n if (num < 127) {\n return 1;\n }\n const t = table || initTable();\n if (num < 65536) {\n return t[num >> 4] >> ((num & 15) << 1) & 3;\n }\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 './Types';\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 - 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 */\n public get alt(): Buffer {\n return this._alt;\n }\n\n /**\n * Returns the normal Buffer of the BufferSet\n */\n public get active(): Buffer {\n return this._activeBuffer;\n }\n\n /**\n * Returns the currently active Buffer of the BufferSet\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 if (this._activeBuffer === this._normal) {\n return;\n }\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 this._activeBuffer = this._normal;\n this.emit('activate', {\n activeBuffer: this._normal,\n inactiveBuffer: this._alt\n });\n }\n\n /**\n * Sets the alt Buffer of the BufferSet as its currently active Buffer\n */\n public activateAltBuffer(): void {\n if (this._activeBuffer === this._alt) {\n return;\n }\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', {\n activeBuffer: this._alt,\n inactiveBuffer: this._normal\n });\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 { CircularList } from './common/CircularList';\nimport { LineData, CharData, ITerminal, IBuffer } from './Types';\nimport { EventEmitter } from './EventEmitter';\nimport { IMarker } from 'xterm';\n\nexport const DEFAULT_ATTR = (0 << 18) | (257 << 9) | (256 << 0);\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\nexport const NULL_CELL_CHAR = ' ';\nexport const NULL_CELL_WIDTH = 1;\nexport const NULL_CELL_CODE = 32;\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 public lines: CircularList;\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 public markers: Marker[] = [];\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 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 = [DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]; // does xterm use the default attr?\n for (let i = 0; i < this.lines.length; i++) {\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 this.x = Math.min(this.x, newCols - 1);\n this.y = Math.min(this.y, newRows - 1);\n if (addToY) {\n this.y += addToY;\n }\n this.savedY = Math.min(this.savedY, newRows - 1);\n this.savedX = Math.min(this.savedX, newCols - 1);\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 // Only set endCol to the line length when it is null. 0 is a valid column.\n if (endCol === null) {\n endCol = line.length;\n }\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 public getWrappedRangeForLine(y: number): { first: number, last: number } {\n let first = y;\n let last = y;\n // Scan upwards for wrapped lines\n while (first > 0 && (this.lines.get(first)).isWrapped) {\n first--;\n }\n // Scan downwards for wrapped lines\n while (last + 1 < this.lines.length && (this.lines.get(last + 1)).isWrapped) {\n last++;\n }\n return { first, last };\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 public addMarker(y: number): Marker {\n const marker = new Marker(y);\n this.markers.push(marker);\n marker.register(this.lines.addDisposableListener('trim', amount => {\n marker.line -= amount;\n // The marker should be disposed when the line is trimmed from the buffer\n if (marker.line < 0) {\n marker.dispose();\n }\n }));\n marker.register(marker.addDisposableListener('dispose', () => this._removeMarker(marker)));\n return marker;\n }\n\n private _removeMarker(marker: Marker): void {\n // TODO: This could probably be optimized by relying on sort order and trimming the array using .length\n this.markers.splice(this.markers.indexOf(marker), 1);\n }\n}\n\nexport class Marker extends EventEmitter implements IMarker {\n private static _nextId = 1;\n\n private _id: number = Marker._nextId++;\n public isDisposed: boolean = false;\n\n public get id(): number { return this._id; }\n\n constructor(\n public line: number\n ) {\n super();\n }\n\n public dispose(): void {\n if (this.isDisposed) {\n return;\n }\n this.isDisposed = true;\n // Emit before super.dispose such that dispose listeners get a change to react\n this.emit('dispose');\n super.dispose();\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport * as Strings from './Strings';\nimport { ITerminal, IBuffer } from './Types';\nimport { isMac } from './shared/utils/Browser';\nimport { RenderDebouncer } from './ui/RenderDebouncer';\nimport { addDisposableDomListener } from './ui/Lifecycle';\nimport { Disposable } from './common/Lifecycle';\n\nconst MAX_ROWS_TO_READ = 20;\n\nconst enum BoundaryPosition {\n TOP,\n BOTTOM\n}\n\nexport class AccessibilityManager extends Disposable {\n private _accessibilityTreeRoot: HTMLElement;\n private _rowContainer: HTMLElement;\n private _rowElements: HTMLElement[];\n private _liveRegion: HTMLElement;\n private _liveRegionLineCount: number = 0;\n\n private _renderRowsDebouncer: RenderDebouncer;\n\n private _topBoundaryFocusListener: (e: FocusEvent) => void;\n private _bottomBoundaryFocusListener: (e: FocusEvent) => void;\n\n /**\n * This queue has a character pushed to it for keys that are pressed, if the\n * next character added to the terminal is equal to the key char then it is\n * not announced (added to live region) because it has already been announced\n * by the textarea event (which cannot be canceled). There are some race\n * condition cases if there is typing while data is streaming, but this covers\n * the main case of typing into the prompt and inputting the answer to a\n * question (Y/N, etc.).\n */\n private _charsToConsume: string[] = [];\n\n constructor(private _terminal: ITerminal) {\n super();\n this._accessibilityTreeRoot = document.createElement('div');\n this._accessibilityTreeRoot.classList.add('xterm-accessibility');\n\n this._rowContainer = document.createElement('div');\n this._rowContainer.classList.add('xterm-accessibility-tree');\n this._rowElements = [];\n for (let i = 0; i < this._terminal.rows; i++) {\n this._rowElements[i] = this._createAccessibilityTreeNode();\n this._rowContainer.appendChild(this._rowElements[i]);\n }\n\n this._topBoundaryFocusListener = e => this._onBoundaryFocus(e, BoundaryPosition.TOP);\n this._bottomBoundaryFocusListener = e => this._onBoundaryFocus(e, BoundaryPosition.BOTTOM);\n this._rowElements[0].addEventListener('focus', this._topBoundaryFocusListener);\n this._rowElements[this._rowElements.length - 1].addEventListener('focus', this._bottomBoundaryFocusListener);\n\n this._refreshRowsDimensions();\n this._accessibilityTreeRoot.appendChild(this._rowContainer);\n\n this._renderRowsDebouncer = new RenderDebouncer(this._terminal, this._renderRows.bind(this));\n this._refreshRows();\n\n this._liveRegion = document.createElement('div');\n this._liveRegion.classList.add('live-region');\n this._liveRegion.setAttribute('aria-live', 'assertive');\n this._accessibilityTreeRoot.appendChild(this._liveRegion);\n\n this._terminal.element.insertAdjacentElement('afterbegin', this._accessibilityTreeRoot);\n\n this.register(this._renderRowsDebouncer);\n this.register(this._terminal.addDisposableListener('resize', data => this._onResize(data.rows)));\n this.register(this._terminal.addDisposableListener('refresh', data => this._refreshRows(data.start, data.end)));\n this.register(this._terminal.addDisposableListener('scroll', data => this._refreshRows()));\n // Line feed is an issue as the prompt won't be read out after a command is run\n this.register(this._terminal.addDisposableListener('a11y.char', (char) => this._onChar(char)));\n this.register(this._terminal.addDisposableListener('linefeed', () => this._onChar('\\n')));\n this.register(this._terminal.addDisposableListener('a11y.tab', spaceCount => this._onTab(spaceCount)));\n this.register(this._terminal.addDisposableListener('key', keyChar => this._onKey(keyChar)));\n this.register(this._terminal.addDisposableListener('blur', () => this._clearLiveRegion()));\n // TODO: Maybe renderer should fire an event on terminal when the characters change and that\n // should be listened to instead? That would mean that the order of events are always\n // guarenteed\n this.register(this._terminal.addDisposableListener('dprchange', () => this._refreshRowsDimensions()));\n this.register(this._terminal.renderer.addDisposableListener('resize', () => this._refreshRowsDimensions()));\n // This shouldn't be needed on modern browsers but is present in case the\n // media query that drives the dprchange event isn't supported\n this.register(addDisposableDomListener(window, 'resize', () => this._refreshRowsDimensions()));\n }\n\n public dispose(): void {\n super.dispose();\n this._terminal.element.removeChild(this._accessibilityTreeRoot);\n this._rowElements.length = 0;\n }\n\n private _onBoundaryFocus(e: FocusEvent, position: BoundaryPosition): void {\n const boundaryElement = e.target;\n const beforeBoundaryElement = this._rowElements[position === BoundaryPosition.TOP ? 1 : this._rowElements.length - 2];\n\n // Don't scroll if the buffer top has reached the end in that direction\n const posInSet = boundaryElement.getAttribute('aria-posinset');\n const lastRowPos = position === BoundaryPosition.TOP ? '1' : `${this._terminal.buffer.lines.length}`;\n if (posInSet === lastRowPos) {\n return;\n }\n\n // Don't scroll when the last focused item was not the second row (focus is going the other\n // direction)\n if (e.relatedTarget !== beforeBoundaryElement) {\n return;\n }\n\n // Remove old boundary element from array\n let topBoundaryElement: HTMLElement;\n let bottomBoundaryElement: HTMLElement;\n if (position === BoundaryPosition.TOP) {\n topBoundaryElement = boundaryElement;\n bottomBoundaryElement = this._rowElements.pop()!;\n this._rowContainer.removeChild(bottomBoundaryElement);\n } else {\n topBoundaryElement = this._rowElements.shift()!;\n bottomBoundaryElement = boundaryElement;\n this._rowContainer.removeChild(topBoundaryElement);\n }\n\n // Remove listeners from old boundary elements\n topBoundaryElement.removeEventListener('focus', this._topBoundaryFocusListener);\n bottomBoundaryElement.removeEventListener('focus', this._bottomBoundaryFocusListener);\n\n // Add new element to array/DOM\n if (position === BoundaryPosition.TOP) {\n const newElement = this._createAccessibilityTreeNode();\n this._rowElements.unshift(newElement);\n this._rowContainer.insertAdjacentElement('afterbegin', newElement);\n } else {\n const newElement = this._createAccessibilityTreeNode();\n this._rowElements.push(newElement);\n this._rowContainer.appendChild(newElement);\n }\n\n // Add listeners to new boundary elements\n this._rowElements[0].addEventListener('focus', this._topBoundaryFocusListener);\n this._rowElements[this._rowElements.length - 1].addEventListener('focus', this._bottomBoundaryFocusListener);\n\n // Scroll up\n this._terminal.scrollLines(position === BoundaryPosition.TOP ? -1 : 1);\n\n // Focus new boundary before element\n this._rowElements[position === BoundaryPosition.TOP ? 1 : this._rowElements.length - 2].focus();\n\n // Prevent the standard behavior\n e.preventDefault();\n e.stopImmediatePropagation();\n }\n\n private _onResize(rows: number): void {\n // Remove bottom boundary listener\n this._rowElements[this._rowElements.length - 1].removeEventListener('focus', this._bottomBoundaryFocusListener);\n\n // Grow rows as required\n for (let i = this._rowContainer.children.length; i < this._terminal.rows; i++) {\n this._rowElements[i] = this._createAccessibilityTreeNode();\n this._rowContainer.appendChild(this._rowElements[i]);\n }\n // Shrink rows as required\n while (this._rowElements.length > rows) {\n this._rowContainer.removeChild(this._rowElements.pop()!);\n }\n\n // Add bottom boundary listener\n this._rowElements[this._rowElements.length - 1].addEventListener('focus', this._bottomBoundaryFocusListener);\n\n this._refreshRowsDimensions();\n }\n\n private _createAccessibilityTreeNode(): HTMLElement {\n const element = document.createElement('div');\n element.setAttribute('role', 'listitem');\n element.tabIndex = -1;\n this._refreshRowDimensions(element);\n return element;\n }\n\n private _onTab(spaceCount: number): void {\n for (let i = 0; i < spaceCount; i++) {\n this._onChar(' ');\n }\n }\n\n private _onChar(char: string): void {\n if (this._liveRegionLineCount < MAX_ROWS_TO_READ + 1) {\n if (this._charsToConsume.length > 0) {\n // Have the screen reader ignore the char if it was just input\n const shiftedChar = this._charsToConsume.shift();\n if (shiftedChar !== char) {\n this._announceCharacter(char);\n }\n } else {\n this._announceCharacter(char);\n }\n\n if (char === '\\n') {\n this._liveRegionLineCount++;\n if (this._liveRegionLineCount === MAX_ROWS_TO_READ + 1) {\n this._liveRegion.textContent += Strings.tooMuchOutput;\n }\n }\n\n // Only detach/attach on mac as otherwise messages can go unaccounced\n if (isMac) {\n if (this._liveRegion.textContent && this._liveRegion.textContent.length > 0 && !this._liveRegion.parentNode) {\n setTimeout(() => {\n this._accessibilityTreeRoot.appendChild(this._liveRegion);\n }, 0);\n }\n }\n }\n }\n\n private _clearLiveRegion(): void {\n this._liveRegion.textContent = '';\n this._liveRegionLineCount = 0;\n\n // Only detach/attach on mac as otherwise messages can go unaccounced\n if (isMac) {\n if (this._liveRegion.parentNode) {\n this._accessibilityTreeRoot.removeChild(this._liveRegion);\n }\n }\n }\n\n private _onKey(keyChar: string): void {\n this._clearLiveRegion();\n this._charsToConsume.push(keyChar);\n }\n\n private _refreshRows(start?: number, end?: number): void {\n this._renderRowsDebouncer.refresh(start, end);\n }\n\n private _renderRows(start: number, end: number): void {\n const buffer: IBuffer = this._terminal.buffer;\n const setSize = buffer.lines.length.toString();\n for (let i = start; i <= end; i++) {\n const lineData = buffer.translateBufferLineToString(buffer.ydisp + i, true);\n const posInSet = (buffer.ydisp + i + 1).toString();\n const element = this._rowElements[i];\n element.textContent = lineData.length === 0 ? Strings.blankLine : lineData;\n element.setAttribute('aria-posinset', posInSet);\n element.setAttribute('aria-setsize', setSize);\n }\n }\n\n private _refreshRowsDimensions(): void {\n if (!this._terminal.renderer.dimensions.actualCellHeight) {\n return;\n }\n if (this._rowElements.length !== this._terminal.rows) {\n this._onResize(this._terminal.rows);\n }\n for (let i = 0; i < this._terminal.rows; i++) {\n this._refreshRowDimensions(this._rowElements[i]);\n }\n }\n\n private _refreshRowDimensions(element: HTMLElement): void {\n element.style.height = `${this._terminal.renderer.dimensions.actualCellHeight}px`;\n }\n\n private _announceCharacter(char: string): void {\n if (char === ' ') {\n // Always use nbsp for spaces in order to preserve the space between characters in\n // voiceover's caption window\n this._liveRegion.innerHTML += ' ';\n } else {\n this._liveRegion.textContent += char;\n }\n }\n}\n",null],"names":[],"mappings":"AqDAA;;;;;;;;;;;;;ADKA;AAEA;AACA;AACA;AACA;AAEA;AAOA;AAAA;AAuBA;AAAA;AAAA;AAlBA;AAgBA;AAIA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAIA;AACA;AAGA;;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAGA;AACA;AAGA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAGA;AACA;AAGA;AAGA;AAGA;AACA;AACA;AAEA;AAEA;AAGA;AACA;AACA;AACA;AAEA;AACA;AACA;AAGA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAGA;AACA;AAAA;AACA;AACA;AACA;AACA;AAAA;AAvQa;;;;;;;;;;;;;;;ADdb;AAEA;AAGa;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AASb;AAmBA;AACA;AACA;AAVA;AAYA;AACA;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;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;AACA;AAEA;AACA;AAEA;AACA;AAYA;AAAA;AAAA;AAEA;AACA;AACA;AACA;AACA;AAMA;AAEA;AACA;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;AAEA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;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;AAEA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAAA;AAzTa;AA2Tb;AAAA;AAQA;AAAA;AACA;AANA;AACA;;AAQA;AANA;AAAA;;;AAAA;AAQA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AArBA;AAsBA;AAAA;AAvBa;;;;;;;;;;;;;;;ADjVb;AACA;AAMA;AAAA;AASA;AAAA;AAAA;AAEA;AACA;AAIA;AACA;AAEA;;AACA;AAKA;AAAA;AACA;AACA;;;AAAA;AAKA;AAAA;AACA;AACA;;;AAAA;AAKA;AAAA;AACA;AACA;;;AAAA;AAKA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AAAA;AAhGa;;;;;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;AAAA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;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;AACA;AAEA;AACA;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;AACA;AACA;AACA;AAEA;AACA;AACA;;;;;ADzJA;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;AAGA;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;AAMA;AACA;AACA;AACA;AACA;AAAA;AAnNa;;;;;;;;;;;;;;;ADXb;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AAGA;AACA;AACA;AACA;AACA;AASA;AACA;AACA;AASA;AACA;AACA;AACA;AACA;AACA;AAAA;AAhCa;AAsCb;AACA;AACA;AACA;AACA;AAMa;AACb;AAEA;AACA;AAGA;AAEA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;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;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;AAKA;AAAA;AAIA;AAHA;AACA;AACA;AACA;AAAA;AAcA;AAAA;AA4BA;AAAA;AAAA;AAAA;AAGA;AACA;AACA;AACA;AACA;AAGA;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;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAGA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAA;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;AACA;AACA;AAAA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AAAA;;AACA;AACA;AACA;AACA;AAAA;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAAA;AAIA;AACA;AACA;AACA;AAAA;;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAAA;AACA;AACA;AAGA;AACA;AACA;AAGA;AAGA;AACA;AACA;AAAA;AAlWa;;;;;;;;;;;;;;;AD3Mb;AAEA;AAAA;AAGA;AAAA;AAIA;;AACA;AAEA;AACA;AACA;AACA;AAOA;AAAA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AAAA;AAAA;AAAA;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAAA;AA3Ea;;;;;;;;;;;;;;;ADFb;AACA;AACA;AAEA;AACA;AAEA;AAKA;AAYA;AAEA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAAA;AAQA;AAGA;AAAA;AAAA;AAEA;AAEA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAAA;AAuBA;AAAA;AAGA;AAEA;AAFA;AACA;AACA;AAIA;AAEA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AAKA;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;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AAMA;AAGA;AAqCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AARA;AAAA;AAQA;AAKA;AACA;AACA;AACA;AAKA;AACA;;AACA;AAEA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAGA;AACA;AACA;AAGA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAGA;AAGA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAIA;AAGA;AACA;AACA;AACA;AAEA;AACA;AACA;AAOA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAGA;AACA;AAEA;AACA;AAAA;AACA;AAGA;AACA;AAEA;AACA;AAKA;AAEA;AAGA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAGA;AAGA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AAMA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAMA;AACA;AAMA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AAOA;AACA;AACA;AAMA;AACA;AACA;AAAA;AAGA;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;AAGA;AAEA;AAEA;AACA;AACA;AAGA;AACA;AACA;AAGA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AAGA;AAEA;AAEA;AACA;AACA;AACA;AAGA;AACA;AACA;AAGA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AAGA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AAGA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AAKA;AACA;AACA;AAGA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AAGA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AAKA;AACA;AAGA;AAEA;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;AAGA;AAEA;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;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;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;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;AAAA;AAGA;AACA;AAEA;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;AACA;AACA;AAYA;AACA;AACA;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;AAQA;AACA;AACA;AACA;AACA;AAQA;AACA;AACA;AACA;AACA;AAQA;AACA;AACA;AAQA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AAQA;AACA;AACA;AACA;AAkBA;AACA;AAAA;AACA;AAAA;AACA;AACA;AAQA;AACA;AACA;AASA;AACA;AACA;AASA;AACA;AACA;AAOA;AACA;AACA;AACA;AAYA;AACA;AACA;AACA;AAAA;AAl1Da;;;;;;;;;;;;;;;AD3Gb;AACA;AAKA;AAAA;AAeA;AAAA;AACA;AARA;AAIA;AAOA;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;AAYA;AAAA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AAEA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAWA;AAAA;AAAA;AAEA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAMA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAtRA;AAuRA;AAAA;AA7Ra;;;;;;;;;;;;;;;ADPb;AACA;AAEA;AACA;AACA;AACA;AAMA;AAKA;AAKA;AAMA;AAMA;AAEA;AACA;AA4BA;AAAA;AAoCA;AAAA;AACA;AACA;AAVA;AAaA;AACA;AAEA;AACA;;AACA;AAEA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;;;AAAA;AAKA;AAAA;AACA;AACA;AACA;AAEA;AACA;AAEA;AAAA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AAKA;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;AAEA;AAEA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAAA;AAEA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;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;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;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;AACA;AAEA;AACA;AAMA;AACA;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;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;AAMA;AACA;AACA;AAOA;AAIA;AAIA;AAGA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAAA;AACA;AACA;AAGA;AAKA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AAEA;AAEA;AACA;AACA;AAAA;AACA;AACA;AACA;AAEA;AACA;AAKA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AAGA;AACA;AAAA;AAIA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AAAA;AAAA;AAEA;AACA;AACA;AAEA;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;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAOA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAOA;AAGA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAt0Ba;;;;;AD5Db;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;AACA;AACA;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;AA5Ha;;;;;ADAA;AAEb;AAGA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAEA;AAEA;AAGA;AACA;AACA;AAAA;AA9Ca;;;;;ADRF;AACA;AACA;;;;;;;;;;;;;;;ADmBX;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AAIA;AAOA;AAMA;AAKA;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;AAAA;AAmHA;AACA;AADA;AAjGA;AAqGA;AACA;;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AAKA;AAEA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAEA;AAEA;AAEA;AACA;AAGA;AACA;AAEA;AAEA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAKA;AAAA;AACA;AACA;;;AAAA;AAKA;AAEA;AACA;AAKA;AACA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;;;AAAA;AAMA;AACA;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;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;AAEA;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;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AAEA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AAKA;AAGA;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;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AAAA;AACA;AAEA;AACA;AACA;AAGA;AACA;AAEA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAGA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AAGA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAEA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AAGA;AACA;AAGA;AAGA;AAGA;AAIA;AAEA;AAEA;AACA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;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;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;AAKA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AAGA;AACA;AAGA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAMA;AACA;AAGA;AACA;AAGA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAIA;AACA;AAAA;AACA;AACA;AACA;AAEA;AACA;AAAA;AACA;AACA;AACA;AAEA;AACA;AAAA;AACA;AACA;AACA;AACA;AAQA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AAAA;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;AAEA;AACA;AACA;AACA;AACA;AACA;AAMA;AAAA;AAEA;AACA;AACA;AAGA;AACA;AACA;AAEA;AAKA;AAGA;AACA;AACA;AAEA;AAEA;AAEA;AACA;AACA;AACA;AACA;AAEA;AAAA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAIA;AACA;AACA;AACA;AAEA;AACA;AAQA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAAA;AACA;AACA;AACA;AAMA;AACA;AACA;AAWA;AACA;AACA;AAYA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;;;AAAA;AAEA;AAEA;AACA;AACA;AAEA;AACA;AAKA;AACA;AACA;AAMA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAQA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AAQA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAEA;AAEA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AAEA;AACA;AACA;AAGA;AACA;AAMA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AAEA;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;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;AACA;AACA;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;AACA;AACA;AAMA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAGA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAGA;AAEA;AACA;AAGA;AACA;AAAA;AA/0Da;AAq1Db;AACA;AACA;AACA;AACA;AASA;AAGA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;AD/8DA;AACA;AAEA;AAMA;AAAA;AAoBA;AAAA;AACA;AACA;AACA;AACA;AAvBA;AACA;AACA;AACA;AACA;AAMA;AAoBA;AACA;AAGA;;AACA;AAEA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;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;AAGA;AACA;AACA;AAEA;AACA;AACA;AACA;AAQA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AAEA;AACA;AACA;AAGA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAOA;AAEA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAjLa;;;;;;;;;;;;;;;ADZb;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;AAmBA;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;AA9La;;;;;ADDb;AAIA;AAHA;AACA;AAGA;AAKA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAnCsB;;;;;ADFtB;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;AAMA;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;AACA;;;;;ADzIa;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;;;;;ADtPA;AAGA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAMA;AACA;AAGA;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;AAAA;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;AAAA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAAA;AACA;AACA;AAAA;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;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AA9TA;;;;;ADhCA;AASA;AAOA;AACA;AACA;AAEA;AACA;AACA;AAEA;AAUA;AACA;;AAEA;AACA;;AACA;AAKA;AACA;AACA;AACA;AACA;AAOA;AAEA;AACA;AACA;AAGA;AACA;AAOA;AACA;AACA;AACA;AACA;AAIA;AAMA;AACA;AACA;AAEA;AAEA;AACA;AAKA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AAEA;AACA;AAEA;AAIA;AAEA;AACA;AACA;AACA;AAUA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAMA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AASA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AAWA;AAOA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAGA;AACA;AACA;AACA;AAAA;AACA;AAGA;AACA;AACA;AACA;AACA;AAEA;AAGA;AAMA;AACA;AACA;AACA;AACA;AAAA;AA7Oa;AAqPb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ADvPA;AACA;AACA;AAFA;AAQA;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;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AArBA;AA8BA;AACA;AAEA;AACA;AACA;AAGA;AACA;AACA;AAVA;;;;;AD9GA;AACA;AAEA;AAGA;AACA;AACA;AAEA;AAAA;;;AAAA;AACA;AAAA;;;AAAA;AACA;AAAA;;;AAAA;AACA;AAAA;;;AAAA;AACA;AAAA;;;AAAA;AACA;AACA;AACA;AACA;AACA;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;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;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AAYA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;;;AAAA;AACA;AAAA;AA/Ia;;;;;ADHb;AAEA;AACA;AAEA;AAYA;AACA;AAGA;AACA;AAdA;AACA;AACA;AACA;AACA;AACA;AAWA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAEA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAGA;AACA;AAEA;AACA;AACA;AAGA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAEA;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;AAEA;AACA;AAOA;AACA;AACA;AACA;AAaA;AACA;AACA;AACA;AAEA;AACA;AACA;AAAA;AAEA;AACA;AAAA;AACA;AACA;AAEA;AAGA;AACA;AACA;AAEA;AAIA;AACA;AAOA;AACA;AACA;AAKA;AACA;AAOA;AACA;AACA;AAEA;AACA;AACA;AAAA;AAxTsB;;;;;ADZtB;AAIA;AAKA;AAAA;AAHA;AACA;AAGA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAMA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AAGA;AAGA;AACA;AAOA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAEA;AACA;AAGA;AACA;AAOA;AACA;AACA;AACA;AAEA;AACA;AAUA;AACA;AAIA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAUA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAEA;AACA;AACA;AACA;AAIA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AAGA;AAGA;AACA;AACA;AAMA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAIA;AACA;AAIA;AACA;AACA;AACA;AAUA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AAGA;AACA;AACA;AAEA;AAGA;AACA;AACA;AAGA;AACA;AAAA;AACA;AAGA;AACA;AACA;AAEA;AAGA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AAEA;AAEA;AACA;AAAA;AAEA;AACA;AAEA;AACA;AACA;AAAA;AA/Qa;;;;;ADKb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIa;AACb;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAKA;AAKA;AAAA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAGA;AAEA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AAiBA;AAEA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAAA;AAtGa;;;;;;;;;;;;;;;AD/Eb;AAEA;AAcA;AAEA;AAAA;AAKA;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;AACA;AACA;AACA;AAAA;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;;;;;ADzVA;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;;;;;;;;;;;;;;;ADEb;AAEA;AAAA;AAGA;AAAA;AAFA;AAIA;AACA;;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAA;AAlDa;;;;;;;;;;;;;;;ADJb;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAEA;AAEA;AAAA;AAaA;AAAA;AAAA;AAPA;AACA;AAQA;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;AAEA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AAGA;AACA;AACA;AACA;AACA;AAEA;AAAA;AACA;AAGA;AACA;AACA;AACA;AAEA;AACA;AACA;AAAA;AACA;AACA;AAEA;AACA;AAEA;AAAA;AAEA;AAGA;AAGA;AACA;AACA;AAAA;AACA;AACA;AAGA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AAAA;AACA;AACA;AAEA;AAAA;AACA;AACA;AAEA;AAAA;AAAA;AACA;AACA;AAEA;AAAA;AACA;AACA;AAEA;AAAA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AAAA;AACA;AACA;AACA;AAKA;AAEA;AACA;AACA;AAMA;AAKA;AAMA;AAIA;AAGA;AAIA;AAIA;AACA;AAOA;AACA;AAQA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAA;AA1Pa;;;;;;;;;;;;;;;ADXb;AASA;AAAA;AAGA;AAAA;AAEA;;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAGA;AAGA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AAAA;AAEA;AACA;AACA;AAGA;AACA;AAGA;AAEA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AAAA;AArGa;;;;;;;;;;;;;;;ADXb;AAGA;AACA;AACA;AASA;AAAA;AAOA;AAAA;AAHA;AAKA;AACA;;AACA;AAEA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AAgBA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AAGA;AACA;AAIA;AACA;AACA;AAKA;AACA;AACA;AAIA;AAMA;AACA;AAGA;AACA;AAMA;AAQA;AACA;AAMA;AACA;AAEA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAWA;AACA;AACA;AACA;AAMA;AAAA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AAGA;AACA;AACA;AACA;AAAA;AACA;AACA;AAEA;AAGA;AACA;AACA;AAAA;AAEA;AACA;AACA;AACA;AACA;AAAA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AAGA;AACA;AACA;AACA;AAEA;AACA;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAEA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AAEA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AAKA;AAGA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AAKA;AAGA;AAGA;AACA;AACA;AAgBA;AAAA;AA/Sa;;;;;ADZb;AAAA;AACA;AA4CA;AAtCA;AACA;AACA;AACA;AACA;AACA;AAMA;AASA;AAkBA;AAAA;;;;;;AD5CA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAUA;AAQA;AAMA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AAhDA;AAsDA;AACA;AACA;AACA;AACA;AAEA;AACA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AAdA;;;;;ADjFA;AAEA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAxBA;AA0BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAjBA;;;;;;;;;;;;;;;AD9BA;AAGA;AACA;AACA;AACA;AAIA;AACA;AAEA;AACA;AACA;AACA;AAQA;AAOA;AACA;AACA;AACA;AAEA;AAAA;AAkBA;AAAA;AAAA;AAFA;AAIA;AACA;AACA;AAIA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;;AAIA;AAEA;AACA;AACA;AAEA;AAMA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAQA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AAOA;AACA;AACA;AACA;AACA;AAWA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAIA;AACA;AAAA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAA;AAEA;AACA;AACA;AACA;AAIA;AACA;AAEA;AAGA;AAGA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AAEA;AAGA;AACA;AACA;AAEA;AACA;AAIA;AAGA;AACA;AACA;AACA;AAGA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AAAA;;;;;;ADrOA;AAOA;AAAA;AANA;AACA;AACA;AACA;AACA;AAEA;AAEA;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;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AAEA;AACA;AAEA;AACA;AACA;AACA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAEA;AACA;AAEA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;;;;;;;;;;;;;;;;ADnHA;AAEA;AAAA;AACA;AACA;AACA;AAEA;AAMA;AACA;AACA;AAAA;;;;;;;;;;;;;;;;ADnBA;AACA;AACA;AACA;AAEA;AAAA;AAGA;AAAA;AAAA;AAAA;AAIA;AACA;AACA;AACA;AAKA;AACA;;AAXA;AAaA;AAAA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AAOA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAGA;AACA;AAGA;AACA;AACA;AAEA;AAYA;AAEA;AACA;AACA;AAAA;;;;;;AD9Fa;AACA;;;;;;;;;;;;;;;ADEb;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AAUA;AAAA;AAcA;AAAA;AAAA;AAXA;AAKA;AAQA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAGA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;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;AAEA;AACA;AACA;AAEA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAGA;AACA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AACA;AAGA;AAEA;AACA;AAGA;AAAA;AAEA;AACA;AACA;AAEA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AAQA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AAEA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAEA;AAAA;AACA;AACA;;;AAAA;AAEA;AACA;AACA;AAAA;AA/Sa;;;;;ADxBb;AAGa;AACA;AACA;AAEb;AACA;AACA;AAEA;AAEA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AAGA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AA5Ea;;;;;ADPb;AAEA;AAiBA;AACA;AACA;AACA;AAIA;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;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AAEA;AAEA;AACA;AAEA;AACA;AAEA;AAGA;AAEA;AACA;AA5FA;AAkGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AAfA;AAiBA;AACA;AACA;;;;;ADtIa;;;;;ADHb;AACA;AACA;AAEa;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AAOb;AACA;AACA;;;;;;;;;;;;;;;ADvBA;AAOA;AAAA;AAOA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA;AAEA;AAAA;AACA;AACA;;;AAAA;AAEA;AAAA;AACA;AACA;;;AAAA;AAEA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAzCa;;;;;ADDb;AAMA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAlBA;;;;;;;;;;;;;;;ADLA;AACA;AAEA;AAUA;AAAA;AAWA;AAAA;AACA;AAXA;AAEA;AAIA;AACA;AACA;AAOA;AAGA;AACA;;AACA;AAEA;AACA;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;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;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AA1La;AA4Lb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAAA;AAba;;;;;AD1Mb;AAKA;AACA;AACA;AAJA;AAMA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAEA;AAEA;AACA;AAGA;AAGA;AACA;AACA;AACA;AACA;AAAA;AA5Ca;;;;;;;;;;;;;;;ADDb;AAcA;AAAA;AAAA;;AA0CA;AApCA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AA1Ca;;;;;ADXA;AAAb;AACA;AACA;AACA;AAGA;AACA;AACA;AAGA;AAEA;AAEA;AACA;AAEA;AACA;;;;;ADnBA;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;;;;;ADDb;AAEA;"}
\ No newline at end of file
diff --git a/webvirtcloud.sh b/webvirtcloud.sh
index 36286b3..9f97784 100755
--- a/webvirtcloud.sh
+++ b/webvirtcloud.sh
@@ -254,7 +254,7 @@ install_webvirtcloud () {
pip3 install -r conf/requirements.txt -q
- cp "$APP_PATH/conf/daemon/consolecallback" "$APP_PATH/venv/bin/consolecallback"
+
chown -R "$nginx_group":"$nginx_group" "$APP_PATH"