{"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 = <HTMLElement>element.offsetParent;\n    }\n    element = originalElement;\n    while (element && element !== element.ownerDocument.body) {\n      x += element.scrollLeft;\n      y += element.scrollTop;\n      element = <HTMLElement>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 = <T>(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 = <number><any>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<ImageBitmap> {\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 = (<any>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<T> {\n  prev: ILinkedListNode<T>;\n  next: ILinkedListNode<T>;\n  key: string;\n  value: T;\n}\n\nexport default class LRUMap<T> {\n  private _map: { [key: string]: ILinkedListNode<T> } = {};\n  private _head: ILinkedListNode<T> = null;\n  private _tail: ILinkedListNode<T> = null;\n  private _nodePool: ILinkedListNode<T>[] = [];\n  public size: number = 0;\n\n  constructor(public capacity: number) { }\n\n  private _unlinkNode(node: ILinkedListNode<T>): 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<T>): 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<IGlyphCacheValue>;\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 = <IColorSet>{\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<CharData>;\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<CharData>();\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 = <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<T> {\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 = <number><any>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 = <number><any>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 = <HTMLCanvasElement>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<LineData>;\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 ((<any>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 = (<any>this._lines.get(currentRow)).isWrapped;\n\n    while (lineWraps && currentRow >= 0 && currentRow < this._terminal.rows) {\n      rowCount++;\n      currentRow--;\n      lineWraps = (<any>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        // <Ctrl> or <Shift> + <Insert> 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 <Esc> 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<T extends IDisposable>(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<T extends IDisposable>(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<T> extends EventEmitter implements ICircularList<T> {\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<T>(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<T>(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 !== (<any>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 = <any>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(<ITheme>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 ((<any>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                  + (<any>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 ((<any>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 = (<WheelEvent>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        (<any>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      (<any>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 = (<any>window).AudioContext || (<any>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(<MouseEvent>event);\n    this._mouseUpListener = event => this._onMouseUp(<MouseEvent>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 ((<any>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 ((<any>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 && (<any>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 && (<any>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 = <number><any>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 ((<any>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 ((<any>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        (<any>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 ((<any>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            (<any>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: ^[[<b;x;yM\n          // release: ^[[<b;x;ym\n          break;\n        case 1015: // urxvt ext mode mouse\n          this._terminal.urxvtMouse = true;\n          // for wide terminals\n          // numbers for fields\n          // press: ^[[b;x;yM\n          // motion: ^[[b;x;yT\n          break;\n        case 25: // show cursor\n          this._terminal.cursorHidden = false;\n          break;\n        case 1049: // alt screen buffer cursor\n          // TODO: Not sure if we need to save/restore after switching the buffer\n          // this.saveCursor(params);\n          // FALL-THROUGH\n        case 47: // alt screen buffer\n        case 1047: // alt screen buffer\n          this._terminal.buffers.activateAltBuffer();\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 = true;\n          break;\n      }\n    }\n  }\n\n  /**\n   * CSI Pm l  Reset Mode (RM).\n   *     Ps = 2  -> 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; <data> ST (set icon name + window title)\n   * OSC 2; <data> 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<LineData>;\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<LineData>(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 && (<any>this.lines.get(first)).isWrapped) {\n      first--;\n    }\n    // Scan downwards for wrapped lines\n    while (last + 1 < this.lines.length && (<any>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 = <HTMLElement>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 += '&nbsp;';\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;"}