From b0df236dea7cf468240dc2508758351321e3cd9b Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 22 Nov 2016 11:36:34 -0800 Subject: [PATCH 01/24] Rename CompositionHelper.js -> CompositionHelper.ts --- src/{CompositionHelper.js => CompositionHelper.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{CompositionHelper.js => CompositionHelper.ts} (100%) diff --git a/src/CompositionHelper.js b/src/CompositionHelper.ts similarity index 100% rename from src/CompositionHelper.js rename to src/CompositionHelper.ts From 30fcdd6ccb50294ad1c29f75299e3d354e41043d Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 22 Nov 2016 11:47:18 -0800 Subject: [PATCH 02/24] tsify CompositionHelper --- src/CompositionHelper.ts | 397 ++++++++++++++++++++------------------- src/Interfaces.ts | 6 + src/xterm.js | 1 - 3 files changed, 213 insertions(+), 191 deletions(-) diff --git a/src/CompositionHelper.ts b/src/CompositionHelper.ts index 3bf829e5..8a29ed72 100644 --- a/src/CompositionHelper.ts +++ b/src/CompositionHelper.ts @@ -3,211 +3,228 @@ * Copyright (c) 2014-2016, SourceLair Private Company (www.sourcelair.com (MIT License) */ -/** - * Encapsulates the logic for handling compositionstart, compositionupdate and compositionend - * events, displaying the in-progress composition to the UI and forwarding the final composition - * to the handler. - * @param {HTMLTextAreaElement} textarea The textarea that xterm uses for input. - * @param {HTMLElement} compositionView The element to display the in-progress composition in. - * @param {Terminal} terminal The Terminal to forward the finished composition to. - */ -function CompositionHelper(textarea, compositionView, terminal) { - this.textarea = textarea; - this.compositionView = compositionView; - this.terminal = terminal; +import { ITerminal } from './Interfaces'; - // Whether input composition is currently happening, eg. via a mobile keyboard, speech input - // or IME. This variable determines whether the compositionText should be displayed on the UI. - this.isComposing = false; - - // The input currently being composed, eg. via a mobile keyboard, speech input or IME. - this.compositionText = null; - - // The position within the input textarea's value of the current composition. - this.compositionPosition = { start: null, end: null }; - - // Whether a composition is in the process of being sent, setting this to false will cancel - // any in-progress composition. - this.isSendingComposition = false; +interface IPosition { + start: number; + end: number; } -/** - * Handles the compositionstart event, activating the composition view. - */ -CompositionHelper.prototype.compositionstart = function() { - this.isComposing = true; - this.compositionPosition.start = this.textarea.value.length; - this.compositionView.textContent = ''; - this.compositionView.classList.add('active'); -}; +export class CompositionHelper { + /** + * Whether input composition is currently happening, eg. via a mobile keyboard, speech input or + * IME. This variable determines whether the compositionText should be displayed on the UI. + */ + private isComposing: boolean; -/** - * Handles the compositionupdate event, updating the composition view. - * @param {CompositionEvent} ev The event. - */ -CompositionHelper.prototype.compositionupdate = function(ev) { - this.compositionView.textContent = ev.data; - this.updateCompositionElements(); - var self = this; - setTimeout(function() { - self.compositionPosition.end = self.textarea.value.length; - }, 0); -}; + /** + * The position within the input textarea's value of the current composition. + */ + private compositionPosition: IPosition;; -/** - * Handles the compositionend event, hiding the composition view and sending the composition to - * the handler. - */ -CompositionHelper.prototype.compositionend = function() { - this.finalizeComposition(true); -}; + /** + * Whether a composition is in the process of being sent, setting this to false will cancel any + * in-progress composition. + */ + private isSendingComposition: boolean; -/** - * Handles the keydown event, routing any necessary events to the CompositionHelper functions. - * @return Whether the Terminal should continue processing the keydown event. - */ -CompositionHelper.prototype.keydown = function(ev) { - if (this.isComposing || this.isSendingComposition) { - if (ev.keyCode === 229) { - // Continue composing if the keyCode is the "composition character" - return false; - } else if (ev.keyCode === 16 || ev.keyCode === 17 || ev.keyCode === 18) { - // Continue composing if the keyCode is a modifier key - return false; - } else { - // Finish composition immediately. This is mainly here for the case where enter is - // pressed and the handler needs to be triggered before the command is executed. - this.finalizeComposition(false); - } - } - - if (ev.keyCode === 229) { - // If the "composition character" is used but gets to this point it means a non-composition - // character (eg. numbers and punctuation) was pressed when the IME was active. - this.handleAnyTextareaChanges(); - return false; - } - - return true; -}; - -/** - * Finalizes the composition, resuming regular input actions. This is called when a composition - * is ending. - * @param {boolean} waitForPropogation Whether to wait for events to propogate before sending - * the input. This should be false if a non-composition keystroke is entered before the - * compositionend event is triggered, such as enter, so that the composition is send before - * the command is executed. - */ -CompositionHelper.prototype.finalizeComposition = function(waitForPropogation) { - this.compositionView.classList.remove('active'); - this.isComposing = false; - this.clearTextareaPosition(); - - if (!waitForPropogation) { - // Cancel any delayed composition send requests and send the input immediately. + /** + * Encapsulates the logic for handling compositionstart, compositionupdate and compositionend + * events, displaying the in-progress composition to the UI and forwarding the final composition + * to the handler. + * @param textarea The textarea that xterm uses for input. + * @param compositionView The element to display the in-progress composition in. + * @param terminal The Terminal to forward the finished composition to. + */ + constructor( + private textarea: HTMLTextAreaElement, + private compositionView: HTMLElement, + private terminal: ITerminal + ) { + this.isComposing = false; this.isSendingComposition = false; - var input = this.textarea.value.substring(this.compositionPosition.start, this.compositionPosition.end); - this.terminal.handler(input); - } else { - // Make a deep copy of the composition position here as a new compositionstart event may - // fire before the setTimeout executes. - var currentCompositionPosition = { - start: this.compositionPosition.start, - end: this.compositionPosition.end, + this.compositionPosition = { start: null, end: null }; + } + + /** + * Handles the compositionstart event, activating the composition view. + */ + public compositionstart() { + this.isComposing = true; + this.compositionPosition.start = this.textarea.value.length; + this.compositionView.textContent = ''; + this.compositionView.classList.add('active'); + } + + /** + * Handles the compositionupdate event, updating the composition view. + * @param {CompositionEvent} ev The event. + */ + public compositionupdate(ev: CompositionEvent) { + this.compositionView.textContent = ev.data; + this.updateCompositionElements(); + var self = this; + setTimeout(function() { + self.compositionPosition.end = self.textarea.value.length; + }, 0); + } + + /** + * Handles the compositionend event, hiding the composition view and sending the composition to + * the handler. + */ + public compositionend() { + this.finalizeComposition(true); + } + + /** + * Handles the keydown event, routing any necessary events to the CompositionHelper functions. + * @param ev The keydown event. + * @return Whether the Terminal should continue processing the keydown event. + */ + public keydown(ev: KeyboardEvent) { + if (this.isComposing || this.isSendingComposition) { + if (ev.keyCode === 229) { + // Continue composing if the keyCode is the "composition character" + return false; + } else if (ev.keyCode === 16 || ev.keyCode === 17 || ev.keyCode === 18) { + // Continue composing if the keyCode is a modifier key + return false; + } else { + // Finish composition immediately. This is mainly here for the case where enter is + // pressed and the handler needs to be triggered before the command is executed. + this.finalizeComposition(false); + } } - // Since composition* events happen before the changes take place in the textarea on most - // browsers, use a setTimeout with 0ms time to allow the native compositionend event to - // complete. This ensures the correct character is retrieved, this solution was used - // because: - // - The compositionend event's data property is unreliable, at least on Chromium - // - The last compositionupdate event's data property does not always accurately describe - // the character, a counter example being Korean where an ending consonsant can move to - // the following character if the following input is a vowel. + if (ev.keyCode === 229) { + // If the "composition character" is used but gets to this point it means a non-composition + // character (eg. numbers and punctuation) was pressed when the IME was active. + this.handleAnyTextareaChanges(); + return false; + } + + return true; + } + + /** + * Finalizes the composition, resuming regular input actions. This is called when a composition + * is ending. + * @param waitForPropogation Whether to wait for events to propogate before sending + * the input. This should be false if a non-composition keystroke is entered before the + * compositionend event is triggered, such as enter, so that the composition is send before + * the command is executed. + */ + private finalizeComposition(waitForPropogation: boolean) { + this.compositionView.classList.remove('active'); + this.isComposing = false; + this.clearTextareaPosition(); + + if (!waitForPropogation) { + // Cancel any delayed composition send requests and send the input immediately. + this.isSendingComposition = false; + var input = this.textarea.value.substring(this.compositionPosition.start, this.compositionPosition.end); + this.terminal.handler(input); + } else { + // Make a deep copy of the composition position here as a new compositionstart event may + // fire before the setTimeout executes. + var currentCompositionPosition = { + start: this.compositionPosition.start, + end: this.compositionPosition.end, + } + + // Since composition* events happen before the changes take place in the textarea on most + // browsers, use a setTimeout with 0ms time to allow the native compositionend event to + // complete. This ensures the correct character is retrieved, this solution was used + // because: + // - The compositionend event's data property is unreliable, at least on Chromium + // - The last compositionupdate event's data property does not always accurately describe + // the character, a counter example being Korean where an ending consonsant can move to + // the following character if the following input is a vowel. + var self = this; + this.isSendingComposition = true; + setTimeout(function () { + // Ensure that the input has not already been sent + if (self.isSendingComposition) { + self.isSendingComposition = false; + var input; + if (self.isComposing) { + // Use the end position to get the string if a new composition has started. + input = self.textarea.value.substring(currentCompositionPosition.start, currentCompositionPosition.end); + } else { + // Don't use the end position here in order to pick up any characters after the + // composition has finished, for example when typing a non-composition character + // (eg. 2) after a composition character. + input = self.textarea.value.substring(currentCompositionPosition.start); + } + self.terminal.handler(input); + } + }, 0); + } + } + + /** + * Apply any changes made to the textarea after the current event chain is allowed to complete. + * This should be called when not currently composing but a keydown event with the "composition + * character" (229) is triggered, in order to allow non-composition text to be entered when an + * IME is active. + */ + private handleAnyTextareaChanges() { + var oldValue = this.textarea.value; var self = this; - this.isSendingComposition = true; - setTimeout(function () { - // Ensure that the input has not already been sent - if (self.isSendingComposition) { - self.isSendingComposition = false; - var input; - if (self.isComposing) { - // Use the end position to get the string if a new composition has started. - input = self.textarea.value.substring(currentCompositionPosition.start, currentCompositionPosition.end); - } else { - // Don't use the end position here in order to pick up any characters after the - // composition has finished, for example when typing a non-composition character - // (eg. 2) after a composition character. - input = self.textarea.value.substring(currentCompositionPosition.start); + setTimeout(function() { + // Ignore if a composition has started since the timeout + if (!self.isComposing) { + var newValue = self.textarea.value; + var diff = newValue.replace(oldValue, ''); + if (diff.length > 0) { + self.terminal.handler(diff); } - self.terminal.handler(input); } }, 0); } -}; -/** - * Apply any changes made to the textarea after the current event chain is allowed to complete. - * This should be called when not currently composing but a keydown event with the "composition - * character" (229) is triggered, in order to allow non-composition text to be entered when an - * IME is active. - */ -CompositionHelper.prototype.handleAnyTextareaChanges = function() { - var oldValue = this.textarea.value; - var self = this; - setTimeout(function() { - // Ignore if a composition has started since the timeout - if (!self.isComposing) { - var newValue = self.textarea.value; - var diff = newValue.replace(oldValue, ''); - if (diff.length > 0) { - self.terminal.handler(diff); - } + /** + * Positions the composition view on top of the cursor and the textarea just below it (so the + * IME helper dialog is positioned correctly). + * @param dontRecurse Whether to use setTimeout to recursively trigger another update, this is + * necessary as the IME events across browsers are not consistently triggered. + */ + public updateCompositionElements(dontRecurse?: boolean) { + if (!this.isComposing) { + return; } - }, 0); -}; + var cursor = this.terminal.element.querySelector('.terminal-cursor'); + if (cursor) { + // Take .xterm-rows offsetTop into account as well in case it's positioned absolutely within + // the .xterm element. + var xtermRows = this.terminal.element.querySelector('.xterm-rows'); + var cursorTop = xtermRows.offsetTop + cursor.offsetTop; -/** - * Positions the composition view on top of the cursor and the textarea just below it (so the - * IME helper dialog is positioned correctly). - */ -CompositionHelper.prototype.updateCompositionElements = function(dontRecurse) { - if (!this.isComposing) { - return; - } - var cursor = this.terminal.element.querySelector('.terminal-cursor'); - if (cursor) { - // Take .xterm-rows offsetTop into account as well in case it's positioned absolutely within - // the .xterm element. - var xtermRows = this.terminal.element.querySelector('.xterm-rows'); - var cursorTop = xtermRows.offsetTop + cursor.offsetTop; + this.compositionView.style.left = cursor.offsetLeft + 'px'; + this.compositionView.style.top = cursorTop + 'px'; + this.compositionView.style.height = cursor.offsetHeight + 'px'; + this.compositionView.style.lineHeight = cursor.offsetHeight + 'px'; + // Sync the textarea to the exact position of the composition view so the IME knows where the + // text is. + var compositionViewBounds = this.compositionView.getBoundingClientRect(); + this.textarea.style.left = cursor.offsetLeft + 'px'; + this.textarea.style.top = cursorTop + 'px'; + this.textarea.style.width = compositionViewBounds.width + 'px'; + this.textarea.style.height = compositionViewBounds.height + 'px'; + this.textarea.style.lineHeight = compositionViewBounds.height + 'px'; + } + if (!dontRecurse) { + setTimeout(this.updateCompositionElements.bind(this, true), 0); + } + }; - this.compositionView.style.left = cursor.offsetLeft + 'px'; - this.compositionView.style.top = cursorTop + 'px'; - this.compositionView.style.height = cursor.offsetHeight + 'px'; - this.compositionView.style.lineHeight = cursor.offsetHeight + 'px'; - // Sync the textarea to the exact position of the composition view so the IME knows where the - // text is. - var compositionViewBounds = this.compositionView.getBoundingClientRect(); - this.textarea.style.left = cursor.offsetLeft + 'px'; - this.textarea.style.top = cursorTop + 'px'; - this.textarea.style.width = compositionViewBounds.width + 'px'; - this.textarea.style.height = compositionViewBounds.height + 'px'; - this.textarea.style.lineHeight = compositionViewBounds.height + 'px'; - } - if (!dontRecurse) { - setTimeout(this.updateCompositionElements.bind(this, true), 0); - } -}; - -/** - * Clears the textarea's position so that the cursor does not blink on IE. - * @private - */ -CompositionHelper.prototype.clearTextareaPosition = function() { - this.textarea.style.left = ''; - this.textarea.style.top = ''; -}; - -export { CompositionHelper }; + /** + * Clears the textarea's position so that the cursor does not blink on IE. + * @private + */ + private clearTextareaPosition() { + this.textarea.style.left = ''; + this.textarea.style.top = ''; + }; +} diff --git a/src/Interfaces.ts b/src/Interfaces.ts index 14355e57..55cceb8b 100644 --- a/src/Interfaces.ts +++ b/src/Interfaces.ts @@ -4,11 +4,17 @@ */ export interface ITerminal { + element: HTMLElement; rowContainer: HTMLElement; ydisp: number; lines: string[]; rows: number; + /** + * Emit the 'data' event and populate the given data. + * @param data The data to populate in the event. + */ + handler(data: string); on(event: string, callback: () => void); scrollDisp(disp: number, suppressScrollEvent: boolean); } diff --git a/src/xterm.js b/src/xterm.js index c88423d4..0ef9427d 100644 --- a/src/xterm.js +++ b/src/xterm.js @@ -5129,7 +5129,6 @@ var wcwidth = (function(opts) { */ Terminal.EventEmitter = EventEmitter; -Terminal.CompositionHelper = CompositionHelper; Terminal.Viewport = Viewport; Terminal.inherits = inherits; From f24cba722a2774b1ea6511160ee28bda519a666f Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 22 Nov 2016 11:48:16 -0800 Subject: [PATCH 03/24] Rename composition-helper-test.js -> CompositionHelper.test.ts --- .../composition-helper-test.js => CompositionHelper.test.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{test/composition-helper-test.js => CompositionHelper.test.ts} (100%) diff --git a/src/test/composition-helper-test.js b/src/CompositionHelper.test.ts similarity index 100% rename from src/test/composition-helper-test.js rename to src/CompositionHelper.test.ts From 3638ef808be050aa1ae3e3d5ef1fd6617952f3df Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 22 Nov 2016 11:50:08 -0800 Subject: [PATCH 04/24] tsify CompositionHelper test --- src/CompositionHelper.test.ts | 113 +++++++++++++--------------------- 1 file changed, 43 insertions(+), 70 deletions(-) diff --git a/src/CompositionHelper.test.ts b/src/CompositionHelper.test.ts index 192df05d..f0acd40e 100644 --- a/src/CompositionHelper.test.ts +++ b/src/CompositionHelper.test.ts @@ -1,20 +1,20 @@ -var assert = require('chai').assert; -var Terminal = require('../xterm'); +import { assert } from 'chai'; +import { CompositionHelper } from './CompositionHelper'; -describe('CompositionHelper', function () { +describe('CompositionHelper', () => { var terminal; var compositionHelper; var compositionView; var textarea; var handledText; - beforeEach(function () { + beforeEach(() => { compositionView = { classList: { - add: function () {}, - remove: function () {}, + add: () => {}, + remove: () => {}, }, - getBoundingClientRect: function () { + getBoundingClientRect: () => { return { width: 0 }; }, style: { @@ -32,7 +32,7 @@ describe('CompositionHelper', function () { }; terminal = { element: { - querySelector: function () { + querySelector: () => { return { offsetLeft: 0, offsetTop: 0 }; } }, @@ -41,53 +41,26 @@ describe('CompositionHelper', function () { } }; handledText = ''; - compositionHelper = new Terminal.CompositionHelper(textarea, compositionView, terminal); + compositionHelper = new CompositionHelper(textarea, compositionView, terminal); }); - describe('Public API', function () { - it('should define CompositionHelper.prototype.compositionstart', function () { - assert.isDefined(Terminal.CompositionHelper.prototype.compositionstart); - }); - it('should define CompositionHelper.prototype.compositionupdate', function () { - assert.isDefined(Terminal.CompositionHelper.prototype.compositionupdate); - }); - it('should define CompositionHelper.prototype.compositionend', function () { - assert.isDefined(Terminal.CompositionHelper.prototype.compositionend); - }); - it('should define CompositionHelper.prototype.finalizeComposition', function () { - assert.isDefined(Terminal.CompositionHelper.prototype.finalizeComposition); - }); - it('should define CompositionHelper.prototype.handleAnyTextareaChanges', function () { - assert.isDefined(Terminal.CompositionHelper.prototype.handleAnyTextareaChanges); - }); - it('should define CompositionHelper.prototype.updateCompositionElements', function () { - assert.isDefined(Terminal.CompositionHelper.prototype.updateCompositionElements); - }); - it('should define CompositionHelper.isComposing', function () { - assert.isDefined(compositionHelper.isComposing); - }); - it('should define CompositionHelper.isSendingComposition', function () { - assert.isDefined(compositionHelper.isSendingComposition); - }); - }); - - describe('Input', function () { + describe('Input', () => { it('Should insert simple characters', function (done) { // First character 'ㅇ' compositionHelper.compositionstart(); compositionHelper.compositionupdate({ data: 'ㅇ' }); textarea.value = 'ㅇ'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates compositionHelper.compositionend(); - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates assert.equal(handledText, 'ㅇ'); // Second character 'ㅇ' compositionHelper.compositionstart(); compositionHelper.compositionupdate({ data: 'ㅇ' }); textarea.value = 'ㅇㅇ'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates compositionHelper.compositionend(); - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates assert.equal(handledText, 'ㅇㅇ'); done(); }, 0); @@ -101,29 +74,29 @@ describe('CompositionHelper', function () { compositionHelper.compositionstart(); compositionHelper.compositionupdate({ data: 'ㅇ' }); textarea.value = 'ㅇ'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates compositionHelper.compositionupdate({ data: '아' }); textarea.value = '아'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates compositionHelper.compositionupdate({ data: '앙' }); textarea.value = '앙'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates compositionHelper.compositionend(); - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates assert.equal(handledText, '앙'); // Second character '앙' compositionHelper.compositionstart(); compositionHelper.compositionupdate({ data: 'ㅇ' }); textarea.value = '앙ㅇ'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates compositionHelper.compositionupdate({ data: '아' }); textarea.value = '앙아'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates compositionHelper.compositionupdate({ data: '앙' }); textarea.value = '앙앙'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates compositionHelper.compositionend(); - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates assert.equal(handledText, '앙앙'); done(); }, 0); @@ -141,21 +114,21 @@ describe('CompositionHelper', function () { compositionHelper.compositionstart(); compositionHelper.compositionupdate({ data: 'ㅇ' }); textarea.value = 'ㅇ'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates compositionHelper.compositionupdate({ data: '아' }); textarea.value = '아'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates // Start second character '아' in first character compositionHelper.compositionupdate({ data: '앙' }); textarea.value = '앙'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates compositionHelper.compositionend(); compositionHelper.compositionstart(); compositionHelper.compositionupdate({ data: '아' }); textarea.value = '아아' - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates compositionHelper.compositionend(); - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates assert.equal(handledText, '아아'); done(); }, 0); @@ -170,16 +143,16 @@ describe('CompositionHelper', function () { compositionHelper.compositionstart(); compositionHelper.compositionupdate({ data: 'd' }); textarea.value = 'd'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates compositionHelper.compositionupdate({ data: 'だ' }); textarea.value = 'だ'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates // Second character 'あ' compositionHelper.compositionupdate({ data: 'だあ' }); textarea.value = 'だあ'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates compositionHelper.compositionend(); - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates assert.equal(handledText, 'だあ'); done(); }, 0); @@ -193,20 +166,20 @@ describe('CompositionHelper', function () { compositionHelper.compositionstart(); compositionHelper.compositionupdate({ data: 'd' }); textarea.value = 'd'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates compositionHelper.compositionupdate({ data: 'だ' }); textarea.value = 'だ'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates // Second character 'ー' compositionHelper.compositionupdate({ data: 'だー' }); textarea.value = 'だー'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates // Convert to katakana 'ダー' compositionHelper.compositionupdate({ data: 'ダー' }); textarea.value = 'ダー'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates compositionHelper.compositionend(); - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates assert.equal(handledText, 'ダー'); done(); }, 0); @@ -221,20 +194,20 @@ describe('CompositionHelper', function () { compositionHelper.compositionstart(); compositionHelper.compositionupdate({ data: 'い' }); textarea.value = 'い'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates // Second character 'ま' compositionHelper.compositionupdate({ data: 'いm' }); textarea.value = 'いm'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates compositionHelper.compositionupdate({ data: 'いま' }); textarea.value = 'いま'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates // Convert to kanji '今' compositionHelper.compositionupdate({ data: '今' }); textarea.value = '今'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates compositionHelper.compositionend(); - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates assert.equal(handledText, '今'); done(); }, 0); @@ -249,11 +222,11 @@ describe('CompositionHelper', function () { compositionHelper.compositionstart(); compositionHelper.compositionupdate({ data: 'ㅇ' }); textarea.value = 'ㅇ'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates compositionHelper.compositionend(); // Second character '1' (a non-composition character) textarea.value = 'ㅇ1'; - setTimeout(function() { // wait for any textarea updates + setTimeout(() => { // wait for any textarea updates assert.equal(handledText, 'ㅇ1'); done(); }, 0); From 81dc48ef00090a642bd2541cb89d2f2920a6cb1f Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 22 Nov 2016 11:53:45 -0800 Subject: [PATCH 05/24] Clean up viewport more after TS conversion Part of #335 --- src/Viewport.ts | 10 +++++++--- src/xterm.js | 1 - 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Viewport.ts b/src/Viewport.ts index 11889dae..8a3e4fc0 100644 --- a/src/Viewport.ts +++ b/src/Viewport.ts @@ -8,15 +8,19 @@ import { ITerminal } from './Interfaces'; /** * Represents the viewport of a terminal, the visible area within the larger buffer of output. * Logic for the virtual scroll bar is included in this object. - * @param viewportElement The DOM element acting as the viewport. - * @param scrollArea The DOM element acting as the scroll area. - * @param charMeasureElement A DOM element used to measure the character size of. the terminal. */ export class Viewport { private currentRowHeight: number; private lastRecordedBufferLength: number; private lastRecordedViewportHeight: number; + /** + * Creates a new Viewport. + * @param terminal The terminal this viewport belongs to. + * @param viewportElement The DOM element acting as the viewport. + * @param scrollArea The DOM element acting as the scroll area. + * @param charMeasureElement A DOM element used to measure the character size of. the terminal. + */ constructor( private terminal: ITerminal, private viewportElement: HTMLElement, diff --git a/src/xterm.js b/src/xterm.js index c88423d4..58f305b9 100644 --- a/src/xterm.js +++ b/src/xterm.js @@ -5130,7 +5130,6 @@ var wcwidth = (function(opts) { Terminal.EventEmitter = EventEmitter; Terminal.CompositionHelper = CompositionHelper; -Terminal.Viewport = Viewport; Terminal.inherits = inherits; /** From f75b7db90e7954bc30c057c3995dc2773136cb7d Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 22 Nov 2016 11:54:42 -0800 Subject: [PATCH 06/24] Move CompositionHelper header comment to class --- src/CompositionHelper.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/CompositionHelper.ts b/src/CompositionHelper.ts index 8a29ed72..a7f97ad1 100644 --- a/src/CompositionHelper.ts +++ b/src/CompositionHelper.ts @@ -10,6 +10,11 @@ interface IPosition { end: number; } +/** + * Encapsulates the logic for handling compositionstart, compositionupdate and compositionend + * events, displaying the in-progress composition to the UI and forwarding the final composition + * to the handler. + */ export class CompositionHelper { /** * Whether input composition is currently happening, eg. via a mobile keyboard, speech input or @@ -29,9 +34,7 @@ export class CompositionHelper { private isSendingComposition: boolean; /** - * Encapsulates the logic for handling compositionstart, compositionupdate and compositionend - * events, displaying the in-progress composition to the UI and forwarding the final composition - * to the handler. + * Creates a new CompositionHelper. * @param textarea The textarea that xterm uses for input. * @param compositionView The element to display the in-progress composition in. * @param terminal The Terminal to forward the finished composition to. From 15a94240ebedd0e223b11d945c8e1c7470c6df06 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 26 Nov 2016 14:59:53 -0800 Subject: [PATCH 07/24] Implement ^\ String Terminator Fixes #376 --- src/xterm.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/xterm.js b/src/xterm.js index c88423d4..32e950b9 100644 --- a/src/xterm.js +++ b/src/xterm.js @@ -2724,10 +2724,13 @@ Terminal.prototype.evaluateKeyEscapeSequence = function(ev) { // delete result.key = String.fromCharCode(127); } else if (ev.keyCode === 219) { - // ^[ - escape + // ^[ - Control Sequence Introducer (CSI) result.key = String.fromCharCode(27); + } else if (ev.keyCode === 220) { + // ^\ - String Terminator (ST) + result.key = String.fromCharCode(28); } else if (ev.keyCode === 221) { - // ^] - group sep + // ^] - Operating System Command (OSC) result.key = String.fromCharCode(29); } } else if (!this.browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) { From 3b2e89d87811f983852665970ba29568663a877b Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 27 Nov 2016 01:49:45 -0800 Subject: [PATCH 08/24] Only scroll to bottom during composition or result.key is evaluated Fixes #378 --- src/test/test.js | 3 ++- src/utils/Keyboard.test.ts | 21 --------------------- src/utils/Keyboard.ts | 22 ---------------------- src/xterm.js | 13 ++++++++----- 4 files changed, 10 insertions(+), 49 deletions(-) delete mode 100644 src/utils/Keyboard.test.ts delete mode 100644 src/utils/Keyboard.ts diff --git a/src/test/test.js b/src/test/test.js index abdc8c17..d8e931fb 100644 --- a/src/test/test.js +++ b/src/test/test.js @@ -189,7 +189,7 @@ describe('xterm.js', function() { it('should scroll down, when a key is pressed and terminal is scrolled up', function () { // Override evaluateKeyEscapeSequence to return cancel code xterm.evaluateKeyEscapeSequence = function() { - return { cancel: true }; + return { key: 'a' }; }; var event = { type: 'keydown', @@ -200,6 +200,7 @@ describe('xterm.js', function() { xterm.ydisp = 0; xterm.ybase = 40; + assert.notEqual(xterm.ydisp, xterm.ybase); xterm.keyDown(event); // Ensure that now the terminal is scrolled to bottom diff --git a/src/utils/Keyboard.test.ts b/src/utils/Keyboard.test.ts deleted file mode 100644 index 618d3331..00000000 --- a/src/utils/Keyboard.test.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { assert } from 'chai'; -import * as Keyboard from './Keyboard'; - -describe('Keyboard', () => { - describe('isModifierOnlyKeyboardEvent', () => { - it('should return true when only modifier keys are used', () => { - // Note that KeyboardEvent.keyCode is deprecated but we're using it to improve browser - // compatibility. This helper returns the `any` type because KeyboardEvent doesn't exist under - // NodeJS. - function createEvent(keyCode: number): any { - return { keyCode }; - } - assert.isTrue(Keyboard.isModifierOnlyKeyboardEvent(createEvent(16))); - assert.isTrue(Keyboard.isModifierOnlyKeyboardEvent(createEvent(17))); - assert.isTrue(Keyboard.isModifierOnlyKeyboardEvent(createEvent(18))); - assert.isTrue(Keyboard.isModifierOnlyKeyboardEvent(createEvent(91))); - assert.isFalse(Keyboard.isModifierOnlyKeyboardEvent(createEvent(19))); - assert.isFalse(Keyboard.isModifierOnlyKeyboardEvent(createEvent(90))); - }); - }); -}); diff --git a/src/utils/Keyboard.ts b/src/utils/Keyboard.ts deleted file mode 100644 index e43cba45..00000000 --- a/src/utils/Keyboard.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * xterm.js: xterm, in the browser - * Copyright (c) 2016, SourceLair Private Company (MIT License) - */ - -/** - * Keyboard utilities module. This module contains utilities for dealing with keyboard interaction. - * @module xterm/utils/Keyboard - */ - -/** - * Gets whether a KeyboardEvent is made up entirely of modifier keys. - * - * @param event The event to check. - * @return Whether the KeyboardEvent is made up entirely of modifier keys. - */ -export function isModifierOnlyKeyboardEvent(event: KeyboardEvent): boolean { - return event.keyCode === 16 || // Shift - event.keyCode === 17 || // Control - event.keyCode === 18 || // Alt - event.keyCode === 91; // Meta -} diff --git a/src/xterm.js b/src/xterm.js index c88423d4..4d65dfe9 100644 --- a/src/xterm.js +++ b/src/xterm.js @@ -2430,12 +2430,10 @@ Terminal.prototype.keyDown = function(ev) { return false; } - // Scroll down to prompt, whenever the user presses a key. - if (!Keyboard.isModifierOnlyKeyboardEvent(ev) && this.ybase !== this.ydisp) { - this.scrollToBottom(); - } - if (!this.compositionHelper.keydown.bind(this.compositionHelper)(ev)) { + if (this.ybase !== this.ydisp) { + this.scrollToBottom(); + } return false; } @@ -2460,6 +2458,11 @@ Terminal.prototype.keyDown = function(ev) { return true; } + // Scroll down to prompt, whenever the user presses a key. + if (this.ybase !== this.ydisp) { + this.scrollToBottom(); + } + this.emit('keydown', ev); this.emit('key', result.key, ev); this.showCursor(); From 2bc8adee8c3cce6c96cd9b74e235964735837c14 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 28 Nov 2016 10:41:03 -0800 Subject: [PATCH 09/24] Scroll to bottom whenever handler is called This catches all current and future cases for correctly scrolling to the bottom on input by handling it in the handler immediately before emitting the data event. Fixes #378 --- src/xterm.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/xterm.js b/src/xterm.js index 752d832c..e6482c4d 100644 --- a/src/xterm.js +++ b/src/xterm.js @@ -2458,11 +2458,6 @@ Terminal.prototype.keyDown = function(ev) { return true; } - // Scroll down to prompt, whenever the user presses a key. - if (this.ybase !== this.ydisp) { - this.scrollToBottom(); - } - this.emit('keydown', ev); this.emit('key', result.key, ev); this.showCursor(); @@ -3153,6 +3148,10 @@ Terminal.prototype.is = function(term) { * @param {string} data The data to populate in the event. */ Terminal.prototype.handler = function(data) { + // Input is being sent to the terminal, the terminal should focus the prompt. + if (this.ybase !== this.ydisp) { + this.scrollToBottom(); + } this.emit('data', data); }; From 5cbc2f0ea5eb353fd0c9b6ba89425fbd6bcd2b92 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 28 Nov 2016 10:46:19 -0800 Subject: [PATCH 10/24] Add link to TravisCI badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ce032509..f7e96c2a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # xterm.js -![xterm.js build status](https://api.travis-ci.org/sourcelair/xterm.js.svg) [![Gitter](https://badges.gitter.im/sourcelair/xterm.js.svg)](https://gitter.im/sourcelair/xterm.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) +[![xterm.js build status](https://api.travis-ci.org/sourcelair/xterm.js.svg)](https://travis-ci.org/sourcelair/xterm.js) [![Gitter](https://badges.gitter.im/sourcelair/xterm.js.svg)](https://gitter.im/sourcelair/xterm.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) Xterm.js is a terminal front-end component written in JavaScript that works in the browser. From 83b06c6bb0b13fc46064fbd90f66d8ecc7b3c397 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 28 Nov 2016 10:52:01 -0800 Subject: [PATCH 11/24] Clean out/* on build in case src/* files were deleted If files in src/ were compiled and then deleted they will hang around in out/ until deleted. This can potentially cause difficult to diagnose build/test errors. This commit removes all files from out/ but keeps the folder to prevent editor file watchers from seeing the folder was deleted and shifting the file explorer around. Fixed #381 --- bin/build | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bin/build b/bin/build index d1b403d2..36a6cf25 100755 --- a/bin/build +++ b/bin/build @@ -1,5 +1,8 @@ #! /usr/bin/env bash +# Clean out/* to prevent confusion if files were deleted in src/ +rm -rf out/* + # Build all TypeScript files (including tests) to out/ tsc From 1d300911887d3bfa354d42e2cf1cd8a4023d8d4d Mon Sep 17 00:00:00 2001 From: Paris Kasidiaris Date: Thu, 1 Dec 2016 15:35:23 +0200 Subject: [PATCH 12/24] Update documentation with cleaner license declaration Fix #366 --- jsdoc.json | 13 ++++++------- package.json | 2 +- src/CompositionHelper.ts | 3 +-- src/EventEmitter.js | 3 +-- src/Interfaces.ts | 3 +-- src/Viewport.ts | 3 +-- src/addons/attach/attach.js | 16 ++++------------ src/addons/fit/fit.js | 25 ++++++++++--------------- src/addons/fullscreen/fullscreen.js | 18 ++++++++---------- src/addons/linkify/linkify.js | 12 ++++++------ src/addons/terminado/terminado.js | 15 ++++----------- src/handlers/Clipboard.js | 10 +++------- src/utils/Browser.js | 9 ++------- src/utils/Generic.js | 9 ++------- src/xterm.js | 23 +---------------------- 15 files changed, 51 insertions(+), 113 deletions(-) diff --git a/jsdoc.json b/jsdoc.json index 6879aa2b..cd864c89 100644 --- a/jsdoc.json +++ b/jsdoc.json @@ -1,13 +1,12 @@ { "source": { "include": [ - "src/xterm.js", - "src/handlers/Clipboard.js", - "addons/attach/attach.js", - "addons/fit/fit.js", - "addons/fullscreen/fullscreen.js", - "addons/linkify/linkify.js" - ] + "src/" + ], + "exclude": [ + "src/test/" + ], + "excludePattern": "src/.+\\.test\\.(js|ts)$" }, "opts": { "readme": "README.md", diff --git a/package.json b/package.json index 0c338451..c7356a1a 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "express": "4.13.4", "express-ws": "2.0.0-rc.1", "glob": "^7.0.5", - "jsdoc": "3.4.0", + "jsdoc": "3.4.3", "mocha": "2.5.3", "nodemon": "1.10.2", "pty.js": "0.3.1", diff --git a/src/CompositionHelper.ts b/src/CompositionHelper.ts index a7f97ad1..21c0a9e9 100644 --- a/src/CompositionHelper.ts +++ b/src/CompositionHelper.ts @@ -1,6 +1,5 @@ /** - * xterm.js: xterm, in the browser - * Copyright (c) 2014-2016, SourceLair Private Company (www.sourcelair.com (MIT License) + * @license MIT */ import { ITerminal } from './Interfaces'; diff --git a/src/EventEmitter.js b/src/EventEmitter.js index cb43818e..36618948 100644 --- a/src/EventEmitter.js +++ b/src/EventEmitter.js @@ -1,6 +1,5 @@ /** - * xterm.js: xterm, in the browser - * Copyright (c) 2014-2016, SourceLair Private Company (www.sourcelair.com (MIT License) + * @license MIT */ function EventEmitter() { diff --git a/src/Interfaces.ts b/src/Interfaces.ts index 55cceb8b..db1b622a 100644 --- a/src/Interfaces.ts +++ b/src/Interfaces.ts @@ -1,6 +1,5 @@ /** - * xterm.js: xterm, in the browser - * Copyright (c) 2014-2016, SourceLair Private Company (www.sourcelair.com (MIT License) + * @license MIT */ export interface ITerminal { diff --git a/src/Viewport.ts b/src/Viewport.ts index 8a3e4fc0..3aa1319f 100644 --- a/src/Viewport.ts +++ b/src/Viewport.ts @@ -1,6 +1,5 @@ /** - * xterm.js: xterm, in the browser - * Copyright (c) 2014-2016, SourceLair Private Company (www.sourcelair.com (MIT License) + * @license MIT */ import { ITerminal } from './Interfaces'; diff --git a/src/addons/attach/attach.js b/src/addons/attach/attach.js index 769a7e53..c2a7989b 100644 --- a/src/addons/attach/attach.js +++ b/src/addons/attach/attach.js @@ -1,9 +1,7 @@ -/* - * Implements the attach method, that - * attaches the terminal to a WebSocket stream. - * - * The bidirectional argument indicates, whether the terminal should - * send data to the socket as well and is true, by default. +/** + * Implements the attach method, that attaches the terminal to a WebSocket stream. + * @module xterm/addons/attach/attach + * @license MIT */ (function (attach) { @@ -26,12 +24,6 @@ })(function (Xterm) { 'use strict'; - /** - * This module provides methods for attaching a terminal to a WebSocket - * stream. - * - * @module xterm/addons/attach/attach - */ var exports = {}; /** diff --git a/src/addons/fit/fit.js b/src/addons/fit/fit.js index 7e24fd9b..7b0ac14f 100644 --- a/src/addons/fit/fit.js +++ b/src/addons/fit/fit.js @@ -1,16 +1,16 @@ -/* - * Fit terminal columns and rows to the dimensions of its - * DOM element. +/** + * Fit terminal columns and rows to the dimensions of its DOM element. * - * Approach: - * - Rows: Truncate the division of the terminal parent element height - * by the terminal row height + * ## Approach + * - Rows: Truncate the division of the terminal parent element height by the terminal row height. * - * - Columns: Truncate the division of the terminal parent element width by - * the terminal character width (apply display: inline at the - * terminal row and truncate its width with the current number - * of columns) + * - Columns: Truncate the division of the terminal parent element width by the terminal character + * width (apply display: inline at the terminal row and truncate its width with the current + * number of columns). + * @module xterm/addons/fit/fit + * @license MIT */ + (function (fit) { if (typeof exports === 'object' && typeof module === 'object') { /* @@ -29,11 +29,6 @@ fit(window.Terminal); } })(function (Xterm) { - /** - * This module provides methods for fitting a terminal's size to a parent container. - * - * @module xterm/addons/fit/fit - */ var exports = {}; exports.proposeGeometry = function (term) { diff --git a/src/addons/fullscreen/fullscreen.js b/src/addons/fullscreen/fullscreen.js index e4098f48..e8e34ea3 100644 --- a/src/addons/fullscreen/fullscreen.js +++ b/src/addons/fullscreen/fullscreen.js @@ -1,14 +1,7 @@ -/* +/** * Fullscreen addon for xterm.js - * - * Implements the toggleFullscreen function. - * - * If the `fullscreen` argument has been supplied, then - * if it is true, the fullscreen mode gets turned on, - * if it is false or null, the fullscreen mode gets turned off. - * - * If the `fullscreen` argument has not been supplied, the - * fullscreen mode is being toggled. + * @module xterm/addons/fullscreen/fullscreen + * @license MIT */ (function (fullscreen) { if (typeof exports === 'object' && typeof module === 'object') { @@ -30,6 +23,11 @@ })(function (Xterm) { var exports = {}; + /** + * Toggle the given terminal's fullscreen mode. + * @param {Xterm} term - The terminal to toggle full screen mode + * @param {boolean} fullscreen - Toggle fullscreen on (true) or off (false) + */ exports.toggleFullScreen = function (term, fullscreen) { var fn; diff --git a/src/addons/linkify/linkify.js b/src/addons/linkify/linkify.js index 2140c0aa..d2391026 100644 --- a/src/addons/linkify/linkify.js +++ b/src/addons/linkify/linkify.js @@ -1,3 +1,9 @@ +/** + * Methods for turning URL subscrings in the terminal's content into links (`a` DOM elements). + * @module xterm/addons/linkify/linkify + * @license MIT + */ + (function (linkify) { if (typeof exports === 'object' && typeof module === 'object') { /* @@ -18,12 +24,6 @@ })(function (Xterm) { 'use strict'; - /** - * This module provides methods for convertings valid URL substrings - * into HTML anchor elements (links), inside a terminal view. - * - * @module xterm/addons/linkify/linkify - */ var exports = {}, protocolClause = '(https?:\\/\\/)', domainCharacterSet = '[\\da-z\\.-]+', diff --git a/src/addons/terminado/terminado.js b/src/addons/terminado/terminado.js index e17a188a..86e6ea2e 100644 --- a/src/addons/terminado/terminado.js +++ b/src/addons/terminado/terminado.js @@ -1,9 +1,8 @@ -/* - * Implements the attach method that - * attaches the terminal to a Terminado WebSocket stream. +/** + * This module provides methods for attaching a terminal to a terminado WebSocket stream. * - * The bidirectional argument indicates, whether the terminal should - * send data to the socket as well and is true, by default. + * @module xterm/addons/terminado/terminado + * @license MIT */ (function (attach) { @@ -26,12 +25,6 @@ })(function (Xterm) { 'use strict'; - /** - * This module provides methods for attaching a terminal to a WebSocket - * stream. - * - * @module xterm/addons/attach/attach - */ var exports = {}; /** diff --git a/src/handlers/Clipboard.js b/src/handlers/Clipboard.js index 1cb07ebb..70c625e4 100644 --- a/src/handlers/Clipboard.js +++ b/src/handlers/Clipboard.js @@ -1,12 +1,8 @@ /** - * xterm.js: xterm, in the browser - * Copyright (c) 2016, SourceLair Private Company (MIT License) - */ - -/** - * Clipboard handler module. This module contains methods for handling all - * clipboard-related events appropriately in the terminal. + * Clipboard handler module: exports methods for handling all clipboard-related events in the + * terminal. * @module xterm/handlers/Clipboard + * @license MIT */ /** diff --git a/src/utils/Browser.js b/src/utils/Browser.js index 47b756ec..cd13e027 100644 --- a/src/utils/Browser.js +++ b/src/utils/Browser.js @@ -1,12 +1,7 @@ /** - * xterm.js: xterm, in the browser - * Copyright (c) 2016, SourceLair Private Company (MIT License) - */ - -/** - * Browser utilities module. This module contains attributes and methods to help with - * identifying the current browser and platform. + * Attributes and methods to help with identifying the current browser and platform. * @module xterm/utils/Browser + * @license MIT */ import { contains } from './Generic.js'; diff --git a/src/utils/Generic.js b/src/utils/Generic.js index 9e48a721..42f876f3 100644 --- a/src/utils/Generic.js +++ b/src/utils/Generic.js @@ -1,12 +1,7 @@ /** - * xterm.js: xterm, in the browser - * Copyright (c) 2016, SourceLair Private Company (MIT License) - */ - -/** - * Generic utilities module. This module contains generic methods that can be helpful at - * different parts of the code base. + * Generic utilities module with methods that can be helpful at different parts of the code base. * @module xterm/utils/Generic + * @license MIT */ /** diff --git a/src/xterm.js b/src/xterm.js index e6482c4d..7f1bf63c 100644 --- a/src/xterm.js +++ b/src/xterm.js @@ -1,27 +1,5 @@ /** * xterm.js: xterm, in the browser - * Copyright (c) 2014-2014, SourceLair Private Company (MIT License) - * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License) - * https://github.com/chjj/term.js - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * * Originally forked from (with the author's permission): * Fabrice Bellard's javascript vt100 for jslinux: * http://bellard.org/jslinux/ @@ -29,6 +7,7 @@ * The original design remains. The terminal itself * has been extended to include xterm CSI codes, among * other features. + * @license MIT */ import { CompositionHelper } from './CompositionHelper.js'; From 6cc66a0b2010f8395819826d027995861a34642c Mon Sep 17 00:00:00 2001 From: Paris Kasidiaris Date: Mon, 5 Dec 2016 13:17:13 +0200 Subject: [PATCH 13/24] Bring back the `build` directory for temporary builds Fix #375 --- .gitignore | 2 +- bin/build | 27 ++++++++++++++++----------- demo/app.js | 2 +- demo/index.html | 12 ++++++------ 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index efa028b6..47a3aa85 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,4 @@ docs/ npm-debug.log /.idea/ .env -dist/* +build/ diff --git a/bin/build b/bin/build index 36a6cf25..126392ab 100755 --- a/bin/build +++ b/bin/build @@ -1,26 +1,31 @@ #! /usr/bin/env bash +set -e + +# $BUILD_DIR should default to "build" +export BUILD_DIR=${BUILD_DIR:=build} + # Clean out/* to prevent confusion if files were deleted in src/ rm -rf out/* # Build all TypeScript files (including tests) to out/ tsc -# Concat all xterm.js files into a single file and output as a UMD to dist/xterm.js -browserify ./out/xterm.js --standalone Terminal --debug --outfile ./dist/xterm.js -cat ./dist/xterm.js | exorcist ./dist/xterm.js.map -b ./dist > ./dist/xterm.temp.js -rm ./dist/xterm.js -mv ./dist/xterm.temp.js ./dist/xterm.js +# Concat all xterm.js files into a single file and output as a UMD to $BUILD_DIR/xterm.js +browserify ./out/xterm.js --standalone Terminal --debug --outfile ./$BUILD_DIR/xterm.js +cat ./$BUILD_DIR/xterm.js | exorcist ./$BUILD_DIR/xterm.js.map -b ./$BUILD_DIR > ./$BUILD_DIR/xterm.temp.js +rm ./$BUILD_DIR/xterm.js +mv ./$BUILD_DIR/xterm.temp.js ./$BUILD_DIR/xterm.js -# Resolve the chain of sourcemaps so that ./dist/xterm.js.map points at ./src -sorcery -i dist/xterm.js +# Resolve the chain of sourcemaps so that ./$BUILD_DIR/xterm.js.map points at ./src +sorcery -i $BUILD_DIR/xterm.js -# Copy all CSS files from src/ to dist/ +# Copy all CSS files from src/ to $BUILD_DIR/ cd src -find . -name '*.css' | cpio -pdm ../dist +find . -name '*.css' | cpio -pdm ../$BUILD_DIR cd .. -# Copy addons from out/ to dist/ +# Copy addons from out/ to $BUILD_DIR/ cd out/addons -find . -name '*.js' | cpio -pdm ../../dist/addons +find . -name '*.js' | cpio -pdm ../../$BUILD_DIR/addons cd ../.. diff --git a/demo/app.js b/demo/app.js index bdedc3be..a4122ace 100644 --- a/demo/app.js +++ b/demo/app.js @@ -7,7 +7,7 @@ var pty = require('pty.js'); var terminals = {}, logs = {}; -app.use('/dist', express.static(__dirname + '/../dist')); +app.use('/build', express.static(__dirname + '/../build')); app.get('/', function(req, res){ res.sendFile(__dirname + '/index.html'); diff --git a/demo/index.html b/demo/index.html index 5391735d..285fe002 100644 --- a/demo/index.html +++ b/demo/index.html @@ -2,14 +2,14 @@ xterm.js demo - - + + - - - - + + + +

xterm.js: xterm, in the browser

From 243d76617b88a9bdf43ceb15ac14ec56b4c3e974 Mon Sep 17 00:00:00 2001 From: Paris Kasidiaris Date: Mon, 5 Dec 2016 13:34:10 +0200 Subject: [PATCH 14/24] Create the build directory if it does not exist already --- bin/build | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bin/build b/bin/build index 126392ab..123bbd51 100755 --- a/bin/build +++ b/bin/build @@ -5,6 +5,10 @@ set -e # $BUILD_DIR should default to "build" export BUILD_DIR=${BUILD_DIR:=build} +# Create the build directory +mkdir -p $BUILD_DIR + + # Clean out/* to prevent confusion if files were deleted in src/ rm -rf out/* From 55314e0fc7196d85dca1ce70fb130a59d2cfc447 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 5 Dec 2016 11:19:35 -0800 Subject: [PATCH 15/24] Position the textarea at top:0 This prevents the browser from scrolling to the top of the page if the terminal can be scrolled out of view. Fixes #357 --- src/xterm.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xterm.css b/src/xterm.css index b30d7b49..4877f86e 100644 --- a/src/xterm.css +++ b/src/xterm.css @@ -61,7 +61,7 @@ position: absolute; opacity: 0; left: -9999em; - top: -9999em; + top: 0; width: 0; height: 0; z-index: -10; From 70ec2496db151df21f704889163b0bdf692a566d Mon Sep 17 00:00:00 2001 From: Paris Kasidiaris Date: Mon, 5 Dec 2016 21:29:50 +0200 Subject: [PATCH 16/24] Remove `export` from build script --- bin/build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/build b/bin/build index 123bbd51..2def2c2b 100755 --- a/bin/build +++ b/bin/build @@ -3,7 +3,7 @@ set -e # $BUILD_DIR should default to "build" -export BUILD_DIR=${BUILD_DIR:=build} +BUILD_DIR=${BUILD_DIR:=build} # Create the build directory mkdir -p $BUILD_DIR From c9eaae6bd5bc57e5da4a8e6f4f249cd2cea043fc Mon Sep 17 00:00:00 2001 From: Paris Kasidiaris Date: Tue, 6 Dec 2016 10:55:40 +0200 Subject: [PATCH 17/24] Update path to addons in README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f7e96c2a..3fd3d884 100644 --- a/README.md +++ b/README.md @@ -54,13 +54,13 @@ Then open http://0.0.0.0:3000 in a web browser (use http://127.0.0.1:3000 if run ## Addons -Addons are JavaScript modules that attach functions to the `Terminal` prototype to extend its functionality. There are a handful available in the main repository in the `addons` directory, you can even write your own (though they may break when the internals of xterm.js change across versions). +Addons are JavaScript modules that attach functions to the `Terminal` prototype to extend its functionality. There are a handful available in the main repository in the `dist/addons` directory, you can even write your own (though they may break when the internals of xterm.js change across versions). To use an addon, just include the JavaScript file after xterm.js and before the `Terminal` object has been instantiated. The function should then be exposed on the `Terminal` object: ```html - + ``` ```js From 824a9c6dbf12dd29685b63bee8899601308fe89c Mon Sep 17 00:00:00 2001 From: Paris Kasidiaris Date: Tue, 6 Dec 2016 11:45:02 +0200 Subject: [PATCH 18/24] Migrate Clipboard handler to TypeScript Also apply JavaScript rules in `.editorconfig` in TypeScript files as well. Part of #335 --- .editorconfig | 2 +- src/Interfaces.ts | 15 +++++ .../Clipboard.test.ts} | 6 +- src/handlers/{Clipboard.js => Clipboard.ts} | 55 +++++++++++-------- 4 files changed, 52 insertions(+), 26 deletions(-) rename src/{test/clipboard-test.js => handlers/Clipboard.test.ts} (81%) rename src/handlers/{Clipboard.js => Clipboard.ts} (74%) diff --git a/.editorconfig b/.editorconfig index f2aa1a38..ae59e935 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,7 +6,7 @@ indent_size = 2 insert_final_newline = true trim_trailing_whitespace = true -[*.js] +[*.{j,t}s] max_line_length = 100 [*.css] diff --git a/src/Interfaces.ts b/src/Interfaces.ts index db1b622a..ff7bbef2 100644 --- a/src/Interfaces.ts +++ b/src/Interfaces.ts @@ -2,12 +2,26 @@ * @license MIT */ +export interface IBrowser { + isNode: boolean; + userAgent: string; + platform: string; + isFirefox: boolean; + isMSIE: boolean; + isMac: boolean; + isIpad: boolean; + isIphone: boolean; + isMSWindows: boolean; +} + export interface ITerminal { element: HTMLElement; rowContainer: HTMLElement; + textarea: HTMLTextAreaElement; ydisp: number; lines: string[]; rows: number; + browser: IBrowser; /** * Emit the 'data' event and populate the given data. @@ -16,4 +30,5 @@ export interface ITerminal { handler(data: string); on(event: string, callback: () => void); scrollDisp(disp: number, suppressScrollEvent: boolean); + cancel(ev: Event, force?: boolean); } diff --git a/src/test/clipboard-test.js b/src/handlers/Clipboard.test.ts similarity index 81% rename from src/test/clipboard-test.js rename to src/handlers/Clipboard.test.ts index 12eeb517..3302cb6c 100644 --- a/src/test/clipboard-test.js +++ b/src/handlers/Clipboard.test.ts @@ -1,6 +1,6 @@ -var assert = require('chai').assert; -var Terminal = require('../xterm'); -var Clipboard = require('../handlers/Clipboard'); +import { assert } from 'chai'; +import * as Terminal from '../xterm'; +import * as Clipboard from './Clipboard'; describe('evaluateCopiedTextProcessing', function () { diff --git a/src/handlers/Clipboard.js b/src/handlers/Clipboard.ts similarity index 74% rename from src/handlers/Clipboard.js rename to src/handlers/Clipboard.ts index 70c625e4..825023f0 100644 --- a/src/handlers/Clipboard.js +++ b/src/handlers/Clipboard.ts @@ -5,6 +5,15 @@ * @license MIT */ +import { ITerminal } from '../Interfaces'; + +// We are extending the ClipboardEvent interface, since TypeScript has not declared the +// clientX and clientY properties that we use. +interface IClipboardEvent extends ClipboardEvent { + clientX: number; + clientY: number; +} + /** * Prepares text copied from terminal selection, to be saved in the clipboard by: * 1. stripping all trailing white spaces @@ -12,14 +21,14 @@ * @param {string} text The copied text that needs processing for storing in clipboard * @returns {string} */ -function prepareTextForClipboard(text) { - var space = String.fromCharCode(32), +export function prepareTextForClipboard(text: string) { + let space = String.fromCharCode(32), nonBreakingSpace = String.fromCharCode(160), allNonBreakingSpaces = new RegExp(nonBreakingSpace, 'g'), processedText = text.split('\n').map(function (line) { // Strip all trailing white spaces and convert all non-breaking spaces // to regular spaces. - var processedLine = line.replace(/\s+$/g, '').replace(allNonBreakingSpaces, space); + let processedLine = line.replace(/\s+$/g, '').replace(allNonBreakingSpaces, space); return processedLine; }).join('\n'); @@ -31,12 +40,15 @@ function prepareTextForClipboard(text) { * Binds copy functionality to the given terminal. * @param {ClipboardEvent} ev The original copy event to be handled */ -function copyHandler(ev, term) { - var copiedText = window.getSelection().toString(), +export function copyHandler(ev: IClipboardEvent, term: ITerminal) { + // We cast `window` to `any` type, because TypeScript has not declared the `clipboardData` + // property that we use below for Internet Explorer. + let w = window, + copiedText = w.getSelection().toString(), text = prepareTextForClipboard(copiedText); if (term.browser.isMSIE) { - window.clipboardData.setData('Text', text); + w.clipboardData.setData('Text', text); } else { ev.clipboardData.setData('text/plain', text); } @@ -49,23 +61,26 @@ function copyHandler(ev, term) { * @param {ClipboardEvent} ev The original paste event to be handled * @param {Terminal} term The terminal on which to apply the handled paste event */ -function pasteHandler(ev, term) { +export function pasteHandler(ev: IClipboardEvent, term: ITerminal) { ev.stopPropagation(); - var dispatchPaste = function(text) { + let w = window, + text: string; + + let dispatchPaste = function(text) { term.handler(text); term.textarea.value = ''; return term.cancel(ev); }; if (term.browser.isMSIE) { - if (window.clipboardData) { - var text = window.clipboardData.getData('Text'); + if (w.clipboardData) { + text = w.clipboardData.getData('Text'); dispatchPaste(text); } } else { if (ev.clipboardData) { - var text = ev.clipboardData.getData('text/plain'); + text = ev.clipboardData.getData('text/plain'); dispatchPaste(text); } } @@ -84,16 +99,16 @@ function pasteHandler(ev, term) { * @param {ClipboardEvent} ev The original paste event to be handled * @param {Terminal} term The terminal on which to apply the handled paste event */ -function rightClickHandler(ev, term) { - var s = document.getSelection(), +export function rightClickHandler(ev: IClipboardEvent, term: ITerminal) { + let s = document.getSelection(), selectedText = prepareTextForClipboard(s.toString()), - clickIsOnSelection = false; + clickIsOnSelection = false, + x = ev.clientX, + y = ev.clientY; if (s.rangeCount) { - var r = s.getRangeAt(0), + let r = s.getRangeAt(0), cr = r.getClientRects(), - x = ev.clientX, - y = ev.clientY, i, rect; for (i=0; i Date: Wed, 7 Dec 2016 00:07:50 +0200 Subject: [PATCH 19/24] Improve interfaces in Clipboard.ts --- src/handlers/Clipboard.ts | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/handlers/Clipboard.ts b/src/handlers/Clipboard.ts index 825023f0..db528f9d 100644 --- a/src/handlers/Clipboard.ts +++ b/src/handlers/Clipboard.ts @@ -14,6 +14,15 @@ interface IClipboardEvent extends ClipboardEvent { clientY: number; } +interface IWindow extends Window { + clipboardData?: { + getData(format: string): string; + setData(format: string, data: string); + }; +} + +declare var window: IWindow; + /** * Prepares text copied from terminal selection, to be saved in the clipboard by: * 1. stripping all trailing white spaces @@ -21,7 +30,7 @@ interface IClipboardEvent extends ClipboardEvent { * @param {string} text The copied text that needs processing for storing in clipboard * @returns {string} */ -export function prepareTextForClipboard(text: string) { +export function prepareTextForClipboard(text: string): string { let space = String.fromCharCode(32), nonBreakingSpace = String.fromCharCode(160), allNonBreakingSpaces = new RegExp(nonBreakingSpace, 'g'), @@ -43,12 +52,11 @@ export function prepareTextForClipboard(text: string) { export function copyHandler(ev: IClipboardEvent, term: ITerminal) { // We cast `window` to `any` type, because TypeScript has not declared the `clipboardData` // property that we use below for Internet Explorer. - let w = window, - copiedText = w.getSelection().toString(), + let copiedText = window.getSelection().toString(), text = prepareTextForClipboard(copiedText); if (term.browser.isMSIE) { - w.clipboardData.setData('Text', text); + window.clipboardData.setData('Text', text); } else { ev.clipboardData.setData('text/plain', text); } @@ -64,8 +72,7 @@ export function copyHandler(ev: IClipboardEvent, term: ITerminal) { export function pasteHandler(ev: IClipboardEvent, term: ITerminal) { ev.stopPropagation(); - let w = window, - text: string; + let text: string; let dispatchPaste = function(text) { term.handler(text); @@ -74,8 +81,8 @@ export function pasteHandler(ev: IClipboardEvent, term: ITerminal) { }; if (term.browser.isMSIE) { - if (w.clipboardData) { - text = w.clipboardData.getData('Text'); + if (window.clipboardData) { + text = window.clipboardData.getData('Text'); dispatchPaste(text); } } else { From cd70d298fcddcdd7e898002d1f09b824bd7f2f14 Mon Sep 17 00:00:00 2001 From: Paris Kasidiaris Date: Wed, 7 Dec 2016 18:41:37 +0000 Subject: [PATCH 20/24] Bump version to 2.2.0 Signed-off-by: Paris Kasidiaris --- AUTHORS | 2 + bower.json | 2 +- dist/xterm.css | 2 +- dist/xterm.js | 5824 ++++++++++++++++++++++++++++++++++----------- dist/xterm.js.map | 28 +- package.json | 2 +- 6 files changed, 4379 insertions(+), 1481 deletions(-) diff --git a/AUTHORS b/AUTHORS index 34402484..8de24580 100644 --- a/AUTHORS +++ b/AUTHORS @@ -24,6 +24,8 @@ Mikko Karvonen Paris Kasidiaris Paris Kasidiaris runarberg +Shuanglei Tao Steven Silvester Thanasis Daglis Tine Jozelj +YuviPanda diff --git a/bower.json b/bower.json index 0e2b4d34..4bb8b471 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "xterm.js", - "version": "2.1.0", + "version": "2.2.0", "ignore": ["demo", "test", ".gitignore"], "main": [ "dist/xterm.js", diff --git a/dist/xterm.css b/dist/xterm.css index b30d7b49..4877f86e 100644 --- a/dist/xterm.css +++ b/dist/xterm.css @@ -61,7 +61,7 @@ position: absolute; opacity: 0; left: -9999em; - top: -9999em; + top: 0; width: 0; height: 0; z-index: -10; diff --git a/dist/xterm.js b/dist/xterm.js index 11ce3c73..6795752c 100644 --- a/dist/xterm.js +++ b/dist/xterm.js @@ -1,433 +1,385 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Terminal = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) { - self.terminal.handler(diff); - } - } - }, 0); -}; - -/** - * Positions the composition view on top of the cursor and the textarea just below it (so the - * IME helper dialog is positioned correctly). - */ -CompositionHelper.prototype.updateCompositionElements = function (dontRecurse) { - if (!this.isComposing) { - return; - } - var cursor = this.terminal.element.querySelector('.terminal-cursor'); - if (cursor) { - // Take .xterm-rows offsetTop into account as well in case it's positioned absolutely within - // the .xterm element. - var xtermRows = this.terminal.element.querySelector('.xterm-rows'); - var cursorTop = xtermRows.offsetTop + cursor.offsetTop; - - this.compositionView.style.left = cursor.offsetLeft + 'px'; - this.compositionView.style.top = cursorTop + 'px'; - this.compositionView.style.height = cursor.offsetHeight + 'px'; - this.compositionView.style.lineHeight = cursor.offsetHeight + 'px'; - // Sync the textarea to the exact position of the composition view so the IME knows where the - // text is. - var compositionViewBounds = this.compositionView.getBoundingClientRect(); - this.textarea.style.left = cursor.offsetLeft + 'px'; - this.textarea.style.top = cursorTop + 'px'; - this.textarea.style.width = compositionViewBounds.width + 'px'; - this.textarea.style.height = compositionViewBounds.height + 'px'; - this.textarea.style.lineHeight = compositionViewBounds.height + 'px'; - } - if (!dontRecurse) { - setTimeout(this.updateCompositionElements.bind(this, true), 0); - } -}; - -/** - * Clears the textarea's position so that the cursor does not blink on IE. - * @private - */ -CompositionHelper.prototype.clearTextareaPosition = function () { - this.textarea.style.left = ''; - this.textarea.style.top = ''; -}; - + if (ev.keyCode === 229) { + // If the "composition character" is used but gets to this point it means a non-composition + // character (eg. numbers and punctuation) was pressed when the IME was active. + this.handleAnyTextareaChanges(); + return false; + } + return true; + }; + /** + * Finalizes the composition, resuming regular input actions. This is called when a composition + * is ending. + * @param waitForPropogation Whether to wait for events to propogate before sending + * the input. This should be false if a non-composition keystroke is entered before the + * compositionend event is triggered, such as enter, so that the composition is send before + * the command is executed. + */ + CompositionHelper.prototype.finalizeComposition = function (waitForPropogation) { + this.compositionView.classList.remove('active'); + this.isComposing = false; + this.clearTextareaPosition(); + if (!waitForPropogation) { + // Cancel any delayed composition send requests and send the input immediately. + this.isSendingComposition = false; + var input = this.textarea.value.substring(this.compositionPosition.start, this.compositionPosition.end); + this.terminal.handler(input); + } + else { + // Make a deep copy of the composition position here as a new compositionstart event may + // fire before the setTimeout executes. + var currentCompositionPosition = { + start: this.compositionPosition.start, + end: this.compositionPosition.end, + }; + // Since composition* events happen before the changes take place in the textarea on most + // browsers, use a setTimeout with 0ms time to allow the native compositionend event to + // complete. This ensures the correct character is retrieved, this solution was used + // because: + // - The compositionend event's data property is unreliable, at least on Chromium + // - The last compositionupdate event's data property does not always accurately describe + // the character, a counter example being Korean where an ending consonsant can move to + // the following character if the following input is a vowel. + var self = this; + this.isSendingComposition = true; + setTimeout(function () { + // Ensure that the input has not already been sent + if (self.isSendingComposition) { + self.isSendingComposition = false; + var input; + if (self.isComposing) { + // Use the end position to get the string if a new composition has started. + input = self.textarea.value.substring(currentCompositionPosition.start, currentCompositionPosition.end); + } + else { + // Don't use the end position here in order to pick up any characters after the + // composition has finished, for example when typing a non-composition character + // (eg. 2) after a composition character. + input = self.textarea.value.substring(currentCompositionPosition.start); + } + self.terminal.handler(input); + } + }, 0); + } + }; + /** + * Apply any changes made to the textarea after the current event chain is allowed to complete. + * This should be called when not currently composing but a keydown event with the "composition + * character" (229) is triggered, in order to allow non-composition text to be entered when an + * IME is active. + */ + CompositionHelper.prototype.handleAnyTextareaChanges = function () { + var oldValue = this.textarea.value; + var self = this; + setTimeout(function () { + // Ignore if a composition has started since the timeout + if (!self.isComposing) { + var newValue = self.textarea.value; + var diff = newValue.replace(oldValue, ''); + if (diff.length > 0) { + self.terminal.handler(diff); + } + } + }, 0); + }; + /** + * Positions the composition view on top of the cursor and the textarea just below it (so the + * IME helper dialog is positioned correctly). + * @param dontRecurse Whether to use setTimeout to recursively trigger another update, this is + * necessary as the IME events across browsers are not consistently triggered. + */ + CompositionHelper.prototype.updateCompositionElements = function (dontRecurse) { + if (!this.isComposing) { + return; + } + var cursor = this.terminal.element.querySelector('.terminal-cursor'); + if (cursor) { + // Take .xterm-rows offsetTop into account as well in case it's positioned absolutely within + // the .xterm element. + var xtermRows = this.terminal.element.querySelector('.xterm-rows'); + var cursorTop = xtermRows.offsetTop + cursor.offsetTop; + this.compositionView.style.left = cursor.offsetLeft + 'px'; + this.compositionView.style.top = cursorTop + 'px'; + this.compositionView.style.height = cursor.offsetHeight + 'px'; + this.compositionView.style.lineHeight = cursor.offsetHeight + 'px'; + // Sync the textarea to the exact position of the composition view so the IME knows where the + // text is. + var compositionViewBounds = this.compositionView.getBoundingClientRect(); + this.textarea.style.left = cursor.offsetLeft + 'px'; + this.textarea.style.top = cursorTop + 'px'; + this.textarea.style.width = compositionViewBounds.width + 'px'; + this.textarea.style.height = compositionViewBounds.height + 'px'; + this.textarea.style.lineHeight = compositionViewBounds.height + 'px'; + } + if (!dontRecurse) { + setTimeout(this.updateCompositionElements.bind(this, true), 0); + } + }; + ; + /** + * Clears the textarea's position so that the cursor does not blink on IE. + * @private + */ + CompositionHelper.prototype.clearTextareaPosition = function () { + this.textarea.style.left = ''; + this.textarea.style.top = ''; + }; + ; + return CompositionHelper; +}()); exports.CompositionHelper = CompositionHelper; -},{}],2:[function(_dereq_,module,exports){ +},{}],2:[function(require,module,exports){ +/** + * @license MIT + */ "use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -/** - * xterm.js: xterm, in the browser - * Copyright (c) 2014-2016, SourceLair Private Company (www.sourcelair.com (MIT License) - */ - function EventEmitter() { - this._events = this._events || {}; + this._events = this._events || {}; } - -EventEmitter.prototype.addListener = function (type, listener) { - this._events[type] = this._events[type] || []; - this._events[type].push(listener); -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.removeListener = function (type, listener) { - if (!this._events[type]) return; - - var obj = this._events[type], - i = obj.length; - - while (i--) { - if (obj[i] === listener || obj[i].listener === listener) { - obj.splice(i, 1); - return; - } - } -}; - -EventEmitter.prototype.off = EventEmitter.prototype.removeListener; - -EventEmitter.prototype.removeAllListeners = function (type) { - if (this._events[type]) delete this._events[type]; -}; - -EventEmitter.prototype.once = function (type, listener) { - var self = this; - function on() { - var args = Array.prototype.slice.call(arguments); - this.removeListener(type, on); - return listener.apply(this, args); - } - on.listener = listener; - return this.on(type, on); -}; - -EventEmitter.prototype.emit = function (type) { - if (!this._events[type]) return; - - var args = Array.prototype.slice.call(arguments, 1), - obj = this._events[type], - l = obj.length, - i = 0; - - for (; i < l; i++) { - obj[i].apply(this, args); - } -}; - -EventEmitter.prototype.listeners = function (type) { - return this._events[type] = this._events[type] || []; -}; - exports.EventEmitter = EventEmitter; +EventEmitter.prototype.addListener = function (type, listener) { + this._events[type] = this._events[type] || []; + this._events[type].push(listener); +}; +EventEmitter.prototype.on = EventEmitter.prototype.addListener; +EventEmitter.prototype.removeListener = function (type, listener) { + if (!this._events[type]) + return; + var obj = this._events[type], i = obj.length; + while (i--) { + if (obj[i] === listener || obj[i].listener === listener) { + obj.splice(i, 1); + return; + } + } +}; +EventEmitter.prototype.off = EventEmitter.prototype.removeListener; +EventEmitter.prototype.removeAllListeners = function (type) { + if (this._events[type]) + delete this._events[type]; +}; +EventEmitter.prototype.once = function (type, listener) { + var self = this; + function on() { + var args = Array.prototype.slice.call(arguments); + this.removeListener(type, on); + return listener.apply(this, args); + } + on.listener = listener; + return this.on(type, on); +}; +EventEmitter.prototype.emit = function (type) { + if (!this._events[type]) + return; + var args = Array.prototype.slice.call(arguments, 1), obj = this._events[type], l = obj.length, i = 0; + for (; i < l; i++) { + obj[i].apply(this, args); + } +}; +EventEmitter.prototype.listeners = function (type) { + return this._events[type] = this._events[type] || []; +}; -},{}],3:[function(_dereq_,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); +},{}],3:[function(require,module,exports){ /** - * xterm.js: xterm, in the browser - * Copyright (c) 2014-2016, SourceLair Private Company (www.sourcelair.com (MIT License) + * @license MIT */ - +"use strict"; /** * Represents the viewport of a terminal, the visible area within the larger buffer of output. * Logic for the virtual scroll bar is included in this object. - * @param {Terminal} terminal The Terminal object. - * @param {HTMLElement} viewportElement The DOM element acting as the viewport - * @param {HTMLElement} charMeasureElement A DOM element used to measure the character size of - * the terminal. */ -function Viewport(terminal, viewportElement, scrollArea, charMeasureElement) { - this.terminal = terminal; - this.viewportElement = viewportElement; - this.scrollArea = scrollArea; - this.charMeasureElement = charMeasureElement; - this.currentRowHeight = 0; - this.lastRecordedBufferLength = 0; - this.lastRecordedViewportHeight = 0; - - this.terminal.on('scroll', this.syncScrollArea.bind(this)); - this.terminal.on('resize', this.syncScrollArea.bind(this)); - this.viewportElement.addEventListener('scroll', this.onScroll.bind(this)); - - this.syncScrollArea(); -} - -/** - * Refreshes row height, setting line-height, viewport height and scroll area height if - * necessary. - * @param {number|undefined} charSize A character size measurement bounding rect object, if it - * doesn't exist it will be created. - */ -Viewport.prototype.refresh = function (charSize) { - var size = charSize || this.charMeasureElement.getBoundingClientRect(); - if (size.height > 0) { - var rowHeightChanged = size.height !== this.currentRowHeight; - if (rowHeightChanged) { - this.currentRowHeight = size.height; - this.viewportElement.style.lineHeight = size.height + 'px'; - this.terminal.rowContainer.style.lineHeight = size.height + 'px'; +var Viewport = (function () { + /** + * Creates a new Viewport. + * @param terminal The terminal this viewport belongs to. + * @param viewportElement The DOM element acting as the viewport. + * @param scrollArea The DOM element acting as the scroll area. + * @param charMeasureElement A DOM element used to measure the character size of. the terminal. + */ + function Viewport(terminal, viewportElement, scrollArea, charMeasureElement) { + this.terminal = terminal; + this.viewportElement = viewportElement; + this.scrollArea = scrollArea; + this.charMeasureElement = charMeasureElement; + this.currentRowHeight = 0; + this.lastRecordedBufferLength = 0; + this.lastRecordedViewportHeight = 0; + this.terminal.on('scroll', this.syncScrollArea.bind(this)); + this.terminal.on('resize', this.syncScrollArea.bind(this)); + this.viewportElement.addEventListener('scroll', this.onScroll.bind(this)); + this.syncScrollArea(); } - var viewportHeightChanged = this.lastRecordedViewportHeight !== this.terminal.rows; - if (rowHeightChanged || viewportHeightChanged) { - this.lastRecordedViewportHeight = this.terminal.rows; - this.viewportElement.style.height = size.height * this.terminal.rows + 'px'; - } - this.scrollArea.style.height = size.height * this.lastRecordedBufferLength + 'px'; - } -}; - -/** - * Updates dimensions and synchronizes the scroll area if necessary. - */ -Viewport.prototype.syncScrollArea = function () { - if (this.lastRecordedBufferLength !== this.terminal.lines.length) { - // If buffer height changed - this.lastRecordedBufferLength = this.terminal.lines.length; - this.refresh(); - } else if (this.lastRecordedViewportHeight !== this.terminal.rows) { - // If viewport height changed - this.refresh(); - } else { - // If size has changed, refresh viewport - var size = this.charMeasureElement.getBoundingClientRect(); - if (size.height !== this.currentRowHeight) { - this.refresh(size); - } - } - - // Sync scrollTop - var scrollTop = this.terminal.ydisp * this.currentRowHeight; - if (this.viewportElement.scrollTop !== scrollTop) { - this.viewportElement.scrollTop = scrollTop; - } -}; - -/** - * Handles scroll events on the viewport, calculating the new viewport and requesting the - * terminal to scroll to it. - * @param {Event} ev The scroll event. - */ -Viewport.prototype.onScroll = function (ev) { - var newRow = Math.round(this.viewportElement.scrollTop / this.currentRowHeight); - var diff = newRow - this.terminal.ydisp; - this.terminal.scrollDisp(diff, true); -}; - -/** - * Handles mouse wheel events by adjusting the viewport's scrollTop and delegating the actual - * scrolling to `onScroll`, this event needs to be attached manually by the consumer of - * `Viewport`. - * @param {WheelEvent} ev The mouse wheel event. - */ -Viewport.prototype.onWheel = function (ev) { - if (ev.deltaY === 0) { - // Do nothing if it's not a vertical scroll event - return; - } - // Fallback to WheelEvent.DOM_DELTA_PIXEL - var multiplier = 1; - if (ev.deltaMode === WheelEvent.DOM_DELTA_LINE) { - multiplier = this.currentRowHeight; - } else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) { - multiplier = this.currentRowHeight * this.terminal.rows; - } - this.viewportElement.scrollTop += ev.deltaY * multiplier; - // Prevent the page from scrolling when the terminal scrolls - ev.preventDefault(); -}; - + /** + * Refreshes row height, setting line-height, viewport height and scroll area height if + * necessary. + * @param charSize A character size measurement bounding rect object, if it doesn't exist it will + * be created. + */ + Viewport.prototype.refresh = function (charSize) { + var size = charSize || this.charMeasureElement.getBoundingClientRect(); + if (size.height > 0) { + var rowHeightChanged = size.height !== this.currentRowHeight; + if (rowHeightChanged) { + this.currentRowHeight = size.height; + this.viewportElement.style.lineHeight = size.height + 'px'; + this.terminal.rowContainer.style.lineHeight = size.height + 'px'; + } + var viewportHeightChanged = this.lastRecordedViewportHeight !== this.terminal.rows; + if (rowHeightChanged || viewportHeightChanged) { + this.lastRecordedViewportHeight = this.terminal.rows; + this.viewportElement.style.height = size.height * this.terminal.rows + 'px'; + } + this.scrollArea.style.height = (size.height * this.lastRecordedBufferLength) + 'px'; + } + }; + /** + * Updates dimensions and synchronizes the scroll area if necessary. + */ + Viewport.prototype.syncScrollArea = function () { + if (this.lastRecordedBufferLength !== this.terminal.lines.length) { + // If buffer height changed + this.lastRecordedBufferLength = this.terminal.lines.length; + this.refresh(); + } + else if (this.lastRecordedViewportHeight !== this.terminal.rows) { + // If viewport height changed + this.refresh(); + } + else { + // If size has changed, refresh viewport + var size = this.charMeasureElement.getBoundingClientRect(); + if (size.height !== this.currentRowHeight) { + this.refresh(size); + } + } + // Sync scrollTop + var scrollTop = this.terminal.ydisp * this.currentRowHeight; + if (this.viewportElement.scrollTop !== scrollTop) { + this.viewportElement.scrollTop = scrollTop; + } + }; + /** + * Handles scroll events on the viewport, calculating the new viewport and requesting the + * terminal to scroll to it. + * @param ev The scroll event. + */ + Viewport.prototype.onScroll = function (ev) { + var newRow = Math.round(this.viewportElement.scrollTop / this.currentRowHeight); + var diff = newRow - this.terminal.ydisp; + this.terminal.scrollDisp(diff, true); + }; + /** + * Handles mouse wheel events by adjusting the viewport's scrollTop and delegating the actual + * scrolling to `onScroll`, this event needs to be attached manually by the consumer of + * `Viewport`. + * @param ev The mouse wheel event. + */ + Viewport.prototype.onWheel = function (ev) { + if (ev.deltaY === 0) { + // Do nothing if it's not a vertical scroll event + return; + } + // Fallback to WheelEvent.DOM_DELTA_PIXEL + var multiplier = 1; + if (ev.deltaMode === WheelEvent.DOM_DELTA_LINE) { + multiplier = this.currentRowHeight; + } + else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) { + multiplier = this.currentRowHeight * this.terminal.rows; + } + this.viewportElement.scrollTop += ev.deltaY * multiplier; + // Prevent the page from scrolling when the terminal scrolls + ev.preventDefault(); + }; + ; + return Viewport; +}()); exports.Viewport = Viewport; -},{}],4:[function(_dereq_,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); +},{}],4:[function(require,module,exports){ /** - * xterm.js: xterm, in the browser - * Copyright (c) 2016, SourceLair Private Company (MIT License) - */ - -/** - * Clipboard handler module. This module contains methods for handling all - * clipboard-related events appropriately in the terminal. + * Clipboard handler module: exports methods for handling all clipboard-related events in the + * terminal. * @module xterm/handlers/Clipboard + * @license MIT */ - +"use strict"; /** * Prepares text copied from terminal selection, to be saved in the clipboard by: * 1. stripping all trailing white spaces @@ -436,64 +388,59 @@ Object.defineProperty(exports, "__esModule", { * @returns {string} */ function prepareTextForClipboard(text) { - var space = String.fromCharCode(32), - nonBreakingSpace = String.fromCharCode(160), - allNonBreakingSpaces = new RegExp(nonBreakingSpace, 'g'), - processedText = text.split('\n').map(function (line) { - // Strip all trailing white spaces and convert all non-breaking spaces - // to regular spaces. - var processedLine = line.replace(/\s+$/g, '').replace(allNonBreakingSpaces, space); - - return processedLine; - }).join('\n'); - - return processedText; + var space = String.fromCharCode(32), nonBreakingSpace = String.fromCharCode(160), allNonBreakingSpaces = new RegExp(nonBreakingSpace, 'g'), processedText = text.split('\n').map(function (line) { + // Strip all trailing white spaces and convert all non-breaking spaces + // to regular spaces. + var processedLine = line.replace(/\s+$/g, '').replace(allNonBreakingSpaces, space); + return processedLine; + }).join('\n'); + return processedText; } - +exports.prepareTextForClipboard = prepareTextForClipboard; /** * Binds copy functionality to the given terminal. * @param {ClipboardEvent} ev The original copy event to be handled */ function copyHandler(ev, term) { - var copiedText = window.getSelection().toString(), - text = prepareTextForClipboard(copiedText); - - if (term.browser.isMSIE) { - window.clipboardData.setData('Text', text); - } else { - ev.clipboardData.setData('text/plain', text); - } - - ev.preventDefault(); // Prevent or the original text will be copied. + // We cast `window` to `any` type, because TypeScript has not declared the `clipboardData` + // property that we use below for Internet Explorer. + var copiedText = window.getSelection().toString(), text = prepareTextForClipboard(copiedText); + if (term.browser.isMSIE) { + window.clipboardData.setData('Text', text); + } + else { + ev.clipboardData.setData('text/plain', text); + } + ev.preventDefault(); // Prevent or the original text will be copied. } - +exports.copyHandler = copyHandler; /** * Redirect the clipboard's data to the terminal's input handler. * @param {ClipboardEvent} ev The original paste event to be handled * @param {Terminal} term The terminal on which to apply the handled paste event */ function pasteHandler(ev, term) { - ev.stopPropagation(); - - var dispatchPaste = function dispatchPaste(text) { - term.handler(text); - term.textarea.value = ''; - return term.cancel(ev); - }; - - if (term.browser.isMSIE) { - if (window.clipboardData) { - var text = window.clipboardData.getData('Text'); - dispatchPaste(text); + ev.stopPropagation(); + var text; + var dispatchPaste = function (text) { + term.handler(text); + term.textarea.value = ''; + return term.cancel(ev); + }; + if (term.browser.isMSIE) { + if (window.clipboardData) { + text = window.clipboardData.getData('Text'); + dispatchPaste(text); + } } - } else { - if (ev.clipboardData) { - var text = ev.clipboardData.getData('text/plain'); - dispatchPaste(text); + else { + if (ev.clipboardData) { + text = ev.clipboardData.getData('text/plain'); + dispatchPaste(text); + } } - } } - +exports.pasteHandler = pasteHandler; /** * Bind to right-click event and allow right-click copy and paste. * @@ -508,148 +455,87 @@ function pasteHandler(ev, term) { * @param {Terminal} term The terminal on which to apply the handled paste event */ function rightClickHandler(ev, term) { - var s = document.getSelection(), - selectedText = prepareTextForClipboard(s.toString()), - clickIsOnSelection = false; - - if (s.rangeCount) { - var r = s.getRangeAt(0), - cr = r.getClientRects(), - x = ev.clientX, - y = ev.clientY, - i, - rect; - - for (i = 0; i < cr.length; i++) { - rect = cr[i]; - clickIsOnSelection = x > rect.left && x < rect.right && y > rect.top && y < rect.bottom; - - if (clickIsOnSelection) { - break; - } + var s = document.getSelection(), selectedText = prepareTextForClipboard(s.toString()), clickIsOnSelection = false, x = ev.clientX, y = ev.clientY; + if (s.rangeCount) { + var r = s.getRangeAt(0), cr = r.getClientRects(), i = void 0, rect = void 0; + for (i = 0; i < cr.length; i++) { + rect = cr[i]; + clickIsOnSelection = ((x > rect.left) && (x < rect.right) && + (y > rect.top) && (y < rect.bottom)); + if (clickIsOnSelection) { + break; + } + } + // If we clicked on selection and selection is not a single space, + // then mark the right click as copy-only. We check for the single + // space selection, as this can happen when clicking on an   + // and there is not much pointing in copying a single space. + if (selectedText.match(/^\s$/) || !selectedText.length) { + clickIsOnSelection = false; + } } - // If we clicked on selection and selection is not a single space, - // then mark the right click as copy-only. We check for the single - // space selection, as this can happen when clicking on an   - // and there is not much pointing in copying a single space. - if (selectedText.match(/^\s$/) || !selectedText.length) { - clickIsOnSelection = false; + // Bring textarea at the cursor position + if (!clickIsOnSelection) { + term.textarea.style.position = 'fixed'; + term.textarea.style.width = '20px'; + term.textarea.style.height = '20px'; + term.textarea.style.left = (x - 10) + 'px'; + term.textarea.style.top = (y - 10) + 'px'; + term.textarea.style.zIndex = '1000'; + term.textarea.focus(); + // Reset the terminal textarea's styling + setTimeout(function () { + term.textarea.style.position = null; + term.textarea.style.width = null; + term.textarea.style.height = null; + term.textarea.style.left = null; + term.textarea.style.top = null; + term.textarea.style.zIndex = null; + }, 4); } - } - - // Bring textarea at the cursor position - if (!clickIsOnSelection) { - term.textarea.style.position = 'fixed'; - term.textarea.style.width = '20px'; - term.textarea.style.height = '20px'; - term.textarea.style.left = x - 10 + 'px'; - term.textarea.style.top = y - 10 + 'px'; - term.textarea.style.zIndex = 1000; - term.textarea.focus(); - - // Reset the terminal textarea's styling - setTimeout(function () { - term.textarea.style.position = null; - term.textarea.style.width = null; - term.textarea.style.height = null; - term.textarea.style.left = null; - term.textarea.style.top = null; - term.textarea.style.zIndex = null; - }, 4); - } } - -exports.prepareTextForClipboard = prepareTextForClipboard; -exports.copyHandler = copyHandler; -exports.pasteHandler = pasteHandler; exports.rightClickHandler = rightClickHandler; -},{}],5:[function(_dereq_,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.isMSWindows = exports.isIphone = exports.isIpad = exports.isMac = exports.isMSIE = exports.isFirefox = undefined; - -var _Generic = _dereq_('./Generic.js'); - -var isNode = typeof navigator == 'undefined' ? true : false; /** - * xterm.js: xterm, in the browser - * Copyright (c) 2016, SourceLair Private Company (MIT License) - */ - +},{}],5:[function(require,module,exports){ /** - * Browser utilities module. This module contains attributes and methods to help with - * identifying the current browser and platform. + * Attributes and methods to help with identifying the current browser and platform. * @module xterm/utils/Browser + * @license MIT */ - -var userAgent = isNode ? 'node' : navigator.userAgent; -var platform = isNode ? 'node' : navigator.platform; - -var isFirefox = exports.isFirefox = !!~userAgent.indexOf('Firefox'); -var isMSIE = exports.isMSIE = !!~userAgent.indexOf('MSIE') || !!~userAgent.indexOf('Trident'); - +"use strict"; +var Generic_js_1 = require('./Generic.js'); +var isNode = (typeof navigator == 'undefined') ? true : false; +var userAgent = (isNode) ? 'node' : navigator.userAgent; +var platform = (isNode) ? 'node' : navigator.platform; +exports.isFirefox = !!~userAgent.indexOf('Firefox'); +exports.isMSIE = !!~userAgent.indexOf('MSIE') || !!~userAgent.indexOf('Trident'); // Find the users platform. We use this to interpret the meta key // and ISO third level shifts. // http://stackoverflow.com/q/19877924/577598 -var isMac = exports.isMac = (0, _Generic.contains)(['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'], platform); -var isIpad = exports.isIpad = platform === 'iPad'; -var isIphone = exports.isIphone = platform === 'iPhone'; -var isMSWindows = exports.isMSWindows = (0, _Generic.contains)(['Windows', 'Win16', 'Win32', 'WinCE'], platform); +exports.isMac = Generic_js_1.contains(['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'], platform); +exports.isIpad = platform === 'iPad'; +exports.isIphone = platform === 'iPhone'; +exports.isMSWindows = Generic_js_1.contains(['Windows', 'Win16', 'Win32', 'WinCE'], platform); -},{"./Generic.js":6}],6:[function(_dereq_,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); +},{"./Generic.js":6}],6:[function(require,module,exports){ /** - * xterm.js: xterm, in the browser - * Copyright (c) 2016, SourceLair Private Company (MIT License) - */ - -/** - * Generic utilities module. This module contains generic methods that can be helpful at - * different parts of the code base. + * Generic utilities module with methods that can be helpful at different parts of the code base. * @module xterm/utils/Generic + * @license MIT */ - +"use strict"; /** * Return if the given array contains the given element * @param {Array} array The array to search for the given element. * @param {Object} el The element to look for into the array */ -var contains = exports.contains = function contains(arr, el) { - return arr.indexOf(el) >= 0; +exports.contains = function (arr, el) { + return arr.indexOf(el) >= 0; }; -},{}],7:[function(_dereq_,module,exports){ -'use strict';var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};/** +},{}],7:[function(require,module,exports){ +/** * xterm.js: xterm, in the browser - * Copyright (c) 2014-2014, SourceLair Private Company (MIT License) - * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License) - * https://github.com/chjj/term.js - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * * Originally forked from (with the author's permission): * Fabrice Bellard's javascript vt100 for jslinux: * http://bellard.org/jslinux/ @@ -657,7 +543,15 @@ var contains = exports.contains = function contains(arr, el) { * The original design remains. The terminal itself * has been extended to include xterm CSI codes, among * other features. - */var _CompositionHelper=_dereq_('./CompositionHelper.js');var _EventEmitter=_dereq_('./EventEmitter.js');var _Viewport=_dereq_('./Viewport.js');var _Clipboard=_dereq_('./handlers/Clipboard.js');var _Browser=_dereq_('./utils/Browser');var Browser=_interopRequireWildcard(_Browser);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}/** + * @license MIT + */ +"use strict"; +var CompositionHelper_js_1 = require('./CompositionHelper.js'); +var EventEmitter_js_1 = require('./EventEmitter.js'); +var Viewport_js_1 = require('./Viewport.js'); +var Clipboard_js_1 = require('./handlers/Clipboard.js'); +var Browser = require('./utils/Browser'); +/** * Terminal Emulation References: * http://vt100.net/ * http://invisible-island.net/xterm/ctlseqs/ctlseqs.txt @@ -666,12 +560,17 @@ var contains = exports.contains = function contains(arr, el) { * http://www.inwap.com/pdp10/ansicode.txt * http://linux.die.net/man/4/console_codes * http://linux.die.net/man/7/urxvt - */// Let it work inside Node.js for automated testing purposes. -var document=typeof window!='undefined'?window.document:null;/** + */ +// Let it work inside Node.js for automated testing purposes. +var document = (typeof window != 'undefined') ? window.document : null; +/** * States - */var normal=0,escaped=1,csi=2,osc=3,charset=4,dcs=5,ignore=6;/** + */ +var normal = 0, escaped = 1, csi = 2, osc = 3, charset = 4, dcs = 5, ignore = 6; +/** * Terminal - *//** + */ +/** * Creates a new `Terminal` object. * * @param {object} options An object containing a set of options, the available options are: @@ -682,103 +581,490 @@ var document=typeof window!='undefined'?window.document:null;/** * @public * @class Xterm Xterm * @alias module:xterm/src/xterm - */function Terminal(options){var self=this;if(!(this instanceof Terminal)){return new Terminal(arguments[0],arguments[1],arguments[2]);}self.browser=Browser;self.cancel=Terminal.cancel;_EventEmitter.EventEmitter.call(this);if(typeof options==='number'){options={cols:arguments[0],rows:arguments[1],handler:arguments[2]};}options=options||{};Object.keys(Terminal.defaults).forEach(function(key){if(options[key]==null){options[key]=Terminal.options[key];if(Terminal[key]!==Terminal.defaults[key]){options[key]=Terminal[key];}}self[key]=options[key];});if(options.colors.length===8){options.colors=options.colors.concat(Terminal._colors.slice(8));}else if(options.colors.length===16){options.colors=options.colors.concat(Terminal._colors.slice(16));}else if(options.colors.length===10){options.colors=options.colors.slice(0,-2).concat(Terminal._colors.slice(8,-2),options.colors.slice(-2));}else if(options.colors.length===18){options.colors=options.colors.concat(Terminal._colors.slice(16,-2),options.colors.slice(-2));}this.colors=options.colors;this.options=options;// this.context = options.context || window; -// this.document = options.document || document; -this.parent=options.body||options.parent||(document?document.getElementsByTagName('body')[0]:null);this.cols=options.cols||options.geometry[0];this.rows=options.rows||options.geometry[1];this.geometry=[this.cols,this.rows];if(options.handler){this.on('data',options.handler);}/** - * The scroll position of the y cursor, ie. ybase + y = the y position within the entire - * buffer - */this.ybase=0;/** - * The scroll position of the viewport - */this.ydisp=0;/** - * The cursor's x position after ybase - */this.x=0;/** - * The cursor's y position after ybase - */this.y=0;/** - * Used to debounce the refresh function - */this.isRefreshing=false;/** - * Whether there is a full terminal refresh queued - */this.cursorState=0;this.cursorHidden=false;this.convertEol;this.state=0;this.queue='';this.scrollTop=0;this.scrollBottom=this.rows-1;this.customKeydownHandler=null;// modes -this.applicationKeypad=false;this.applicationCursor=false;this.originMode=false;this.insertMode=false;this.wraparoundMode=true;// defaults: xterm - true, vt100 - false -this.normal=null;// charset -this.charset=null;this.gcharset=null;this.glevel=0;this.charsets=[null];// mouse properties -this.decLocator;this.x10Mouse;this.vt200Mouse;this.vt300Mouse;this.normalMouse;this.mouseEvents;this.sendFocus;this.utfMouse;this.sgrMouse;this.urxvtMouse;// misc -this.element;this.children;this.refreshStart;this.refreshEnd;this.savedX;this.savedY;this.savedCols;// stream -this.readable=true;this.writable=true;this.defAttr=0<<18|257<<9|256<<0;this.curAttr=this.defAttr;this.params=[];this.currentParam=0;this.prefix='';this.postfix='';// leftover surrogate high from previous write invocation -this.surrogate_high='';/** - * An array of all lines in the entire buffer, including the prompt. The lines are array of - * characters which are 2-length arrays where [0] is an attribute and [1] is the character. - */this.lines=[];var i=this.rows;while(i--){this.lines.push(this.blankLine());}this.tabs;this.setupStops();// Store if user went browsing history in scrollback -this.userScrolling=false;}inherits(Terminal,_EventEmitter.EventEmitter);/** + */ +function Terminal(options) { + var self = this; + if (!(this instanceof Terminal)) { + return new Terminal(arguments[0], arguments[1], arguments[2]); + } + self.browser = Browser; + self.cancel = Terminal.cancel; + EventEmitter_js_1.EventEmitter.call(this); + if (typeof options === 'number') { + options = { + cols: arguments[0], + rows: arguments[1], + handler: arguments[2] + }; + } + options = options || {}; + Object.keys(Terminal.defaults).forEach(function (key) { + if (options[key] == null) { + options[key] = Terminal.options[key]; + if (Terminal[key] !== Terminal.defaults[key]) { + options[key] = Terminal[key]; + } + } + self[key] = options[key]; + }); + if (options.colors.length === 8) { + options.colors = options.colors.concat(Terminal._colors.slice(8)); + } + else if (options.colors.length === 16) { + options.colors = options.colors.concat(Terminal._colors.slice(16)); + } + else if (options.colors.length === 10) { + options.colors = options.colors.slice(0, -2).concat(Terminal._colors.slice(8, -2), options.colors.slice(-2)); + } + else if (options.colors.length === 18) { + options.colors = options.colors.concat(Terminal._colors.slice(16, -2), options.colors.slice(-2)); + } + this.colors = options.colors; + this.options = options; + // this.context = options.context || window; + // this.document = options.document || document; + this.parent = options.body || options.parent || (document ? document.getElementsByTagName('body')[0] : null); + this.cols = options.cols || options.geometry[0]; + this.rows = options.rows || options.geometry[1]; + this.geometry = [this.cols, this.rows]; + if (options.handler) { + this.on('data', options.handler); + } + /** + * The scroll position of the y cursor, ie. ybase + y = the y position within the entire + * buffer + */ + this.ybase = 0; + /** + * The scroll position of the viewport + */ + this.ydisp = 0; + /** + * The cursor's x position after ybase + */ + this.x = 0; + /** + * The cursor's y position after ybase + */ + this.y = 0; + /** + * Used to debounce the refresh function + */ + this.isRefreshing = false; + /** + * Whether there is a full terminal refresh queued + */ + this.cursorState = 0; + this.cursorHidden = false; + this.convertEol; + this.state = 0; + this.queue = ''; + this.scrollTop = 0; + this.scrollBottom = this.rows - 1; + this.customKeydownHandler = null; + // modes + this.applicationKeypad = false; + this.applicationCursor = false; + this.originMode = false; + this.insertMode = false; + this.wraparoundMode = true; // defaults: xterm - true, vt100 - false + this.normal = null; + // charset + this.charset = null; + this.gcharset = null; + this.glevel = 0; + this.charsets = [null]; + // mouse properties + this.decLocator; + this.x10Mouse; + this.vt200Mouse; + this.vt300Mouse; + this.normalMouse; + this.mouseEvents; + this.sendFocus; + this.utfMouse; + this.sgrMouse; + this.urxvtMouse; + // misc + this.element; + this.children; + this.refreshStart; + this.refreshEnd; + this.savedX; + this.savedY; + this.savedCols; + // stream + this.readable = true; + this.writable = true; + this.defAttr = (0 << 18) | (257 << 9) | (256 << 0); + this.curAttr = this.defAttr; + this.params = []; + this.currentParam = 0; + this.prefix = ''; + this.postfix = ''; + // leftover surrogate high from previous write invocation + this.surrogate_high = ''; + /** + * An array of all lines in the entire buffer, including the prompt. The lines are array of + * characters which are 2-length arrays where [0] is an attribute and [1] is the character. + */ + this.lines = []; + var i = this.rows; + while (i--) { + this.lines.push(this.blankLine()); + } + this.tabs; + this.setupStops(); + // Store if user went browsing history in scrollback + this.userScrolling = false; +} +inherits(Terminal, EventEmitter_js_1.EventEmitter); +/** * back_color_erase feature for xterm. - */Terminal.prototype.eraseAttr=function(){// if (this.is('screen')) return this.defAttr; -return this.defAttr&~0x1ff|this.curAttr&0x1ff;};/** + */ +Terminal.prototype.eraseAttr = function () { + // if (this.is('screen')) return this.defAttr; + return (this.defAttr & ~0x1ff) | (this.curAttr & 0x1ff); +}; +/** * Colors - */// Colors 0-15 -Terminal.tangoColors=[// dark: -'#2e3436','#cc0000','#4e9a06','#c4a000','#3465a4','#75507b','#06989a','#d3d7cf',// bright: -'#555753','#ef2929','#8ae234','#fce94f','#729fcf','#ad7fa8','#34e2e2','#eeeeec'];// Colors 0-15 + 16-255 + */ +// Colors 0-15 +Terminal.tangoColors = [ + // dark: + '#2e3436', + '#cc0000', + '#4e9a06', + '#c4a000', + '#3465a4', + '#75507b', + '#06989a', + '#d3d7cf', + // bright: + '#555753', + '#ef2929', + '#8ae234', + '#fce94f', + '#729fcf', + '#ad7fa8', + '#34e2e2', + '#eeeeec' +]; +// Colors 0-15 + 16-255 // Much thanks to TooTallNate for writing this. -Terminal.colors=function(){var colors=Terminal.tangoColors.slice(),r=[0x00,0x5f,0x87,0xaf,0xd7,0xff],i;// 16-231 -i=0;for(;i<216;i++){out(r[i/36%6|0],r[i/6%6|0],r[i%6]);}// 232-255 (grey) -i=0;for(;i<24;i++){r=8+i*10;out(r,r,r);}function out(r,g,b){colors.push('#'+hex(r)+hex(g)+hex(b));}function hex(c){c=c.toString(16);return c.length<2?'0'+c:c;}return colors;}();Terminal._colors=Terminal.colors.slice();Terminal.vcolors=function(){var out=[],colors=Terminal.colors,i=0,color;for(;i<256;i++){color=parseInt(colors[i].substring(1),16);out.push([color>>16&0xff,color>>8&0xff,color&0xff]);}return out;}();/** +Terminal.colors = (function () { + var colors = Terminal.tangoColors.slice(), r = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff], i; + // 16-231 + i = 0; + for (; i < 216; i++) { + out(r[(i / 36) % 6 | 0], r[(i / 6) % 6 | 0], r[i % 6]); + } + // 232-255 (grey) + i = 0; + for (; i < 24; i++) { + r = 8 + i * 10; + out(r, r, r); + } + function out(r, g, b) { + colors.push('#' + hex(r) + hex(g) + hex(b)); + } + function hex(c) { + c = c.toString(16); + return c.length < 2 ? '0' + c : c; + } + return colors; +})(); +Terminal._colors = Terminal.colors.slice(); +Terminal.vcolors = (function () { + var out = [], colors = Terminal.colors, i = 0, color; + for (; i < 256; i++) { + color = parseInt(colors[i].substring(1), 16); + out.push([ + (color >> 16) & 0xff, + (color >> 8) & 0xff, + color & 0xff + ]); + } + return out; +})(); +/** * Options - */Terminal.defaults={colors:Terminal.colors,theme:'default',convertEol:false,termName:'xterm',geometry:[80,24],cursorBlink:false,visualBell:false,popOnBell:false,scrollback:1000,screenKeys:false,debug:false,cancelEvents:false// programFeatures: false, -// focusKeys: false, -};Terminal.options={};Terminal.focus=null;each(keys(Terminal.defaults),function(key){Terminal[key]=Terminal.defaults[key];Terminal.options[key]=Terminal.defaults[key];});/** + */ +Terminal.defaults = { + colors: Terminal.colors, + theme: 'default', + convertEol: false, + termName: 'xterm', + geometry: [80, 24], + cursorBlink: false, + visualBell: false, + popOnBell: false, + scrollback: 1000, + screenKeys: false, + debug: false, + cancelEvents: false +}; +Terminal.options = {}; +Terminal.focus = null; +each(keys(Terminal.defaults), function (key) { + Terminal[key] = Terminal.defaults[key]; + Terminal.options[key] = Terminal.defaults[key]; +}); +/** * Focus the terminal. Delegates focus handling to the terminal's DOM element. - */Terminal.prototype.focus=function(){return this.textarea.focus();};/** + */ +Terminal.prototype.focus = function () { + return this.textarea.focus(); +}; +/** * Retrieves an option's value from the terminal. * @param {string} key The option key. - */Terminal.prototype.getOption=function(key,value){if(!(key in Terminal.defaults)){throw new Error('No option with key "'+key+'"');}if(typeof this.options[key]!=='undefined'){return this.options[key];}return this[key];};/** + */ +Terminal.prototype.getOption = function (key, value) { + if (!(key in Terminal.defaults)) { + throw new Error('No option with key "' + key + '"'); + } + if (typeof this.options[key] !== 'undefined') { + return this.options[key]; + } + return this[key]; +}; +/** * Sets an option on the terminal. * @param {string} key The option key. * @param {string} value The option value. - */Terminal.prototype.setOption=function(key,value){if(!(key in Terminal.defaults)){throw new Error('No option with key "'+key+'"');}this[key]=value;this.options[key]=value;};/** + */ +Terminal.prototype.setOption = function (key, value) { + if (!(key in Terminal.defaults)) { + throw new Error('No option with key "' + key + '"'); + } + this[key] = value; + this.options[key] = value; +}; +/** * Binds the desired focus behavior on a given terminal object. * * @static - */Terminal.bindFocus=function(term){on(term.textarea,'focus',function(ev){if(term.sendFocus){term.send('\x1b[I');}term.element.classList.add('focus');term.showCursor();Terminal.focus=term;term.emit('focus',{terminal:term});});};/** + */ +Terminal.bindFocus = function (term) { + on(term.textarea, 'focus', function (ev) { + if (term.sendFocus) { + term.send('\x1b[I'); + } + term.element.classList.add('focus'); + term.showCursor(); + Terminal.focus = term; + term.emit('focus', { terminal: term }); + }); +}; +/** * Blur the terminal. Delegates blur handling to the terminal's DOM element. - */Terminal.prototype.blur=function(){return this.textarea.blur();};/** + */ +Terminal.prototype.blur = function () { + return this.textarea.blur(); +}; +/** * Binds the desired blur behavior on a given terminal object. * * @static - */Terminal.bindBlur=function(term){on(term.textarea,'blur',function(ev){term.refresh(term.y,term.y);if(term.sendFocus){term.send('\x1b[O');}term.element.classList.remove('focus');Terminal.focus=null;term.emit('blur',{terminal:term});});};/** + */ +Terminal.bindBlur = function (term) { + on(term.textarea, 'blur', function (ev) { + term.refresh(term.y, term.y); + if (term.sendFocus) { + term.send('\x1b[O'); + } + term.element.classList.remove('focus'); + Terminal.focus = null; + term.emit('blur', { terminal: term }); + }); +}; +/** * Initialize default behavior - */Terminal.prototype.initGlobal=function(){var term=this;Terminal.bindKeys(this);Terminal.bindFocus(this);Terminal.bindBlur(this);// Bind clipboard functionality -on(this.element,'copy',function(ev){_Clipboard.copyHandler.call(this,ev,term);});on(this.textarea,'paste',function(ev){_Clipboard.pasteHandler.call(this,ev,term);});function rightClickHandlerWrapper(ev){_Clipboard.rightClickHandler.call(this,ev,term);}if(term.browser.isFirefox){on(this.element,'mousedown',function(ev){if(ev.button==2){rightClickHandlerWrapper(ev);}});}else{on(this.element,'contextmenu',rightClickHandlerWrapper);}};/** + */ +Terminal.prototype.initGlobal = function () { + var term = this; + Terminal.bindKeys(this); + Terminal.bindFocus(this); + Terminal.bindBlur(this); + // Bind clipboard functionality + on(this.element, 'copy', function (ev) { + Clipboard_js_1.copyHandler.call(this, ev, term); + }); + on(this.textarea, 'paste', function (ev) { + Clipboard_js_1.pasteHandler.call(this, ev, term); + }); + function rightClickHandlerWrapper(ev) { + Clipboard_js_1.rightClickHandler.call(this, ev, term); + } + if (term.browser.isFirefox) { + on(this.element, 'mousedown', function (ev) { + if (ev.button == 2) { + rightClickHandlerWrapper(ev); + } + }); + } + else { + on(this.element, 'contextmenu', rightClickHandlerWrapper); + } +}; +/** * Apply key handling to the terminal - */Terminal.bindKeys=function(term){on(term.element,'keydown',function(ev){if(document.activeElement!=this){return;}term.keyDown(ev);},true);on(term.element,'keypress',function(ev){if(document.activeElement!=this){return;}term.keyPress(ev);},true);on(term.element,'keyup',term.focus.bind(term));on(term.textarea,'keydown',function(ev){term.keyDown(ev);},true);on(term.textarea,'keypress',function(ev){term.keyPress(ev);// Truncate the textarea's value, since it is not needed -this.value='';},true);on(term.textarea,'compositionstart',term.compositionHelper.compositionstart.bind(term.compositionHelper));on(term.textarea,'compositionupdate',term.compositionHelper.compositionupdate.bind(term.compositionHelper));on(term.textarea,'compositionend',term.compositionHelper.compositionend.bind(term.compositionHelper));term.on('refresh',term.compositionHelper.updateCompositionElements.bind(term.compositionHelper));};/** + */ +Terminal.bindKeys = function (term) { + on(term.element, 'keydown', function (ev) { + if (document.activeElement != this) { + return; + } + term.keyDown(ev); + }, true); + on(term.element, 'keypress', function (ev) { + if (document.activeElement != this) { + return; + } + term.keyPress(ev); + }, true); + on(term.element, 'keyup', term.focus.bind(term)); + on(term.textarea, 'keydown', function (ev) { + term.keyDown(ev); + }, true); + on(term.textarea, 'keypress', function (ev) { + term.keyPress(ev); + // Truncate the textarea's value, since it is not needed + this.value = ''; + }, true); + on(term.textarea, 'compositionstart', term.compositionHelper.compositionstart.bind(term.compositionHelper)); + on(term.textarea, 'compositionupdate', term.compositionHelper.compositionupdate.bind(term.compositionHelper)); + on(term.textarea, 'compositionend', term.compositionHelper.compositionend.bind(term.compositionHelper)); + term.on('refresh', term.compositionHelper.updateCompositionElements.bind(term.compositionHelper)); +}; +/** * Insert the given row to the terminal or produce a new one * if no row argument is passed. Return the inserted row. * @param {HTMLElement} row (optional) The row to append to the terminal. - */Terminal.prototype.insertRow=function(row){if((typeof row==='undefined'?'undefined':_typeof(row))!='object'){row=document.createElement('div');}this.rowContainer.appendChild(row);this.children.push(row);return row;};/** + */ +Terminal.prototype.insertRow = function (row) { + if (typeof row != 'object') { + row = document.createElement('div'); + } + this.rowContainer.appendChild(row); + this.children.push(row); + return row; +}; +/** * Opens the terminal within an element. * * @param {HTMLElement} parent The element to create the terminal within. - */Terminal.prototype.open=function(parent){var self=this,i=0,div;this.parent=parent||this.parent;if(!this.parent){throw new Error('Terminal requires a parent element.');}// Grab global elements -this.context=this.parent.ownerDocument.defaultView;this.document=this.parent.ownerDocument;this.body=this.document.getElementsByTagName('body')[0];//Create main element container -this.element=this.document.createElement('div');this.element.classList.add('terminal');this.element.classList.add('xterm');this.element.classList.add('xterm-theme-'+this.theme);this.element.style.height;this.element.setAttribute('tabindex',0);this.viewportElement=document.createElement('div');this.viewportElement.classList.add('xterm-viewport');this.element.appendChild(this.viewportElement);this.viewportScrollArea=document.createElement('div');this.viewportScrollArea.classList.add('xterm-scroll-area');this.viewportElement.appendChild(this.viewportScrollArea);// Create the container that will hold the lines of the terminal and then -// produce the lines the lines. -this.rowContainer=document.createElement('div');this.rowContainer.classList.add('xterm-rows');this.element.appendChild(this.rowContainer);this.children=[];// Create the container that will hold helpers like the textarea for -// capturing DOM Events. Then produce the helpers. -this.helperContainer=document.createElement('div');this.helperContainer.classList.add('xterm-helpers');// TODO: This should probably be inserted once it's filled to prevent an additional layout -this.element.appendChild(this.helperContainer);this.textarea=document.createElement('textarea');this.textarea.classList.add('xterm-helper-textarea');this.textarea.setAttribute('autocorrect','off');this.textarea.setAttribute('autocapitalize','off');this.textarea.setAttribute('spellcheck','false');this.textarea.tabIndex=0;this.textarea.addEventListener('focus',function(){self.emit('focus',{terminal:self});});this.textarea.addEventListener('blur',function(){self.emit('blur',{terminal:self});});this.helperContainer.appendChild(this.textarea);this.compositionView=document.createElement('div');this.compositionView.classList.add('composition-view');this.compositionHelper=new _CompositionHelper.CompositionHelper(this.textarea,this.compositionView,this);this.helperContainer.appendChild(this.compositionView);this.charMeasureElement=document.createElement('div');this.charMeasureElement.classList.add('xterm-char-measure-element');this.charMeasureElement.innerHTML='W';this.helperContainer.appendChild(this.charMeasureElement);for(;i -function sendButton(ev){var button,pos;// get the xterm-style button -button=getButton(ev);// get mouse coordinates -pos=getCoords(ev);if(!pos)return;sendEvent(button,pos);switch(ev.overrideType||ev.type){case'mousedown':pressed=button;break;case'mouseup':// keep it at the left -// button, just in case. -pressed=32;break;case'wheel':// nothing. don't -// interfere with -// `pressed`. -break;}}// motion example of a left click: -// ^[[M 3<^[[M@4<^[[M@5<^[[M@6<^[[M@7<^[[M#7< -function sendMove(ev){var button=pressed,pos;pos=getCoords(ev);if(!pos)return;// buttons marked as motions -// are incremented by 32 -button+=32;sendEvent(button,pos);}// encode button and -// position to characters -function encode(data,ch){if(!self.utfMouse){if(ch===255)return data.push(0);if(ch>127)ch=127;data.push(ch);}else{if(ch===2047)return data.push(0);if(ch<127){data.push(ch);}else{if(ch>2047)ch=2047;data.push(0xC0|ch>>6);data.push(0x80|ch&0x3F);}}}// send a mouse event: -// regular/utf8: ^[[M Cb Cx Cy -// urxvt: ^[[ Cb ; Cx ; Cy M -// sgr: ^[[ Cb ; Cx ; Cy M/m -// vt300: ^[[ 24(1/3/5)~ [ Cx , Cy ] \r -// locator: CSI P e ; P b ; P r ; P c ; P p & w -function sendEvent(button,pos){// self.emit('mouse', { -// x: pos.x - 32, -// y: pos.x - 32, -// button: button -// }); -if(self.vt300Mouse){// NOTE: Unstable. -// http://www.vt100.net/docs/vt3xx-gp/chapter15.html -button&=3;pos.x-=32;pos.y-=32;var data='\x1b[24';if(button===0)data+='1';else if(button===1)data+='3';else if(button===2)data+='5';else if(button===3)return;else data+='0';data+='~['+pos.x+','+pos.y+']\r';self.send(data);return;}if(self.decLocator){// NOTE: Unstable. -button&=3;pos.x-=32;pos.y-=32;if(button===0)button=2;else if(button===1)button=4;else if(button===2)button=6;else if(button===3)button=3;self.send('\x1b['+button+';'+(button===3?4:0)+';'+pos.y+';'+pos.x+';'+(pos.page||0)+'&w');return;}if(self.urxvtMouse){pos.x-=32;pos.y-=32;pos.x++;pos.y++;self.send('\x1b['+button+';'+pos.x+';'+pos.y+'M');return;}if(self.sgrMouse){pos.x-=32;pos.y-=32;self.send('\x1b[<'+((button&3)===3?button&~3:button)+';'+pos.x+';'+pos.y+((button&3)===3?'m':'M'));return;}var data=[];encode(data,button);encode(data,pos.x);encode(data,pos.y);self.send('\x1b[M'+String.fromCharCode.apply(String,data));}function getButton(ev){var button,shift,meta,ctrl,mod;// two low bits: -// 0 = left -// 1 = middle -// 2 = right -// 3 = release -// wheel up/down: -// 1, and 2 - with 64 added -switch(ev.overrideType||ev.type){case'mousedown':button=ev.button!=null?+ev.button:ev.which!=null?ev.which-1:null;if(self.browser.isMSIE){button=button===1?0:button===4?1:button;}break;case'mouseup':button=3;break;case'DOMMouseScroll':button=ev.detail<0?64:65;break;case'wheel':button=ev.wheelDeltaY>0?64:65;break;}// next three bits are the modifiers: -// 4 = shift, 8 = meta, 16 = control -shift=ev.shiftKey?4:0;meta=ev.metaKey?8:0;ctrl=ev.ctrlKey?16:0;mod=shift|meta|ctrl;// no mods -if(self.vt200Mouse){// ctrl only -mod&=ctrl;}else if(!self.normalMouse){mod=0;}// increment to SP -button=32+(mod<<2)+button;return button;}// mouse coordinates measured in cols/rows -function getCoords(ev){var x,y,w,h,el;// ignore browsers without pageX for now -if(ev.pageX==null)return;x=ev.pageX;y=ev.pageY;el=self.element;// should probably check offsetParent -// but this is more portable -while(el&&el!==self.document.documentElement){x-=el.offsetLeft;y-=el.offsetTop;el='offsetParent'in el?el.offsetParent:el.parentNode;}// convert to cols/rows -w=self.element.clientWidth;h=self.element.clientHeight;x=Math.ceil(x/w*self.cols);y=Math.ceil(y/h*self.rows);// be sure to avoid sending -// bad positions to the program -if(x<0)x=0;if(x>self.cols)x=self.cols;if(y<0)y=0;if(y>self.rows)y=self.rows;// xterm sends raw bytes and -// starts at 32 (SP) for each. -x+=32;y+=32;return{x:x,y:y,type:'wheel'};}on(el,'mousedown',function(ev){if(!self.mouseEvents)return;// send the button -sendButton(ev);// ensure focus -self.focus();// fix for odd bug -//if (self.vt200Mouse && !self.normalMouse) { -if(self.vt200Mouse){ev.overrideType='mouseup';sendButton(ev);return self.cancel(ev);}// bind events -if(self.normalMouse)on(self.document,'mousemove',sendMove);// x10 compatibility mode can't send button releases -if(!self.x10Mouse){on(self.document,'mouseup',function up(ev){sendButton(ev);if(self.normalMouse)off(self.document,'mousemove',sendMove);off(self.document,'mouseup',up);return self.cancel(ev);});}return self.cancel(ev);});//if (self.normalMouse) { -// on(self.document, 'mousemove', sendMove); -//} -on(el,'wheel',function(ev){if(!self.mouseEvents)return;if(self.x10Mouse||self.vt300Mouse||self.decLocator)return;sendButton(ev);return self.cancel(ev);});// allow wheel scrolling in -// the shell for example -on(el,'wheel',function(ev){if(self.mouseEvents)return;self.viewport.onWheel(ev);return self.cancel(ev);});};/** + */ +Terminal.prototype.bindMouse = function () { + var el = this.element, self = this, pressed = 32; + // mouseup, mousedown, wheel + // left click: ^[[M 3<^[[M#3< + // wheel up: ^[[M`3> + function sendButton(ev) { + var button, pos; + // get the xterm-style button + button = getButton(ev); + // get mouse coordinates + pos = getCoords(ev); + if (!pos) + return; + sendEvent(button, pos); + switch (ev.overrideType || ev.type) { + case 'mousedown': + pressed = button; + break; + case 'mouseup': + // keep it at the left + // button, just in case. + pressed = 32; + break; + case 'wheel': + // nothing. don't + // interfere with + // `pressed`. + break; + } + } + // motion example of a left click: + // ^[[M 3<^[[M@4<^[[M@5<^[[M@6<^[[M@7<^[[M#7< + function sendMove(ev) { + var button = pressed, pos; + pos = getCoords(ev); + if (!pos) + return; + // buttons marked as motions + // are incremented by 32 + button += 32; + sendEvent(button, pos); + } + // encode button and + // position to characters + function encode(data, ch) { + if (!self.utfMouse) { + if (ch === 255) + return data.push(0); + if (ch > 127) + ch = 127; + data.push(ch); + } + else { + if (ch === 2047) + return data.push(0); + if (ch < 127) { + data.push(ch); + } + else { + if (ch > 2047) + ch = 2047; + data.push(0xC0 | (ch >> 6)); + data.push(0x80 | (ch & 0x3F)); + } + } + } + // send a mouse event: + // regular/utf8: ^[[M Cb Cx Cy + // urxvt: ^[[ Cb ; Cx ; Cy M + // sgr: ^[[ Cb ; Cx ; Cy M/m + // vt300: ^[[ 24(1/3/5)~ [ Cx , Cy ] \r + // locator: CSI P e ; P b ; P r ; P c ; P p & w + function sendEvent(button, pos) { + // self.emit('mouse', { + // x: pos.x - 32, + // y: pos.x - 32, + // button: button + // }); + if (self.vt300Mouse) { + // NOTE: Unstable. + // http://www.vt100.net/docs/vt3xx-gp/chapter15.html + button &= 3; + pos.x -= 32; + pos.y -= 32; + var data = '\x1b[24'; + if (button === 0) + data += '1'; + else if (button === 1) + data += '3'; + else if (button === 2) + data += '5'; + else if (button === 3) + return; + else + data += '0'; + data += '~[' + pos.x + ',' + pos.y + ']\r'; + self.send(data); + return; + } + if (self.decLocator) { + // NOTE: Unstable. + button &= 3; + pos.x -= 32; + pos.y -= 32; + if (button === 0) + button = 2; + else if (button === 1) + button = 4; + else if (button === 2) + button = 6; + else if (button === 3) + button = 3; + self.send('\x1b[' + + button + + ';' + + (button === 3 ? 4 : 0) + + ';' + + pos.y + + ';' + + pos.x + + ';' + + (pos.page || 0) + + '&w'); + return; + } + if (self.urxvtMouse) { + pos.x -= 32; + pos.y -= 32; + pos.x++; + pos.y++; + self.send('\x1b[' + button + ';' + pos.x + ';' + pos.y + 'M'); + return; + } + if (self.sgrMouse) { + pos.x -= 32; + pos.y -= 32; + self.send('\x1b[<' + + ((button & 3) === 3 ? button & ~3 : button) + + ';' + + pos.x + + ';' + + pos.y + + ((button & 3) === 3 ? 'm' : 'M')); + return; + } + var data = []; + encode(data, button); + encode(data, pos.x); + encode(data, pos.y); + self.send('\x1b[M' + String.fromCharCode.apply(String, data)); + } + function getButton(ev) { + var button, shift, meta, ctrl, mod; + // two low bits: + // 0 = left + // 1 = middle + // 2 = right + // 3 = release + // wheel up/down: + // 1, and 2 - with 64 added + switch (ev.overrideType || ev.type) { + case 'mousedown': + button = ev.button != null + ? +ev.button + : ev.which != null + ? ev.which - 1 + : null; + if (self.browser.isMSIE) { + button = button === 1 ? 0 : button === 4 ? 1 : button; + } + break; + case 'mouseup': + button = 3; + break; + case 'DOMMouseScroll': + button = ev.detail < 0 + ? 64 + : 65; + break; + case 'wheel': + button = ev.wheelDeltaY > 0 + ? 64 + : 65; + break; + } + // next three bits are the modifiers: + // 4 = shift, 8 = meta, 16 = control + shift = ev.shiftKey ? 4 : 0; + meta = ev.metaKey ? 8 : 0; + ctrl = ev.ctrlKey ? 16 : 0; + mod = shift | meta | ctrl; + // no mods + if (self.vt200Mouse) { + // ctrl only + mod &= ctrl; + } + else if (!self.normalMouse) { + mod = 0; + } + // increment to SP + button = (32 + (mod << 2)) + button; + return button; + } + // mouse coordinates measured in cols/rows + function getCoords(ev) { + var x, y, w, h, el; + // ignore browsers without pageX for now + if (ev.pageX == null) + return; + x = ev.pageX; + y = ev.pageY; + el = self.element; + // should probably check offsetParent + // but this is more portable + while (el && el !== self.document.documentElement) { + x -= el.offsetLeft; + y -= el.offsetTop; + el = 'offsetParent' in el + ? el.offsetParent + : el.parentNode; + } + // convert to cols/rows + w = self.element.clientWidth; + h = self.element.clientHeight; + x = Math.ceil((x / w) * self.cols); + y = Math.ceil((y / h) * self.rows); + // be sure to avoid sending + // bad positions to the program + if (x < 0) + x = 0; + if (x > self.cols) + x = self.cols; + if (y < 0) + y = 0; + if (y > self.rows) + y = self.rows; + // xterm sends raw bytes and + // starts at 32 (SP) for each. + x += 32; + y += 32; + return { + x: x, + y: y, + type: 'wheel' + }; + } + on(el, 'mousedown', function (ev) { + if (!self.mouseEvents) + return; + // send the button + sendButton(ev); + // ensure focus + self.focus(); + // fix for odd bug + //if (self.vt200Mouse && !self.normalMouse) { + if (self.vt200Mouse) { + ev.overrideType = 'mouseup'; + sendButton(ev); + return self.cancel(ev); + } + // bind events + if (self.normalMouse) + on(self.document, 'mousemove', sendMove); + // x10 compatibility mode can't send button releases + if (!self.x10Mouse) { + on(self.document, 'mouseup', function up(ev) { + sendButton(ev); + if (self.normalMouse) + off(self.document, 'mousemove', sendMove); + off(self.document, 'mouseup', up); + return self.cancel(ev); + }); + } + return self.cancel(ev); + }); + //if (self.normalMouse) { + // on(self.document, 'mousemove', sendMove); + //} + on(el, 'wheel', function (ev) { + if (!self.mouseEvents) + return; + if (self.x10Mouse + || self.vt300Mouse + || self.decLocator) + return; + sendButton(ev); + return self.cancel(ev); + }); + // allow wheel scrolling in + // the shell for example + on(el, 'wheel', function (ev) { + if (self.mouseEvents) + return; + self.viewport.onWheel(ev); + return self.cancel(ev); + }); +}; +/** * Destroys the terminal. - */Terminal.prototype.destroy=function(){this.readable=false;this.writable=false;this._events={};this.handler=function(){};this.write=function(){};if(this.element.parentNode){this.element.parentNode.removeChild(this.element);}//this.emit('close'); -};/** + */ +Terminal.prototype.destroy = function () { + this.readable = false; + this.writable = false; + this._events = {}; + this.handler = function () { }; + this.write = function () { }; + if (this.element.parentNode) { + this.element.parentNode.removeChild(this.element); + } + //this.emit('close'); +}; +/** * Flags used to render terminal text properly - */Terminal.flags={BOLD:1,UNDERLINE:2,BLINK:4,INVERSE:8,INVISIBLE:16};/** + */ +Terminal.flags = { + BOLD: 1, + UNDERLINE: 2, + BLINK: 4, + INVERSE: 8, + INVISIBLE: 16 +}; +/** * Refreshes (re-renders) terminal content within two rows (inclusive) * * Rendering Engine: @@ -875,605 +1416,2083 @@ on(el,'wheel',function(ev){if(self.mouseEvents)return;self.viewport.onWheel(ev); * @param {number} start The row to start from (between 0 and terminal's height terminal - 1) * @param {number} end The row to end at (between fromRow and terminal's height terminal - 1) * @param {boolean} queue Whether the refresh should ran right now or be queued - */Terminal.prototype.refresh=function(start,end,queue){var self=this;// queue defaults to true -queue=typeof queue=='undefined'?true:queue;/** - * The refresh queue allows refresh to execute only approximately 30 times a second. For - * commands that pass a significant amount of output to the write function, this prevents the - * terminal from maxing out the CPU and making the UI unresponsive. While commands can still - * run beyond what they do on the terminal, it is far better with a debounce in place as - * every single terminal manipulation does not need to be constructed in the DOM. - * - * A side-effect of this is that it makes ^C to interrupt a process seem more responsive. - */if(queue){// If refresh should be queued, order the refresh and return. -if(this._refreshIsQueued){// If a refresh has already been queued, just order a full refresh next -this._fullRefreshNext=true;}else{setTimeout(function(){self.refresh(start,end,false);},34);this._refreshIsQueued=true;}return;}// If refresh should be run right now (not be queued), release the lock -this._refreshIsQueued=false;// If multiple refreshes were requested, make a full refresh. -if(this._fullRefreshNext){start=0;end=this.rows-1;this._fullRefreshNext=false;// reset lock -}var x,y,i,line,out,ch,ch_width,width,data,attr,bg,fg,flags,row,parent,focused=document.activeElement;// If this is a big refresh, remove the terminal rows from the DOM for faster calculations -if(end-start>=this.rows/2){parent=this.element.parentNode;if(parent){this.element.removeChild(this.rowContainer);}}width=this.cols;y=start;if(end>=this.rows.length){this.log('`end` is too large. Most likely a bad CSR.');end=this.rows.length-1;}for(;y<=end;y++){row=y+this.ydisp;line=this.lines[row];out='';if(this.y===y-(this.ybase-this.ydisp)&&this.cursorState&&!this.cursorHidden){x=this.x;}else{x=-1;}attr=this.defAttr;i=0;for(;i';}if(data!==this.defAttr){if(data===-1){out+='';}else{var classNames=[];bg=data&0x1ff;fg=data>>9&0x1ff;flags=data>>18;if(flags&Terminal.flags.BOLD){if(!Terminal.brokenBold){classNames.push('xterm-bold');}// See: XTerm*boldColors -if(fg<8)fg+=8;}if(flags&Terminal.flags.UNDERLINE){classNames.push('xterm-underline');}if(flags&Terminal.flags.BLINK){classNames.push('xterm-blink');}// If inverse flag is on, then swap the foreground and background variables. -if(flags&Terminal.flags.INVERSE){/* One-line variable swap in JavaScript: http://stackoverflow.com/a/16201730 */bg=[fg,fg=bg][0];// Should inverse just be before the -// above boldColors effect instead? -if(flags&1&&fg<8)fg+=8;}if(flags&Terminal.flags.INVISIBLE){classNames.push('xterm-hidden');}/** - * Weird situation: Invert flag used black foreground and white background results - * in invalid background color, positioned at the 256 index of the 256 terminal - * color map. Pin the colors manually in such a case. - * - * Source: https://github.com/sourcelair/xterm.js/issues/57 - */if(flags&Terminal.flags.INVERSE){if(bg==257){bg=15;}if(fg==256){fg=0;}}if(bg<256){classNames.push('xterm-bg-color-'+bg);}if(fg<256){classNames.push('xterm-color-'+fg);}out+='':out+='>';break;default:if(ch<=' '){out+=' ';}else{out+=ch;}break;}attr=data;}if(attr!==this.defAttr){out+='';}this.children[y].innerHTML=out;}if(parent){this.element.appendChild(this.rowContainer);}this.emit('refresh',{element:this.element,start:start,end:end});};/** + */ +Terminal.prototype.refresh = function (start, end, queue) { + var self = this; + // queue defaults to true + queue = (typeof queue == 'undefined') ? true : queue; + /** + * The refresh queue allows refresh to execute only approximately 30 times a second. For + * commands that pass a significant amount of output to the write function, this prevents the + * terminal from maxing out the CPU and making the UI unresponsive. While commands can still + * run beyond what they do on the terminal, it is far better with a debounce in place as + * every single terminal manipulation does not need to be constructed in the DOM. + * + * A side-effect of this is that it makes ^C to interrupt a process seem more responsive. + */ + if (queue) { + // If refresh should be queued, order the refresh and return. + if (this._refreshIsQueued) { + // If a refresh has already been queued, just order a full refresh next + this._fullRefreshNext = true; + } + else { + setTimeout(function () { + self.refresh(start, end, false); + }, 34); + this._refreshIsQueued = true; + } + return; + } + // If refresh should be run right now (not be queued), release the lock + this._refreshIsQueued = false; + // If multiple refreshes were requested, make a full refresh. + if (this._fullRefreshNext) { + start = 0; + end = this.rows - 1; + this._fullRefreshNext = false; // reset lock + } + var x, y, i, line, out, ch, ch_width, width, data, attr, bg, fg, flags, row, parent, focused = document.activeElement; + // If this is a big refresh, remove the terminal rows from the DOM for faster calculations + if (end - start >= this.rows / 2) { + parent = this.element.parentNode; + if (parent) { + this.element.removeChild(this.rowContainer); + } + } + width = this.cols; + y = start; + if (end >= this.rows.length) { + this.log('`end` is too large. Most likely a bad CSR.'); + end = this.rows.length - 1; + } + for (; y <= end; y++) { + row = y + this.ydisp; + line = this.lines[row]; + out = ''; + if (this.y === y - (this.ybase - this.ydisp) + && this.cursorState + && !this.cursorHidden) { + x = this.x; + } + else { + x = -1; + } + attr = this.defAttr; + i = 0; + for (; i < width; i++) { + data = line[i][0]; + ch = line[i][1]; + ch_width = line[i][2]; + if (!ch_width) + continue; + if (i === x) + data = -1; + if (data !== attr) { + if (attr !== this.defAttr) { + out += ''; + } + if (data !== this.defAttr) { + if (data === -1) { + out += ''; + } + else { + var classNames = []; + bg = data & 0x1ff; + fg = (data >> 9) & 0x1ff; + flags = data >> 18; + if (flags & Terminal.flags.BOLD) { + if (!Terminal.brokenBold) { + classNames.push('xterm-bold'); + } + // See: XTerm*boldColors + if (fg < 8) + fg += 8; + } + if (flags & Terminal.flags.UNDERLINE) { + classNames.push('xterm-underline'); + } + if (flags & Terminal.flags.BLINK) { + classNames.push('xterm-blink'); + } + // If inverse flag is on, then swap the foreground and background variables. + if (flags & Terminal.flags.INVERSE) { + /* One-line variable swap in JavaScript: http://stackoverflow.com/a/16201730 */ + bg = [fg, fg = bg][0]; + // Should inverse just be before the + // above boldColors effect instead? + if ((flags & 1) && fg < 8) + fg += 8; + } + if (flags & Terminal.flags.INVISIBLE) { + classNames.push('xterm-hidden'); + } + /** + * Weird situation: Invert flag used black foreground and white background results + * in invalid background color, positioned at the 256 index of the 256 terminal + * color map. Pin the colors manually in such a case. + * + * Source: https://github.com/sourcelair/xterm.js/issues/57 + */ + if (flags & Terminal.flags.INVERSE) { + if (bg == 257) { + bg = 15; + } + if (fg == 256) { + fg = 0; + } + } + if (bg < 256) { + classNames.push('xterm-bg-color-' + bg); + } + if (fg < 256) { + classNames.push('xterm-color-' + fg); + } + out += '': + out += '>'; + break; + default: + if (ch <= ' ') { + out += ' '; + } + else { + out += ch; + } + break; + } + attr = data; + } + if (attr !== this.defAttr) { + out += ''; + } + this.children[y].innerHTML = out; + } + if (parent) { + this.element.appendChild(this.rowContainer); + } + this.emit('refresh', { element: this.element, start: start, end: end }); +}; +/** * Display the cursor element - */Terminal.prototype.showCursor=function(){if(!this.cursorState){this.cursorState=1;this.refresh(this.y,this.y);}};/** + */ +Terminal.prototype.showCursor = function () { + if (!this.cursorState) { + this.cursorState = 1; + this.refresh(this.y, this.y); + } +}; +/** * Scroll the terminal - */Terminal.prototype.scroll=function(){var row;if(++this.ybase===this.scrollback){this.ybase=this.ybase/2|0;this.lines=this.lines.slice(-(this.ybase+this.rows)+1);}if(!this.userScrolling){this.ydisp=this.ybase;}// last line -row=this.ybase+this.rows-1;// subtract the bottom scroll region -row-=this.rows-1-this.scrollBottom;if(row===this.lines.length){// potential optimization: -// pushing is faster than splicing -// when they amount to the same -// behavior. -this.lines.push(this.blankLine());}else{// add our new line -this.lines.splice(row,0,this.blankLine());}if(this.scrollTop!==0){if(this.ybase!==0){this.ybase--;if(!this.userScrolling){this.ydisp=this.ybase;}}this.lines.splice(this.ybase+this.scrollTop,1);}// this.maxRange(); -this.updateRange(this.scrollTop);this.updateRange(this.scrollBottom);this.emit('scroll',this.ydisp);};/** + */ +Terminal.prototype.scroll = function () { + var row; + if (++this.ybase === this.scrollback) { + this.ybase = this.ybase / 2 | 0; + this.lines = this.lines.slice(-(this.ybase + this.rows) + 1); + } + if (!this.userScrolling) { + this.ydisp = this.ybase; + } + // last line + row = this.ybase + this.rows - 1; + // subtract the bottom scroll region + row -= this.rows - 1 - this.scrollBottom; + if (row === this.lines.length) { + // potential optimization: + // pushing is faster than splicing + // when they amount to the same + // behavior. + this.lines.push(this.blankLine()); + } + else { + // add our new line + this.lines.splice(row, 0, this.blankLine()); + } + if (this.scrollTop !== 0) { + if (this.ybase !== 0) { + this.ybase--; + if (!this.userScrolling) { + this.ydisp = this.ybase; + } + } + this.lines.splice(this.ybase + this.scrollTop, 1); + } + // this.maxRange(); + this.updateRange(this.scrollTop); + this.updateRange(this.scrollBottom); + /** + * This event is emitted whenever the terminal is scrolled. + * The one parameter passed is the new y display position. + * + * @event scroll + */ + this.emit('scroll', this.ydisp); +}; +/** * Scroll the display of the terminal * @param {number} disp The number of lines to scroll down (negatives scroll up). * @param {boolean} suppressScrollEvent Don't emit the scroll event as scrollDisp. This is used * to avoid unwanted events being handled by the veiwport when the event was triggered from the * viewport originally. - */Terminal.prototype.scrollDisp=function(disp,suppressScrollEvent){if(disp<0){this.userScrolling=true;}else if(disp+this.ydisp>=this.ybase){this.userScrolling=false;}this.ydisp+=disp;if(this.ydisp>this.ybase){this.ydisp=this.ybase;}else if(this.ydisp<0){this.ydisp=0;}if(!suppressScrollEvent){this.emit('scroll',this.ydisp);}this.refresh(0,this.rows-1);};/** + */ +Terminal.prototype.scrollDisp = function (disp, suppressScrollEvent) { + if (disp < 0) { + this.userScrolling = true; + } + else if (disp + this.ydisp >= this.ybase) { + this.userScrolling = false; + } + this.ydisp += disp; + if (this.ydisp > this.ybase) { + this.ydisp = this.ybase; + } + else if (this.ydisp < 0) { + this.ydisp = 0; + } + if (!suppressScrollEvent) { + this.emit('scroll', this.ydisp); + } + this.refresh(0, this.rows - 1); +}; +/** * Scroll the display of the terminal by a number of pages. * @param {number} pageCount The number of pages to scroll (negative scrolls up). - */Terminal.prototype.scrollPages=function(pageCount){this.scrollDisp(pageCount*(this.rows-1));};/** + */ +Terminal.prototype.scrollPages = function (pageCount) { + this.scrollDisp(pageCount * (this.rows - 1)); +}; +/** * Scrolls the display of the terminal to the top. - */Terminal.prototype.scrollToTop=function(){this.scrollDisp(-this.ydisp);};/** + */ +Terminal.prototype.scrollToTop = function () { + this.scrollDisp(-this.ydisp); +}; +/** * Scrolls the display of the terminal to the bottom. - */Terminal.prototype.scrollToBottom=function(){this.scrollDisp(this.ybase-this.ydisp);};/** + */ +Terminal.prototype.scrollToBottom = function () { + this.scrollDisp(this.ybase - this.ydisp); +}; +/** * Writes text to the terminal. * @param {string} text The text to write to the terminal. - */Terminal.prototype.write=function(data){var l=data.length,i=0,j,cs,ch,code,low,ch_width,row;this.refreshStart=this.y;this.refreshEnd=this.y;// apply leftover surrogate high from last write -if(this.surrogate_high){data=this.surrogate_high+data;this.surrogate_high='';}for(;i maybe move to default -code=data.charCodeAt(i);if(0xD800<=code&&code<=0xDBFF){// we got a surrogate high -// get surrogate low (next 2 bytes) -low=data.charCodeAt(i+1);if(isNaN(low)){// end of data stream, save surrogate high -this.surrogate_high=ch;continue;}code=(code-0xD800)*0x400+(low-0xDC00)+0x10000;ch+=data.charAt(i+1);}// surrogate low - already handled above -if(0xDC00<=code&&code<=0xDFFF)continue;switch(this.state){case normal:switch(ch){case'\x07':this.bell();break;// '\n', '\v', '\f' -case'\n':case'\x0b':case'\x0c':if(this.convertEol){this.x=0;}this.y++;if(this.y>this.scrollBottom){this.y--;this.scroll();}break;// '\r' -case'\r':this.x=0;break;// '\b' -case'\x08':if(this.x>0){this.x--;}break;// '\t' -case'\t':this.x=this.nextStop();break;// shift out -case'\x0e':this.setgLevel(1);break;// shift in -case'\x0f':this.setgLevel(0);break;// '\e' -case'\x1b':this.state=escaped;break;default:// ' ' -// calculate print space -// expensive call, therefore we save width in line buffer -ch_width=wcwidth(code);if(ch>=' '){if(this.charset&&this.charset[ch]){ch=this.charset[ch];}row=this.y+this.ybase;// insert combining char in last cell -// FIXME: needs handling after cursor jumps -if(!ch_width&&this.x){// dont overflow left -if(this.lines[row][this.x-1]){if(!this.lines[row][this.x-1][2]){// found empty cell after fullwidth, need to go 2 cells back -if(this.lines[row][this.x-2])this.lines[row][this.x-2][1]+=ch;}else{this.lines[row][this.x-1][1]+=ch;}this.updateRange(this.y);}break;}// goto next line if ch would overflow -// TODO: needs a global min terminal width of 2 -if(this.x+ch_width-1>=this.cols){// autowrap - DECAWM -if(this.wraparoundMode){this.x=0;this.y++;if(this.y>this.scrollBottom){this.y--;this.scroll();}}else{this.x=this.cols-1;if(ch_width===2)// FIXME: check for xterm behavior -continue;}}row=this.y+this.ybase;// insert mode: move characters to right -if(this.insertMode){// do this twice for a fullwidth char -for(var moves=0;moves Normal Keypad (DECKPNM). -case'>':this.log('Switching back to normal keypad.');this.applicationKeypad=false;this.viewport.syncScrollArea();this.state=normal;break;default:this.state=normal;this.error('Unknown ESC control: %s.',ch);break;}break;case charset:switch(ch){case'0':// DEC Special Character and Line Drawing Set. -cs=Terminal.charsets.SCLD;break;case'A':// UK -cs=Terminal.charsets.UK;break;case'B':// United States (USASCII). -cs=Terminal.charsets.US;break;case'4':// Dutch -cs=Terminal.charsets.Dutch;break;case'C':// Finnish -case'5':cs=Terminal.charsets.Finnish;break;case'R':// French -cs=Terminal.charsets.French;break;case'Q':// FrenchCanadian -cs=Terminal.charsets.FrenchCanadian;break;case'K':// German -cs=Terminal.charsets.German;break;case'Y':// Italian -cs=Terminal.charsets.Italian;break;case'E':// NorwegianDanish -case'6':cs=Terminal.charsets.NorwegianDanish;break;case'Z':// Spanish -cs=Terminal.charsets.Spanish;break;case'H':// Swedish -case'7':cs=Terminal.charsets.Swedish;break;case'=':// Swiss -cs=Terminal.charsets.Swiss;break;case'/':// ISOLatin (actually /A) -cs=Terminal.charsets.ISOLatin;i++;break;default:// Default -cs=Terminal.charsets.US;break;}this.setgCharset(this.gcharset,cs);this.gcharset=null;this.state=normal;break;case osc:// OSC Ps ; Pt ST -// OSC Ps ; Pt BEL -// Set Text Parameters. -if(ch==='\x1b'||ch==='\x07'){if(ch==='\x1b')i++;this.params.push(this.currentParam);switch(this.params[0]){case 0:case 1:case 2:if(this.params[1]){this.title=this.params[1];this.handleTitle(this.title);}break;case 3:// set X property -break;case 4:case 5:// change dynamic colors -break;case 10:case 11:case 12:case 13:case 14:case 15:case 16:case 17:case 18:case 19:// change dynamic ui colors -break;case 46:// change log file -break;case 50:// dynamic font -break;case 51:// emacs shell -break;case 52:// manipulate selection data -break;case 104:case 105:case 110:case 111:case 112:case 113:case 114:case 115:case 116:case 117:case 118:// reset colors -break;}this.params=[];this.currentParam=0;this.state=normal;}else{if(!this.params.length){if(ch>='0'&&ch<='9'){this.currentParam=this.currentParam*10+ch.charCodeAt(0)-48;}else if(ch===';'){this.params.push(this.currentParam);this.currentParam='';}}else{this.currentParam+=ch;}}break;case csi:// '?', '>', '!' -if(ch==='?'||ch==='>'||ch==='!'){this.prefix=ch;break;}// 0 - 9 -if(ch>='0'&&ch<='9'){this.currentParam=this.currentParam*10+ch.charCodeAt(0)-48;break;}// '$', '"', ' ', '\'' -if(ch==='$'||ch==='"'||ch===' '||ch==='\''){this.postfix=ch;break;}this.params.push(this.currentParam);this.currentParam=0;// ';' -if(ch===';')break;this.state=normal;switch(ch){// CSI Ps A -// Cursor Up Ps Times (default = 1) (CUU). -case'A':this.cursorUp(this.params);break;// CSI Ps B -// Cursor Down Ps Times (default = 1) (CUD). -case'B':this.cursorDown(this.params);break;// CSI Ps C -// Cursor Forward Ps Times (default = 1) (CUF). -case'C':this.cursorForward(this.params);break;// CSI Ps D -// Cursor Backward Ps Times (default = 1) (CUB). -case'D':this.cursorBackward(this.params);break;// CSI Ps ; Ps H -// Cursor Position [row;column] (default = [1,1]) (CUP). -case'H':this.cursorPos(this.params);break;// CSI Ps J Erase in Display (ED). -case'J':this.eraseInDisplay(this.params);break;// CSI Ps K Erase in Line (EL). -case'K':this.eraseInLine(this.params);break;// CSI Pm m Character Attributes (SGR). -case'm':if(!this.prefix){this.charAttributes(this.params);}break;// CSI Ps n Device Status Report (DSR). -case'n':if(!this.prefix){this.deviceStatus(this.params);}break;/** - * Additions - */// CSI Ps @ -// Insert Ps (Blank) Character(s) (default = 1) (ICH). -case'@':this.insertChars(this.params);break;// CSI Ps E -// Cursor Next Line Ps Times (default = 1) (CNL). -case'E':this.cursorNextLine(this.params);break;// CSI Ps F -// Cursor Preceding Line Ps Times (default = 1) (CNL). -case'F':this.cursorPrecedingLine(this.params);break;// CSI Ps G -// Cursor Character Absolute [column] (default = [row,1]) (CHA). -case'G':this.cursorCharAbsolute(this.params);break;// CSI Ps L -// Insert Ps Line(s) (default = 1) (IL). -case'L':this.insertLines(this.params);break;// CSI Ps M -// Delete Ps Line(s) (default = 1) (DL). -case'M':this.deleteLines(this.params);break;// CSI Ps P -// Delete Ps Character(s) (default = 1) (DCH). -case'P':this.deleteChars(this.params);break;// CSI Ps X -// Erase Ps Character(s) (default = 1) (ECH). -case'X':this.eraseChars(this.params);break;// CSI Pm ` Character Position Absolute -// [column] (default = [row,1]) (HPA). -case'`':this.charPosAbsolute(this.params);break;// 141 61 a * HPR - -// Horizontal Position Relative -case'a':this.HPositionRelative(this.params);break;// CSI P s c -// Send Device Attributes (Primary DA). -// CSI > P s c -// Send Device Attributes (Secondary DA) -case'c':this.sendDeviceAttributes(this.params);break;// CSI Pm d -// Line Position Absolute [row] (default = [1,column]) (VPA). -case'd':this.linePosAbsolute(this.params);break;// 145 65 e * VPR - Vertical Position Relative -case'e':this.VPositionRelative(this.params);break;// CSI Ps ; Ps f -// Horizontal and Vertical Position [row;column] (default = -// [1,1]) (HVP). -case'f':this.HVPosition(this.params);break;// CSI Pm h Set Mode (SM). -// CSI ? Pm h - mouse escape codes, cursor escape codes -case'h':this.setMode(this.params);break;// CSI Pm l Reset Mode (RM). -// CSI ? Pm l -case'l':this.resetMode(this.params);break;// CSI Ps ; Ps r -// Set Scrolling Region [top;bottom] (default = full size of win- -// dow) (DECSTBM). -// CSI ? Pm r -case'r':this.setScrollRegion(this.params);break;// CSI s -// Save cursor (ANSI.SYS). -case's':this.saveCursor(this.params);break;// CSI u -// Restore cursor (ANSI.SYS). -case'u':this.restoreCursor(this.params);break;/** - * Lesser Used - */// CSI Ps I -// Cursor Forward Tabulation Ps tab stops (default = 1) (CHT). -case'I':this.cursorForwardTab(this.params);break;// CSI Ps S Scroll up Ps lines (default = 1) (SU). -case'S':this.scrollUp(this.params);break;// CSI Ps T Scroll down Ps lines (default = 1) (SD). -// CSI Ps ; Ps ; Ps ; Ps ; Ps T -// CSI > Ps; Ps T -case'T':// if (this.prefix === '>') { -// this.resetTitleModes(this.params); -// break; -// } -// if (this.params.length > 2) { -// this.initMouseTracking(this.params); -// break; -// } -if(this.params.length<2&&!this.prefix){this.scrollDown(this.params);}break;// CSI Ps Z -// Cursor Backward Tabulation Ps tab stops (default = 1) (CBT). -case'Z':this.cursorBackwardTab(this.params);break;// CSI Ps b Repeat the preceding graphic character Ps times (REP). -case'b':this.repeatPrecedingCharacter(this.params);break;// CSI Ps g Tab Clear (TBC). -case'g':this.tabClear(this.params);break;// CSI Pm i Media Copy (MC). -// CSI ? Pm i -// case 'i': -// this.mediaCopy(this.params); -// break; -// CSI Pm m Character Attributes (SGR). -// CSI > Ps; Ps m -// case 'm': // duplicate -// if (this.prefix === '>') { -// this.setResources(this.params); -// } else { -// this.charAttributes(this.params); -// } -// break; -// CSI Ps n Device Status Report (DSR). -// CSI > Ps n -// case 'n': // duplicate -// if (this.prefix === '>') { -// this.disableModifiers(this.params); -// } else { -// this.deviceStatus(this.params); -// } -// break; -// CSI > Ps p Set pointer mode. -// CSI ! p Soft terminal reset (DECSTR). -// CSI Ps$ p -// Request ANSI mode (DECRQM). -// CSI ? Ps$ p -// Request DEC private mode (DECRQM). -// CSI Ps ; Ps " p -case'p':switch(this.prefix){// case '>': -// this.setPointerMode(this.params); -// break; -case'!':this.softReset(this.params);break;// case '?': -// if (this.postfix === '$') { -// this.requestPrivateMode(this.params); -// } -// break; -// default: -// if (this.postfix === '"') { -// this.setConformanceLevel(this.params); -// } else if (this.postfix === '$') { -// this.requestAnsiMode(this.params); -// } -// break; -}break;// CSI Ps q Load LEDs (DECLL). -// CSI Ps SP q -// CSI Ps " q -// case 'q': -// if (this.postfix === ' ') { -// this.setCursorStyle(this.params); -// break; -// } -// if (this.postfix === '"') { -// this.setCharProtectionAttr(this.params); -// break; -// } -// this.loadLEDs(this.params); -// break; -// CSI Ps ; Ps r -// Set Scrolling Region [top;bottom] (default = full size of win- -// dow) (DECSTBM). -// CSI ? Pm r -// CSI Pt; Pl; Pb; Pr; Ps$ r -// case 'r': // duplicate -// if (this.prefix === '?') { -// this.restorePrivateValues(this.params); -// } else if (this.postfix === '$') { -// this.setAttrInRectangle(this.params); -// } else { -// this.setScrollRegion(this.params); -// } -// break; -// CSI s Save cursor (ANSI.SYS). -// CSI ? Pm s -// case 's': // duplicate -// if (this.prefix === '?') { -// this.savePrivateValues(this.params); -// } else { -// this.saveCursor(this.params); -// } -// break; -// CSI Ps ; Ps ; Ps t -// CSI Pt; Pl; Pb; Pr; Ps$ t -// CSI > Ps; Ps t -// CSI Ps SP t -// case 't': -// if (this.postfix === '$') { -// this.reverseAttrInRectangle(this.params); -// } else if (this.postfix === ' ') { -// this.setWarningBellVolume(this.params); -// } else { -// if (this.prefix === '>') { -// this.setTitleModeFeature(this.params); -// } else { -// this.manipulateWindow(this.params); -// } -// } -// break; -// CSI u Restore cursor (ANSI.SYS). -// CSI Ps SP u -// case 'u': // duplicate -// if (this.postfix === ' ') { -// this.setMarginBellVolume(this.params); -// } else { -// this.restoreCursor(this.params); -// } -// break; -// CSI Pt; Pl; Pb; Pr; Pp; Pt; Pl; Pp$ v -// case 'v': -// if (this.postfix === '$') { -// this.copyRectagle(this.params); -// } -// break; -// CSI Pt ; Pl ; Pb ; Pr ' w -// case 'w': -// if (this.postfix === '\'') { -// this.enableFilterRectangle(this.params); -// } -// break; -// CSI Ps x Request Terminal Parameters (DECREQTPARM). -// CSI Ps x Select Attribute Change Extent (DECSACE). -// CSI Pc; Pt; Pl; Pb; Pr$ x -// case 'x': -// if (this.postfix === '$') { -// this.fillRectangle(this.params); -// } else { -// this.requestParameters(this.params); -// //this.__(this.params); -// } -// break; -// CSI Ps ; Pu ' z -// CSI Pt; Pl; Pb; Pr$ z -// case 'z': -// if (this.postfix === '\'') { -// this.enableLocatorReporting(this.params); -// } else if (this.postfix === '$') { -// this.eraseRectangle(this.params); -// } -// break; -// CSI Pm ' { -// CSI Pt; Pl; Pb; Pr$ { -// case '{': -// if (this.postfix === '\'') { -// this.setLocatorEvents(this.params); -// } else if (this.postfix === '$') { -// this.selectiveEraseRectangle(this.params); -// } -// break; -// CSI Ps ' | -// case '|': -// if (this.postfix === '\'') { -// this.requestLocatorPosition(this.params); -// } -// break; -// CSI P m SP } -// Insert P s Column(s) (default = 1) (DECIC), VT420 and up. -// case '}': -// if (this.postfix === ' ') { -// this.insertColumns(this.params); -// } -// break; -// CSI P m SP ~ -// Delete P s Column(s) (default = 1) (DECDC), VT420 and up -// case '~': -// if (this.postfix === ' ') { -// this.deleteColumns(this.params); -// } -// break; -default:this.error('Unknown CSI code: %s.',ch);break;}this.prefix='';this.postfix='';break;case dcs:if(ch==='\x1b'||ch==='\x07'){if(ch==='\x1b')i++;switch(this.prefix){// User-Defined Keys (DECUDK). -case'':break;// Request Status String (DECRQSS). -// test: echo -e '\eP$q"p\e\\' -case'$q':var pt=this.currentParam,valid=false;switch(pt){// DECSCA -case'"q':pt='0"q';break;// DECSCL -case'"p':pt='61"p';break;// DECSTBM -case'r':pt=''+(this.scrollTop+1)+';'+(this.scrollBottom+1)+'r';break;// SGR -case'm':pt='0m';break;default:this.error('Unknown DCS Pt: %s.',pt);pt='';break;}this.send('\x1bP'+ +valid+'$r'+pt+'\x1b\\');break;// Set Termcap/Terminfo Data (xterm, experimental). -case'+p':break;// Request Termcap/Terminfo String (xterm, experimental) -// Regular xterm does not even respond to this sequence. -// This can cause a small glitch in vim. -// test: echo -ne '\eP+q6b64\e\\' -case'+q':var pt=this.currentParam,valid=false;this.send('\x1bP'+ +valid+'+r'+pt+'\x1b\\');break;default:this.error('Unknown DCS prefix: %s.',this.prefix);break;}this.currentParam=0;this.prefix='';this.state=normal;}else if(!this.currentParam){if(!this.prefix&&ch!=='$'&&ch!=='+'){this.currentParam=ch;}else if(this.prefix.length===2){this.currentParam=ch;}else{this.prefix+=ch;}}else{this.currentParam+=ch;}break;case ignore:// For PM and APC. -if(ch==='\x1b'||ch==='\x07'){if(ch==='\x1b')i++;this.state=normal;}break;}}this.updateRange(this.y);this.refresh(this.refreshStart,this.refreshEnd);};/** + */ +Terminal.prototype.write = function (data) { + var l = data.length, i = 0, j, cs, ch, code, low, ch_width, row; + this.refreshStart = this.y; + this.refreshEnd = this.y; + // apply leftover surrogate high from last write + if (this.surrogate_high) { + data = this.surrogate_high + data; + this.surrogate_high = ''; + } + for (; i < l; i++) { + ch = data[i]; + // FIXME: higher chars than 0xa0 are not allowed in escape sequences + // --> maybe move to default + code = data.charCodeAt(i); + if (0xD800 <= code && code <= 0xDBFF) { + // we got a surrogate high + // get surrogate low (next 2 bytes) + low = data.charCodeAt(i + 1); + if (isNaN(low)) { + // end of data stream, save surrogate high + this.surrogate_high = ch; + continue; + } + code = ((code - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000; + ch += data.charAt(i + 1); + } + // surrogate low - already handled above + if (0xDC00 <= code && code <= 0xDFFF) + continue; + switch (this.state) { + case normal: + switch (ch) { + case '\x07': + this.bell(); + break; + // '\n', '\v', '\f' + case '\n': + case '\x0b': + case '\x0c': + if (this.convertEol) { + this.x = 0; + } + this.y++; + if (this.y > this.scrollBottom) { + this.y--; + this.scroll(); + } + break; + // '\r' + case '\r': + this.x = 0; + break; + // '\b' + case '\x08': + if (this.x > 0) { + this.x--; + } + break; + // '\t' + case '\t': + this.x = this.nextStop(); + break; + // shift out + case '\x0e': + this.setgLevel(1); + break; + // shift in + case '\x0f': + this.setgLevel(0); + break; + // '\e' + case '\x1b': + this.state = escaped; + break; + default: + // ' ' + // calculate print space + // expensive call, therefore we save width in line buffer + ch_width = wcwidth(code); + if (ch >= ' ') { + if (this.charset && this.charset[ch]) { + ch = this.charset[ch]; + } + row = this.y + this.ybase; + // insert combining char in last cell + // FIXME: needs handling after cursor jumps + if (!ch_width && this.x) { + // dont overflow left + if (this.lines[row][this.x - 1]) { + if (!this.lines[row][this.x - 1][2]) { + // found empty cell after fullwidth, need to go 2 cells back + if (this.lines[row][this.x - 2]) + this.lines[row][this.x - 2][1] += ch; + } + else { + this.lines[row][this.x - 1][1] += ch; + } + this.updateRange(this.y); + } + break; + } + // goto next line if ch would overflow + // TODO: needs a global min terminal width of 2 + if (this.x + ch_width - 1 >= this.cols) { + // autowrap - DECAWM + if (this.wraparoundMode) { + this.x = 0; + this.y++; + if (this.y > this.scrollBottom) { + this.y--; + this.scroll(); + } + } + else { + this.x = this.cols - 1; + if (ch_width === 2) + continue; + } + } + row = this.y + this.ybase; + // insert mode: move characters to right + if (this.insertMode) { + // do this twice for a fullwidth char + for (var moves = 0; moves < ch_width; ++moves) { + // remove last cell, if it's width is 0 + // we have to adjust the second last cell as well + var removed = this.lines[this.y + this.ybase].pop(); + if (removed[2] === 0 + && this.lines[row][this.cols - 2] + && this.lines[row][this.cols - 2][2] === 2) + this.lines[row][this.cols - 2] = [this.curAttr, ' ', 1]; + // insert empty cell at cursor + this.lines[row].splice(this.x, 0, [this.curAttr, ' ', 1]); + } + } + this.lines[row][this.x] = [this.curAttr, ch, ch_width]; + this.x++; + this.updateRange(this.y); + // fullwidth char - set next cell width to zero and advance cursor + if (ch_width === 2) { + this.lines[row][this.x] = [this.curAttr, '', 0]; + this.x++; + } + } + break; + } + break; + case escaped: + switch (ch) { + // ESC [ Control Sequence Introducer ( CSI is 0x9b). + case '[': + this.params = []; + this.currentParam = 0; + this.state = csi; + break; + // ESC ] Operating System Command ( OSC is 0x9d). + case ']': + this.params = []; + this.currentParam = 0; + this.state = osc; + break; + // ESC P Device Control String ( DCS is 0x90). + case 'P': + this.params = []; + this.currentParam = 0; + this.state = dcs; + break; + // ESC _ Application Program Command ( APC is 0x9f). + case '_': + this.state = ignore; + break; + // ESC ^ Privacy Message ( PM is 0x9e). + case '^': + this.state = ignore; + break; + // ESC c Full Reset (RIS). + case 'c': + this.reset(); + break; + // ESC E Next Line ( NEL is 0x85). + // ESC D Index ( IND is 0x84). + case 'E': + this.x = 0; + ; + case 'D': + this.index(); + break; + // ESC M Reverse Index ( RI is 0x8d). + case 'M': + this.reverseIndex(); + break; + // ESC % Select default/utf-8 character set. + // @ = default, G = utf-8 + case '%': + //this.charset = null; + this.setgLevel(0); + this.setgCharset(0, Terminal.charsets.US); + this.state = normal; + i++; + break; + // ESC (,),*,+,-,. Designate G0-G2 Character Set. + case '(': // <-- this seems to get all the attention + case ')': + case '*': + case '+': + case '-': + case '.': + switch (ch) { + case '(': + this.gcharset = 0; + break; + case ')': + this.gcharset = 1; + break; + case '*': + this.gcharset = 2; + break; + case '+': + this.gcharset = 3; + break; + case '-': + this.gcharset = 1; + break; + case '.': + this.gcharset = 2; + break; + } + this.state = charset; + break; + // Designate G3 Character Set (VT300). + // A = ISO Latin-1 Supplemental. + // Not implemented. + case '/': + this.gcharset = 3; + this.state = charset; + i--; + break; + // ESC N + // Single Shift Select of G2 Character Set + // ( SS2 is 0x8e). This affects next character only. + case 'N': + break; + // ESC O + // Single Shift Select of G3 Character Set + // ( SS3 is 0x8f). This affects next character only. + case 'O': + break; + // ESC n + // Invoke the G2 Character Set as GL (LS2). + case 'n': + this.setgLevel(2); + break; + // ESC o + // Invoke the G3 Character Set as GL (LS3). + case 'o': + this.setgLevel(3); + break; + // ESC | + // Invoke the G3 Character Set as GR (LS3R). + case '|': + this.setgLevel(3); + break; + // ESC } + // Invoke the G2 Character Set as GR (LS2R). + case '}': + this.setgLevel(2); + break; + // ESC ~ + // Invoke the G1 Character Set as GR (LS1R). + case '~': + this.setgLevel(1); + break; + // ESC 7 Save Cursor (DECSC). + case '7': + this.saveCursor(); + this.state = normal; + break; + // ESC 8 Restore Cursor (DECRC). + case '8': + this.restoreCursor(); + this.state = normal; + break; + // ESC # 3 DEC line height/width + case '#': + this.state = normal; + i++; + break; + // ESC H Tab Set (HTS is 0x88). + case 'H': + this.tabSet(); + break; + // ESC = Application Keypad (DECKPAM). + case '=': + this.log('Serial port requested application keypad.'); + this.applicationKeypad = true; + this.viewport.syncScrollArea(); + this.state = normal; + break; + // ESC > Normal Keypad (DECKPNM). + case '>': + this.log('Switching back to normal keypad.'); + this.applicationKeypad = false; + this.viewport.syncScrollArea(); + this.state = normal; + break; + default: + this.state = normal; + this.error('Unknown ESC control: %s.', ch); + break; + } + break; + case charset: + switch (ch) { + case '0': + cs = Terminal.charsets.SCLD; + break; + case 'A': + cs = Terminal.charsets.UK; + break; + case 'B': + cs = Terminal.charsets.US; + break; + case '4': + cs = Terminal.charsets.Dutch; + break; + case 'C': // Finnish + case '5': + cs = Terminal.charsets.Finnish; + break; + case 'R': + cs = Terminal.charsets.French; + break; + case 'Q': + cs = Terminal.charsets.FrenchCanadian; + break; + case 'K': + cs = Terminal.charsets.German; + break; + case 'Y': + cs = Terminal.charsets.Italian; + break; + case 'E': // NorwegianDanish + case '6': + cs = Terminal.charsets.NorwegianDanish; + break; + case 'Z': + cs = Terminal.charsets.Spanish; + break; + case 'H': // Swedish + case '7': + cs = Terminal.charsets.Swedish; + break; + case '=': + cs = Terminal.charsets.Swiss; + break; + case '/': + cs = Terminal.charsets.ISOLatin; + i++; + break; + default: + cs = Terminal.charsets.US; + break; + } + this.setgCharset(this.gcharset, cs); + this.gcharset = null; + this.state = normal; + break; + case osc: + // OSC Ps ; Pt ST + // OSC Ps ; Pt BEL + // Set Text Parameters. + if (ch === '\x1b' || ch === '\x07') { + if (ch === '\x1b') + i++; + this.params.push(this.currentParam); + switch (this.params[0]) { + case 0: + case 1: + case 2: + if (this.params[1]) { + this.title = this.params[1]; + this.handleTitle(this.title); + } + break; + case 3: + // set X property + break; + case 4: + case 5: + // change dynamic colors + break; + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + case 19: + // change dynamic ui colors + break; + case 46: + // change log file + break; + case 50: + // dynamic font + break; + case 51: + // emacs shell + break; + case 52: + // manipulate selection data + break; + case 104: + case 105: + case 110: + case 111: + case 112: + case 113: + case 114: + case 115: + case 116: + case 117: + case 118: + // reset colors + break; + } + this.params = []; + this.currentParam = 0; + this.state = normal; + } + else { + if (!this.params.length) { + if (ch >= '0' && ch <= '9') { + this.currentParam = + this.currentParam * 10 + ch.charCodeAt(0) - 48; + } + else if (ch === ';') { + this.params.push(this.currentParam); + this.currentParam = ''; + } + } + else { + this.currentParam += ch; + } + } + break; + case csi: + // '?', '>', '!' + if (ch === '?' || ch === '>' || ch === '!') { + this.prefix = ch; + break; + } + // 0 - 9 + if (ch >= '0' && ch <= '9') { + this.currentParam = this.currentParam * 10 + ch.charCodeAt(0) - 48; + break; + } + // '$', '"', ' ', '\'' + if (ch === '$' || ch === '"' || ch === ' ' || ch === '\'') { + this.postfix = ch; + break; + } + this.params.push(this.currentParam); + this.currentParam = 0; + // ';' + if (ch === ';') + break; + this.state = normal; + switch (ch) { + // CSI Ps A + // Cursor Up Ps Times (default = 1) (CUU). + case 'A': + this.cursorUp(this.params); + break; + // CSI Ps B + // Cursor Down Ps Times (default = 1) (CUD). + case 'B': + this.cursorDown(this.params); + break; + // CSI Ps C + // Cursor Forward Ps Times (default = 1) (CUF). + case 'C': + this.cursorForward(this.params); + break; + // CSI Ps D + // Cursor Backward Ps Times (default = 1) (CUB). + case 'D': + this.cursorBackward(this.params); + break; + // CSI Ps ; Ps H + // Cursor Position [row;column] (default = [1,1]) (CUP). + case 'H': + this.cursorPos(this.params); + break; + // CSI Ps J Erase in Display (ED). + case 'J': + this.eraseInDisplay(this.params); + break; + // CSI Ps K Erase in Line (EL). + case 'K': + this.eraseInLine(this.params); + break; + // CSI Pm m Character Attributes (SGR). + case 'm': + if (!this.prefix) { + this.charAttributes(this.params); + } + break; + // CSI Ps n Device Status Report (DSR). + case 'n': + if (!this.prefix) { + this.deviceStatus(this.params); + } + break; + /** + * Additions + */ + // CSI Ps @ + // Insert Ps (Blank) Character(s) (default = 1) (ICH). + case '@': + this.insertChars(this.params); + break; + // CSI Ps E + // Cursor Next Line Ps Times (default = 1) (CNL). + case 'E': + this.cursorNextLine(this.params); + break; + // CSI Ps F + // Cursor Preceding Line Ps Times (default = 1) (CNL). + case 'F': + this.cursorPrecedingLine(this.params); + break; + // CSI Ps G + // Cursor Character Absolute [column] (default = [row,1]) (CHA). + case 'G': + this.cursorCharAbsolute(this.params); + break; + // CSI Ps L + // Insert Ps Line(s) (default = 1) (IL). + case 'L': + this.insertLines(this.params); + break; + // CSI Ps M + // Delete Ps Line(s) (default = 1) (DL). + case 'M': + this.deleteLines(this.params); + break; + // CSI Ps P + // Delete Ps Character(s) (default = 1) (DCH). + case 'P': + this.deleteChars(this.params); + break; + // CSI Ps X + // Erase Ps Character(s) (default = 1) (ECH). + case 'X': + this.eraseChars(this.params); + break; + // CSI Pm ` Character Position Absolute + // [column] (default = [row,1]) (HPA). + case '`': + this.charPosAbsolute(this.params); + break; + // 141 61 a * HPR - + // Horizontal Position Relative + case 'a': + this.HPositionRelative(this.params); + break; + // CSI P s c + // Send Device Attributes (Primary DA). + // CSI > P s c + // Send Device Attributes (Secondary DA) + case 'c': + this.sendDeviceAttributes(this.params); + break; + // CSI Pm d + // Line Position Absolute [row] (default = [1,column]) (VPA). + case 'd': + this.linePosAbsolute(this.params); + break; + // 145 65 e * VPR - Vertical Position Relative + case 'e': + this.VPositionRelative(this.params); + break; + // CSI Ps ; Ps f + // Horizontal and Vertical Position [row;column] (default = + // [1,1]) (HVP). + case 'f': + this.HVPosition(this.params); + break; + // CSI Pm h Set Mode (SM). + // CSI ? Pm h - mouse escape codes, cursor escape codes + case 'h': + this.setMode(this.params); + break; + // CSI Pm l Reset Mode (RM). + // CSI ? Pm l + case 'l': + this.resetMode(this.params); + break; + // CSI Ps ; Ps r + // Set Scrolling Region [top;bottom] (default = full size of win- + // dow) (DECSTBM). + // CSI ? Pm r + case 'r': + this.setScrollRegion(this.params); + break; + // CSI s + // Save cursor (ANSI.SYS). + case 's': + this.saveCursor(this.params); + break; + // CSI u + // Restore cursor (ANSI.SYS). + case 'u': + this.restoreCursor(this.params); + break; + /** + * Lesser Used + */ + // CSI Ps I + // Cursor Forward Tabulation Ps tab stops (default = 1) (CHT). + case 'I': + this.cursorForwardTab(this.params); + break; + // CSI Ps S Scroll up Ps lines (default = 1) (SU). + case 'S': + this.scrollUp(this.params); + break; + // CSI Ps T Scroll down Ps lines (default = 1) (SD). + // CSI Ps ; Ps ; Ps ; Ps ; Ps T + // CSI > Ps; Ps T + case 'T': + // if (this.prefix === '>') { + // this.resetTitleModes(this.params); + // break; + // } + // if (this.params.length > 2) { + // this.initMouseTracking(this.params); + // break; + // } + if (this.params.length < 2 && !this.prefix) { + this.scrollDown(this.params); + } + break; + // CSI Ps Z + // Cursor Backward Tabulation Ps tab stops (default = 1) (CBT). + case 'Z': + this.cursorBackwardTab(this.params); + break; + // CSI Ps b Repeat the preceding graphic character Ps times (REP). + case 'b': + this.repeatPrecedingCharacter(this.params); + break; + // CSI Ps g Tab Clear (TBC). + case 'g': + this.tabClear(this.params); + break; + // CSI Pm i Media Copy (MC). + // CSI ? Pm i + // case 'i': + // this.mediaCopy(this.params); + // break; + // CSI Pm m Character Attributes (SGR). + // CSI > Ps; Ps m + // case 'm': // duplicate + // if (this.prefix === '>') { + // this.setResources(this.params); + // } else { + // this.charAttributes(this.params); + // } + // break; + // CSI Ps n Device Status Report (DSR). + // CSI > Ps n + // case 'n': // duplicate + // if (this.prefix === '>') { + // this.disableModifiers(this.params); + // } else { + // this.deviceStatus(this.params); + // } + // break; + // CSI > Ps p Set pointer mode. + // CSI ! p Soft terminal reset (DECSTR). + // CSI Ps$ p + // Request ANSI mode (DECRQM). + // CSI ? Ps$ p + // Request DEC private mode (DECRQM). + // CSI Ps ; Ps " p + case 'p': + switch (this.prefix) { + // case '>': + // this.setPointerMode(this.params); + // break; + case '!': + this.softReset(this.params); + break; + } + break; + // CSI Ps q Load LEDs (DECLL). + // CSI Ps SP q + // CSI Ps " q + // case 'q': + // if (this.postfix === ' ') { + // this.setCursorStyle(this.params); + // break; + // } + // if (this.postfix === '"') { + // this.setCharProtectionAttr(this.params); + // break; + // } + // this.loadLEDs(this.params); + // break; + // CSI Ps ; Ps r + // Set Scrolling Region [top;bottom] (default = full size of win- + // dow) (DECSTBM). + // CSI ? Pm r + // CSI Pt; Pl; Pb; Pr; Ps$ r + // case 'r': // duplicate + // if (this.prefix === '?') { + // this.restorePrivateValues(this.params); + // } else if (this.postfix === '$') { + // this.setAttrInRectangle(this.params); + // } else { + // this.setScrollRegion(this.params); + // } + // break; + // CSI s Save cursor (ANSI.SYS). + // CSI ? Pm s + // case 's': // duplicate + // if (this.prefix === '?') { + // this.savePrivateValues(this.params); + // } else { + // this.saveCursor(this.params); + // } + // break; + // CSI Ps ; Ps ; Ps t + // CSI Pt; Pl; Pb; Pr; Ps$ t + // CSI > Ps; Ps t + // CSI Ps SP t + // case 't': + // if (this.postfix === '$') { + // this.reverseAttrInRectangle(this.params); + // } else if (this.postfix === ' ') { + // this.setWarningBellVolume(this.params); + // } else { + // if (this.prefix === '>') { + // this.setTitleModeFeature(this.params); + // } else { + // this.manipulateWindow(this.params); + // } + // } + // break; + // CSI u Restore cursor (ANSI.SYS). + // CSI Ps SP u + // case 'u': // duplicate + // if (this.postfix === ' ') { + // this.setMarginBellVolume(this.params); + // } else { + // this.restoreCursor(this.params); + // } + // break; + // CSI Pt; Pl; Pb; Pr; Pp; Pt; Pl; Pp$ v + // case 'v': + // if (this.postfix === '$') { + // this.copyRectagle(this.params); + // } + // break; + // CSI Pt ; Pl ; Pb ; Pr ' w + // case 'w': + // if (this.postfix === '\'') { + // this.enableFilterRectangle(this.params); + // } + // break; + // CSI Ps x Request Terminal Parameters (DECREQTPARM). + // CSI Ps x Select Attribute Change Extent (DECSACE). + // CSI Pc; Pt; Pl; Pb; Pr$ x + // case 'x': + // if (this.postfix === '$') { + // this.fillRectangle(this.params); + // } else { + // this.requestParameters(this.params); + // //this.__(this.params); + // } + // break; + // CSI Ps ; Pu ' z + // CSI Pt; Pl; Pb; Pr$ z + // case 'z': + // if (this.postfix === '\'') { + // this.enableLocatorReporting(this.params); + // } else if (this.postfix === '$') { + // this.eraseRectangle(this.params); + // } + // break; + // CSI Pm ' { + // CSI Pt; Pl; Pb; Pr$ { + // case '{': + // if (this.postfix === '\'') { + // this.setLocatorEvents(this.params); + // } else if (this.postfix === '$') { + // this.selectiveEraseRectangle(this.params); + // } + // break; + // CSI Ps ' | + // case '|': + // if (this.postfix === '\'') { + // this.requestLocatorPosition(this.params); + // } + // break; + // CSI P m SP } + // Insert P s Column(s) (default = 1) (DECIC), VT420 and up. + // case '}': + // if (this.postfix === ' ') { + // this.insertColumns(this.params); + // } + // break; + // CSI P m SP ~ + // Delete P s Column(s) (default = 1) (DECDC), VT420 and up + // case '~': + // if (this.postfix === ' ') { + // this.deleteColumns(this.params); + // } + // break; + default: + this.error('Unknown CSI code: %s.', ch); + break; + } + this.prefix = ''; + this.postfix = ''; + break; + case dcs: + if (ch === '\x1b' || ch === '\x07') { + if (ch === '\x1b') + i++; + switch (this.prefix) { + // User-Defined Keys (DECUDK). + case '': + break; + // Request Status String (DECRQSS). + // test: echo -e '\eP$q"p\e\\' + case '$q': + var pt = this.currentParam, valid = false; + switch (pt) { + // DECSCA + case '"q': + pt = '0"q'; + break; + // DECSCL + case '"p': + pt = '61"p'; + break; + // DECSTBM + case 'r': + pt = '' + + (this.scrollTop + 1) + + ';' + + (this.scrollBottom + 1) + + 'r'; + break; + // SGR + case 'm': + pt = '0m'; + break; + default: + this.error('Unknown DCS Pt: %s.', pt); + pt = ''; + break; + } + this.send('\x1bP' + +valid + '$r' + pt + '\x1b\\'); + break; + // Set Termcap/Terminfo Data (xterm, experimental). + case '+p': + break; + // Request Termcap/Terminfo String (xterm, experimental) + // Regular xterm does not even respond to this sequence. + // This can cause a small glitch in vim. + // test: echo -ne '\eP+q6b64\e\\' + case '+q': + var pt = this.currentParam, valid = false; + this.send('\x1bP' + +valid + '+r' + pt + '\x1b\\'); + break; + default: + this.error('Unknown DCS prefix: %s.', this.prefix); + break; + } + this.currentParam = 0; + this.prefix = ''; + this.state = normal; + } + else if (!this.currentParam) { + if (!this.prefix && ch !== '$' && ch !== '+') { + this.currentParam = ch; + } + else if (this.prefix.length === 2) { + this.currentParam = ch; + } + else { + this.prefix += ch; + } + } + else { + this.currentParam += ch; + } + break; + case ignore: + // For PM and APC. + if (ch === '\x1b' || ch === '\x07') { + if (ch === '\x1b') + i++; + this.state = normal; + } + break; + } + } + this.updateRange(this.y); + this.refresh(this.refreshStart, this.refreshEnd); +}; +/** * Writes text to the terminal, followed by a break line character (\n). * @param {string} text The text to write to the terminal. - */Terminal.prototype.writeln=function(data){this.write(data+'\r\n');};/** + */ +Terminal.prototype.writeln = function (data) { + this.write(data + '\r\n'); +}; +/** * Attaches a custom keydown handler which is run before keys are processed, giving consumers of * xterm.js ultimate control as to what keys should be processed by the terminal and what keys * should not. * @param {function} customKeydownHandler The custom KeyboardEvent handler to attach. This is a * function that takes a KeyboardEvent, allowing consumers to stop propogation and/or prevent * the default action. The function returns whether the event should be processed by xterm.js. - */Terminal.prototype.attachCustomKeydownHandler=function(customKeydownHandler){this.customKeydownHandler=customKeydownHandler;};/** + */ +Terminal.prototype.attachCustomKeydownHandler = function (customKeydownHandler) { + this.customKeydownHandler = customKeydownHandler; +}; +/** * Handle a keydown event * Key Resources: * - https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent * @param {KeyboardEvent} ev The keydown event to be handled. - */Terminal.prototype.keyDown=function(ev){// Scroll down to prompt, whenever the user presses a key. -if(this.ybase!==this.ydisp){this.scrollToBottom();}if(this.customKeydownHandler&&this.customKeydownHandler(ev)===false){return false;}if(!this.compositionHelper.keydown.bind(this.compositionHelper)(ev)){return false;}var self=this;var result=this.evaluateKeyEscapeSequence(ev);if(result.scrollDisp){this.scrollDisp(result.scrollDisp);return this.cancel(ev,true);}if(isThirdLevelShift(this,ev)){return true;}if(result.cancel){// The event is canceled at the end already, is this necessary? -this.cancel(ev,true);}if(!result.key){return true;}this.emit('keydown',ev);this.emit('key',result.key,ev);this.showCursor();this.handler(result.key);return this.cancel(ev,true);};/** + */ +Terminal.prototype.keyDown = function (ev) { + if (this.customKeydownHandler && this.customKeydownHandler(ev) === false) { + return false; + } + if (!this.compositionHelper.keydown.bind(this.compositionHelper)(ev)) { + if (this.ybase !== this.ydisp) { + this.scrollToBottom(); + } + return false; + } + var self = this; + var result = this.evaluateKeyEscapeSequence(ev); + if (result.scrollDisp) { + this.scrollDisp(result.scrollDisp); + return this.cancel(ev, true); + } + if (isThirdLevelShift(this, ev)) { + return true; + } + if (result.cancel) { + // The event is canceled at the end already, is this necessary? + this.cancel(ev, true); + } + if (!result.key) { + return true; + } + this.emit('keydown', ev); + this.emit('key', result.key, ev); + this.showCursor(); + this.handler(result.key); + return this.cancel(ev, true); +}; +/** * Returns an object that determines how a KeyboardEvent should be handled. The key of the * returned value is the new key code to pass to the PTY. * * Reference: http://invisible-island.net/xterm/ctlseqs/ctlseqs.html * @param {KeyboardEvent} ev The keyboard event to be translated to key escape sequence. - */Terminal.prototype.evaluateKeyEscapeSequence=function(ev){var result={// Whether to cancel event propogation (NOTE: this may not be needed since the event is -// canceled at the end of keyDown -cancel:false,// The new key even to emit -key:undefined,// The number of characters to scroll, if this is defined it will cancel the event -scrollDisp:undefined};var modifiers=ev.shiftKey<<0|ev.altKey<<1|ev.ctrlKey<<2|ev.metaKey<<3;switch(ev.keyCode){case 8:// backspace -if(ev.shiftKey){result.key='\x08';// ^H -break;}result.key='\x7f';// ^? -break;case 9:// tab -if(ev.shiftKey){result.key='\x1b[Z';break;}result.key='\t';result.cancel=true;break;case 13:// return/enter -result.key='\r';result.cancel=true;break;case 27:// escape -result.key='\x1b';result.cancel=true;break;case 37:// left-arrow -if(modifiers){result.key='\x1b[1;'+(modifiers+1)+'D';// HACK: Make Alt + left-arrow behave like Ctrl + left-arrow: move one word backwards -// http://unix.stackexchange.com/a/108106 -if(result.key=='\x1b[1;3D'){result.key='\x1b[1;5D';}}else if(this.applicationCursor){result.key='\x1bOD';}else{result.key='\x1b[D';}break;case 39:// right-arrow -if(modifiers){result.key='\x1b[1;'+(modifiers+1)+'C';// HACK: Make Alt + right-arrow behave like Ctrl + right-arrow: move one word forward -// http://unix.stackexchange.com/a/108106 -if(result.key=='\x1b[1;3C'){result.key='\x1b[1;5C';}}else if(this.applicationCursor){result.key='\x1bOC';}else{result.key='\x1b[C';}break;case 38:// up-arrow -if(modifiers){result.key='\x1b[1;'+(modifiers+1)+'A';// HACK: Make Alt + up-arrow behave like Ctrl + up-arrow -// http://unix.stackexchange.com/a/108106 -if(result.key=='\x1b[1;3A'){result.key='\x1b[1;5A';}}else if(this.applicationCursor){result.key='\x1bOA';}else{result.key='\x1b[A';}break;case 40:// down-arrow -if(modifiers){result.key='\x1b[1;'+(modifiers+1)+'B';// HACK: Make Alt + down-arrow behave like Ctrl + down-arrow -// http://unix.stackexchange.com/a/108106 -if(result.key=='\x1b[1;3B'){result.key='\x1b[1;5B';}}else if(this.applicationCursor){result.key='\x1bOB';}else{result.key='\x1b[B';}break;case 45:// insert -if(!ev.shiftKey&&!ev.ctrlKey){// or + are used to -// copy-paste on some systems. -result.key='\x1b[2~';}break;case 46:// delete -if(modifiers){result.key='\x1b[3;'+(modifiers+1)+'~';}else{result.key='\x1b[3~';}break;case 36:// home -if(modifiers)result.key='\x1b[1;'+(modifiers+1)+'H';else if(this.applicationCursor)result.key='\x1bOH';else result.key='\x1b[H';break;case 35:// end -if(modifiers)result.key='\x1b[1;'+(modifiers+1)+'F';else if(this.applicationCursor)result.key='\x1bOF';else result.key='\x1b[F';break;case 33:// page up -if(ev.shiftKey){result.scrollDisp=-(this.rows-1);}else{result.key='\x1b[5~';}break;case 34:// page down -if(ev.shiftKey){result.scrollDisp=this.rows-1;}else{result.key='\x1b[6~';}break;case 112:// F1-F12 -if(modifiers){result.key='\x1b[1;'+(modifiers+1)+'P';}else{result.key='\x1bOP';}break;case 113:if(modifiers){result.key='\x1b[1;'+(modifiers+1)+'Q';}else{result.key='\x1bOQ';}break;case 114:if(modifiers){result.key='\x1b[1;'+(modifiers+1)+'R';}else{result.key='\x1bOR';}break;case 115:if(modifiers){result.key='\x1b[1;'+(modifiers+1)+'S';}else{result.key='\x1bOS';}break;case 116:if(modifiers){result.key='\x1b[15;'+(modifiers+1)+'~';}else{result.key='\x1b[15~';}break;case 117:if(modifiers){result.key='\x1b[17;'+(modifiers+1)+'~';}else{result.key='\x1b[17~';}break;case 118:if(modifiers){result.key='\x1b[18;'+(modifiers+1)+'~';}else{result.key='\x1b[18~';}break;case 119:if(modifiers){result.key='\x1b[19;'+(modifiers+1)+'~';}else{result.key='\x1b[19~';}break;case 120:if(modifiers){result.key='\x1b[20;'+(modifiers+1)+'~';}else{result.key='\x1b[20~';}break;case 121:if(modifiers){result.key='\x1b[21;'+(modifiers+1)+'~';}else{result.key='\x1b[21~';}break;case 122:if(modifiers){result.key='\x1b[23;'+(modifiers+1)+'~';}else{result.key='\x1b[23~';}break;case 123:if(modifiers){result.key='\x1b[24;'+(modifiers+1)+'~';}else{result.key='\x1b[24~';}break;default:// a-z and space -if(ev.ctrlKey&&!ev.shiftKey&&!ev.altKey&&!ev.metaKey){if(ev.keyCode>=65&&ev.keyCode<=90){result.key=String.fromCharCode(ev.keyCode-64);}else if(ev.keyCode===32){// NUL -result.key=String.fromCharCode(0);}else if(ev.keyCode>=51&&ev.keyCode<=55){// escape, file sep, group sep, record sep, unit sep -result.key=String.fromCharCode(ev.keyCode-51+27);}else if(ev.keyCode===56){// delete -result.key=String.fromCharCode(127);}else if(ev.keyCode===219){// ^[ - escape -result.key=String.fromCharCode(27);}else if(ev.keyCode===221){// ^] - group sep -result.key=String.fromCharCode(29);}}else if(!this.browser.isMac&&ev.altKey&&!ev.ctrlKey&&!ev.metaKey){// On Mac this is a third level shift. Use instead. -if(ev.keyCode>=65&&ev.keyCode<=90){result.key='\x1b'+String.fromCharCode(ev.keyCode+32);}else if(ev.keyCode===192){result.key='\x1b`';}else if(ev.keyCode>=48&&ev.keyCode<=57){result.key='\x1b'+(ev.keyCode-48);}}break;}return result;};/** + */ +Terminal.prototype.evaluateKeyEscapeSequence = function (ev) { + var result = { + // Whether to cancel event propogation (NOTE: this may not be needed since the event is + // canceled at the end of keyDown + cancel: false, + // The new key even to emit + key: undefined, + // The number of characters to scroll, if this is defined it will cancel the event + scrollDisp: undefined + }; + var modifiers = ev.shiftKey << 0 | ev.altKey << 1 | ev.ctrlKey << 2 | ev.metaKey << 3; + switch (ev.keyCode) { + case 8: + // backspace + if (ev.shiftKey) { + result.key = '\x08'; // ^H + break; + } + result.key = '\x7f'; // ^? + break; + case 9: + // tab + if (ev.shiftKey) { + result.key = '\x1b[Z'; + break; + } + result.key = '\t'; + result.cancel = true; + break; + case 13: + // return/enter + result.key = '\r'; + result.cancel = true; + break; + case 27: + // escape + result.key = '\x1b'; + result.cancel = true; + break; + case 37: + // left-arrow + if (modifiers) { + result.key = '\x1b[1;' + (modifiers + 1) + 'D'; + // HACK: Make Alt + left-arrow behave like Ctrl + left-arrow: move one word backwards + // http://unix.stackexchange.com/a/108106 + if (result.key == '\x1b[1;3D') { + result.key = '\x1b[1;5D'; + } + } + else if (this.applicationCursor) { + result.key = '\x1bOD'; + } + else { + result.key = '\x1b[D'; + } + break; + case 39: + // right-arrow + if (modifiers) { + result.key = '\x1b[1;' + (modifiers + 1) + 'C'; + // HACK: Make Alt + right-arrow behave like Ctrl + right-arrow: move one word forward + // http://unix.stackexchange.com/a/108106 + if (result.key == '\x1b[1;3C') { + result.key = '\x1b[1;5C'; + } + } + else if (this.applicationCursor) { + result.key = '\x1bOC'; + } + else { + result.key = '\x1b[C'; + } + break; + case 38: + // up-arrow + if (modifiers) { + result.key = '\x1b[1;' + (modifiers + 1) + 'A'; + // HACK: Make Alt + up-arrow behave like Ctrl + up-arrow + // http://unix.stackexchange.com/a/108106 + if (result.key == '\x1b[1;3A') { + result.key = '\x1b[1;5A'; + } + } + else if (this.applicationCursor) { + result.key = '\x1bOA'; + } + else { + result.key = '\x1b[A'; + } + break; + case 40: + // down-arrow + if (modifiers) { + result.key = '\x1b[1;' + (modifiers + 1) + 'B'; + // HACK: Make Alt + down-arrow behave like Ctrl + down-arrow + // http://unix.stackexchange.com/a/108106 + if (result.key == '\x1b[1;3B') { + result.key = '\x1b[1;5B'; + } + } + else if (this.applicationCursor) { + result.key = '\x1bOB'; + } + else { + result.key = '\x1b[B'; + } + break; + case 45: + // insert + if (!ev.shiftKey && !ev.ctrlKey) { + // or + are used to + // copy-paste on some systems. + result.key = '\x1b[2~'; + } + break; + case 46: + // delete + if (modifiers) { + result.key = '\x1b[3;' + (modifiers + 1) + '~'; + } + else { + result.key = '\x1b[3~'; + } + break; + case 36: + // home + if (modifiers) + result.key = '\x1b[1;' + (modifiers + 1) + 'H'; + else if (this.applicationCursor) + result.key = '\x1bOH'; + else + result.key = '\x1b[H'; + break; + case 35: + // end + if (modifiers) + result.key = '\x1b[1;' + (modifiers + 1) + 'F'; + else if (this.applicationCursor) + result.key = '\x1bOF'; + else + result.key = '\x1b[F'; + break; + case 33: + // page up + if (ev.shiftKey) { + result.scrollDisp = -(this.rows - 1); + } + else { + result.key = '\x1b[5~'; + } + break; + case 34: + // page down + if (ev.shiftKey) { + result.scrollDisp = this.rows - 1; + } + else { + result.key = '\x1b[6~'; + } + break; + case 112: + // F1-F12 + if (modifiers) { + result.key = '\x1b[1;' + (modifiers + 1) + 'P'; + } + else { + result.key = '\x1bOP'; + } + break; + case 113: + if (modifiers) { + result.key = '\x1b[1;' + (modifiers + 1) + 'Q'; + } + else { + result.key = '\x1bOQ'; + } + break; + case 114: + if (modifiers) { + result.key = '\x1b[1;' + (modifiers + 1) + 'R'; + } + else { + result.key = '\x1bOR'; + } + break; + case 115: + if (modifiers) { + result.key = '\x1b[1;' + (modifiers + 1) + 'S'; + } + else { + result.key = '\x1bOS'; + } + break; + case 116: + if (modifiers) { + result.key = '\x1b[15;' + (modifiers + 1) + '~'; + } + else { + result.key = '\x1b[15~'; + } + break; + case 117: + if (modifiers) { + result.key = '\x1b[17;' + (modifiers + 1) + '~'; + } + else { + result.key = '\x1b[17~'; + } + break; + case 118: + if (modifiers) { + result.key = '\x1b[18;' + (modifiers + 1) + '~'; + } + else { + result.key = '\x1b[18~'; + } + break; + case 119: + if (modifiers) { + result.key = '\x1b[19;' + (modifiers + 1) + '~'; + } + else { + result.key = '\x1b[19~'; + } + break; + case 120: + if (modifiers) { + result.key = '\x1b[20;' + (modifiers + 1) + '~'; + } + else { + result.key = '\x1b[20~'; + } + break; + case 121: + if (modifiers) { + result.key = '\x1b[21;' + (modifiers + 1) + '~'; + } + else { + result.key = '\x1b[21~'; + } + break; + case 122: + if (modifiers) { + result.key = '\x1b[23;' + (modifiers + 1) + '~'; + } + else { + result.key = '\x1b[23~'; + } + break; + case 123: + if (modifiers) { + result.key = '\x1b[24;' + (modifiers + 1) + '~'; + } + else { + result.key = '\x1b[24~'; + } + break; + default: + // a-z and space + if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) { + if (ev.keyCode >= 65 && ev.keyCode <= 90) { + result.key = String.fromCharCode(ev.keyCode - 64); + } + else if (ev.keyCode === 32) { + // NUL + result.key = String.fromCharCode(0); + } + else if (ev.keyCode >= 51 && ev.keyCode <= 55) { + // escape, file sep, group sep, record sep, unit sep + result.key = String.fromCharCode(ev.keyCode - 51 + 27); + } + else if (ev.keyCode === 56) { + // delete + result.key = String.fromCharCode(127); + } + else if (ev.keyCode === 219) { + // ^[ - Control Sequence Introducer (CSI) + result.key = String.fromCharCode(27); + } + else if (ev.keyCode === 220) { + // ^\ - String Terminator (ST) + result.key = String.fromCharCode(28); + } + else if (ev.keyCode === 221) { + // ^] - Operating System Command (OSC) + result.key = String.fromCharCode(29); + } + } + else if (!this.browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) { + // On Mac this is a third level shift. Use instead. + if (ev.keyCode >= 65 && ev.keyCode <= 90) { + result.key = '\x1b' + String.fromCharCode(ev.keyCode + 32); + } + else if (ev.keyCode === 192) { + result.key = '\x1b`'; + } + else if (ev.keyCode >= 48 && ev.keyCode <= 57) { + result.key = '\x1b' + (ev.keyCode - 48); + } + } + break; + } + return result; +}; +/** * Set the G level of the terminal * @param g - */Terminal.prototype.setgLevel=function(g){this.glevel=g;this.charset=this.charsets[g];};/** + */ +Terminal.prototype.setgLevel = function (g) { + this.glevel = g; + this.charset = this.charsets[g]; +}; +/** * Set the charset for the given G level of the terminal * @param g * @param charset - */Terminal.prototype.setgCharset=function(g,charset){this.charsets[g]=charset;if(this.glevel===g){this.charset=charset;}};/** + */ +Terminal.prototype.setgCharset = function (g, charset) { + this.charsets[g] = charset; + if (this.glevel === g) { + this.charset = charset; + } +}; +/** * Handle a keypress event. * Key Resources: * - https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent * @param {KeyboardEvent} ev The keypress event to be handled. - */Terminal.prototype.keyPress=function(ev){var key;this.cancel(ev);if(ev.charCode){key=ev.charCode;}else if(ev.which==null){key=ev.keyCode;}else if(ev.which!==0&&ev.charCode!==0){key=ev.which;}else{return false;}if(!key||(ev.altKey||ev.ctrlKey||ev.metaKey)&&!isThirdLevelShift(this,ev)){return false;}key=String.fromCharCode(key);this.emit('keypress',key,ev);this.emit('key',key,ev);this.showCursor();this.handler(key);return false;};/** + */ +Terminal.prototype.keyPress = function (ev) { + var key; + this.cancel(ev); + if (ev.charCode) { + key = ev.charCode; + } + else if (ev.which == null) { + key = ev.keyCode; + } + else if (ev.which !== 0 && ev.charCode !== 0) { + key = ev.which; + } + else { + return false; + } + if (!key || ((ev.altKey || ev.ctrlKey || ev.metaKey) && !isThirdLevelShift(this, ev))) { + return false; + } + key = String.fromCharCode(key); + this.emit('keypress', key, ev); + this.emit('key', key, ev); + this.showCursor(); + this.handler(key); + return false; +}; +/** * Send data for handling to the terminal * @param {string} data - */Terminal.prototype.send=function(data){var self=this;if(!this.queue){setTimeout(function(){self.handler(self.queue);self.queue='';},1);}this.queue+=data;};/** + */ +Terminal.prototype.send = function (data) { + var self = this; + if (!this.queue) { + setTimeout(function () { + self.handler(self.queue); + self.queue = ''; + }, 1); + } + this.queue += data; +}; +/** * Ring the bell. * Note: We could do sweet things with webaudio here - */Terminal.prototype.bell=function(){if(!this.visualBell)return;var self=this;this.element.style.borderColor='white';setTimeout(function(){self.element.style.borderColor='';},10);if(this.popOnBell)this.focus();};/** + */ +Terminal.prototype.bell = function () { + if (!this.visualBell) + return; + var self = this; + this.element.style.borderColor = 'white'; + setTimeout(function () { + self.element.style.borderColor = ''; + }, 10); + if (this.popOnBell) + this.focus(); +}; +/** * Log the current state to the console. - */Terminal.prototype.log=function(){if(!this.debug)return;if(!this.context.console||!this.context.console.log)return;var args=Array.prototype.slice.call(arguments);this.context.console.log.apply(this.context.console,args);};/** + */ +Terminal.prototype.log = function () { + if (!this.debug) + return; + if (!this.context.console || !this.context.console.log) + return; + var args = Array.prototype.slice.call(arguments); + this.context.console.log.apply(this.context.console, args); +}; +/** * Log the current state as error to the console. - */Terminal.prototype.error=function(){if(!this.debug)return;if(!this.context.console||!this.context.console.error)return;var args=Array.prototype.slice.call(arguments);this.context.console.error.apply(this.context.console,args);};/** + */ +Terminal.prototype.error = function () { + if (!this.debug) + return; + if (!this.context.console || !this.context.console.error) + return; + var args = Array.prototype.slice.call(arguments); + this.context.console.error.apply(this.context.console, args); +}; +/** * Resizes the terminal. * * @param {number} x The number of columns to resize to. * @param {number} y The number of rows to resize to. - */Terminal.prototype.resize=function(x,y){var line,el,i,j,ch,addToY;if(x===this.cols&&y===this.rows){return;}if(x<1)x=1;if(y<1)y=1;// resize cols -j=this.cols;if(j x) -i=this.lines.length;while(i--){while(this.lines[i].length>x){this.lines[i].pop();}}}this.setupStops(j);this.cols=x;// resize rows -j=this.rows;addToY=0;if(j0&&this.lines.length<=this.ybase+this.y+addToY+1){// There is room above the buffer and there are no empty elements below the line, -// scroll up -this.ybase--;addToY++;if(this.ydisp>0){// Viewport is at the top of the buffer, must increase downwards -this.ydisp--;}}else{// Add a blank line if there is no buffer left at the top to scroll to, or if there -// are blank lines after the cursor -this.lines.push(this.blankLine());}}if(this.children.length y) -while(j-->y){if(this.lines.length>y+this.ybase){if(this.lines.length>this.ybase+this.y+1){// The line is a blank line below the cursor, remove it -this.lines.pop();}else{// The line is the cursor, scroll down -this.ybase++;this.ydisp++;}}if(this.children.length>y){el=this.children.shift();if(!el)continue;el.parentNode.removeChild(el);}}}this.rows=y;// Make sure that the cursor stays on screen -if(this.y>=y){this.y=y-1;}if(addToY){this.y+=addToY;}if(this.x>=x){this.x=x-1;}this.scrollTop=0;this.scrollBottom=y-1;this.refresh(0,this.rows-1);this.normal=null;this.geometry=[this.cols,this.rows];this.emit('resize',{terminal:this,cols:x,rows:y});};/** + */ +Terminal.prototype.resize = function (x, y) { + var line, el, i, j, ch, addToY; + if (x === this.cols && y === this.rows) { + return; + } + if (x < 1) + x = 1; + if (y < 1) + y = 1; + // resize cols + j = this.cols; + if (j < x) { + ch = [this.defAttr, ' ', 1]; // does xterm use the default attr? + i = this.lines.length; + while (i--) { + while (this.lines[i].length < x) { + this.lines[i].push(ch); + } + } + } + else { + i = this.lines.length; + while (i--) { + while (this.lines[i].length > x) { + this.lines[i].pop(); + } + } + } + this.setupStops(j); + this.cols = x; + // resize rows + j = this.rows; + addToY = 0; + if (j < y) { + el = this.element; + while (j++ < y) { + // y is rows, not this.y + if (this.lines.length < y + this.ybase) { + if (this.ybase > 0 && this.lines.length <= this.ybase + this.y + addToY + 1) { + // There is room above the buffer and there are no empty elements below the line, + // scroll up + this.ybase--; + addToY++; + if (this.ydisp > 0) { + // Viewport is at the top of the buffer, must increase downwards + this.ydisp--; + } + } + else { + // Add a blank line if there is no buffer left at the top to scroll to, or if there + // are blank lines after the cursor + this.lines.push(this.blankLine()); + } + } + if (this.children.length < y) { + this.insertRow(); + } + } + } + else { + while (j-- > y) { + if (this.lines.length > y + this.ybase) { + if (this.lines.length > this.ybase + this.y + 1) { + // The line is a blank line below the cursor, remove it + this.lines.pop(); + } + else { + // The line is the cursor, scroll down + this.ybase++; + this.ydisp++; + } + } + if (this.children.length > y) { + el = this.children.shift(); + if (!el) + continue; + el.parentNode.removeChild(el); + } + } + } + this.rows = y; + // Make sure that the cursor stays on screen + if (this.y >= y) { + this.y = y - 1; + } + if (addToY) { + this.y += addToY; + } + if (this.x >= x) { + this.x = x - 1; + } + this.scrollTop = 0; + this.scrollBottom = y - 1; + this.refresh(0, this.rows - 1); + this.normal = null; + this.geometry = [this.cols, this.rows]; + this.emit('resize', { terminal: this, cols: x, rows: y }); +}; +/** * Updates the range of rows to refresh * @param {number} y The number of rows to refresh next. - */Terminal.prototype.updateRange=function(y){if(ythis.refreshEnd)this.refreshEnd=y;// if (y > this.refreshEnd) { -// this.refreshEnd = y; -// if (y > this.rows - 1) { -// this.refreshEnd = this.rows - 1; -// } -// } -};/** + */ +Terminal.prototype.updateRange = function (y) { + if (y < this.refreshStart) + this.refreshStart = y; + if (y > this.refreshEnd) + this.refreshEnd = y; + // if (y > this.refreshEnd) { + // this.refreshEnd = y; + // if (y > this.rows - 1) { + // this.refreshEnd = this.rows - 1; + // } + // } +}; +/** * Set the range of refreshing to the maximum value - */Terminal.prototype.maxRange=function(){this.refreshStart=0;this.refreshEnd=this.rows-1;};/** + */ +Terminal.prototype.maxRange = function () { + this.refreshStart = 0; + this.refreshEnd = this.rows - 1; +}; +/** * Setup the tab stops. * @param {number} i - */Terminal.prototype.setupStops=function(i){if(i!=null){if(!this.tabs[i]){i=this.prevStop(i);}}else{this.tabs={};i=0;}for(;i0){}return x>=this.cols?this.cols-1:x<0?0:x;};/** + */ +Terminal.prototype.prevStop = function (x) { + if (x == null) + x = this.x; + while (!this.tabs[--x] && x > 0) + ; + return x >= this.cols + ? this.cols - 1 + : x < 0 ? 0 : x; +}; +/** * Move the cursor one tab stop forward from the given position (default is current). * @param {number} x The position to move the cursor one tab stop forward. - */Terminal.prototype.nextStop=function(x){if(x==null)x=this.x;while(!this.tabs[++x]&&x=this.cols?this.cols-1:x<0?0:x;};/** + */ +Terminal.prototype.nextStop = function (x) { + if (x == null) + x = this.x; + while (!this.tabs[++x] && x < this.cols) + ; + return x >= this.cols + ? this.cols - 1 + : x < 0 ? 0 : x; +}; +/** * Erase in the identified line everything from "x" to the end of the line (right). * @param {number} x The column from which to start erasing to the end of the line. * @param {number} y The line in which to operate. - */Terminal.prototype.eraseRight=function(x,y){var line=this.lines[this.ybase+y],ch=[this.eraseAttr(),' ',1];// xterm -for(;xthis.scrollBottom){this.y--;this.scroll();}this.state=normal;};/** + */ +Terminal.prototype.index = function () { + this.y++; + if (this.y > this.scrollBottom) { + this.y--; + this.scroll(); + } + this.state = normal; +}; +/** * ESC M Reverse Index (RI is 0x8d). - */Terminal.prototype.reverseIndex=function(){var j;this.y--;if(this.y=this.rows){this.y=this.rows-1;}};/** + */ +Terminal.prototype.cursorDown = function (params) { + var param = params[0]; + if (param < 1) + param = 1; + this.y += param; + if (this.y >= this.rows) { + this.y = this.rows - 1; + } +}; +/** * CSI Ps C * Cursor Forward Ps Times (default = 1) (CUF). - */Terminal.prototype.cursorForward=function(params){var param=params[0];if(param<1)param=1;this.x+=param;if(this.x>=this.cols){this.x=this.cols-1;}};/** + */ +Terminal.prototype.cursorForward = function (params) { + var param = params[0]; + if (param < 1) + param = 1; + this.x += param; + if (this.x >= this.cols) { + this.x = this.cols - 1; + } +}; +/** * CSI Ps D * Cursor Backward Ps Times (default = 1) (CUB). - */Terminal.prototype.cursorBackward=function(params){var param=params[0];if(param<1)param=1;this.x-=param;if(this.x<0)this.x=0;};/** + */ +Terminal.prototype.cursorBackward = function (params) { + var param = params[0]; + if (param < 1) + param = 1; + this.x -= param; + if (this.x < 0) + this.x = 0; +}; +/** * CSI Ps ; Ps H * Cursor Position [row;column] (default = [1,1]) (CUP). - */Terminal.prototype.cursorPos=function(params){var row,col;row=params[0]-1;if(params.length>=2){col=params[1]-1;}else{col=0;}if(row<0){row=0;}else if(row>=this.rows){row=this.rows-1;}if(col<0){col=0;}else if(col>=this.cols){col=this.cols-1;}this.x=col;this.y=row;};/** + */ +Terminal.prototype.cursorPos = function (params) { + var row, col; + row = params[0] - 1; + if (params.length >= 2) { + col = params[1] - 1; + } + else { + col = 0; + } + if (row < 0) { + row = 0; + } + else if (row >= this.rows) { + row = this.rows - 1; + } + if (col < 0) { + col = 0; + } + else if (col >= this.cols) { + col = this.cols - 1; + } + this.x = col; + this.y = row; +}; +/** * CSI Ps J Erase in Display (ED). * Ps = 0 -> Erase Below (default). * Ps = 1 -> Erase Above. @@ -1484,8 +3503,35 @@ this.updateRange(this.scrollTop);this.updateRange(this.scrollBottom);}this.state * Ps = 0 -> Selective Erase Below (default). * Ps = 1 -> Selective Erase Above. * Ps = 2 -> Selective Erase All. - */Terminal.prototype.eraseInDisplay=function(params){var j;switch(params[0]){case 0:this.eraseRight(this.x,this.y);j=this.y+1;for(;j Erase to Right (default). * Ps = 1 -> Erase to Left. @@ -1495,7 +3541,21 @@ break;}};/** * Ps = 0 -> Selective Erase to Right (default). * Ps = 1 -> Selective Erase to Left. * Ps = 2 -> Selective Erase All. - */Terminal.prototype.eraseInLine=function(params){switch(params[0]){case 0:this.eraseRight(this.x,this.y);break;case 1:this.eraseLeft(this.x,this.y);break;case 2:this.eraseLine(this.y);break;}};/** + */ +Terminal.prototype.eraseInLine = function (params) { + switch (params[0]) { + case 0: + this.eraseRight(this.x, this.y); + break; + case 1: + this.eraseLeft(this.x, this.y); + break; + case 2: + this.eraseLine(this.y); + break; + } +}; +/** * CSI Pm m Character Attributes (SGR). * Ps = 0 -> Normal (default). * Ps = 1 -> Bold. @@ -1558,32 +3618,131 @@ break;}};/** * Ps. * Ps = 4 8 ; 5 ; Ps -> Set background color to the second * Ps. - */Terminal.prototype.charAttributes=function(params){// Optimize a single SGR0. -if(params.length===1&¶ms[0]===0){this.curAttr=this.defAttr;return;}var l=params.length,i=0,flags=this.curAttr>>18,fg=this.curAttr>>9&0x1ff,bg=this.curAttr&0x1ff,p;for(;i=30&&p<=37){// fg color 8 -fg=p-30;}else if(p>=40&&p<=47){// bg color 8 -bg=p-40;}else if(p>=90&&p<=97){// fg color 16 -p+=8;fg=p-90;}else if(p>=100&&p<=107){// bg color 16 -p+=8;bg=p-100;}else if(p===0){// default -flags=this.defAttr>>18;fg=this.defAttr>>9&0x1ff;bg=this.defAttr&0x1ff;// flags = 0; -// fg = 0x1ff; -// bg = 0x1ff; -}else if(p===1){// bold text -flags|=1;}else if(p===4){// underlined text -flags|=2;}else if(p===5){// blink -flags|=4;}else if(p===7){// inverse and positive -// test with: echo -e '\e[31m\e[42mhello\e[7mworld\e[27mhi\e[m' -flags|=8;}else if(p===8){// invisible -flags|=16;}else if(p===22){// not bold -flags&=~1;}else if(p===24){// not underlined -flags&=~2;}else if(p===25){// not blink -flags&=~4;}else if(p===27){// not inverse -flags&=~8;}else if(p===28){// not invisible -flags&=~16;}else if(p===39){// reset fg -fg=this.defAttr>>9&0x1ff;}else if(p===49){// reset bg -bg=this.defAttr&0x1ff;}else if(p===38){// fg color 256 -if(params[i+1]===2){i+=2;fg=matchColor(params[i]&0xff,params[i+1]&0xff,params[i+2]&0xff);if(fg===-1)fg=0x1ff;i+=2;}else if(params[i+1]===5){i+=2;p=params[i]&0xff;fg=p;}}else if(p===48){// bg color 256 -if(params[i+1]===2){i+=2;bg=matchColor(params[i]&0xff,params[i+1]&0xff,params[i+2]&0xff);if(bg===-1)bg=0x1ff;i+=2;}else if(params[i+1]===5){i+=2;p=params[i]&0xff;bg=p;}}else if(p===100){// reset fg/bg -fg=this.defAttr>>9&0x1ff;bg=this.defAttr&0x1ff;}else{this.error('Unknown SGR attribute: %d.',p);}}this.curAttr=flags<<18|fg<<9|bg;};/** + */ +Terminal.prototype.charAttributes = function (params) { + // Optimize a single SGR0. + if (params.length === 1 && params[0] === 0) { + this.curAttr = this.defAttr; + return; + } + var l = params.length, i = 0, flags = this.curAttr >> 18, fg = (this.curAttr >> 9) & 0x1ff, bg = this.curAttr & 0x1ff, p; + for (; i < l; i++) { + p = params[i]; + if (p >= 30 && p <= 37) { + // fg color 8 + fg = p - 30; + } + else if (p >= 40 && p <= 47) { + // bg color 8 + bg = p - 40; + } + else if (p >= 90 && p <= 97) { + // fg color 16 + p += 8; + fg = p - 90; + } + else if (p >= 100 && p <= 107) { + // bg color 16 + p += 8; + bg = p - 100; + } + else if (p === 0) { + // default + flags = this.defAttr >> 18; + fg = (this.defAttr >> 9) & 0x1ff; + bg = this.defAttr & 0x1ff; + } + else if (p === 1) { + // bold text + flags |= 1; + } + else if (p === 4) { + // underlined text + flags |= 2; + } + else if (p === 5) { + // blink + flags |= 4; + } + else if (p === 7) { + // inverse and positive + // test with: echo -e '\e[31m\e[42mhello\e[7mworld\e[27mhi\e[m' + flags |= 8; + } + else if (p === 8) { + // invisible + flags |= 16; + } + else if (p === 22) { + // not bold + flags &= ~1; + } + else if (p === 24) { + // not underlined + flags &= ~2; + } + else if (p === 25) { + // not blink + flags &= ~4; + } + else if (p === 27) { + // not inverse + flags &= ~8; + } + else if (p === 28) { + // not invisible + flags &= ~16; + } + else if (p === 39) { + // reset fg + fg = (this.defAttr >> 9) & 0x1ff; + } + else if (p === 49) { + // reset bg + bg = this.defAttr & 0x1ff; + } + else if (p === 38) { + // fg color 256 + if (params[i + 1] === 2) { + i += 2; + fg = matchColor(params[i] & 0xff, params[i + 1] & 0xff, params[i + 2] & 0xff); + if (fg === -1) + fg = 0x1ff; + i += 2; + } + else if (params[i + 1] === 5) { + i += 2; + p = params[i] & 0xff; + fg = p; + } + } + else if (p === 48) { + // bg color 256 + if (params[i + 1] === 2) { + i += 2; + bg = matchColor(params[i] & 0xff, params[i + 1] & 0xff, params[i + 2] & 0xff); + if (bg === -1) + bg = 0x1ff; + i += 2; + } + else if (params[i + 1] === 5) { + i += 2; + p = params[i] & 0xff; + bg = p; + } + } + else if (p === 100) { + // reset fg/bg + fg = (this.defAttr >> 9) & 0x1ff; + bg = this.defAttr & 0x1ff; + } + else { + this.error('Unknown SGR attribute: %d.', p); + } + } + this.curAttr = (flags << 18) | (fg << 9) | bg; +}; +/** * CSI Ps n Device Status Report (DSR). * Ps = 5 -> Status Report. Result (``OK'') is * CSI 0 n @@ -1605,64 +3764,218 @@ fg=this.defAttr>>9&0x1ff;bg=this.defAttr&0x1ff;}else{this.error('Unknown SGR att * Ps = 5 3 -> Report Locator status as * CSI ? 5 3 n Locator available, if compiled-in, or * CSI ? 5 0 n No Locator, if not. - */Terminal.prototype.deviceStatus=function(params){if(!this.prefix){switch(params[0]){case 5:// status report -this.send('\x1b[0n');break;case 6:// cursor position -this.send('\x1b['+(this.y+1)+';'+(this.x+1)+'R');break;}}else if(this.prefix==='?'){// modern xterm doesnt seem to -// respond to any of these except ?6, 6, and 5 -switch(params[0]){case 6:// cursor position -this.send('\x1b[?'+(this.y+1)+';'+(this.x+1)+'R');break;case 15:// no printer -// this.send('\x1b[?11n'); -break;case 25:// dont support user defined keys -// this.send('\x1b[?21n'); -break;case 26:// north american keyboard -// this.send('\x1b[?27;1;0;0n'); -break;case 53:// no dec locator/mouse -// this.send('\x1b[?50n'); -break;}}};/** + */ +Terminal.prototype.deviceStatus = function (params) { + if (!this.prefix) { + switch (params[0]) { + case 5: + // status report + this.send('\x1b[0n'); + break; + case 6: + // cursor position + this.send('\x1b[' + + (this.y + 1) + + ';' + + (this.x + 1) + + 'R'); + break; + } + } + else if (this.prefix === '?') { + // modern xterm doesnt seem to + // respond to any of these except ?6, 6, and 5 + switch (params[0]) { + case 6: + // cursor position + this.send('\x1b[?' + + (this.y + 1) + + ';' + + (this.x + 1) + + 'R'); + break; + case 15: + // no printer + // this.send('\x1b[?11n'); + break; + case 25: + // dont support user defined keys + // this.send('\x1b[?21n'); + break; + case 26: + // north american keyboard + // this.send('\x1b[?27;1;0;0n'); + break; + case 53: + // no dec locator/mouse + // this.send('\x1b[?50n'); + break; + } + } +}; +/** * Additions - *//** + */ +/** * CSI Ps @ * Insert Ps (Blank) Character(s) (default = 1) (ICH). - */Terminal.prototype.insertChars=function(params){var param,row,j,ch;param=params[0];if(param<1)param=1;row=this.y+this.ybase;j=this.x;ch=[this.eraseAttr(),' ',1];// xterm -while(param--&&j=this.rows){this.y=this.rows-1;}this.x=0;};/** + */ +Terminal.prototype.cursorNextLine = function (params) { + var param = params[0]; + if (param < 1) + param = 1; + this.y += param; + if (this.y >= this.rows) { + this.y = this.rows - 1; + } + this.x = 0; +}; +/** * CSI Ps F * Cursor Preceding Line Ps Times (default = 1) (CNL). * reuse CSI Ps A ? - */Terminal.prototype.cursorPrecedingLine=function(params){var param=params[0];if(param<1)param=1;this.y-=param;if(this.y<0)this.y=0;this.x=0;};/** + */ +Terminal.prototype.cursorPrecedingLine = function (params) { + var param = params[0]; + if (param < 1) + param = 1; + this.y -= param; + if (this.y < 0) + this.y = 0; + this.x = 0; +}; +/** * CSI Ps G * Cursor Character Absolute [column] (default = [row,1]) (CHA). - */Terminal.prototype.cursorCharAbsolute=function(params){var param=params[0];if(param<1)param=1;this.x=param-1;};/** + */ +Terminal.prototype.cursorCharAbsolute = function (params) { + var param = params[0]; + if (param < 1) + param = 1; + this.x = param - 1; +}; +/** * CSI Ps L * Insert Ps Line(s) (default = 1) (IL). - */Terminal.prototype.insertLines=function(params){var param,row,j;param=params[0];if(param<1)param=1;row=this.y+this.ybase;j=this.rows-1-this.scrollBottom;j=this.rows-1+this.ybase-j+1;while(param--){// test: echo -e '\e[44m\e[1L\e[0m' -// blankLine(true) - xterm/linux behavior -this.lines.splice(row,0,this.blankLine(true));this.lines.splice(j,1);}// this.maxRange(); -this.updateRange(this.y);this.updateRange(this.scrollBottom);};/** + */ +Terminal.prototype.insertLines = function (params) { + var param, row, j; + param = params[0]; + if (param < 1) + param = 1; + row = this.y + this.ybase; + j = this.rows - 1 - this.scrollBottom; + j = this.rows - 1 + this.ybase - j + 1; + while (param--) { + // test: echo -e '\e[44m\e[1L\e[0m' + // blankLine(true) - xterm/linux behavior + this.lines.splice(row, 0, this.blankLine(true)); + this.lines.splice(j, 1); + } + // this.maxRange(); + this.updateRange(this.y); + this.updateRange(this.scrollBottom); +}; +/** * CSI Ps M * Delete Ps Line(s) (default = 1) (DL). - */Terminal.prototype.deleteLines=function(params){var param,row,j;param=params[0];if(param<1)param=1;row=this.y+this.ybase;j=this.rows-1-this.scrollBottom;j=this.rows-1+this.ybase-j;while(param--){// test: echo -e '\e[44m\e[1M\e[0m' -// blankLine(true) - xterm/linux behavior -this.lines.splice(j+1,0,this.blankLine(true));this.lines.splice(row,1);}// this.maxRange(); -this.updateRange(this.y);this.updateRange(this.scrollBottom);};/** + */ +Terminal.prototype.deleteLines = function (params) { + var param, row, j; + param = params[0]; + if (param < 1) + param = 1; + row = this.y + this.ybase; + j = this.rows - 1 - this.scrollBottom; + j = this.rows - 1 + this.ybase - j; + while (param--) { + // test: echo -e '\e[44m\e[1M\e[0m' + // blankLine(true) - xterm/linux behavior + this.lines.splice(j + 1, 0, this.blankLine(true)); + this.lines.splice(row, 1); + } + // this.maxRange(); + this.updateRange(this.y); + this.updateRange(this.scrollBottom); +}; +/** * CSI Ps P * Delete Ps Character(s) (default = 1) (DCH). - */Terminal.prototype.deleteChars=function(params){var param,row,ch;param=params[0];if(param<1)param=1;row=this.y+this.ybase;ch=[this.eraseAttr(),' ',1];// xterm -while(param--){this.lines[row].splice(this.x,1);this.lines[row].push(ch);}};/** + */ +Terminal.prototype.deleteChars = function (params) { + var param, row, ch; + param = params[0]; + if (param < 1) + param = 1; + row = this.y + this.ybase; + ch = [this.eraseAttr(), ' ', 1]; // xterm + while (param--) { + this.lines[row].splice(this.x, 1); + this.lines[row].push(ch); + } +}; +/** * CSI Ps X * Erase Ps Character(s) (default = 1) (ECH). - */Terminal.prototype.eraseChars=function(params){var param,row,j,ch;param=params[0];if(param<1)param=1;row=this.y+this.ybase;j=this.x;ch=[this.eraseAttr(),' ',1];// xterm -while(param--&&j=this.cols){this.x=this.cols-1;}};/** + */ +Terminal.prototype.charPosAbsolute = function (params) { + var param = params[0]; + if (param < 1) + param = 1; + this.x = param - 1; + if (this.x >= this.cols) { + this.x = this.cols - 1; + } +}; +/** * 141 61 a * HPR - * Horizontal Position Relative * reuse CSI Ps C ? - */Terminal.prototype.HPositionRelative=function(params){var param=params[0];if(param<1)param=1;this.x+=param;if(this.x>=this.cols){this.x=this.cols-1;}};/** + */ +Terminal.prototype.HPositionRelative = function (params) { + var param = params[0]; + if (param < 1) + param = 1; + this.x += param; + if (this.x >= this.cols) { + this.x = this.cols - 1; + } +}; +/** * CSI Ps c Send Device Attributes (Primary DA). * Ps = 0 or omitted -> request attributes from terminal. The * response depends on the decTerminalID resource setting. @@ -1698,22 +4011,86 @@ while(param--&&j0)return;if(!this.prefix){if(this.is('xterm')||this.is('rxvt-unicode')||this.is('screen')){this.send('\x1b[?1;2c');}else if(this.is('linux')){this.send('\x1b[?6c');}}else if(this.prefix==='>'){// xterm and urxvt -// seem to spit this -// out around ~370 times (?). -if(this.is('xterm')){this.send('\x1b[>0;276;0c');}else if(this.is('rxvt-unicode')){this.send('\x1b[>85;95;0c');}else if(this.is('linux')){// not supported by linux console. -// linux console echoes parameters. -this.send(params[0]+'c');}else if(this.is('screen')){this.send('\x1b[>83;40003;0c');}}};/** + */ +Terminal.prototype.sendDeviceAttributes = function (params) { + if (params[0] > 0) + return; + if (!this.prefix) { + if (this.is('xterm') + || this.is('rxvt-unicode') + || this.is('screen')) { + this.send('\x1b[?1;2c'); + } + else if (this.is('linux')) { + this.send('\x1b[?6c'); + } + } + else if (this.prefix === '>') { + // xterm and urxvt + // seem to spit this + // out around ~370 times (?). + if (this.is('xterm')) { + this.send('\x1b[>0;276;0c'); + } + else if (this.is('rxvt-unicode')) { + this.send('\x1b[>85;95;0c'); + } + else if (this.is('linux')) { + // not supported by linux console. + // linux console echoes parameters. + this.send(params[0] + 'c'); + } + else if (this.is('screen')) { + this.send('\x1b[>83;40003;0c'); + } + } +}; +/** * CSI Pm d * Line Position Absolute [row] (default = [1,column]) (VPA). - */Terminal.prototype.linePosAbsolute=function(params){var param=params[0];if(param<1)param=1;this.y=param-1;if(this.y>=this.rows){this.y=this.rows-1;}};/** + */ +Terminal.prototype.linePosAbsolute = function (params) { + var param = params[0]; + if (param < 1) + param = 1; + this.y = param - 1; + if (this.y >= this.rows) { + this.y = this.rows - 1; + } +}; +/** * 145 65 e * VPR - Vertical Position Relative * reuse CSI Ps B ? - */Terminal.prototype.VPositionRelative=function(params){var param=params[0];if(param<1)param=1;this.y+=param;if(this.y>=this.rows){this.y=this.rows-1;}};/** + */ +Terminal.prototype.VPositionRelative = function (params) { + var param = params[0]; + if (param < 1) + param = 1; + this.y += param; + if (this.y >= this.rows) { + this.y = this.rows - 1; + } +}; +/** * CSI Ps ; Ps f * Horizontal and Vertical Position [row;column] (default = * [1,1]) (HVP). - */Terminal.prototype.HVPosition=function(params){if(params[0]<1)params[0]=1;if(params[1]<1)params[1]=1;this.y=params[0]-1;if(this.y>=this.rows){this.y=this.rows-1;}this.x=params[1]-1;if(this.x>=this.cols){this.x=this.cols-1;}};/** + */ +Terminal.prototype.HVPosition = function (params) { + if (params[0] < 1) + params[0] = 1; + if (params[1] < 1) + params[1] = 1; + this.y = params[0] - 1; + if (this.y >= this.rows) { + this.y = this.rows - 1; + } + this.x = params[1] - 1; + if (this.x >= this.cols) { + this.x = this.cols - 1; + } +}; +/** * CSI Pm h Set Mode (SM). * Ps = 2 -> Keyboard Action Mode (AM). * Ps = 4 -> Insert Mode (IRM). @@ -1798,46 +4175,123 @@ this.send(params[0]+'c');}else if(this.is('screen')){this.send('\x1b[>83;40003;0 * Ps = 2 0 0 4 -> Set bracketed paste mode. * Modes: * http: *vt100.net/docs/vt220-rm/chapter4.html - */Terminal.prototype.setMode=function(params){if((typeof params==='undefined'?'undefined':_typeof(params))==='object'){var l=params.length,i=0;for(;i1000;this.mouseEvents=true;this.element.style.cursor='default';this.log('Binding to mouse events.');break;case 1004:// send focusin/focusout events -// focusin: ^[[I -// focusout: ^[[O -this.sendFocus=true;break;case 1005:// utf8 ext mode mouse -this.utfMouse=true;// for wide terminals -// simply encodes large values as utf8 characters -break;case 1006:// sgr ext mode mouse -this.sgrMouse=true;// for wide terminals -// does not add 32 to fields -// press: ^[[ 1000; + this.mouseEvents = true; + this.element.style.cursor = 'default'; + this.log('Binding to mouse events.'); + break; + case 1004: + // focusin: ^[[I + // focusout: ^[[O + this.sendFocus = true; + break; + case 1005: + this.utfMouse = true; + // for wide terminals + // simply encodes large values as utf8 characters + break; + case 1006: + this.sgrMouse = true; + // for wide terminals + // does not add 32 to fields + // press: ^[[ Keyboard Action Mode (AM). * Ps = 4 -> Replace Mode (IRM). @@ -1918,54 +4372,179 @@ if(!this.normal){var normal={lines:this.lines,ybase:this.ybase,ydisp:this.ydisp, * Ps = 1 0 6 0 -> Reset legacy keyboard emulation (X11R6). * Ps = 1 0 6 1 -> Reset keyboard emulation to Sun/PC style. * Ps = 2 0 0 4 -> Reset bracketed paste mode. - */Terminal.prototype.resetMode=function(params){if((typeof params==='undefined'?'undefined':_typeof(params))==='object'){var l=params.length,i=0;for(;i Ps; Ps T * Reset one or more features of the title modes to the default * value. Normally, "reset" disables the feature. It is possi- @@ -1977,18 +4556,45 @@ this.updateRange(this.scrollTop);this.updateRange(this.scrollBottom);};/** * Ps = 2 -> Do not set window/icon labels using UTF-8. * Ps = 3 -> Do not query window/icon labels using UTF-8. * (See discussion of "Title Modes"). - */Terminal.prototype.resetTitleModes=function(params){;};/** + */ +Terminal.prototype.resetTitleModes = function (params) { + ; +}; +/** * CSI Ps Z Cursor Backward Tabulation Ps tab stops (default = 1) (CBT). - */Terminal.prototype.cursorBackwardTab=function(params){var param=params[0]||1;while(param--){this.x=this.prevStop();}};/** + */ +Terminal.prototype.cursorBackwardTab = function (params) { + var param = params[0] || 1; + while (param--) { + this.x = this.prevStop(); + } +}; +/** * CSI Ps b Repeat the preceding graphic character Ps times (REP). - */Terminal.prototype.repeatPrecedingCharacter=function(params){var param=params[0]||1,line=this.lines[this.ybase+this.y],ch=line[this.x-1]||[this.defAttr,' ',1];while(param--){line[this.x++]=ch;}};/** + */ +Terminal.prototype.repeatPrecedingCharacter = function (params) { + var param = params[0] || 1, line = this.lines[this.ybase + this.y], ch = line[this.x - 1] || [this.defAttr, ' ', 1]; + while (param--) + line[this.x++] = ch; +}; +/** * CSI Ps g Tab Clear (TBC). * Ps = 0 -> Clear Current Column (default). * Ps = 3 -> Clear All. * Potentially: * Ps = 2 -> Clear Stops on Line. * http://vt100.net/annarbor/aaa-ug/section6.html - */Terminal.prototype.tabClear=function(params){var param=params[0];if(param<=0){delete this.tabs[this.x];}else if(param===3){this.tabs={};}};/** + */ +Terminal.prototype.tabClear = function (params) { + var param = params[0]; + if (param <= 0) { + delete this.tabs[this.x]; + } + else if (param === 3) { + this.tabs = {}; + } +}; +/** * CSI Pm i Media Copy (MC). * Ps = 0 -> Print screen (default). * Ps = 4 -> Turn off printer controller mode. @@ -2000,7 +4606,11 @@ this.updateRange(this.scrollTop);this.updateRange(this.scrollBottom);};/** * Ps = 5 -> Turn on autoprint mode. * Ps = 1 0 -> Print composed display, ignores DECPEX. * Ps = 1 1 -> Print all pages. - */Terminal.prototype.mediaCopy=function(params){;};/** + */ +Terminal.prototype.mediaCopy = function (params) { + ; +}; +/** * CSI > Ps; Ps m * Set or reset resource-values used by xterm to decide whether * to construct escape sequences holding information about the @@ -2013,7 +4623,11 @@ this.updateRange(this.scrollTop);this.updateRange(this.scrollBottom);};/** * Ps = 4 -> modifyOtherKeys. * If no parameters are given, all resources are reset to their * initial values. - */Terminal.prototype.setResources=function(params){;};/** + */ +Terminal.prototype.setResources = function (params) { + ; +}; +/** * CSI > Ps n * Disable modifiers which may be enabled via the CSI > Ps; Ps m * sequence. This corresponds to a resource value of "-1", which @@ -2027,7 +4641,11 @@ this.updateRange(this.scrollTop);this.updateRange(this.scrollBottom);};/** * keys to make an extended sequence of functions rather than * adding a parameter to each function key to denote the modi- * fiers. - */Terminal.prototype.disableModifiers=function(params){;};/** + */ +Terminal.prototype.disableModifiers = function (params) { + ; +}; +/** * CSI > Ps p * Set resource value pointerMode. This is used by xterm to * decide whether to hide the pointer cursor as the user types. @@ -2036,15 +4654,31 @@ this.updateRange(this.scrollTop);this.updateRange(this.scrollBottom);};/** * Ps = 1 -> hide if the mouse tracking mode is not enabled. * Ps = 2 -> always hide the pointer. If no parameter is * given, xterm uses the default, which is 1 . - */Terminal.prototype.setPointerMode=function(params){;};/** + */ +Terminal.prototype.setPointerMode = function (params) { + ; +}; +/** * CSI ! p Soft terminal reset (DECSTR). * http://vt100.net/docs/vt220-rm/table4-10.html - */Terminal.prototype.softReset=function(params){this.cursorHidden=false;this.insertMode=false;this.originMode=false;this.wraparoundMode=false;// autowrap -this.applicationKeypad=false;// ? -this.viewport.syncScrollArea();this.applicationCursor=false;this.scrollTop=0;this.scrollBottom=this.rows-1;this.curAttr=this.defAttr;this.x=this.y=0;// ? -this.charset=null;this.glevel=0;// ?? -this.charsets=[null];// ?? -};/** + */ +Terminal.prototype.softReset = function (params) { + this.cursorHidden = false; + this.insertMode = false; + this.originMode = false; + this.wraparoundMode = false; // autowrap + this.applicationKeypad = false; // ? + this.viewport.syncScrollArea(); + this.applicationCursor = false; + this.scrollTop = 0; + this.scrollBottom = this.rows - 1; + this.curAttr = this.defAttr; + this.x = this.y = 0; // ? + this.charset = null; + this.glevel = 0; // ?? + this.charsets = [null]; // ?? +}; +/** * CSI Ps$ p * Request ANSI mode (DECRQM). For VT300 and up, reply is * CSI Ps; Pm$ y @@ -2055,13 +4689,21 @@ this.charsets=[null];// ?? * 2 - reset * 3 - permanently set * 4 - permanently reset - */Terminal.prototype.requestAnsiMode=function(params){;};/** + */ +Terminal.prototype.requestAnsiMode = function (params) { + ; +}; +/** * CSI ? Ps$ p * Request DEC private mode (DECRQM). For VT300 and up, reply is * CSI ? Ps; Pm$ p * where Ps is the mode number as in DECSET, Pm is the mode value * as in the ANSI DECRQM. - */Terminal.prototype.requestPrivateMode=function(params){;};/** + */ +Terminal.prototype.requestPrivateMode = function (params) { + ; +}; +/** * CSI Ps ; Ps " p * Set conformance level (DECSCL). Valid values for the first * parameter: @@ -2072,7 +4714,11 @@ this.charsets=[null];// ?? * Ps = 0 -> 8-bit controls. * Ps = 1 -> 7-bit controls (always set for VT100). * Ps = 2 -> 8-bit controls. - */Terminal.prototype.setConformanceLevel=function(params){;};/** + */ +Terminal.prototype.setConformanceLevel = function (params) { + ; +}; +/** * CSI Ps q Load LEDs (DECLL). * Ps = 0 -> Clear all LEDS (default). * Ps = 1 -> Light Num Lock. @@ -2081,7 +4727,11 @@ this.charsets=[null];// ?? * Ps = 2 1 -> Extinguish Num Lock. * Ps = 2 2 -> Extinguish Caps Lock. * Ps = 2 3 -> Extinguish Scroll Lock. - */Terminal.prototype.loadLEDs=function(params){;};/** + */ +Terminal.prototype.loadLEDs = function (params) { + ; +}; +/** * CSI Ps SP q * Set cursor style (DECSCUSR, VT520). * Ps = 0 -> blinking block. @@ -2089,32 +4739,70 @@ this.charsets=[null];// ?? * Ps = 2 -> steady block. * Ps = 3 -> blinking underline. * Ps = 4 -> steady underline. - */Terminal.prototype.setCursorStyle=function(params){;};/** + */ +Terminal.prototype.setCursorStyle = function (params) { + ; +}; +/** * CSI Ps " q * Select character protection attribute (DECSCA). Valid values * for the parameter: * Ps = 0 -> DECSED and DECSEL can erase (default). * Ps = 1 -> DECSED and DECSEL cannot erase. * Ps = 2 -> DECSED and DECSEL can erase. - */Terminal.prototype.setCharProtectionAttr=function(params){;};/** + */ +Terminal.prototype.setCharProtectionAttr = function (params) { + ; +}; +/** * CSI ? Pm r * Restore DEC Private Mode Values. The value of Ps previously * saved is restored. Ps values are the same as for DECSET. - */Terminal.prototype.restorePrivateValues=function(params){;};/** + */ +Terminal.prototype.restorePrivateValues = function (params) { + ; +}; +/** * CSI Pt; Pl; Pb; Pr; Ps$ r * Change Attributes in Rectangular Area (DECCARA), VT400 and up. * Pt; Pl; Pb; Pr denotes the rectangle. * Ps denotes the SGR attributes to change: 0, 1, 4, 5, 7. * NOTE: xterm doesn't enable this code by default. - */Terminal.prototype.setAttrInRectangle=function(params){var t=params[0],l=params[1],b=params[2],r=params[3],attr=params[4];var line,i;for(;t default to character cells. * Pu = 1 <- device physical pixels. * Pu = 2 <- character cells. - */Terminal.prototype.enableLocatorReporting=function(params){var val=params[0]>0;//this.mouseEvents = val; -//this.decLocator = val; -};/** + */ +Terminal.prototype.enableLocatorReporting = function (params) { + var val = params[0] > 0; + //this.mouseEvents = val; + //this.decLocator = val; +}; +/** * CSI Pt; Pl; Pb; Pr$ z * Erase Rectangular Area (DECERA), VT400 and up. * Pt; Pl; Pb; Pr denotes the rectangle. * NOTE: xterm doesn't enable this code by default. - */Terminal.prototype.eraseRectangle=function(params){var t=params[0],l=params[1],b=params[2],r=params[3];var line,i,ch;ch=[this.eraseAttr(),' ',1];// xterm? -for(;t47);}function matchColor(r1,g1,b1){var hash=r1<<16|g1<<8|b1;if(matchColor._cache[hash]!=null){return matchColor._cache[hash];}var ldiff=Infinity,li=-1,i=0,c,r2,g2,b2,diff;for(;iCOMBINING[max][1])return false;while(max>=min){mid=Math.floor((min+max)/2);if(ucs>COMBINING[mid][1])min=mid+1;else if(ucs=0x7f&&ucs<0xa0)return opts.control;// binary search in table of non-spacing characters -if(bisearch(ucs))return 0;// if we arrive here, ucs is not a combining or C0/C1 control character -return 1+(ucs>=0x1100&&(ucs<=0x115f||// Hangul Jamo init. consonants -ucs==0x2329||ucs==0x232a||ucs>=0x2e80&&ucs<=0xa4cf&&ucs!=0x303f||// CJK..Yi -ucs>=0xac00&&ucs<=0xd7a3||// Hangul Syllables -ucs>=0xf900&&ucs<=0xfaff||// CJK Compat Ideographs -ucs>=0xfe10&&ucs<=0xfe19||// Vertical forms -ucs>=0xfe30&&ucs<=0xfe6f||// CJK Compat Forms -ucs>=0xff00&&ucs<=0xff60||// Fullwidth Forms -ucs>=0xffe0&&ucs<=0xffe6||ucs>=0x20000&&ucs<=0x2fffd||ucs>=0x30000&&ucs<=0x3fffd));}return wcwidth;}({nul:0,control:0});// configurable options +function isBoldBroken(document) { + var body = document.getElementsByTagName('body')[0]; + var el = document.createElement('span'); + el.innerHTML = 'hello world'; + body.appendChild(el); + var w1 = el.scrollWidth; + el.style.fontWeight = 'bold'; + var w2 = el.scrollWidth; + body.removeChild(el); + return w1 !== w2; +} +function indexOf(obj, el) { + var i = obj.length; + while (i--) { + if (obj[i] === el) + return i; + } + return -1; +} +function isThirdLevelShift(term, ev) { + var thirdLevelKey = (term.browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) || + (term.browser.isMSWindows && ev.altKey && ev.ctrlKey && !ev.metaKey); + if (ev.type == 'keypress') { + return thirdLevelKey; + } + // Don't invoke for arrows, pageDown, home, backspace, etc. (on non-keypress events) + return thirdLevelKey && (!ev.keyCode || ev.keyCode > 47); +} +function matchColor(r1, g1, b1) { + var hash = (r1 << 16) | (g1 << 8) | b1; + if (matchColor._cache[hash] != null) { + return matchColor._cache[hash]; + } + var ldiff = Infinity, li = -1, i = 0, c, r2, g2, b2, diff; + for (; i < Terminal.vcolors.length; i++) { + c = Terminal.vcolors[i]; + r2 = c[0]; + g2 = c[1]; + b2 = c[2]; + diff = matchColor.distance(r1, g1, b1, r2, g2, b2); + if (diff === 0) { + li = i; + break; + } + if (diff < ldiff) { + ldiff = diff; + li = i; + } + } + return matchColor._cache[hash] = li; +} +matchColor._cache = {}; +// http://stackoverflow.com/questions/1633828 +matchColor.distance = function (r1, g1, b1, r2, g2, b2) { + return Math.pow(30 * (r1 - r2), 2) + + Math.pow(59 * (g1 - g2), 2) + + Math.pow(11 * (b1 - b2), 2); +}; +function each(obj, iter, con) { + if (obj.forEach) + return obj.forEach(iter, con); + for (var i = 0; i < obj.length; i++) { + iter.call(con, obj[i], i, obj); + } +} +function keys(obj) { + if (Object.keys) + return Object.keys(obj); + var key, keys = []; + for (key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + keys.push(key); + } + } + return keys; +} +var wcwidth = (function (opts) { + // extracted from https://www.cl.cam.ac.uk/%7Emgk25/ucs/wcwidth.c + // combining characters + var COMBINING = [ + [0x0300, 0x036F], [0x0483, 0x0486], [0x0488, 0x0489], + [0x0591, 0x05BD], [0x05BF, 0x05BF], [0x05C1, 0x05C2], + [0x05C4, 0x05C5], [0x05C7, 0x05C7], [0x0600, 0x0603], + [0x0610, 0x0615], [0x064B, 0x065E], [0x0670, 0x0670], + [0x06D6, 0x06E4], [0x06E7, 0x06E8], [0x06EA, 0x06ED], + [0x070F, 0x070F], [0x0711, 0x0711], [0x0730, 0x074A], + [0x07A6, 0x07B0], [0x07EB, 0x07F3], [0x0901, 0x0902], + [0x093C, 0x093C], [0x0941, 0x0948], [0x094D, 0x094D], + [0x0951, 0x0954], [0x0962, 0x0963], [0x0981, 0x0981], + [0x09BC, 0x09BC], [0x09C1, 0x09C4], [0x09CD, 0x09CD], + [0x09E2, 0x09E3], [0x0A01, 0x0A02], [0x0A3C, 0x0A3C], + [0x0A41, 0x0A42], [0x0A47, 0x0A48], [0x0A4B, 0x0A4D], + [0x0A70, 0x0A71], [0x0A81, 0x0A82], [0x0ABC, 0x0ABC], + [0x0AC1, 0x0AC5], [0x0AC7, 0x0AC8], [0x0ACD, 0x0ACD], + [0x0AE2, 0x0AE3], [0x0B01, 0x0B01], [0x0B3C, 0x0B3C], + [0x0B3F, 0x0B3F], [0x0B41, 0x0B43], [0x0B4D, 0x0B4D], + [0x0B56, 0x0B56], [0x0B82, 0x0B82], [0x0BC0, 0x0BC0], + [0x0BCD, 0x0BCD], [0x0C3E, 0x0C40], [0x0C46, 0x0C48], + [0x0C4A, 0x0C4D], [0x0C55, 0x0C56], [0x0CBC, 0x0CBC], + [0x0CBF, 0x0CBF], [0x0CC6, 0x0CC6], [0x0CCC, 0x0CCD], + [0x0CE2, 0x0CE3], [0x0D41, 0x0D43], [0x0D4D, 0x0D4D], + [0x0DCA, 0x0DCA], [0x0DD2, 0x0DD4], [0x0DD6, 0x0DD6], + [0x0E31, 0x0E31], [0x0E34, 0x0E3A], [0x0E47, 0x0E4E], + [0x0EB1, 0x0EB1], [0x0EB4, 0x0EB9], [0x0EBB, 0x0EBC], + [0x0EC8, 0x0ECD], [0x0F18, 0x0F19], [0x0F35, 0x0F35], + [0x0F37, 0x0F37], [0x0F39, 0x0F39], [0x0F71, 0x0F7E], + [0x0F80, 0x0F84], [0x0F86, 0x0F87], [0x0F90, 0x0F97], + [0x0F99, 0x0FBC], [0x0FC6, 0x0FC6], [0x102D, 0x1030], + [0x1032, 0x1032], [0x1036, 0x1037], [0x1039, 0x1039], + [0x1058, 0x1059], [0x1160, 0x11FF], [0x135F, 0x135F], + [0x1712, 0x1714], [0x1732, 0x1734], [0x1752, 0x1753], + [0x1772, 0x1773], [0x17B4, 0x17B5], [0x17B7, 0x17BD], + [0x17C6, 0x17C6], [0x17C9, 0x17D3], [0x17DD, 0x17DD], + [0x180B, 0x180D], [0x18A9, 0x18A9], [0x1920, 0x1922], + [0x1927, 0x1928], [0x1932, 0x1932], [0x1939, 0x193B], + [0x1A17, 0x1A18], [0x1B00, 0x1B03], [0x1B34, 0x1B34], + [0x1B36, 0x1B3A], [0x1B3C, 0x1B3C], [0x1B42, 0x1B42], + [0x1B6B, 0x1B73], [0x1DC0, 0x1DCA], [0x1DFE, 0x1DFF], + [0x200B, 0x200F], [0x202A, 0x202E], [0x2060, 0x2063], + [0x206A, 0x206F], [0x20D0, 0x20EF], [0x302A, 0x302F], + [0x3099, 0x309A], [0xA806, 0xA806], [0xA80B, 0xA80B], + [0xA825, 0xA826], [0xFB1E, 0xFB1E], [0xFE00, 0xFE0F], + [0xFE20, 0xFE23], [0xFEFF, 0xFEFF], [0xFFF9, 0xFFFB], + [0x10A01, 0x10A03], [0x10A05, 0x10A06], [0x10A0C, 0x10A0F], + [0x10A38, 0x10A3A], [0x10A3F, 0x10A3F], [0x1D167, 0x1D169], + [0x1D173, 0x1D182], [0x1D185, 0x1D18B], [0x1D1AA, 0x1D1AD], + [0x1D242, 0x1D244], [0xE0001, 0xE0001], [0xE0020, 0xE007F], + [0xE0100, 0xE01EF] + ]; + // binary search + function bisearch(ucs) { + var min = 0; + var max = COMBINING.length - 1; + var mid; + if (ucs < COMBINING[0][0] || ucs > COMBINING[max][1]) + return false; + while (max >= min) { + mid = Math.floor((min + max) / 2); + if (ucs > COMBINING[mid][1]) + min = mid + 1; + else if (ucs < COMBINING[mid][0]) + max = mid - 1; + else + return true; + } + return false; + } + function wcwidth(ucs) { + // test for 8-bit control characters + if (ucs === 0) + return opts.nul; + if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) + return opts.control; + // binary search in table of non-spacing characters + if (bisearch(ucs)) + return 0; + // if we arrive here, ucs is not a combining or C0/C1 control character + return 1 + + (ucs >= 0x1100 && + (ucs <= 0x115f || + ucs == 0x2329 || + ucs == 0x232a || + (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs != 0x303f) || + (ucs >= 0xac00 && ucs <= 0xd7a3) || + (ucs >= 0xf900 && ucs <= 0xfaff) || + (ucs >= 0xfe10 && ucs <= 0xfe19) || + (ucs >= 0xfe30 && ucs <= 0xfe6f) || + (ucs >= 0xff00 && ucs <= 0xff60) || + (ucs >= 0xffe0 && ucs <= 0xffe6) || + (ucs >= 0x20000 && ucs <= 0x2fffd) || + (ucs >= 0x30000 && ucs <= 0x3fffd))); + } + return wcwidth; +})({ nul: 0, control: 0 }); // configurable options /** * Expose - */Terminal.EventEmitter=_EventEmitter.EventEmitter;Terminal.CompositionHelper=_CompositionHelper.CompositionHelper;Terminal.Viewport=_Viewport.Viewport;Terminal.inherits=inherits;/** + */ +Terminal.EventEmitter = EventEmitter_js_1.EventEmitter; +Terminal.inherits = inherits; +/** * Adds an event listener to the terminal. * * @param {string} event The name of the event. TODO: Document all event types * @param {function} callback The function to call when the event is triggered. - */Terminal.on=on;Terminal.off=off;Terminal.cancel=cancel;module.exports=Terminal; + */ +Terminal.on = on; +Terminal.off = off; +Terminal.cancel = cancel; +module.exports = Terminal; },{"./CompositionHelper.js":1,"./EventEmitter.js":2,"./Viewport.js":3,"./handlers/Clipboard.js":4,"./utils/Browser":5}]},{},[7])(7) }); diff --git a/dist/xterm.js.map b/dist/xterm.js.map index d3ba6b45..a0bde090 100644 --- a/dist/xterm.js.map +++ b/dist/xterm.js.map @@ -1,27 +1 @@ -{ - "version": 3, - "sources": [ - "node_modules/browser-pack/_prelude.js", - "src/CompositionHelper.js", - "src/EventEmitter.js", - "src/Viewport.js", - "src/handlers/Clipboard.js", - "src/utils/Browser.js", - "src/utils/Generic.js", - "src/xterm.js" - ], - "names": [], - "mappings": "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,KAAK,MAArB,EACA,MAEF;AACA;AACA,IAAK,GAAL,CACE,KAAK,aAAL,CAAmB,KAAK,MAAxB,EACA,MAEA;;eAIF;AACA;AACA,IAAK,GAAL,CACE,KAAK,gBAAL,CAAsB,KAAK,MAA3B,EACA,MAEF;AACA,IAAK,GAAL,CACE,KAAK,QAAL,CAAc,KAAK,MAAnB,EACA,MAEF;AACA;AACA;AACA,IAAK,GAAL,CACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAI,KAAK,MAAL,CAAY,MAAZ,CAAqB,CAArB,EAA0B,CAAC,KAAK,MAApC,CAA4C,CAC1C,KAAK,UAAL,CAAgB,KAAK,MAArB,EACD,CACD,MAEF;AACA;AACA,IAAK,GAAL,CACE,KAAK,iBAAL,CAAuB,KAAK,MAA5B,EACA,MAEF;AACA,IAAK,GAAL,CACE,KAAK,wBAAL,CAA8B,KAAK,MAAnC,EACA,MAEF;AACA,IAAK,GAAL,CACE,KAAK,QAAL,CAAc,KAAK,MAAnB,EACA,MAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,IAAK,GAAL,CACE,OAAQ,KAAK,MAAb,EACI;AACA;AACA;AACF,IAAK,GAAL,CACE,KAAK,SAAL,CAAe,KAAK,MAApB,EACA,MACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAlBJ,CAoBA,MAEA;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;AAEA;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;AACA;AACA;AAC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", - "file": "generated.js", - "sourceRoot": "", - "sourcesContent": [ - "(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o 0) {\n self.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 */\nCompositionHelper.prototype.updateCompositionElements = function(dontRecurse) {\n if (!this.isComposing) {\n return;\n }\n var cursor = this.terminal.element.querySelector('.terminal-cursor');\n if (cursor) {\n // Take .xterm-rows offsetTop into account as well in case it's positioned absolutely within\n // the .xterm element.\n var xtermRows = this.terminal.element.querySelector('.xterm-rows');\n var cursorTop = xtermRows.offsetTop + cursor.offsetTop;\n\n this.compositionView.style.left = cursor.offsetLeft + 'px';\n this.compositionView.style.top = cursorTop + 'px';\n this.compositionView.style.height = cursor.offsetHeight + 'px';\n this.compositionView.style.lineHeight = cursor.offsetHeight + 'px';\n // Sync the textarea to the exact position of the composition view so the IME knows where the\n // text is.\n var compositionViewBounds = this.compositionView.getBoundingClientRect();\n this.textarea.style.left = cursor.offsetLeft + '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 if (!dontRecurse) {\n setTimeout(this.updateCompositionElements.bind(this, true), 0);\n }\n};\n\n/**\n * Clears the textarea's position so that the cursor does not blink on IE.\n * @private\n */\nCompositionHelper.prototype.clearTextareaPosition = function() {\n this.textarea.style.left = '';\n this.textarea.style.top = '';\n};\n\nexport { CompositionHelper };\n", - "/**\n * xterm.js: xterm, in the browser\n * Copyright (c) 2014-2016, SourceLair Private Company (www.sourcelair.com (MIT License)\n */\n\nfunction EventEmitter() {\n this._events = this._events || {};\n}\n\nEventEmitter.prototype.addListener = function(type, listener) {\n this._events[type] = this._events[type] || [];\n this._events[type].push(listener);\n};\n\nEventEmitter.prototype.on = EventEmitter.prototype.addListener;\n\nEventEmitter.prototype.removeListener = function(type, listener) {\n if (!this._events[type]) return;\n\n var obj = this._events[type]\n , i = obj.length;\n\n while (i--) {\n if (obj[i] === listener || obj[i].listener === listener) {\n obj.splice(i, 1);\n return;\n }\n }\n};\n\nEventEmitter.prototype.off = EventEmitter.prototype.removeListener;\n\nEventEmitter.prototype.removeAllListeners = function(type) {\n if (this._events[type]) delete this._events[type];\n};\n\nEventEmitter.prototype.once = function(type, listener) {\n var self = this;\n function on() {\n var args = Array.prototype.slice.call(arguments);\n this.removeListener(type, on);\n return listener.apply(this, args);\n }\n on.listener = listener;\n return this.on(type, on);\n};\n\nEventEmitter.prototype.emit = function(type) {\n if (!this._events[type]) return;\n\n var args = Array.prototype.slice.call(arguments, 1)\n , obj = this._events[type]\n , l = obj.length\n , i = 0;\n\n for (; i < l; i++) {\n obj[i].apply(this, args);\n }\n};\n\nEventEmitter.prototype.listeners = function(type) {\n return this._events[type] = this._events[type] || [];\n};\n\nexport { EventEmitter };\n", - "/**\n * xterm.js: xterm, in the browser\n * Copyright (c) 2014-2016, SourceLair Private Company (www.sourcelair.com (MIT License)\n */\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 * @param {Terminal} terminal The Terminal object.\n * @param {HTMLElement} viewportElement The DOM element acting as the viewport\n * @param {HTMLElement} charMeasureElement A DOM element used to measure the character size of\n * the terminal.\n */\nfunction Viewport(terminal, viewportElement, scrollArea, charMeasureElement) {\n this.terminal = terminal;\n this.viewportElement = viewportElement;\n this.scrollArea = scrollArea;\n this.charMeasureElement = charMeasureElement;\n this.currentRowHeight = 0;\n this.lastRecordedBufferLength = 0;\n this.lastRecordedViewportHeight = 0;\n\n this.terminal.on('scroll', this.syncScrollArea.bind(this));\n this.terminal.on('resize', this.syncScrollArea.bind(this));\n this.viewportElement.addEventListener('scroll', this.onScroll.bind(this));\n\n this.syncScrollArea();\n}\n\n/**\n * Refreshes row height, setting line-height, viewport height and scroll area height if\n * necessary.\n * @param {number|undefined} charSize A character size measurement bounding rect object, if it\n * doesn't exist it will be created.\n */\nViewport.prototype.refresh = function(charSize) {\n var size = charSize || this.charMeasureElement.getBoundingClientRect();\n if (size.height > 0) {\n var rowHeightChanged = size.height !== this.currentRowHeight;\n if (rowHeightChanged) {\n this.currentRowHeight = size.height;\n this.viewportElement.style.lineHeight = size.height + 'px';\n this.terminal.rowContainer.style.lineHeight = size.height + 'px';\n }\n var viewportHeightChanged = this.lastRecordedViewportHeight !== this.terminal.rows;\n if (rowHeightChanged || viewportHeightChanged) {\n this.lastRecordedViewportHeight = this.terminal.rows;\n this.viewportElement.style.height = size.height * this.terminal.rows + 'px';\n }\n this.scrollArea.style.height = (size.height * this.lastRecordedBufferLength) + 'px';\n }\n};\n\n/**\n * Updates dimensions and synchronizes the scroll area if necessary.\n */\nViewport.prototype.syncScrollArea = function() {\n if (this.lastRecordedBufferLength !== this.terminal.lines.length) {\n // If buffer height changed\n this.lastRecordedBufferLength = this.terminal.lines.length;\n this.refresh();\n } else if (this.lastRecordedViewportHeight !== this.terminal.rows) {\n // If viewport height changed\n this.refresh();\n } else {\n // If size has changed, refresh viewport\n var size = this.charMeasureElement.getBoundingClientRect();\n if (size.height !== this.currentRowHeight) {\n this.refresh(size);\n }\n }\n\n // Sync scrollTop\n var scrollTop = this.terminal.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 {Event} ev The scroll event.\n */\nViewport.prototype.onScroll = function(ev) {\n var newRow = Math.round(this.viewportElement.scrollTop / this.currentRowHeight);\n var diff = newRow - this.terminal.ydisp;\n this.terminal.scrollDisp(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 {WheelEvent} ev The mouse wheel event.\n */\nViewport.prototype.onWheel = function(ev) {\n if (ev.deltaY === 0) {\n // Do nothing if it's not a vertical scroll event\n return;\n }\n // Fallback to WheelEvent.DOM_DELTA_PIXEL\n var multiplier = 1;\n if (ev.deltaMode === WheelEvent.DOM_DELTA_LINE) {\n multiplier = this.currentRowHeight;\n } else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) {\n multiplier = this.currentRowHeight * this.terminal.rows;\n }\n this.viewportElement.scrollTop += ev.deltaY * multiplier;\n // Prevent the page from scrolling when the terminal scrolls\n ev.preventDefault();\n};\n\nexport { Viewport };\n", - "/**\n * xterm.js: xterm, in the browser\n * Copyright (c) 2016, SourceLair Private Company (MIT License)\n */\n\n/**\n * Clipboard handler module. This module contains methods for handling all\n * clipboard-related events appropriately in the terminal.\n * @module xterm/handlers/Clipboard\n */\n\n/**\n * Prepares text copied from terminal selection, to be saved in the clipboard by:\n * 1. stripping all trailing white spaces\n * 2. converting all non-breaking spaces to regular spaces\n * @param {string} text The copied text that needs processing for storing in clipboard\n * @returns {string}\n */\nfunction prepareTextForClipboard(text) {\n var space = String.fromCharCode(32),\n nonBreakingSpace = String.fromCharCode(160),\n allNonBreakingSpaces = new RegExp(nonBreakingSpace, 'g'),\n processedText = text.split('\\n').map(function (line) {\n // Strip all trailing white spaces and convert all non-breaking spaces\n // to regular spaces.\n var processedLine = line.replace(/\\s+$/g, '').replace(allNonBreakingSpaces, space);\n\n return processedLine;\n }).join('\\n');\n\n return processedText;\n}\n\n/**\n * Binds copy functionality to the given terminal.\n * @param {ClipboardEvent} ev The original copy event to be handled\n */\nfunction copyHandler(ev, term) {\n var copiedText = window.getSelection().toString(),\n text = prepareTextForClipboard(copiedText);\n\n if (term.browser.isMSIE) {\n window.clipboardData.setData('Text', text);\n } else {\n ev.clipboardData.setData('text/plain', text);\n }\n\n ev.preventDefault(); // Prevent or the original text will be copied.\n}\n\n/**\n * Redirect the clipboard's data to the terminal's input handler.\n * @param {ClipboardEvent} ev The original paste event to be handled\n * @param {Terminal} term The terminal on which to apply the handled paste event\n */\nfunction pasteHandler(ev, term) {\n ev.stopPropagation();\n\n var dispatchPaste = function(text) {\n term.handler(text);\n term.textarea.value = '';\n return term.cancel(ev);\n };\n\n if (term.browser.isMSIE) {\n if (window.clipboardData) {\n var text = window.clipboardData.getData('Text');\n dispatchPaste(text);\n }\n } else {\n if (ev.clipboardData) {\n var text = ev.clipboardData.getData('text/plain');\n dispatchPaste(text);\n }\n }\n}\n\n/**\n * Bind to right-click event and allow right-click copy and paste.\n *\n * **Logic**\n * If text is selected and right-click happens on selected text, then\n * do nothing to allow seamless copying.\n * If no text is selected or right-click is outside of the selection\n * area, then bring the terminal's input below the cursor, in order to\n * trigger the event on the textarea and allow-right click paste, without\n * caring about disappearing selection.\n * @param {ClipboardEvent} ev The original paste event to be handled\n * @param {Terminal} term The terminal on which to apply the handled paste event\n */\nfunction rightClickHandler(ev, term) {\n var s = document.getSelection(),\n selectedText = prepareTextForClipboard(s.toString()),\n clickIsOnSelection = false;\n\n if (s.rangeCount) {\n var r = s.getRangeAt(0),\n cr = r.getClientRects(),\n x = ev.clientX,\n y = ev.clientY,\n i, rect;\n\n for (i=0; i rect.left) && (x < rect.right) &&\n (y > rect.top) && (y < rect.bottom)\n );\n\n if (clickIsOnSelection) {\n break;\n }\n }\n // If we clicked on selection and selection is not a single space,\n // then mark the right click as copy-only. We check for the single\n // space selection, as this can happen when clicking on an  \n // and there is not much pointing in copying a single space.\n if (selectedText.match(/^\\s$/) || !selectedText.length) {\n clickIsOnSelection = false;\n }\n }\n\n // Bring textarea at the cursor position\n if (!clickIsOnSelection) {\n term.textarea.style.position = 'fixed';\n term.textarea.style.width = '20px';\n term.textarea.style.height = '20px';\n term.textarea.style.left = (x - 10) + 'px';\n term.textarea.style.top = (y - 10) + 'px';\n term.textarea.style.zIndex = 1000;\n term.textarea.focus();\n\n // Reset the terminal textarea's styling\n setTimeout(function () {\n term.textarea.style.position = null;\n term.textarea.style.width = null;\n term.textarea.style.height = null;\n term.textarea.style.left = null;\n term.textarea.style.top = null;\n term.textarea.style.zIndex = null;\n }, 4);\n }\n}\n\nexport {\n prepareTextForClipboard, copyHandler, pasteHandler, rightClickHandler\n};\n", - "/**\n * xterm.js: xterm, in the browser\n * Copyright (c) 2016, SourceLair Private Company (MIT License)\n */\n\n/**\n * Browser utilities module. This module contains attributes and methods to help with\n * identifying the current browser and platform.\n * @module xterm/utils/Browser\n */\n\nimport { contains } from './Generic.js';\n\nlet isNode = (typeof navigator == 'undefined') ? true : false;\nlet userAgent = (isNode) ? 'node' : navigator.userAgent;\nlet platform = (isNode) ? 'node' : navigator.platform;\n\nexport let isFirefox = !!~userAgent.indexOf('Firefox');\nexport let 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 let isMac = contains(['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'], platform);\nexport let isIpad = platform === 'iPad';\nexport let isIphone = platform === 'iPhone';\nexport let isMSWindows = contains(['Windows', 'Win16', 'Win32', 'WinCE'], platform);\n", - "/**\n * xterm.js: xterm, in the browser\n * Copyright (c) 2016, SourceLair Private Company (MIT License)\n */\n\n/**\n * Generic utilities module. This module contains generic methods that can be helpful at\n * different parts of the code base.\n * @module xterm/utils/Generic\n */\n\n/**\n * Return if the given array contains the given element\n * @param {Array} array The array to search for the given element.\n * @param {Object} el The element to look for into the array\n */\nexport let contains = function(arr, el) {\n return arr.indexOf(el) >= 0;\n};\n", - "/**\n * xterm.js: xterm, in the browser\n * Copyright (c) 2014-2014, SourceLair Private Company (MIT License)\n * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)\n * https://github.com/chjj/term.js\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\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\nimport { CompositionHelper } from './CompositionHelper.js';\nimport { EventEmitter } from './EventEmitter.js';\nimport { Viewport } from './Viewport.js';\nimport { rightClickHandler, pasteHandler, copyHandler } from './handlers/Clipboard.js';\nimport * as Browser from './utils/Browser';\n\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\n// Let it work inside Node.js for automated testing purposes.\nvar document = (typeof window != 'undefined') ? window.document : null;\n\n/**\n * States\n */\nvar normal = 0, escaped = 1, csi = 2, osc = 3, charset = 4, dcs = 5, ignore = 6;\n\n/**\n * Terminal\n */\n\n/**\n * Creates a new `Terminal` object.\n *\n * @param {object} options An object containing a set of options, the available options are:\n * - `cursorBlink` (boolean): Whether the terminal cursor blinks\n * - `cols` (number): The number of columns of the terminal (horizontal size)\n * - `rows` (number): The number of rows of the terminal (vertical size)\n *\n * @public\n * @class Xterm Xterm\n * @alias module:xterm/src/xterm\n */\nfunction Terminal(options) {\n var self = this;\n\n if (!(this instanceof Terminal)) {\n return new Terminal(arguments[0], arguments[1], arguments[2]);\n }\n\n self.browser = Browser;\n self.cancel = Terminal.cancel;\n\n EventEmitter.call(this);\n\n if (typeof options === 'number') {\n options = {\n cols: arguments[0],\n rows: arguments[1],\n handler: arguments[2]\n };\n }\n\n options = options || {};\n\n\n Object.keys(Terminal.defaults).forEach(function(key) {\n if (options[key] == null) {\n options[key] = Terminal.options[key];\n\n if (Terminal[key] !== Terminal.defaults[key]) {\n options[key] = Terminal[key];\n }\n }\n self[key] = options[key];\n });\n\n if (options.colors.length === 8) {\n options.colors = options.colors.concat(Terminal._colors.slice(8));\n } else if (options.colors.length === 16) {\n options.colors = options.colors.concat(Terminal._colors.slice(16));\n } else if (options.colors.length === 10) {\n options.colors = options.colors.slice(0, -2).concat(\n Terminal._colors.slice(8, -2), options.colors.slice(-2));\n } else if (options.colors.length === 18) {\n options.colors = options.colors.concat(\n Terminal._colors.slice(16, -2), options.colors.slice(-2));\n }\n this.colors = options.colors;\n\n this.options = options;\n\n // this.context = options.context || window;\n // this.document = options.document || document;\n this.parent = options.body || options.parent || (\n document ? document.getElementsByTagName('body')[0] : null\n );\n\n this.cols = options.cols || options.geometry[0];\n this.rows = options.rows || options.geometry[1];\n this.geometry = [this.cols, this.rows];\n\n if (options.handler) {\n this.on('data', options.handler);\n }\n\n /**\n * The scroll position of the y cursor, ie. ybase + y = the y position within the entire\n * buffer\n */\n this.ybase = 0;\n\n /**\n * The scroll position of the viewport\n */\n this.ydisp = 0;\n\n /**\n * The cursor's x position after ybase\n */\n this.x = 0;\n\n /**\n * The cursor's y position after ybase\n */\n this.y = 0;\n\n /**\n * Used to debounce the refresh function\n */\n this.isRefreshing = false;\n\n /**\n * Whether there is a full terminal refresh queued\n */\n\n this.cursorState = 0;\n this.cursorHidden = false;\n this.convertEol;\n this.state = 0;\n this.queue = '';\n this.scrollTop = 0;\n this.scrollBottom = this.rows - 1;\n this.customKeydownHandler = 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.normal = null;\n\n // charset\n this.charset = null;\n this.gcharset = null;\n this.glevel = 0;\n this.charsets = [null];\n\n // mouse properties\n this.decLocator;\n this.x10Mouse;\n this.vt200Mouse;\n this.vt300Mouse;\n this.normalMouse;\n this.mouseEvents;\n this.sendFocus;\n this.utfMouse;\n this.sgrMouse;\n this.urxvtMouse;\n\n // misc\n this.element;\n this.children;\n this.refreshStart;\n this.refreshEnd;\n this.savedX;\n this.savedY;\n this.savedCols;\n\n // stream\n this.readable = true;\n this.writable = true;\n\n this.defAttr = (0 << 18) | (257 << 9) | (256 << 0);\n this.curAttr = this.defAttr;\n\n this.params = [];\n this.currentParam = 0;\n this.prefix = '';\n this.postfix = '';\n\n // leftover surrogate high from previous write invocation\n this.surrogate_high = '';\n\n /**\n * An array of all lines in the entire buffer, including the prompt. The lines are array of\n * characters which are 2-length arrays where [0] is an attribute and [1] is the character.\n */\n this.lines = [];\n var i = this.rows;\n while (i--) {\n this.lines.push(this.blankLine());\n }\n\n this.tabs;\n this.setupStops();\n\n // Store if user went browsing history in scrollback\n this.userScrolling = false;\n}\n\ninherits(Terminal, EventEmitter);\n\n/**\n * back_color_erase feature for xterm.\n */\nTerminal.prototype.eraseAttr = function() {\n // if (this.is('screen')) return this.defAttr;\n return (this.defAttr & ~0x1ff) | (this.curAttr & 0x1ff);\n};\n\n/**\n * Colors\n */\n\n// Colors 0-15\nTerminal.tangoColors = [\n // dark:\n '#2e3436',\n '#cc0000',\n '#4e9a06',\n '#c4a000',\n '#3465a4',\n '#75507b',\n '#06989a',\n '#d3d7cf',\n // bright:\n '#555753',\n '#ef2929',\n '#8ae234',\n '#fce94f',\n '#729fcf',\n '#ad7fa8',\n '#34e2e2',\n '#eeeeec'\n];\n\n// Colors 0-15 + 16-255\n// Much thanks to TooTallNate for writing this.\nTerminal.colors = (function() {\n var colors = Terminal.tangoColors.slice()\n , r = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff]\n , i;\n\n // 16-231\n i = 0;\n for (; i < 216; i++) {\n out(r[(i / 36) % 6 | 0], r[(i / 6) % 6 | 0], r[i % 6]);\n }\n\n // 232-255 (grey)\n i = 0;\n for (; i < 24; i++) {\n r = 8 + i * 10;\n out(r, r, r);\n }\n\n function out(r, g, b) {\n colors.push('#' + hex(r) + hex(g) + hex(b));\n }\n\n function hex(c) {\n c = c.toString(16);\n return c.length < 2 ? '0' + c : c;\n }\n\n return colors;\n})();\n\nTerminal._colors = Terminal.colors.slice();\n\nTerminal.vcolors = (function() {\n var out = []\n , colors = Terminal.colors\n , i = 0\n , color;\n\n for (; i < 256; i++) {\n color = parseInt(colors[i].substring(1), 16);\n out.push([\n (color >> 16) & 0xff,\n (color >> 8) & 0xff,\n color & 0xff\n ]);\n }\n\n return out;\n})();\n\n/**\n * Options\n */\n\nTerminal.defaults = {\n colors: Terminal.colors,\n theme: 'default',\n convertEol: false,\n termName: 'xterm',\n geometry: [80, 24],\n cursorBlink: false,\n visualBell: false,\n popOnBell: false,\n scrollback: 1000,\n screenKeys: false,\n debug: false,\n cancelEvents: false\n // programFeatures: false,\n // focusKeys: false,\n};\n\nTerminal.options = {};\n\nTerminal.focus = null;\n\neach(keys(Terminal.defaults), function(key) {\n Terminal[key] = Terminal.defaults[key];\n Terminal.options[key] = Terminal.defaults[key];\n});\n\n/**\n * Focus the terminal. Delegates focus handling to the terminal's DOM element.\n */\nTerminal.prototype.focus = function() {\n return this.textarea.focus();\n};\n\n/**\n * Retrieves an option's value from the terminal.\n * @param {string} key The option key.\n */\nTerminal.prototype.getOption = function(key, value) {\n if (!(key in Terminal.defaults)) {\n throw new Error('No option with key \"' + key + '\"');\n }\n\n if (typeof this.options[key] !== 'undefined') {\n return this.options[key];\n }\n\n return this[key];\n};\n\n/**\n * Sets an option on the terminal.\n * @param {string} key The option key.\n * @param {string} value The option value.\n */\nTerminal.prototype.setOption = function(key, value) {\n if (!(key in Terminal.defaults)) {\n throw new Error('No option with key \"' + key + '\"');\n }\n this[key] = value;\n this.options[key] = value;\n};\n\n/**\n * Binds the desired focus behavior on a given terminal object.\n *\n * @static\n */\nTerminal.bindFocus = function (term) {\n on(term.textarea, 'focus', function (ev) {\n if (term.sendFocus) {\n term.send('\\x1b[I');\n }\n term.element.classList.add('focus');\n term.showCursor();\n Terminal.focus = term;\n term.emit('focus', {terminal: term});\n });\n};\n\n/**\n * Blur the terminal. Delegates blur handling to the terminal's DOM element.\n */\nTerminal.prototype.blur = function() {\n return this.textarea.blur();\n};\n\n/**\n * Binds the desired blur behavior on a given terminal object.\n *\n * @static\n */\nTerminal.bindBlur = function (term) {\n on(term.textarea, 'blur', function (ev) {\n term.refresh(term.y, term.y);\n if (term.sendFocus) {\n term.send('\\x1b[O');\n }\n term.element.classList.remove('focus');\n Terminal.focus = null;\n term.emit('blur', {terminal: term});\n });\n};\n\n/**\n * Initialize default behavior\n */\nTerminal.prototype.initGlobal = function() {\n var term = this;\n\n Terminal.bindKeys(this);\n Terminal.bindFocus(this);\n Terminal.bindBlur(this);\n\n // Bind clipboard functionality\n on(this.element, 'copy', function (ev) {\n copyHandler.call(this, ev, term);\n });\n on(this.textarea, 'paste', function (ev) {\n pasteHandler.call(this, ev, term);\n });\n\n function rightClickHandlerWrapper (ev) {\n rightClickHandler.call(this, ev, term);\n }\n\n if (term.browser.isFirefox) {\n on(this.element, 'mousedown', function (ev) {\n if (ev.button == 2) {\n rightClickHandlerWrapper(ev);\n }\n });\n } else {\n on(this.element, 'contextmenu', rightClickHandlerWrapper);\n }\n};\n\n/**\n * Apply key handling to the terminal\n */\nTerminal.bindKeys = function(term) {\n on(term.element, 'keydown', function(ev) {\n if (document.activeElement != this) {\n return;\n }\n term.keyDown(ev);\n }, true);\n\n on(term.element, 'keypress', function(ev) {\n if (document.activeElement != this) {\n return;\n }\n term.keyPress(ev);\n }, true);\n\n on(term.element, 'keyup', term.focus.bind(term));\n\n on(term.textarea, 'keydown', function(ev) {\n term.keyDown(ev);\n }, true);\n\n on(term.textarea, 'keypress', function(ev) {\n term.keyPress(ev);\n // Truncate the textarea's value, since it is not needed\n this.value = '';\n }, true);\n\n on(term.textarea, 'compositionstart', term.compositionHelper.compositionstart.bind(term.compositionHelper));\n on(term.textarea, 'compositionupdate', term.compositionHelper.compositionupdate.bind(term.compositionHelper));\n on(term.textarea, 'compositionend', term.compositionHelper.compositionend.bind(term.compositionHelper));\n term.on('refresh', term.compositionHelper.updateCompositionElements.bind(term.compositionHelper));\n};\n\n\n/**\n * Insert the given row to the terminal or produce a new one\n * if no row argument is passed. Return the inserted row.\n * @param {HTMLElement} row (optional) The row to append to the terminal.\n */\nTerminal.prototype.insertRow = function (row) {\n if (typeof row != 'object') {\n row = document.createElement('div');\n }\n\n this.rowContainer.appendChild(row);\n this.children.push(row);\n\n return row;\n};\n\n/**\n * Opens the terminal within an element.\n *\n * @param {HTMLElement} parent The element to create the terminal within.\n */\nTerminal.prototype.open = function(parent) {\n var self=this, i=0, div;\n\n this.parent = parent || this.parent;\n\n if (!this.parent) {\n throw new Error('Terminal requires a parent element.');\n }\n\n // Grab global elements\n this.context = this.parent.ownerDocument.defaultView;\n this.document = this.parent.ownerDocument;\n this.body = this.document.getElementsByTagName('body')[0];\n\n //Create main element container\n this.element = this.document.createElement('div');\n this.element.classList.add('terminal');\n this.element.classList.add('xterm');\n this.element.classList.add('xterm-theme-' + this.theme);\n\n this.element.style.height\n this.element.setAttribute('tabindex', 0);\n\n this.viewportElement = document.createElement('div');\n this.viewportElement.classList.add('xterm-viewport');\n this.element.appendChild(this.viewportElement);\n this.viewportScrollArea = document.createElement('div');\n this.viewportScrollArea.classList.add('xterm-scroll-area');\n this.viewportElement.appendChild(this.viewportScrollArea);\n\n // Create the container that will hold the lines of the terminal and then\n // produce the lines the lines.\n this.rowContainer = document.createElement('div');\n this.rowContainer.classList.add('xterm-rows');\n this.element.appendChild(this.rowContainer);\n this.children = [];\n\n // Create the container that will hold helpers like the textarea for\n // capturing DOM Events. Then produce the helpers.\n this.helperContainer = document.createElement('div');\n this.helperContainer.classList.add('xterm-helpers');\n // TODO: This should probably be inserted once it's filled to prevent an additional layout\n this.element.appendChild(this.helperContainer);\n this.textarea = document.createElement('textarea');\n this.textarea.classList.add('xterm-helper-textarea');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.tabIndex = 0;\n this.textarea.addEventListener('focus', function() {\n self.emit('focus', {terminal: self});\n });\n this.textarea.addEventListener('blur', function() {\n self.emit('blur', {terminal: self});\n });\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.charMeasureElement = document.createElement('div');\n this.charMeasureElement.classList.add('xterm-char-measure-element');\n this.charMeasureElement.innerHTML = 'W';\n this.helperContainer.appendChild(this.charMeasureElement);\n\n for (; i < this.rows; i++) {\n this.insertRow();\n }\n this.parent.appendChild(this.element);\n\n this.viewport = new Viewport(this, this.viewportElement, this.viewportScrollArea, this.charMeasureElement);\n\n // Draw the screen.\n this.refresh(0, this.rows - 1);\n\n // Initialize global actions that\n // need to be taken on the document.\n this.initGlobal();\n\n // Ensure there is a Terminal.focus.\n this.focus();\n\n on(this.element, 'click', function() {\n var selection = document.getSelection(),\n collapsed = selection.isCollapsed,\n isRange = typeof collapsed == 'boolean' ? !collapsed : selection.type == 'Range';\n if (!isRange) {\n self.focus();\n }\n });\n\n // Listen for mouse events and translate\n // them into terminal mouse protocols.\n this.bindMouse();\n\n // Figure out whether boldness affects\n // the character width of monospace fonts.\n if (Terminal.brokenBold == null) {\n Terminal.brokenBold = isBoldBroken(this.document);\n }\n\n this.emit('open');\n};\n\n\n/**\n * Attempts to load an add-on using CommonJS or RequireJS (whichever is available).\n * @param {string} addon The name of the addon to load\n * @static\n */\nTerminal.loadAddon = function(addon, callback) {\n if (typeof exports === 'object' && typeof module === 'object') {\n // CommonJS\n return require('../addons/' + addon);\n } else if (typeof define == 'function') {\n // RequireJS\n return require(['../addons/' + addon + '/' + addon], callback);\n } else {\n console.error('Cannot load a module without a CommonJS or RequireJS environment.');\n return false;\n }\n};\n\n\n/**\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 */\nTerminal.prototype.bindMouse = function() {\n var el = this.element, self = this, pressed = 32;\n\n // mouseup, mousedown, wheel\n // left click: ^[[M 3<^[[M#3<\n // wheel up: ^[[M`3>\n function sendButton(ev) {\n var button\n , pos;\n\n // get the xterm-style button\n button = getButton(ev);\n\n // get mouse coordinates\n pos = getCoords(ev);\n if (!pos) return;\n\n sendEvent(button, pos);\n\n switch (ev.overrideType || ev.type) {\n case 'mousedown':\n pressed = button;\n break;\n case 'mouseup':\n // keep it at the left\n // button, just in case.\n pressed = 32;\n break;\n case 'wheel':\n // nothing. don't\n // interfere with\n // `pressed`.\n break;\n }\n }\n\n // motion example of a left click:\n // ^[[M 3<^[[M@4<^[[M@5<^[[M@6<^[[M@7<^[[M#7<\n function sendMove(ev) {\n var button = pressed\n , pos;\n\n pos = getCoords(ev);\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, ch) {\n if (!self.utfMouse) {\n if (ch === 255) return data.push(0);\n if (ch > 127) ch = 127;\n data.push(ch);\n } else {\n if (ch === 2047) return data.push(0);\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, pos) {\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 var data = '\\x1b[24';\n if (button === 0) data += '1';\n else if (button === 1) data += '3';\n else if (button === 2) data += '5';\n else if (button === 3) return;\n else data += '0';\n data += '~[' + pos.x + ',' + pos.y + ']\\r';\n self.send(data);\n return;\n }\n\n if (self.decLocator) {\n // NOTE: Unstable.\n button &= 3;\n pos.x -= 32;\n pos.y -= 32;\n if (button === 0) button = 2;\n else if (button === 1) button = 4;\n else if (button === 2) button = 6;\n else if (button === 3) button = 3;\n self.send('\\x1b['\n + button\n + ';'\n + (button === 3 ? 4 : 0)\n + ';'\n + pos.y\n + ';'\n + pos.x\n + ';'\n + (pos.page || 0)\n + '&w');\n return;\n }\n\n if (self.urxvtMouse) {\n pos.x -= 32;\n pos.y -= 32;\n pos.x++;\n pos.y++;\n self.send('\\x1b[' + button + ';' + pos.x + ';' + pos.y + 'M');\n return;\n }\n\n if (self.sgrMouse) {\n pos.x -= 32;\n pos.y -= 32;\n self.send('\\x1b[<'\n + ((button & 3) === 3 ? button & ~3 : button)\n + ';'\n + pos.x\n + ';'\n + pos.y\n + ((button & 3) === 3 ? 'm' : 'M'));\n return;\n }\n\n var data = [];\n\n encode(data, button);\n encode(data, pos.x);\n encode(data, pos.y);\n\n self.send('\\x1b[M' + String.fromCharCode.apply(String, data));\n }\n\n function getButton(ev) {\n var button\n , shift\n , meta\n , ctrl\n , mod;\n\n // two low bits:\n // 0 = left\n // 1 = middle\n // 2 = right\n // 3 = release\n // wheel up/down:\n // 1, and 2 - with 64 added\n switch (ev.overrideType || ev.type) {\n case 'mousedown':\n button = ev.button != null\n ? +ev.button\n : ev.which != null\n ? ev.which - 1\n : null;\n\n if (self.browser.isMSIE) {\n button = button === 1 ? 0 : button === 4 ? 1 : button;\n }\n break;\n case 'mouseup':\n button = 3;\n break;\n case 'DOMMouseScroll':\n button = ev.detail < 0\n ? 64\n : 65;\n break;\n case 'wheel':\n button = ev.wheelDeltaY > 0\n ? 64\n : 65;\n break;\n }\n\n // next three bits are the modifiers:\n // 4 = shift, 8 = meta, 16 = control\n shift = ev.shiftKey ? 4 : 0;\n meta = ev.metaKey ? 8 : 0;\n ctrl = ev.ctrlKey ? 16 : 0;\n mod = shift | meta | ctrl;\n\n // no mods\n if (self.vt200Mouse) {\n // ctrl only\n mod &= ctrl;\n } else if (!self.normalMouse) {\n mod = 0;\n }\n\n // increment to SP\n button = (32 + (mod << 2)) + button;\n\n return button;\n }\n\n // mouse coordinates measured in cols/rows\n function getCoords(ev) {\n var x, y, w, h, el;\n\n // ignore browsers without pageX for now\n if (ev.pageX == null) return;\n\n x = ev.pageX;\n y = ev.pageY;\n el = self.element;\n\n // should probably check offsetParent\n // but this is more portable\n while (el && el !== self.document.documentElement) {\n x -= el.offsetLeft;\n y -= el.offsetTop;\n el = 'offsetParent' in el\n ? el.offsetParent\n : el.parentNode;\n }\n\n // convert to cols/rows\n w = self.element.clientWidth;\n h = self.element.clientHeight;\n x = Math.ceil((x / w) * self.cols);\n y = Math.ceil((y / h) * self.rows);\n\n // be sure to avoid sending\n // bad positions to the program\n if (x < 0) x = 0;\n if (x > self.cols) x = self.cols;\n if (y < 0) y = 0;\n if (y > self.rows) y = self.rows;\n\n // xterm sends raw bytes and\n // starts at 32 (SP) for each.\n x += 32;\n y += 32;\n\n return {\n x: x,\n y: y,\n type: 'wheel'\n };\n }\n\n on(el, 'mousedown', function(ev) {\n if (!self.mouseEvents) return;\n\n // send the button\n sendButton(ev);\n\n // ensure focus\n self.focus();\n\n // fix for odd bug\n //if (self.vt200Mouse && !self.normalMouse) {\n if (self.vt200Mouse) {\n ev.overrideType = 'mouseup';\n sendButton(ev);\n return self.cancel(ev);\n }\n\n // bind events\n if (self.normalMouse) on(self.document, 'mousemove', sendMove);\n\n // x10 compatibility mode can't send button releases\n if (!self.x10Mouse) {\n on(self.document, 'mouseup', function up(ev) {\n sendButton(ev);\n if (self.normalMouse) off(self.document, 'mousemove', sendMove);\n off(self.document, 'mouseup', up);\n return self.cancel(ev);\n });\n }\n\n return self.cancel(ev);\n });\n\n //if (self.normalMouse) {\n // on(self.document, 'mousemove', sendMove);\n //}\n\n on(el, 'wheel', function(ev) {\n if (!self.mouseEvents) return;\n if (self.x10Mouse\n || self.vt300Mouse\n || self.decLocator) return;\n sendButton(ev);\n return self.cancel(ev);\n });\n\n // allow wheel scrolling in\n // the shell for example\n on(el, 'wheel', function(ev) {\n if (self.mouseEvents) return;\n self.viewport.onWheel(ev);\n return self.cancel(ev);\n });\n};\n\n/**\n * Destroys the terminal.\n */\nTerminal.prototype.destroy = function() {\n this.readable = false;\n this.writable = false;\n this._events = {};\n this.handler = function() {};\n this.write = function() {};\n if (this.element.parentNode) {\n this.element.parentNode.removeChild(this.element);\n }\n //this.emit('close');\n};\n\n\n/**\n * Flags used to render terminal text properly\n */\nTerminal.flags = {\n BOLD: 1,\n UNDERLINE: 2,\n BLINK: 4,\n INVERSE: 8,\n INVISIBLE: 16\n}\n\n/**\n * Refreshes (re-renders) terminal content within two rows (inclusive)\n *\n * Rendering Engine:\n *\n * In the screen buffer, each character is stored as a an array with a character\n * and a 32-bit integer:\n * - First value: a utf-16 character.\n * - Second value:\n * - Next 9 bits: background color (0-511).\n * - Next 9 bits: foreground color (0-511).\n * - Next 14 bits: a mask for misc. flags:\n * - 1=bold\n * - 2=underline\n * - 4=blink\n * - 8=inverse\n * - 16=invisible\n *\n * @param {number} start The row to start from (between 0 and terminal's height terminal - 1)\n * @param {number} end The row to end at (between fromRow and terminal's height terminal - 1)\n * @param {boolean} queue Whether the refresh should ran right now or be queued\n */\nTerminal.prototype.refresh = function(start, end, queue) {\n var self = this;\n\n // queue defaults to true\n queue = (typeof queue == 'undefined') ? true : queue;\n\n /**\n * The refresh queue allows refresh to execute only approximately 30 times a second. For\n * commands that pass a significant amount of output to the write function, this prevents the\n * terminal from maxing out the CPU and making the UI unresponsive. While commands can still\n * run beyond what they do on the terminal, it is far better with a debounce in place as\n * every single terminal manipulation does not need to be constructed in the DOM.\n *\n * A side-effect of this is that it makes ^C to interrupt a process seem more responsive.\n */\n if (queue) {\n // If refresh should be queued, order the refresh and return.\n if (this._refreshIsQueued) {\n // If a refresh has already been queued, just order a full refresh next\n this._fullRefreshNext = true;\n } else {\n setTimeout(function () {\n self.refresh(start, end, false);\n }, 34)\n this._refreshIsQueued = true;\n }\n return;\n }\n\n // If refresh should be run right now (not be queued), release the lock\n this._refreshIsQueued = false;\n\n // If multiple refreshes were requested, make a full refresh.\n if (this._fullRefreshNext) {\n start = 0;\n end = this.rows - 1;\n this._fullRefreshNext = false // reset lock\n }\n\n var x, y, i, line, out, ch, ch_width, width, data, attr, bg, fg, flags, row, parent, focused = document.activeElement;\n\n // If this is a big refresh, remove the terminal rows from the DOM for faster calculations\n if (end - start >= this.rows / 2) {\n parent = this.element.parentNode;\n if (parent) {\n this.element.removeChild(this.rowContainer);\n }\n }\n\n width = this.cols;\n y = start;\n\n if (end >= this.rows.length) {\n this.log('`end` is too large. Most likely a bad CSR.');\n end = this.rows.length - 1;\n }\n\n for (; y <= end; y++) {\n row = y + this.ydisp;\n\n line = this.lines[row];\n out = '';\n\n if (this.y === y - (this.ybase - this.ydisp)\n && this.cursorState\n && !this.cursorHidden) {\n x = this.x;\n } else {\n x = -1;\n }\n\n attr = this.defAttr;\n i = 0;\n\n for (; i < width; i++) {\n data = line[i][0];\n ch = line[i][1];\n ch_width = line[i][2];\n if (!ch_width)\n continue;\n\n if (i === x) data = -1;\n\n if (data !== attr) {\n if (attr !== this.defAttr) {\n out += '';\n }\n if (data !== this.defAttr) {\n if (data === -1) {\n out += '> 9) & 0x1ff;\n flags = data >> 18;\n\n if (flags & Terminal.flags.BOLD) {\n if (!Terminal.brokenBold) {\n classNames.push('xterm-bold');\n }\n // See: XTerm*boldColors\n if (fg < 8) fg += 8;\n }\n\n if (flags & Terminal.flags.UNDERLINE) {\n classNames.push('xterm-underline');\n }\n\n if (flags & Terminal.flags.BLINK) {\n classNames.push('xterm-blink');\n }\n\n // If inverse flag is on, then swap the foreground and background variables.\n if (flags & Terminal.flags.INVERSE) {\n /* One-line variable swap in JavaScript: http://stackoverflow.com/a/16201730 */\n bg = [fg, fg = bg][0];\n // Should inverse just be before the\n // above boldColors effect instead?\n if ((flags & 1) && fg < 8) fg += 8;\n }\n\n if (flags & Terminal.flags.INVISIBLE) {\n classNames.push('xterm-hidden');\n }\n\n /**\n * Weird situation: Invert flag used black foreground and white background results\n * in invalid background color, positioned at the 256 index of the 256 terminal\n * color map. Pin the colors manually in such a case.\n *\n * Source: https://github.com/sourcelair/xterm.js/issues/57\n */\n if (flags & Terminal.flags.INVERSE) {\n if (bg == 257) {\n bg = 15;\n }\n if (fg == 256) {\n fg = 0;\n }\n }\n\n if (bg < 256) {\n classNames.push('xterm-bg-color-' + bg);\n }\n\n if (fg < 256) {\n classNames.push('xterm-color-' + fg);\n }\n\n out += '':\n out += '>';\n break;\n default:\n if (ch <= ' ') {\n out += ' ';\n } else {\n out += ch;\n }\n break;\n }\n\n attr = data;\n }\n\n if (attr !== this.defAttr) {\n out += '';\n }\n\n this.children[y].innerHTML = out;\n }\n\n if (parent) {\n this.element.appendChild(this.rowContainer);\n }\n\n this.emit('refresh', {element: this.element, start: start, end: end});\n};\n\n/**\n * Display the cursor element\n */\nTerminal.prototype.showCursor = function() {\n if (!this.cursorState) {\n this.cursorState = 1;\n this.refresh(this.y, this.y);\n }\n};\n\n/**\n * Scroll the terminal\n */\nTerminal.prototype.scroll = function() {\n var row;\n\n if (++this.ybase === this.scrollback) {\n this.ybase = this.ybase / 2 | 0;\n this.lines = this.lines.slice(-(this.ybase + this.rows) + 1);\n }\n\n if (!this.userScrolling) {\n this.ydisp = this.ybase;\n }\n\n // last line\n row = this.ybase + this.rows - 1;\n\n // subtract the bottom scroll region\n row -= this.rows - 1 - this.scrollBottom;\n\n if (row === this.lines.length) {\n // potential optimization:\n // pushing is faster than splicing\n // when they amount to the same\n // behavior.\n this.lines.push(this.blankLine());\n } else {\n // add our new line\n this.lines.splice(row, 0, this.blankLine());\n }\n\n if (this.scrollTop !== 0) {\n if (this.ybase !== 0) {\n this.ybase--;\n if (!this.userScrolling) {\n this.ydisp = this.ybase;\n }\n }\n this.lines.splice(this.ybase + this.scrollTop, 1);\n }\n\n // this.maxRange();\n this.updateRange(this.scrollTop);\n this.updateRange(this.scrollBottom);\n\n this.emit('scroll', this.ydisp);\n};\n\n/**\n * Scroll the display of the terminal\n * @param {number} disp The number of lines to scroll down (negatives scroll up).\n * @param {boolean} suppressScrollEvent Don't emit the scroll event as scrollDisp. This is used\n * to avoid unwanted events being handled by the veiwport when the event was triggered from the\n * viewport originally.\n */\nTerminal.prototype.scrollDisp = function(disp, suppressScrollEvent) {\n if (disp < 0) {\n this.userScrolling = true;\n } else if (disp + this.ydisp >= this.ybase) {\n this.userScrolling = false;\n }\n\n this.ydisp += disp;\n\n if (this.ydisp > this.ybase) {\n this.ydisp = this.ybase;\n } else if (this.ydisp < 0) {\n this.ydisp = 0;\n }\n\n if (!suppressScrollEvent) {\n this.emit('scroll', this.ydisp);\n }\n\n this.refresh(0, this.rows - 1);\n};\n\n/**\n * Scroll the display of the terminal by a number of pages.\n * @param {number} pageCount The number of pages to scroll (negative scrolls up).\n */\nTerminal.prototype.scrollPages = function(pageCount) {\n this.scrollDisp(pageCount * (this.rows - 1));\n}\n\n/**\n * Scrolls the display of the terminal to the top.\n */\nTerminal.prototype.scrollToTop = function() {\n this.scrollDisp(-this.ydisp);\n}\n\n/**\n * Scrolls the display of the terminal to the bottom.\n */\nTerminal.prototype.scrollToBottom = function() {\n this.scrollDisp(this.ybase - this.ydisp);\n}\n\n/**\n * Writes text to the terminal.\n * @param {string} text The text to write to the terminal.\n */\nTerminal.prototype.write = function(data) {\n var l = data.length, i = 0, j, cs, ch, code, low, ch_width, row;\n\n this.refreshStart = this.y;\n this.refreshEnd = this.y;\n\n // apply leftover surrogate high from last write\n if (this.surrogate_high) {\n data = this.surrogate_high + data;\n this.surrogate_high = '';\n }\n\n for (; i < l; i++) {\n ch = data[i];\n\n // FIXME: higher chars than 0xa0 are not allowed in escape sequences\n // --> maybe move to default\n code = data.charCodeAt(i);\n if (0xD800 <= code && code <= 0xDBFF) {\n // we got a surrogate high\n // get surrogate low (next 2 bytes)\n low = data.charCodeAt(i+1);\n if (isNaN(low)) {\n // end of data stream, save surrogate high\n this.surrogate_high = ch;\n continue;\n }\n code = ((code - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;\n ch += data.charAt(i+1);\n }\n // surrogate low - already handled above\n if (0xDC00 <= code && code <= 0xDFFF)\n continue;\n\n switch (this.state) {\n case normal:\n switch (ch) {\n case '\\x07':\n this.bell();\n break;\n\n // '\\n', '\\v', '\\f'\n case '\\n':\n case '\\x0b':\n case '\\x0c':\n if (this.convertEol) {\n this.x = 0;\n }\n this.y++;\n if (this.y > this.scrollBottom) {\n this.y--;\n this.scroll();\n }\n break;\n\n // '\\r'\n case '\\r':\n this.x = 0;\n break;\n\n // '\\b'\n case '\\x08':\n if (this.x > 0) {\n this.x--;\n }\n break;\n\n // '\\t'\n case '\\t':\n this.x = this.nextStop();\n break;\n\n // shift out\n case '\\x0e':\n this.setgLevel(1);\n break;\n\n // shift in\n case '\\x0f':\n this.setgLevel(0);\n break;\n\n // '\\e'\n case '\\x1b':\n this.state = escaped;\n break;\n\n default:\n // ' '\n // calculate print space\n // expensive call, therefore we save width in line buffer\n ch_width = wcwidth(code);\n\n if (ch >= ' ') {\n if (this.charset && this.charset[ch]) {\n ch = this.charset[ch];\n }\n\n row = this.y + this.ybase;\n\n // insert combining char in last cell\n // FIXME: needs handling after cursor jumps\n if (!ch_width && this.x) {\n\n // dont overflow left\n if (this.lines[row][this.x-1]) {\n if (!this.lines[row][this.x-1][2]) {\n\n // found empty cell after fullwidth, need to go 2 cells back\n if (this.lines[row][this.x-2])\n this.lines[row][this.x-2][1] += ch;\n\n } else {\n this.lines[row][this.x-1][1] += ch;\n }\n this.updateRange(this.y);\n }\n break;\n }\n\n // goto next line if ch would overflow\n // TODO: needs a global min terminal width of 2\n if (this.x+ch_width-1 >= this.cols) {\n // autowrap - DECAWM\n if (this.wraparoundMode) {\n this.x = 0;\n this.y++;\n if (this.y > this.scrollBottom) {\n this.y--;\n this.scroll();\n }\n } else {\n this.x = this.cols-1;\n if(ch_width===2) // FIXME: check for xterm behavior\n continue;\n }\n }\n row = this.y + this.ybase;\n\n // insert mode: move characters to right\n if (this.insertMode) {\n // do this twice for a fullwidth char\n for (var moves=0; moves Normal Keypad (DECKPNM).\n case '>':\n this.log('Switching back to normal keypad.');\n this.applicationKeypad = false;\n this.viewport.syncScrollArea();\n this.state = normal;\n break;\n\n default:\n this.state = normal;\n this.error('Unknown ESC control: %s.', ch);\n break;\n }\n break;\n\n case charset:\n switch (ch) {\n case '0': // DEC Special Character and Line Drawing Set.\n cs = Terminal.charsets.SCLD;\n break;\n case 'A': // UK\n cs = Terminal.charsets.UK;\n break;\n case 'B': // United States (USASCII).\n cs = Terminal.charsets.US;\n break;\n case '4': // Dutch\n cs = Terminal.charsets.Dutch;\n break;\n case 'C': // Finnish\n case '5':\n cs = Terminal.charsets.Finnish;\n break;\n case 'R': // French\n cs = Terminal.charsets.French;\n break;\n case 'Q': // FrenchCanadian\n cs = Terminal.charsets.FrenchCanadian;\n break;\n case 'K': // German\n cs = Terminal.charsets.German;\n break;\n case 'Y': // Italian\n cs = Terminal.charsets.Italian;\n break;\n case 'E': // NorwegianDanish\n case '6':\n cs = Terminal.charsets.NorwegianDanish;\n break;\n case 'Z': // Spanish\n cs = Terminal.charsets.Spanish;\n break;\n case 'H': // Swedish\n case '7':\n cs = Terminal.charsets.Swedish;\n break;\n case '=': // Swiss\n cs = Terminal.charsets.Swiss;\n break;\n case '/': // ISOLatin (actually /A)\n cs = Terminal.charsets.ISOLatin;\n i++;\n break;\n default: // Default\n cs = Terminal.charsets.US;\n break;\n }\n this.setgCharset(this.gcharset, cs);\n this.gcharset = null;\n this.state = normal;\n break;\n\n case osc:\n // OSC Ps ; Pt ST\n // OSC Ps ; Pt BEL\n // Set Text Parameters.\n if (ch === '\\x1b' || ch === '\\x07') {\n if (ch === '\\x1b') i++;\n\n this.params.push(this.currentParam);\n\n switch (this.params[0]) {\n case 0:\n case 1:\n case 2:\n if (this.params[1]) {\n this.title = this.params[1];\n this.handleTitle(this.title);\n }\n break;\n case 3:\n // set X property\n break;\n case 4:\n case 5:\n // change dynamic colors\n break;\n case 10:\n case 11:\n case 12:\n case 13:\n case 14:\n case 15:\n case 16:\n case 17:\n case 18:\n case 19:\n // change dynamic ui colors\n break;\n case 46:\n // change log file\n break;\n case 50:\n // dynamic font\n break;\n case 51:\n // emacs shell\n break;\n case 52:\n // manipulate selection data\n break;\n case 104:\n case 105:\n case 110:\n case 111:\n case 112:\n case 113:\n case 114:\n case 115:\n case 116:\n case 117:\n case 118:\n // reset colors\n break;\n }\n\n this.params = [];\n this.currentParam = 0;\n this.state = normal;\n } else {\n if (!this.params.length) {\n if (ch >= '0' && ch <= '9') {\n this.currentParam =\n this.currentParam * 10 + ch.charCodeAt(0) - 48;\n } else if (ch === ';') {\n this.params.push(this.currentParam);\n this.currentParam = '';\n }\n } else {\n this.currentParam += ch;\n }\n }\n break;\n\n case csi:\n // '?', '>', '!'\n if (ch === '?' || ch === '>' || ch === '!') {\n this.prefix = ch;\n break;\n }\n\n // 0 - 9\n if (ch >= '0' && ch <= '9') {\n this.currentParam = this.currentParam * 10 + ch.charCodeAt(0) - 48;\n break;\n }\n\n // '$', '\"', ' ', '\\''\n if (ch === '$' || ch === '\"' || ch === ' ' || ch === '\\'') {\n this.postfix = ch;\n break;\n }\n\n this.params.push(this.currentParam);\n this.currentParam = 0;\n\n // ';'\n if (ch === ';') break;\n\n this.state = normal;\n\n switch (ch) {\n // CSI Ps A\n // Cursor Up Ps Times (default = 1) (CUU).\n case 'A':\n this.cursorUp(this.params);\n break;\n\n // CSI Ps B\n // Cursor Down Ps Times (default = 1) (CUD).\n case 'B':\n this.cursorDown(this.params);\n break;\n\n // CSI Ps C\n // Cursor Forward Ps Times (default = 1) (CUF).\n case 'C':\n this.cursorForward(this.params);\n break;\n\n // CSI Ps D\n // Cursor Backward Ps Times (default = 1) (CUB).\n case 'D':\n this.cursorBackward(this.params);\n break;\n\n // CSI Ps ; Ps H\n // Cursor Position [row;column] (default = [1,1]) (CUP).\n case 'H':\n this.cursorPos(this.params);\n break;\n\n // CSI Ps J Erase in Display (ED).\n case 'J':\n this.eraseInDisplay(this.params);\n break;\n\n // CSI Ps K Erase in Line (EL).\n case 'K':\n this.eraseInLine(this.params);\n break;\n\n // CSI Pm m Character Attributes (SGR).\n case 'm':\n if (!this.prefix) {\n this.charAttributes(this.params);\n }\n break;\n\n // CSI Ps n Device Status Report (DSR).\n case 'n':\n if (!this.prefix) {\n this.deviceStatus(this.params);\n }\n break;\n\n /**\n * Additions\n */\n\n // CSI Ps @\n // Insert Ps (Blank) Character(s) (default = 1) (ICH).\n case '@':\n this.insertChars(this.params);\n break;\n\n // CSI Ps E\n // Cursor Next Line Ps Times (default = 1) (CNL).\n case 'E':\n this.cursorNextLine(this.params);\n break;\n\n // CSI Ps F\n // Cursor Preceding Line Ps Times (default = 1) (CNL).\n case 'F':\n this.cursorPrecedingLine(this.params);\n break;\n\n // CSI Ps G\n // Cursor Character Absolute [column] (default = [row,1]) (CHA).\n case 'G':\n this.cursorCharAbsolute(this.params);\n break;\n\n // CSI Ps L\n // Insert Ps Line(s) (default = 1) (IL).\n case 'L':\n this.insertLines(this.params);\n break;\n\n // CSI Ps M\n // Delete Ps Line(s) (default = 1) (DL).\n case 'M':\n this.deleteLines(this.params);\n break;\n\n // CSI Ps P\n // Delete Ps Character(s) (default = 1) (DCH).\n case 'P':\n this.deleteChars(this.params);\n break;\n\n // CSI Ps X\n // Erase Ps Character(s) (default = 1) (ECH).\n case 'X':\n this.eraseChars(this.params);\n break;\n\n // CSI Pm ` Character Position Absolute\n // [column] (default = [row,1]) (HPA).\n case '`':\n this.charPosAbsolute(this.params);\n break;\n\n // 141 61 a * HPR -\n // Horizontal Position Relative\n case 'a':\n this.HPositionRelative(this.params);\n break;\n\n // CSI P s c\n // Send Device Attributes (Primary DA).\n // CSI > P s c\n // Send Device Attributes (Secondary DA)\n case 'c':\n this.sendDeviceAttributes(this.params);\n break;\n\n // CSI Pm d\n // Line Position Absolute [row] (default = [1,column]) (VPA).\n case 'd':\n this.linePosAbsolute(this.params);\n break;\n\n // 145 65 e * VPR - Vertical Position Relative\n case 'e':\n this.VPositionRelative(this.params);\n break;\n\n // CSI Ps ; Ps f\n // Horizontal and Vertical Position [row;column] (default =\n // [1,1]) (HVP).\n case 'f':\n this.HVPosition(this.params);\n break;\n\n // CSI Pm h Set Mode (SM).\n // CSI ? Pm h - mouse escape codes, cursor escape codes\n case 'h':\n this.setMode(this.params);\n break;\n\n // CSI Pm l Reset Mode (RM).\n // CSI ? Pm l\n case 'l':\n this.resetMode(this.params);\n break;\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 case 'r':\n this.setScrollRegion(this.params);\n break;\n\n // CSI s\n // Save cursor (ANSI.SYS).\n case 's':\n this.saveCursor(this.params);\n break;\n\n // CSI u\n // Restore cursor (ANSI.SYS).\n case 'u':\n this.restoreCursor(this.params);\n break;\n\n /**\n * Lesser Used\n */\n\n // CSI Ps I\n // Cursor Forward Tabulation Ps tab stops (default = 1) (CHT).\n case 'I':\n this.cursorForwardTab(this.params);\n break;\n\n // CSI Ps S Scroll up Ps lines (default = 1) (SU).\n case 'S':\n this.scrollUp(this.params);\n break;\n\n // CSI Ps T Scroll down Ps lines (default = 1) (SD).\n // CSI Ps ; Ps ; Ps ; Ps ; Ps T\n // CSI > Ps; Ps T\n case 'T':\n // if (this.prefix === '>') {\n // this.resetTitleModes(this.params);\n // break;\n // }\n // if (this.params.length > 2) {\n // this.initMouseTracking(this.params);\n // break;\n // }\n if (this.params.length < 2 && !this.prefix) {\n this.scrollDown(this.params);\n }\n break;\n\n // CSI Ps Z\n // Cursor Backward Tabulation Ps tab stops (default = 1) (CBT).\n case 'Z':\n this.cursorBackwardTab(this.params);\n break;\n\n // CSI Ps b Repeat the preceding graphic character Ps times (REP).\n case 'b':\n this.repeatPrecedingCharacter(this.params);\n break;\n\n // CSI Ps g Tab Clear (TBC).\n case 'g':\n this.tabClear(this.params);\n break;\n\n // CSI Pm i Media Copy (MC).\n // CSI ? Pm i\n // case 'i':\n // this.mediaCopy(this.params);\n // break;\n\n // CSI Pm m Character Attributes (SGR).\n // CSI > Ps; Ps m\n // case 'm': // duplicate\n // if (this.prefix === '>') {\n // this.setResources(this.params);\n // } else {\n // this.charAttributes(this.params);\n // }\n // break;\n\n // CSI Ps n Device Status Report (DSR).\n // CSI > Ps n\n // case 'n': // duplicate\n // if (this.prefix === '>') {\n // this.disableModifiers(this.params);\n // } else {\n // this.deviceStatus(this.params);\n // }\n // break;\n\n // CSI > Ps p Set pointer mode.\n // CSI ! p Soft terminal reset (DECSTR).\n // CSI Ps$ p\n // Request ANSI mode (DECRQM).\n // CSI ? Ps$ p\n // Request DEC private mode (DECRQM).\n // CSI Ps ; Ps \" p\n case 'p':\n switch (this.prefix) {\n // case '>':\n // this.setPointerMode(this.params);\n // break;\n case '!':\n this.softReset(this.params);\n break;\n // case '?':\n // if (this.postfix === '$') {\n // this.requestPrivateMode(this.params);\n // }\n // break;\n // default:\n // if (this.postfix === '\"') {\n // this.setConformanceLevel(this.params);\n // } else if (this.postfix === '$') {\n // this.requestAnsiMode(this.params);\n // }\n // break;\n }\n break;\n\n // CSI Ps q Load LEDs (DECLL).\n // CSI Ps SP q\n // CSI Ps \" q\n // case 'q':\n // if (this.postfix === ' ') {\n // this.setCursorStyle(this.params);\n // break;\n // }\n // if (this.postfix === '\"') {\n // this.setCharProtectionAttr(this.params);\n // break;\n // }\n // this.loadLEDs(this.params);\n // break;\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 // CSI Pt; Pl; Pb; Pr; Ps$ r\n // case 'r': // duplicate\n // if (this.prefix === '?') {\n // this.restorePrivateValues(this.params);\n // } else if (this.postfix === '$') {\n // this.setAttrInRectangle(this.params);\n // } else {\n // this.setScrollRegion(this.params);\n // }\n // break;\n\n // CSI s Save cursor (ANSI.SYS).\n // CSI ? Pm s\n // case 's': // duplicate\n // if (this.prefix === '?') {\n // this.savePrivateValues(this.params);\n // } else {\n // this.saveCursor(this.params);\n // }\n // break;\n\n // CSI Ps ; Ps ; Ps t\n // CSI Pt; Pl; Pb; Pr; Ps$ t\n // CSI > Ps; Ps t\n // CSI Ps SP t\n // case 't':\n // if (this.postfix === '$') {\n // this.reverseAttrInRectangle(this.params);\n // } else if (this.postfix === ' ') {\n // this.setWarningBellVolume(this.params);\n // } else {\n // if (this.prefix === '>') {\n // this.setTitleModeFeature(this.params);\n // } else {\n // this.manipulateWindow(this.params);\n // }\n // }\n // break;\n\n // CSI u Restore cursor (ANSI.SYS).\n // CSI Ps SP u\n // case 'u': // duplicate\n // if (this.postfix === ' ') {\n // this.setMarginBellVolume(this.params);\n // } else {\n // this.restoreCursor(this.params);\n // }\n // break;\n\n // CSI Pt; Pl; Pb; Pr; Pp; Pt; Pl; Pp$ v\n // case 'v':\n // if (this.postfix === '$') {\n // this.copyRectagle(this.params);\n // }\n // break;\n\n // CSI Pt ; Pl ; Pb ; Pr ' w\n // case 'w':\n // if (this.postfix === '\\'') {\n // this.enableFilterRectangle(this.params);\n // }\n // break;\n\n // CSI Ps x Request Terminal Parameters (DECREQTPARM).\n // CSI Ps x Select Attribute Change Extent (DECSACE).\n // CSI Pc; Pt; Pl; Pb; Pr$ x\n // case 'x':\n // if (this.postfix === '$') {\n // this.fillRectangle(this.params);\n // } else {\n // this.requestParameters(this.params);\n // //this.__(this.params);\n // }\n // break;\n\n // CSI Ps ; Pu ' z\n // CSI Pt; Pl; Pb; Pr$ z\n // case 'z':\n // if (this.postfix === '\\'') {\n // this.enableLocatorReporting(this.params);\n // } else if (this.postfix === '$') {\n // this.eraseRectangle(this.params);\n // }\n // break;\n\n // CSI Pm ' {\n // CSI Pt; Pl; Pb; Pr$ {\n // case '{':\n // if (this.postfix === '\\'') {\n // this.setLocatorEvents(this.params);\n // } else if (this.postfix === '$') {\n // this.selectiveEraseRectangle(this.params);\n // }\n // break;\n\n // CSI Ps ' |\n // case '|':\n // if (this.postfix === '\\'') {\n // this.requestLocatorPosition(this.params);\n // }\n // break;\n\n // CSI P m SP }\n // Insert P s Column(s) (default = 1) (DECIC), VT420 and up.\n // case '}':\n // if (this.postfix === ' ') {\n // this.insertColumns(this.params);\n // }\n // break;\n\n // CSI P m SP ~\n // Delete P s Column(s) (default = 1) (DECDC), VT420 and up\n // case '~':\n // if (this.postfix === ' ') {\n // this.deleteColumns(this.params);\n // }\n // break;\n\n default:\n this.error('Unknown CSI code: %s.', ch);\n break;\n }\n\n this.prefix = '';\n this.postfix = '';\n break;\n\n case dcs:\n if (ch === '\\x1b' || ch === '\\x07') {\n if (ch === '\\x1b') i++;\n\n switch (this.prefix) {\n // User-Defined Keys (DECUDK).\n case '':\n break;\n\n // Request Status String (DECRQSS).\n // test: echo -e '\\eP$q\"p\\e\\\\'\n case '$q':\n var pt = this.currentParam\n , valid = false;\n\n switch (pt) {\n // DECSCA\n case '\"q':\n pt = '0\"q';\n break;\n\n // DECSCL\n case '\"p':\n pt = '61\"p';\n break;\n\n // DECSTBM\n case 'r':\n pt = ''\n + (this.scrollTop + 1)\n + ';'\n + (this.scrollBottom + 1)\n + 'r';\n break;\n\n // SGR\n case 'm':\n pt = '0m';\n break;\n\n default:\n this.error('Unknown DCS Pt: %s.', pt);\n pt = '';\n break;\n }\n\n this.send('\\x1bP' + +valid + '$r' + pt + '\\x1b\\\\');\n break;\n\n // Set Termcap/Terminfo Data (xterm, experimental).\n case '+p':\n break;\n\n // Request Termcap/Terminfo String (xterm, experimental)\n // Regular xterm does not even respond to this sequence.\n // This can cause a small glitch in vim.\n // test: echo -ne '\\eP+q6b64\\e\\\\'\n case '+q':\n var pt = this.currentParam\n , valid = false;\n\n this.send('\\x1bP' + +valid + '+r' + pt + '\\x1b\\\\');\n break;\n\n default:\n this.error('Unknown DCS prefix: %s.', this.prefix);\n break;\n }\n\n this.currentParam = 0;\n this.prefix = '';\n this.state = normal;\n } else if (!this.currentParam) {\n if (!this.prefix && ch !== '$' && ch !== '+') {\n this.currentParam = ch;\n } else if (this.prefix.length === 2) {\n this.currentParam = ch;\n } else {\n this.prefix += ch;\n }\n } else {\n this.currentParam += ch;\n }\n break;\n\n case ignore:\n // For PM and APC.\n if (ch === '\\x1b' || ch === '\\x07') {\n if (ch === '\\x1b') i++;\n this.state = normal;\n }\n break;\n }\n }\n\n this.updateRange(this.y);\n this.refresh(this.refreshStart, this.refreshEnd);\n};\n\n/**\n * Writes text to the terminal, followed by a break line character (\\n).\n * @param {string} text The text to write to the terminal.\n */\nTerminal.prototype.writeln = function(data) {\n this.write(data + '\\r\\n');\n};\n\n/**\n * Attaches a custom keydown handler which is run before keys are processed, giving consumers of\n * xterm.js ultimate control as to what keys should be processed by the terminal and what keys\n * should not.\n * @param {function} customKeydownHandler The custom KeyboardEvent handler to attach. This is a\n * function that takes a KeyboardEvent, allowing consumers to stop propogation and/or prevent\n * the default action. The function returns whether the event should be processed by xterm.js.\n */\nTerminal.prototype.attachCustomKeydownHandler = function(customKeydownHandler) {\n this.customKeydownHandler = customKeydownHandler;\n}\n\n/**\n * Handle a keydown event\n * Key Resources:\n * - https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent\n * @param {KeyboardEvent} ev The keydown event to be handled.\n */\nTerminal.prototype.keyDown = function(ev) {\n // Scroll down to prompt, whenever the user presses a key.\n if (this.ybase !== this.ydisp) {\n this.scrollToBottom();\n }\n\n if (this.customKeydownHandler && this.customKeydownHandler(ev) === false) {\n return false;\n }\n\n if (!this.compositionHelper.keydown.bind(this.compositionHelper)(ev)) {\n return false;\n }\n\n var self = this;\n var result = this.evaluateKeyEscapeSequence(ev);\n\n if (result.scrollDisp) {\n this.scrollDisp(result.scrollDisp);\n return this.cancel(ev, true);\n }\n\n if (isThirdLevelShift(this, ev)) {\n return true;\n }\n\n if (result.cancel) {\n // The event is canceled at the end already, is this necessary?\n this.cancel(ev, true);\n }\n\n if (!result.key) {\n return true;\n }\n\n this.emit('keydown', ev);\n this.emit('key', result.key, ev);\n this.showCursor();\n this.handler(result.key);\n\n return this.cancel(ev, true);\n};\n\n/**\n * Returns an object that determines how a KeyboardEvent should be handled. The key of the\n * returned value is the new key code to pass to the PTY.\n *\n * Reference: http://invisible-island.net/xterm/ctlseqs/ctlseqs.html\n * @param {KeyboardEvent} ev The keyboard event to be translated to key escape sequence.\n */\nTerminal.prototype.evaluateKeyEscapeSequence = function(ev) {\n var result = {\n // Whether to cancel event propogation (NOTE: this may not be needed since the event is\n // canceled at the end of keyDown\n cancel: false,\n // The new key even to emit\n key: undefined,\n // The number of characters to scroll, if this is defined it will cancel the event\n scrollDisp: undefined\n };\n var modifiers = ev.shiftKey << 0 | ev.altKey << 1 | ev.ctrlKey << 2 | ev.metaKey << 3;\n switch (ev.keyCode) {\n case 8:\n // backspace\n if (ev.shiftKey) {\n result.key = '\\x08'; // ^H\n break;\n }\n result.key = '\\x7f'; // ^?\n break;\n case 9:\n // tab\n if (ev.shiftKey) {\n result.key = '\\x1b[Z';\n break;\n }\n result.key = '\\t';\n result.cancel = true;\n break;\n case 13:\n // return/enter\n result.key = '\\r';\n result.cancel = true;\n break;\n case 27:\n // escape\n result.key = '\\x1b';\n result.cancel = true;\n break;\n case 37:\n // left-arrow\n if (modifiers) {\n result.key = '\\x1b[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 if (result.key == '\\x1b[1;3D') {\n result.key = '\\x1b[1;5D';\n }\n } else if (this.applicationCursor) {\n result.key = '\\x1bOD';\n } else {\n result.key = '\\x1b[D';\n }\n break;\n case 39:\n // right-arrow\n if (modifiers) {\n result.key = '\\x1b[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 if (result.key == '\\x1b[1;3C') {\n result.key = '\\x1b[1;5C';\n }\n } else if (this.applicationCursor) {\n result.key = '\\x1bOC';\n } else {\n result.key = '\\x1b[C';\n }\n break;\n case 38:\n // up-arrow\n if (modifiers) {\n result.key = '\\x1b[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 == '\\x1b[1;3A') {\n result.key = '\\x1b[1;5A';\n }\n } else if (this.applicationCursor) {\n result.key = '\\x1bOA';\n } else {\n result.key = '\\x1b[A';\n }\n break;\n case 40:\n // down-arrow\n if (modifiers) {\n result.key = '\\x1b[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 == '\\x1b[1;3B') {\n result.key = '\\x1b[1;5B';\n }\n } else if (this.applicationCursor) {\n result.key = '\\x1bOB';\n } else {\n result.key = '\\x1b[B';\n }\n break;\n case 45:\n // insert\n if (!ev.shiftKey && !ev.ctrlKey) {\n // or + are used to\n // copy-paste on some systems.\n result.key = '\\x1b[2~';\n }\n break;\n case 46:\n // delete\n if (modifiers) {\n result.key = '\\x1b[3;' + (modifiers + 1) + '~';\n } else {\n result.key = '\\x1b[3~';\n }\n break;\n case 36:\n // home\n if (modifiers)\n result.key = '\\x1b[1;' + (modifiers + 1) + 'H';\n else if (this.applicationCursor)\n result.key = '\\x1bOH';\n else\n result.key = '\\x1b[H';\n break;\n case 35:\n // end\n if (modifiers)\n result.key = '\\x1b[1;' + (modifiers + 1) + 'F';\n else if (this.applicationCursor)\n result.key = '\\x1bOF';\n else\n result.key = '\\x1b[F';\n break;\n case 33:\n // page up\n if (ev.shiftKey) {\n result.scrollDisp = -(this.rows - 1);\n } else {\n result.key = '\\x1b[5~';\n }\n break;\n case 34:\n // page down\n if (ev.shiftKey) {\n result.scrollDisp = this.rows - 1;\n } else {\n result.key = '\\x1b[6~';\n }\n break;\n case 112:\n // F1-F12\n if (modifiers) {\n result.key = '\\x1b[1;' + (modifiers + 1) + 'P';\n } else {\n result.key = '\\x1bOP';\n }\n break;\n case 113:\n if (modifiers) {\n result.key = '\\x1b[1;' + (modifiers + 1) + 'Q';\n } else {\n result.key = '\\x1bOQ';\n }\n break;\n case 114:\n if (modifiers) {\n result.key = '\\x1b[1;' + (modifiers + 1) + 'R';\n } else {\n result.key = '\\x1bOR';\n }\n break;\n case 115:\n if (modifiers) {\n result.key = '\\x1b[1;' + (modifiers + 1) + 'S';\n } else {\n result.key = '\\x1bOS';\n }\n break;\n case 116:\n if (modifiers) {\n result.key = '\\x1b[15;' + (modifiers + 1) + '~';\n } else {\n result.key = '\\x1b[15~';\n }\n break;\n case 117:\n if (modifiers) {\n result.key = '\\x1b[17;' + (modifiers + 1) + '~';\n } else {\n result.key = '\\x1b[17~';\n }\n break;\n case 118:\n if (modifiers) {\n result.key = '\\x1b[18;' + (modifiers + 1) + '~';\n } else {\n result.key = '\\x1b[18~';\n }\n break;\n case 119:\n if (modifiers) {\n result.key = '\\x1b[19;' + (modifiers + 1) + '~';\n } else {\n result.key = '\\x1b[19~';\n }\n break;\n case 120:\n if (modifiers) {\n result.key = '\\x1b[20;' + (modifiers + 1) + '~';\n } else {\n result.key = '\\x1b[20~';\n }\n break;\n case 121:\n if (modifiers) {\n result.key = '\\x1b[21;' + (modifiers + 1) + '~';\n } else {\n result.key = '\\x1b[21~';\n }\n break;\n case 122:\n if (modifiers) {\n result.key = '\\x1b[23;' + (modifiers + 1) + '~';\n } else {\n result.key = '\\x1b[23~';\n }\n break;\n case 123:\n if (modifiers) {\n result.key = '\\x1b[24;' + (modifiers + 1) + '~';\n } else {\n result.key = '\\x1b[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 // ^[ - escape\n result.key = String.fromCharCode(27);\n } else if (ev.keyCode === 221) {\n // ^] - group sep\n result.key = String.fromCharCode(29);\n }\n } else if (!this.browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) {\n // On Mac this is a third level shift. Use instead.\n if (ev.keyCode >= 65 && ev.keyCode <= 90) {\n result.key = '\\x1b' + String.fromCharCode(ev.keyCode + 32);\n } else if (ev.keyCode === 192) {\n result.key = '\\x1b`';\n } else if (ev.keyCode >= 48 && ev.keyCode <= 57) {\n result.key = '\\x1b' + (ev.keyCode - 48);\n }\n }\n break;\n }\n return result;\n};\n\n/**\n * Set the G level of the terminal\n * @param g\n */\nTerminal.prototype.setgLevel = function(g) {\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 */\nTerminal.prototype.setgCharset = function(g, charset) {\n this.charsets[g] = charset;\n if (this.glevel === g) {\n this.charset = charset;\n }\n};\n\n/**\n * Handle a keypress event.\n * Key Resources:\n * - https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent\n * @param {KeyboardEvent} ev The keypress event to be handled.\n */\nTerminal.prototype.keyPress = function(ev) {\n var key;\n\n this.cancel(ev);\n\n if (ev.charCode) {\n key = ev.charCode;\n } else if (ev.which == null) {\n key = ev.keyCode;\n } else if (ev.which !== 0 && ev.charCode !== 0) {\n key = ev.which;\n } else {\n return false;\n }\n\n if (!key || (\n (ev.altKey || ev.ctrlKey || ev.metaKey) && !isThirdLevelShift(this, 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 false;\n};\n\n/**\n * Send data for handling to the terminal\n * @param {string} data\n */\nTerminal.prototype.send = function(data) {\n var self = this;\n\n if (!this.queue) {\n setTimeout(function() {\n self.handler(self.queue);\n self.queue = '';\n }, 1);\n }\n\n this.queue += data;\n};\n\n/**\n * Ring the bell.\n * Note: We could do sweet things with webaudio here\n */\nTerminal.prototype.bell = function() {\n if (!this.visualBell) return;\n var self = this;\n this.element.style.borderColor = 'white';\n setTimeout(function() {\n self.element.style.borderColor = '';\n }, 10);\n if (this.popOnBell) this.focus();\n};\n\n/**\n * Log the current state to the console.\n */\nTerminal.prototype.log = function() {\n if (!this.debug) return;\n if (!this.context.console || !this.context.console.log) return;\n var args = Array.prototype.slice.call(arguments);\n this.context.console.log.apply(this.context.console, args);\n};\n\n/**\n * Log the current state as error to the console.\n */\nTerminal.prototype.error = function() {\n if (!this.debug) return;\n if (!this.context.console || !this.context.console.error) return;\n var args = Array.prototype.slice.call(arguments);\n this.context.console.error.apply(this.context.console, args);\n};\n\n/**\n * Resizes the terminal.\n *\n * @param {number} x The number of columns to resize to.\n * @param {number} y The number of rows to resize to.\n */\nTerminal.prototype.resize = function(x, y) {\n var line\n , el\n , i\n , j\n , ch\n , addToY;\n\n if (x === this.cols && y === this.rows) {\n return;\n }\n\n if (x < 1) x = 1;\n if (y < 1) y = 1;\n\n // resize cols\n j = this.cols;\n if (j < x) {\n ch = [this.defAttr, ' ', 1]; // does xterm use the default attr?\n i = this.lines.length;\n while (i--) {\n while (this.lines[i].length < x) {\n this.lines[i].push(ch);\n }\n }\n } else { // (j > x)\n i = this.lines.length;\n while (i--) {\n while (this.lines[i].length > x) {\n this.lines[i].pop();\n }\n }\n }\n this.setupStops(j);\n this.cols = x;\n\n // resize rows\n j = this.rows;\n addToY = 0;\n if (j < y) {\n el = this.element;\n while (j++ < y) {\n // y is rows, not this.y\n if (this.lines.length < y + 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.blankLine());\n }\n }\n if (this.children.length < y) {\n this.insertRow();\n }\n }\n } else { // (j > y)\n while (j-- > y) {\n if (this.lines.length > y + 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 if (this.children.length > y) {\n el = this.children.shift();\n if (!el) continue;\n el.parentNode.removeChild(el);\n }\n }\n }\n this.rows = y;\n\n // Make sure that the cursor stays on screen\n if (this.y >= y) {\n this.y = y - 1;\n }\n if (addToY) {\n this.y += addToY;\n }\n\n if (this.x >= x) {\n this.x = x - 1;\n }\n\n this.scrollTop = 0;\n this.scrollBottom = y - 1;\n\n this.refresh(0, this.rows - 1);\n\n this.normal = null;\n\n this.geometry = [this.cols, this.rows];\n this.emit('resize', {terminal: this, cols: x, rows: y});\n};\n\n/**\n * Updates the range of rows to refresh\n * @param {number} y The number of rows to refresh next.\n */\nTerminal.prototype.updateRange = function(y) {\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 */\nTerminal.prototype.maxRange = function() {\n this.refreshStart = 0;\n this.refreshEnd = this.rows - 1;\n};\n\n\n\n/**\n * Setup the tab stops.\n * @param {number} i\n */\nTerminal.prototype.setupStops = function(i) {\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.cols; i += 8) {\n this.tabs[i] = true;\n }\n};\n\n\n/**\n * Move the cursor to the previous tab stop from the given position (default is current).\n * @param {number} x The position to move the cursor to the previous tab stop.\n */\nTerminal.prototype.prevStop = function(x) {\n if (x == null) x = this.x;\n while (!this.tabs[--x] && x > 0);\n return x >= this.cols\n ? this.cols - 1\n : x < 0 ? 0 : x;\n};\n\n\n/**\n * Move the cursor one tab stop forward from the given position (default is current).\n * @param {number} x The position to move the cursor one tab stop forward.\n */\nTerminal.prototype.nextStop = function(x) {\n if (x == null) x = this.x;\n while (!this.tabs[++x] && x < this.cols);\n return x >= this.cols\n ? this.cols - 1\n : x < 0 ? 0 : x;\n};\n\n\n/**\n * Erase in the identified line everything from \"x\" to the end of the line (right).\n * @param {number} x The column from which to start erasing to the end of the line.\n * @param {number} y The line in which to operate.\n */\nTerminal.prototype.eraseRight = function(x, y) {\n var line = this.lines[this.ybase + y]\n , ch = [this.eraseAttr(), ' ', 1]; // xterm\n\n\n for (; x < this.cols; x++) {\n line[x] = ch;\n }\n\n this.updateRange(y);\n};\n\n\n\n/**\n * Erase in the identified line everything from \"x\" to the start of the line (left).\n * @param {number} x The column from which to start erasing to the start of the line.\n * @param {number} y The line in which to operate.\n */\nTerminal.prototype.eraseLeft = function(x, y) {\n var line = this.lines[this.ybase + y]\n , ch = [this.eraseAttr(), ' ', 1]; // xterm\n\n x++;\n while (x--) line[x] = ch;\n\n this.updateRange(y);\n};\n\n/**\n * Clears the entire buffer, making the prompt line the new first line.\n */\nTerminal.prototype.clear = function() {\n if (this.ybase === 0 && this.y === 0) {\n // Don't clear if it's already clear\n return;\n }\n this.lines = [this.lines[this.ybase + this.y]];\n this.ydisp = 0;\n this.ybase = 0;\n this.y = 0;\n for (var i = 1; i < this.rows; i++) {\n this.lines.push(this.blankLine());\n }\n this.refresh(0, this.rows - 1);\n this.emit('scroll', this.ydisp);\n};\n\n/**\n * Erase all content in the given line\n * @param {number} y The line to erase all of its contents.\n */\nTerminal.prototype.eraseLine = function(y) {\n this.eraseRight(0, y);\n};\n\n\n/**\n * Return the data array of a blank line/\n * @param {number} cur First bunch of data for each \"blank\" character.\n */\nTerminal.prototype.blankLine = function(cur) {\n var attr = cur\n ? this.eraseAttr()\n : this.defAttr;\n\n var ch = [attr, ' ', 1] // width defaults to 1 halfwidth character\n , line = []\n , i = 0;\n\n for (; i < this.cols; i++) {\n line[i] = ch;\n }\n\n return line;\n};\n\n\n/**\n * If cur return the back color xterm feature attribute. Else return defAttr.\n * @param {object} cur\n */\nTerminal.prototype.ch = function(cur) {\n return cur\n ? [this.eraseAttr(), ' ', 1]\n : [this.defAttr, ' ', 1];\n};\n\n\n/**\n * Evaluate if the current erminal is the given argument.\n * @param {object} term The terminal to evaluate\n */\nTerminal.prototype.is = function(term) {\n var name = this.termName;\n return (name + '').indexOf(term) === 0;\n};\n\n\n/**\n * Emit the 'data' event and populate the given data.\n * @param {string} data The data to populate in the event.\n */\nTerminal.prototype.handler = function(data) {\n this.emit('data', data);\n};\n\n\n/**\n * Emit the 'title' event and populate the given title.\n * @param {string} title The title to populate in the event.\n */\nTerminal.prototype.handleTitle = function(title) {\n this.emit('title', title);\n};\n\n\n/**\n * ESC\n */\n\n/**\n * ESC D Index (IND is 0x84).\n */\nTerminal.prototype.index = function() {\n this.y++;\n if (this.y > this.scrollBottom) {\n this.y--;\n this.scroll();\n }\n this.state = normal;\n};\n\n\n/**\n * ESC M Reverse Index (RI is 0x8d).\n */\nTerminal.prototype.reverseIndex = function() {\n var j;\n this.y--;\n if (this.y < this.scrollTop) {\n this.y++;\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 this.lines.splice(this.y + this.ybase, 0, this.blankLine(true));\n j = this.rows - 1 - this.scrollBottom;\n this.lines.splice(this.rows - 1 + this.ybase - j + 1, 1);\n // this.maxRange();\n this.updateRange(this.scrollTop);\n this.updateRange(this.scrollBottom);\n }\n this.state = normal;\n};\n\n\n/**\n * ESC c Full Reset (RIS).\n */\nTerminal.prototype.reset = function() {\n this.options.rows = this.rows;\n this.options.cols = this.cols;\n var customKeydownHandler = this.customKeydownHandler;\n Terminal.call(this, this.options);\n this.customKeydownHandler = customKeydownHandler;\n this.refresh(0, this.rows - 1);\n this.viewport.syncScrollArea();\n};\n\n\n/**\n * ESC H Tab Set (HTS is 0x88).\n */\nTerminal.prototype.tabSet = function() {\n this.tabs[this.x] = true;\n this.state = normal;\n};\n\n\n/**\n * CSI\n */\n\n/**\n * CSI Ps A\n * Cursor Up Ps Times (default = 1) (CUU).\n */\nTerminal.prototype.cursorUp = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.y -= param;\n if (this.y < 0) this.y = 0;\n};\n\n\n/**\n * CSI Ps B\n * Cursor Down Ps Times (default = 1) (CUD).\n */\nTerminal.prototype.cursorDown = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.y += param;\n if (this.y >= this.rows) {\n this.y = this.rows - 1;\n }\n};\n\n\n/**\n * CSI Ps C\n * Cursor Forward Ps Times (default = 1) (CUF).\n */\nTerminal.prototype.cursorForward = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.x += param;\n if (this.x >= this.cols) {\n this.x = this.cols - 1;\n }\n};\n\n\n/**\n * CSI Ps D\n * Cursor Backward Ps Times (default = 1) (CUB).\n */\nTerminal.prototype.cursorBackward = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.x -= param;\n if (this.x < 0) this.x = 0;\n};\n\n\n/**\n * CSI Ps ; Ps H\n * Cursor Position [row;column] (default = [1,1]) (CUP).\n */\nTerminal.prototype.cursorPos = function(params) {\n var row, col;\n\n row = 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.rows) {\n row = this.rows - 1;\n }\n\n if (col < 0) {\n col = 0;\n } else if (col >= this.cols) {\n col = this.cols - 1;\n }\n\n this.x = col;\n this.y = row;\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 */\nTerminal.prototype.eraseInDisplay = function(params) {\n var j;\n switch (params[0]) {\n case 0:\n this.eraseRight(this.x, this.y);\n j = this.y + 1;\n for (; j < this.rows; j++) {\n this.eraseLine(j);\n }\n break;\n case 1:\n this.eraseLeft(this.x, this.y);\n j = this.y;\n while (j--) {\n this.eraseLine(j);\n }\n break;\n case 2:\n j = this.rows;\n while (j--) this.eraseLine(j);\n break;\n case 3:\n ; // no saved lines\n break;\n }\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 */\nTerminal.prototype.eraseInLine = function(params) {\n switch (params[0]) {\n case 0:\n this.eraseRight(this.x, this.y);\n break;\n case 1:\n this.eraseLeft(this.x, this.y);\n break;\n case 2:\n this.eraseLine(this.y);\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 = 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 */\nTerminal.prototype.charAttributes = function(params) {\n // Optimize a single SGR0.\n if (params.length === 1 && params[0] === 0) {\n this.curAttr = this.defAttr;\n return;\n }\n\n var l = params.length\n , i = 0\n , flags = this.curAttr >> 18\n , fg = (this.curAttr >> 9) & 0x1ff\n , bg = this.curAttr & 0x1ff\n , p;\n\n for (; i < l; i++) {\n p = params[i];\n if (p >= 30 && p <= 37) {\n // fg color 8\n fg = p - 30;\n } else if (p >= 40 && p <= 47) {\n // bg color 8\n bg = p - 40;\n } else if (p >= 90 && p <= 97) {\n // fg color 16\n p += 8;\n fg = p - 90;\n } else if (p >= 100 && p <= 107) {\n // bg color 16\n p += 8;\n bg = p - 100;\n } else if (p === 0) {\n // default\n flags = this.defAttr >> 18;\n fg = (this.defAttr >> 9) & 0x1ff;\n bg = this.defAttr & 0x1ff;\n // flags = 0;\n // fg = 0x1ff;\n // bg = 0x1ff;\n } else if (p === 1) {\n // bold text\n flags |= 1;\n } else if (p === 4) {\n // underlined text\n flags |= 2;\n } else if (p === 5) {\n // blink\n flags |= 4;\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 |= 8;\n } else if (p === 8) {\n // invisible\n flags |= 16;\n } else if (p === 22) {\n // not bold\n flags &= ~1;\n } else if (p === 24) {\n // not underlined\n flags &= ~2;\n } else if (p === 25) {\n // not blink\n flags &= ~4;\n } else if (p === 27) {\n // not inverse\n flags &= ~8;\n } else if (p === 28) {\n // not invisible\n flags &= ~16;\n } else if (p === 39) {\n // reset fg\n fg = (this.defAttr >> 9) & 0x1ff;\n } else if (p === 49) {\n // reset bg\n bg = this.defAttr & 0x1ff;\n } else if (p === 38) {\n // fg color 256\n if (params[i + 1] === 2) {\n i += 2;\n fg = 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 = matchColor(\n params[i] & 0xff,\n params[i + 1] & 0xff,\n params[i + 2] & 0xff);\n if (bg === -1) bg = 0x1ff;\n i += 2;\n } else if (params[i + 1] === 5) {\n i += 2;\n p = params[i] & 0xff;\n bg = p;\n }\n } else if (p === 100) {\n // reset fg/bg\n fg = (this.defAttr >> 9) & 0x1ff;\n bg = this.defAttr & 0x1ff;\n } else {\n this.error('Unknown SGR attribute: %d.', p);\n }\n }\n\n this.curAttr = (flags << 18) | (fg << 9) | bg;\n};\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 */\nTerminal.prototype.deviceStatus = function(params) {\n if (!this.prefix) {\n switch (params[0]) {\n case 5:\n // status report\n this.send('\\x1b[0n');\n break;\n case 6:\n // cursor position\n this.send('\\x1b['\n + (this.y + 1)\n + ';'\n + (this.x + 1)\n + 'R');\n break;\n }\n } else if (this.prefix === '?') {\n // modern xterm doesnt seem to\n // respond to any of these except ?6, 6, and 5\n switch (params[0]) {\n case 6:\n // cursor position\n this.send('\\x1b[?'\n + (this.y + 1)\n + ';'\n + (this.x + 1)\n + 'R');\n break;\n case 15:\n // no printer\n // this.send('\\x1b[?11n');\n break;\n case 25:\n // dont support user defined keys\n // this.send('\\x1b[?21n');\n break;\n case 26:\n // north american keyboard\n // this.send('\\x1b[?27;1;0;0n');\n break;\n case 53:\n // no dec locator/mouse\n // this.send('\\x1b[?50n');\n break;\n }\n }\n};\n\n\n/**\n * Additions\n */\n\n/**\n * CSI Ps @\n * Insert Ps (Blank) Character(s) (default = 1) (ICH).\n */\nTerminal.prototype.insertChars = function(params) {\n var param, row, j, ch;\n\n param = params[0];\n if (param < 1) param = 1;\n\n row = this.y + this.ybase;\n j = this.x;\n ch = [this.eraseAttr(), ' ', 1]; // xterm\n\n while (param-- && j < this.cols) {\n this.lines[row].splice(j++, 0, ch);\n this.lines[row].pop();\n }\n};\n\n/**\n * CSI Ps E\n * Cursor Next Line Ps Times (default = 1) (CNL).\n * same as CSI Ps B ?\n */\nTerminal.prototype.cursorNextLine = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.y += param;\n if (this.y >= this.rows) {\n this.y = this.rows - 1;\n }\n this.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 */\nTerminal.prototype.cursorPrecedingLine = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.y -= param;\n if (this.y < 0) this.y = 0;\n this.x = 0;\n};\n\n\n/**\n * CSI Ps G\n * Cursor Character Absolute [column] (default = [row,1]) (CHA).\n */\nTerminal.prototype.cursorCharAbsolute = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.x = param - 1;\n};\n\n\n/**\n * CSI Ps L\n * Insert Ps Line(s) (default = 1) (IL).\n */\nTerminal.prototype.insertLines = function(params) {\n var param, row, j;\n\n param = params[0];\n if (param < 1) param = 1;\n row = this.y + this.ybase;\n\n j = this.rows - 1 - this.scrollBottom;\n j = this.rows - 1 + this.ybase - j + 1;\n\n while (param--) {\n // test: echo -e '\\e[44m\\e[1L\\e[0m'\n // blankLine(true) - xterm/linux behavior\n this.lines.splice(row, 0, this.blankLine(true));\n this.lines.splice(j, 1);\n }\n\n // this.maxRange();\n this.updateRange(this.y);\n this.updateRange(this.scrollBottom);\n};\n\n\n/**\n * CSI Ps M\n * Delete Ps Line(s) (default = 1) (DL).\n */\nTerminal.prototype.deleteLines = function(params) {\n var param, row, j;\n\n param = params[0];\n if (param < 1) param = 1;\n row = this.y + this.ybase;\n\n j = this.rows - 1 - this.scrollBottom;\n j = this.rows - 1 + this.ybase - j;\n\n while (param--) {\n // test: echo -e '\\e[44m\\e[1M\\e[0m'\n // blankLine(true) - xterm/linux behavior\n this.lines.splice(j + 1, 0, this.blankLine(true));\n this.lines.splice(row, 1);\n }\n\n // this.maxRange();\n this.updateRange(this.y);\n this.updateRange(this.scrollBottom);\n};\n\n\n/**\n * CSI Ps P\n * Delete Ps Character(s) (default = 1) (DCH).\n */\nTerminal.prototype.deleteChars = function(params) {\n var param, row, ch;\n\n param = params[0];\n if (param < 1) param = 1;\n\n row = this.y + this.ybase;\n ch = [this.eraseAttr(), ' ', 1]; // xterm\n\n while (param--) {\n this.lines[row].splice(this.x, 1);\n this.lines[row].push(ch);\n }\n};\n\n/**\n * CSI Ps X\n * Erase Ps Character(s) (default = 1) (ECH).\n */\nTerminal.prototype.eraseChars = function(params) {\n var param, row, j, ch;\n\n param = params[0];\n if (param < 1) param = 1;\n\n row = this.y + this.ybase;\n j = this.x;\n ch = [this.eraseAttr(), ' ', 1]; // xterm\n\n while (param-- && j < this.cols) {\n this.lines[row][j++] = ch;\n }\n};\n\n/**\n * CSI Pm ` Character Position Absolute\n * [column] (default = [row,1]) (HPA).\n */\nTerminal.prototype.charPosAbsolute = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.x = param - 1;\n if (this.x >= this.cols) {\n this.x = this.cols - 1;\n }\n};\n\n\n/**\n * 141 61 a * HPR -\n * Horizontal Position Relative\n * reuse CSI Ps C ?\n */\nTerminal.prototype.HPositionRelative = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.x += param;\n if (this.x >= this.cols) {\n this.x = this.cols - 1;\n }\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 */\nTerminal.prototype.sendDeviceAttributes = function(params) {\n if (params[0] > 0) return;\n\n if (!this.prefix) {\n if (this.is('xterm')\n || this.is('rxvt-unicode')\n || this.is('screen')) {\n this.send('\\x1b[?1;2c');\n } else if (this.is('linux')) {\n this.send('\\x1b[?6c');\n }\n } else if (this.prefix === '>') {\n // xterm and urxvt\n // seem to spit this\n // out around ~370 times (?).\n if (this.is('xterm')) {\n this.send('\\x1b[>0;276;0c');\n } else if (this.is('rxvt-unicode')) {\n this.send('\\x1b[>85;95;0c');\n } else if (this.is('linux')) {\n // not supported by linux console.\n // linux console echoes parameters.\n this.send(params[0] + 'c');\n } else if (this.is('screen')) {\n this.send('\\x1b[>83;40003;0c');\n }\n }\n};\n\n\n/**\n * CSI Pm d\n * Line Position Absolute [row] (default = [1,column]) (VPA).\n */\nTerminal.prototype.linePosAbsolute = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.y = param - 1;\n if (this.y >= this.rows) {\n this.y = this.rows - 1;\n }\n};\n\n\n/**\n * 145 65 e * VPR - Vertical Position Relative\n * reuse CSI Ps B ?\n */\nTerminal.prototype.VPositionRelative = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.y += param;\n if (this.y >= this.rows) {\n this.y = this.rows - 1;\n }\n};\n\n\n/**\n * CSI Ps ; Ps f\n * Horizontal and Vertical Position [row;column] (default =\n * [1,1]) (HVP).\n */\nTerminal.prototype.HVPosition = function(params) {\n if (params[0] < 1) params[0] = 1;\n if (params[1] < 1) params[1] = 1;\n\n this.y = params[0] - 1;\n if (this.y >= this.rows) {\n this.y = this.rows - 1;\n }\n\n this.x = params[1] - 1;\n if (this.x >= this.cols) {\n this.x = this.cols - 1;\n }\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 */\nTerminal.prototype.setMode = function(params) {\n if (typeof params === 'object') {\n var l = params.length\n , i = 0;\n\n for (; i < l; i++) {\n this.setMode(params[i]);\n }\n\n return;\n }\n\n if (!this.prefix) {\n switch (params) {\n case 4:\n this.insertMode = true;\n break;\n case 20:\n //this.convertEol = true;\n break;\n }\n } else if (this.prefix === '?') {\n switch (params) {\n case 1:\n this.applicationCursor = true;\n break;\n case 2:\n this.setgCharset(0, Terminal.charsets.US);\n this.setgCharset(1, Terminal.charsets.US);\n this.setgCharset(2, Terminal.charsets.US);\n this.setgCharset(3, Terminal.charsets.US);\n // set VT100 mode here\n break;\n case 3: // 132 col mode\n this.savedCols = this.cols;\n this.resize(132, this.rows);\n break;\n case 6:\n this.originMode = true;\n break;\n case 7:\n this.wraparoundMode = true;\n break;\n case 12:\n // this.cursorBlink = true;\n break;\n case 66:\n this.log('Serial port requested application keypad.');\n this.applicationKeypad = true;\n this.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 this.x10Mouse = params === 9;\n this.vt200Mouse = params === 1000;\n this.normalMouse = params > 1000;\n this.mouseEvents = true;\n this.element.style.cursor = 'default';\n this.log('Binding to mouse events.');\n break;\n case 1004: // send focusin/focusout events\n // focusin: ^[[I\n // focusout: ^[[O\n this.sendFocus = true;\n break;\n case 1005: // utf8 ext mode mouse\n this.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.sgrMouse = true;\n // for wide terminals\n // does not add 32 to fields\n // press: ^[[ Keyboard Action Mode (AM).\n * Ps = 4 -> Replace Mode (IRM).\n * Ps = 1 2 -> Send/receive (SRM).\n * Ps = 2 0 -> Normal Linefeed (LNM).\n * CSI ? Pm l\n * DEC Private Mode Reset (DECRST).\n * Ps = 1 -> Normal Cursor Keys (DECCKM).\n * Ps = 2 -> Designate VT52 mode (DECANM).\n * Ps = 3 -> 80 Column Mode (DECCOLM).\n * Ps = 4 -> Jump (Fast) Scroll (DECSCLM).\n * Ps = 5 -> Normal Video (DECSCNM).\n * Ps = 6 -> Normal Cursor Mode (DECOM).\n * Ps = 7 -> No Wraparound Mode (DECAWM).\n * Ps = 8 -> No Auto-repeat Keys (DECARM).\n * Ps = 9 -> Don't send Mouse X & Y on button press.\n * Ps = 1 0 -> Hide toolbar (rxvt).\n * Ps = 1 2 -> Stop Blinking Cursor (att610).\n * Ps = 1 8 -> Don't print form feed (DECPFF).\n * Ps = 1 9 -> Limit print to scrolling region (DECPEX).\n * Ps = 2 5 -> Hide Cursor (DECTCEM).\n * Ps = 3 0 -> Don't show scrollbar (rxvt).\n * Ps = 3 5 -> Disable font-shifting functions (rxvt).\n * Ps = 4 0 -> Disallow 80 -> 132 Mode.\n * Ps = 4 1 -> No more(1) fix (see curses resource).\n * Ps = 4 2 -> Disable Nation Replacement Character sets (DEC-\n * NRCM).\n * Ps = 4 4 -> Turn Off Margin Bell.\n * Ps = 4 5 -> No Reverse-wraparound Mode.\n * Ps = 4 6 -> Stop Logging. (This is normally disabled by a\n * compile-time option).\n * Ps = 4 7 -> Use Normal Screen Buffer.\n * Ps = 6 6 -> Numeric keypad (DECNKM).\n * Ps = 6 7 -> Backarrow key sends delete (DECBKM).\n * Ps = 1 0 0 0 -> Don't send Mouse X & Y on button press and\n * release. See the section Mouse Tracking.\n * Ps = 1 0 0 1 -> Don't use Hilite Mouse Tracking.\n * Ps = 1 0 0 2 -> Don't use Cell Motion Mouse Tracking.\n * Ps = 1 0 0 3 -> Don't use All Motion Mouse Tracking.\n * Ps = 1 0 0 4 -> Don't send FocusIn/FocusOut events.\n * Ps = 1 0 0 5 -> Disable Extended Mouse Mode.\n * Ps = 1 0 1 0 -> Don't scroll to bottom on tty output\n * (rxvt).\n * Ps = 1 0 1 1 -> Don't scroll to bottom on key press (rxvt).\n * Ps = 1 0 3 4 -> Don't interpret \"meta\" key. (This disables\n * the eightBitInput resource).\n * Ps = 1 0 3 5 -> Disable special modifiers for Alt and Num-\n * Lock keys. (This disables the numLock resource).\n * Ps = 1 0 3 6 -> Don't send ESC when Meta modifies a key.\n * (This disables the metaSendsEscape resource).\n * Ps = 1 0 3 7 -> Send VT220 Remove from the editing-keypad\n * Delete key.\n * Ps = 1 0 3 9 -> Don't send ESC when Alt modifies a key.\n * (This disables the altSendsEscape resource).\n * Ps = 1 0 4 0 -> Do not keep selection when not highlighted.\n * (This disables the keepSelection resource).\n * Ps = 1 0 4 1 -> Use the PRIMARY selection. (This disables\n * the selectToClipboard resource).\n * Ps = 1 0 4 2 -> Disable Urgency window manager hint when\n * Control-G is received. (This disables the bellIsUrgent\n * resource).\n * Ps = 1 0 4 3 -> Disable raising of the window when Control-\n * G is received. (This disables the popOnBell resource).\n * Ps = 1 0 4 7 -> Use Normal Screen Buffer, clearing screen\n * first if in the Alternate Screen. (This may be disabled by\n * the titeInhibit resource).\n * Ps = 1 0 4 8 -> Restore cursor as in DECRC. (This may be\n * disabled by the titeInhibit resource).\n * Ps = 1 0 4 9 -> Use Normal Screen Buffer and restore cursor\n * as in DECRC. (This may be disabled by the titeInhibit\n * resource). This combines the effects of the 1 0 4 7 and 1 0\n * 4 8 modes. Use this with terminfo-based applications rather\n * than the 4 7 mode.\n * Ps = 1 0 5 0 -> Reset terminfo/termcap function-key mode.\n * Ps = 1 0 5 1 -> Reset Sun function-key mode.\n * Ps = 1 0 5 2 -> Reset HP function-key mode.\n * Ps = 1 0 5 3 -> Reset SCO function-key mode.\n * Ps = 1 0 6 0 -> Reset legacy keyboard emulation (X11R6).\n * Ps = 1 0 6 1 -> Reset keyboard emulation to Sun/PC style.\n * Ps = 2 0 0 4 -> Reset bracketed paste mode.\n */\nTerminal.prototype.resetMode = function(params) {\n if (typeof params === 'object') {\n var l = params.length\n , i = 0;\n\n for (; i < l; i++) {\n this.resetMode(params[i]);\n }\n\n return;\n }\n\n if (!this.prefix) {\n switch (params) {\n case 4:\n this.insertMode = false;\n break;\n case 20:\n //this.convertEol = false;\n break;\n }\n } else if (this.prefix === '?') {\n switch (params) {\n case 1:\n this.applicationCursor = false;\n break;\n case 3:\n if (this.cols === 132 && this.savedCols) {\n this.resize(this.savedCols, this.rows);\n }\n delete this.savedCols;\n break;\n case 6:\n this.originMode = false;\n break;\n case 7:\n this.wraparoundMode = false;\n break;\n case 12:\n // this.cursorBlink = false;\n break;\n case 66:\n this.log('Switching back to normal keypad.');\n this.applicationKeypad = false;\n this.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.x10Mouse = false;\n this.vt200Mouse = false;\n this.normalMouse = false;\n this.mouseEvents = false;\n this.element.style.cursor = '';\n break;\n case 1004: // send focusin/focusout events\n this.sendFocus = false;\n break;\n case 1005: // utf8 ext mode mouse\n this.utfMouse = false;\n break;\n case 1006: // sgr ext mode mouse\n this.sgrMouse = false;\n break;\n case 1015: // urxvt ext mode mouse\n this.urxvtMouse = false;\n break;\n case 25: // hide cursor\n this.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 if (this.normal) {\n this.lines = this.normal.lines;\n this.ybase = this.normal.ybase;\n this.ydisp = this.normal.ydisp;\n this.x = this.normal.x;\n this.y = this.normal.y;\n this.scrollTop = this.normal.scrollTop;\n this.scrollBottom = this.normal.scrollBottom;\n this.tabs = this.normal.tabs;\n this.normal = null;\n // if (params === 1049) {\n // this.x = this.savedX;\n // this.y = this.savedY;\n // }\n this.refresh(0, this.rows - 1);\n this.showCursor();\n }\n break;\n }\n }\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 */\nTerminal.prototype.setScrollRegion = function(params) {\n if (this.prefix) return;\n this.scrollTop = (params[0] || 1) - 1;\n this.scrollBottom = (params[1] || this.rows) - 1;\n this.x = 0;\n this.y = 0;\n};\n\n\n/**\n * CSI s\n * Save cursor (ANSI.SYS).\n */\nTerminal.prototype.saveCursor = function(params) {\n this.savedX = this.x;\n this.savedY = this.y;\n};\n\n\n/**\n * CSI u\n * Restore cursor (ANSI.SYS).\n */\nTerminal.prototype.restoreCursor = function(params) {\n this.x = this.savedX || 0;\n this.y = this.savedY || 0;\n};\n\n\n/**\n * Lesser Used\n */\n\n/**\n * CSI Ps I\n * Cursor Forward Tabulation Ps tab stops (default = 1) (CHT).\n */\nTerminal.prototype.cursorForwardTab = function(params) {\n var param = params[0] || 1;\n while (param--) {\n this.x = this.nextStop();\n }\n};\n\n\n/**\n * CSI Ps S Scroll up Ps lines (default = 1) (SU).\n */\nTerminal.prototype.scrollUp = function(params) {\n var param = params[0] || 1;\n while (param--) {\n this.lines.splice(this.ybase + this.scrollTop, 1);\n this.lines.splice(this.ybase + this.scrollBottom, 0, this.blankLine());\n }\n // this.maxRange();\n this.updateRange(this.scrollTop);\n this.updateRange(this.scrollBottom);\n};\n\n\n/**\n * CSI Ps T Scroll down Ps lines (default = 1) (SD).\n */\nTerminal.prototype.scrollDown = function(params) {\n var param = params[0] || 1;\n while (param--) {\n this.lines.splice(this.ybase + this.scrollBottom, 1);\n this.lines.splice(this.ybase + this.scrollTop, 0, this.blankLine());\n }\n // this.maxRange();\n this.updateRange(this.scrollTop);\n this.updateRange(this.scrollBottom);\n};\n\n\n/**\n * CSI Ps ; Ps ; Ps ; Ps ; Ps T\n * Initiate highlight mouse tracking. Parameters are\n * [func;startx;starty;firstrow;lastrow]. See the section Mouse\n * Tracking.\n */\nTerminal.prototype.initMouseTracking = function(params) {\n // Relevant: DECSET 1001\n};\n\n\n/**\n * CSI > Ps; Ps T\n * Reset one or more features of the title modes to the default\n * value. Normally, \"reset\" disables the feature. It is possi-\n * ble to disable the ability to reset features by compiling a\n * different default for the title modes into xterm.\n * Ps = 0 -> Do not set window/icon labels using hexadecimal.\n * Ps = 1 -> Do not query window/icon labels using hexadeci-\n * mal.\n * Ps = 2 -> Do not set window/icon labels using UTF-8.\n * Ps = 3 -> Do not query window/icon labels using UTF-8.\n * (See discussion of \"Title Modes\").\n */\nTerminal.prototype.resetTitleModes = function(params) {\n ;\n};\n\n\n/**\n * CSI Ps Z Cursor Backward Tabulation Ps tab stops (default = 1) (CBT).\n */\nTerminal.prototype.cursorBackwardTab = function(params) {\n var param = params[0] || 1;\n while (param--) {\n this.x = this.prevStop();\n }\n};\n\n\n/**\n * CSI Ps b Repeat the preceding graphic character Ps times (REP).\n */\nTerminal.prototype.repeatPrecedingCharacter = function(params) {\n var param = params[0] || 1\n , line = this.lines[this.ybase + this.y]\n , ch = line[this.x - 1] || [this.defAttr, ' ', 1];\n\n while (param--) line[this.x++] = ch;\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 */\nTerminal.prototype.tabClear = function(params) {\n var param = params[0];\n if (param <= 0) {\n delete this.tabs[this.x];\n } else if (param === 3) {\n this.tabs = {};\n }\n};\n\n\n/**\n * CSI Pm i Media Copy (MC).\n * Ps = 0 -> Print screen (default).\n * Ps = 4 -> Turn off printer controller mode.\n * Ps = 5 -> Turn on printer controller mode.\n * CSI ? Pm i\n * Media Copy (MC, DEC-specific).\n * Ps = 1 -> Print line containing cursor.\n * Ps = 4 -> Turn off autoprint mode.\n * Ps = 5 -> Turn on autoprint mode.\n * Ps = 1 0 -> Print composed display, ignores DECPEX.\n * Ps = 1 1 -> Print all pages.\n */\nTerminal.prototype.mediaCopy = function(params) {\n ;\n};\n\n\n/**\n * CSI > Ps; Ps m\n * Set or reset resource-values used by xterm to decide whether\n * to construct escape sequences holding information about the\n * modifiers pressed with a given key. The first parameter iden-\n * tifies the resource to set/reset. The second parameter is the\n * value to assign to the resource. If the second parameter is\n * omitted, the resource is reset to its initial value.\n * Ps = 1 -> modifyCursorKeys.\n * Ps = 2 -> modifyFunctionKeys.\n * Ps = 4 -> modifyOtherKeys.\n * If no parameters are given, all resources are reset to their\n * initial values.\n */\nTerminal.prototype.setResources = function(params) {\n ;\n};\n\n\n/**\n * CSI > Ps n\n * Disable modifiers which may be enabled via the CSI > Ps; Ps m\n * sequence. This corresponds to a resource value of \"-1\", which\n * cannot be set with the other sequence. The parameter identi-\n * fies the resource to be disabled:\n * Ps = 1 -> modifyCursorKeys.\n * Ps = 2 -> modifyFunctionKeys.\n * Ps = 4 -> modifyOtherKeys.\n * If the parameter is omitted, modifyFunctionKeys is disabled.\n * When modifyFunctionKeys is disabled, xterm uses the modifier\n * keys to make an extended sequence of functions rather than\n * adding a parameter to each function key to denote the modi-\n * fiers.\n */\nTerminal.prototype.disableModifiers = function(params) {\n ;\n};\n\n\n/**\n * CSI > Ps p\n * Set resource value pointerMode. This is used by xterm to\n * decide whether to hide the pointer cursor as the user types.\n * Valid values for the parameter:\n * Ps = 0 -> never hide the pointer.\n * Ps = 1 -> hide if the mouse tracking mode is not enabled.\n * Ps = 2 -> always hide the pointer. If no parameter is\n * given, xterm uses the default, which is 1 .\n */\nTerminal.prototype.setPointerMode = function(params) {\n ;\n};\n\n\n/**\n * CSI ! p Soft terminal reset (DECSTR).\n * http://vt100.net/docs/vt220-rm/table4-10.html\n */\nTerminal.prototype.softReset = function(params) {\n this.cursorHidden = false;\n this.insertMode = false;\n this.originMode = false;\n this.wraparoundMode = false; // autowrap\n this.applicationKeypad = false; // ?\n this.viewport.syncScrollArea();\n this.applicationCursor = false;\n this.scrollTop = 0;\n this.scrollBottom = this.rows - 1;\n this.curAttr = this.defAttr;\n this.x = this.y = 0; // ?\n this.charset = null;\n this.glevel = 0; // ??\n this.charsets = [null]; // ??\n};\n\n\n/**\n * CSI Ps$ p\n * Request ANSI mode (DECRQM). For VT300 and up, reply is\n * CSI Ps; Pm$ y\n * where Ps is the mode number as in RM, and Pm is the mode\n * value:\n * 0 - not recognized\n * 1 - set\n * 2 - reset\n * 3 - permanently set\n * 4 - permanently reset\n */\nTerminal.prototype.requestAnsiMode = function(params) {\n ;\n};\n\n\n/**\n * CSI ? Ps$ p\n * Request DEC private mode (DECRQM). For VT300 and up, reply is\n * CSI ? Ps; Pm$ p\n * where Ps is the mode number as in DECSET, Pm is the mode value\n * as in the ANSI DECRQM.\n */\nTerminal.prototype.requestPrivateMode = function(params) {\n ;\n};\n\n\n/**\n * CSI Ps ; Ps \" p\n * Set conformance level (DECSCL). Valid values for the first\n * parameter:\n * Ps = 6 1 -> VT100.\n * Ps = 6 2 -> VT200.\n * Ps = 6 3 -> VT300.\n * Valid values for the second parameter:\n * Ps = 0 -> 8-bit controls.\n * Ps = 1 -> 7-bit controls (always set for VT100).\n * Ps = 2 -> 8-bit controls.\n */\nTerminal.prototype.setConformanceLevel = function(params) {\n ;\n};\n\n\n/**\n * CSI Ps q Load LEDs (DECLL).\n * Ps = 0 -> Clear all LEDS (default).\n * Ps = 1 -> Light Num Lock.\n * Ps = 2 -> Light Caps Lock.\n * Ps = 3 -> Light Scroll Lock.\n * Ps = 2 1 -> Extinguish Num Lock.\n * Ps = 2 2 -> Extinguish Caps Lock.\n * Ps = 2 3 -> Extinguish Scroll Lock.\n */\nTerminal.prototype.loadLEDs = function(params) {\n ;\n};\n\n\n/**\n * CSI Ps SP q\n * 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 */\nTerminal.prototype.setCursorStyle = function(params) {\n ;\n};\n\n\n/**\n * CSI Ps \" q\n * Select character protection attribute (DECSCA). Valid values\n * for the parameter:\n * Ps = 0 -> DECSED and DECSEL can erase (default).\n * Ps = 1 -> DECSED and DECSEL cannot erase.\n * Ps = 2 -> DECSED and DECSEL can erase.\n */\nTerminal.prototype.setCharProtectionAttr = function(params) {\n ;\n};\n\n\n/**\n * CSI ? Pm r\n * Restore DEC Private Mode Values. The value of Ps previously\n * saved is restored. Ps values are the same as for DECSET.\n */\nTerminal.prototype.restorePrivateValues = function(params) {\n ;\n};\n\n\n/**\n * CSI Pt; Pl; Pb; Pr; Ps$ r\n * Change Attributes in Rectangular Area (DECCARA), VT400 and up.\n * Pt; Pl; Pb; Pr denotes the rectangle.\n * Ps denotes the SGR attributes to change: 0, 1, 4, 5, 7.\n * NOTE: xterm doesn't enable this code by default.\n */\nTerminal.prototype.setAttrInRectangle = function(params) {\n var t = params[0]\n , l = params[1]\n , b = params[2]\n , r = params[3]\n , attr = params[4];\n\n var line\n , i;\n\n for (; t < b + 1; t++) {\n line = this.lines[this.ybase + t];\n for (i = l; i < r; i++) {\n line[i] = [attr, line[i][1]];\n }\n }\n\n // this.maxRange();\n this.updateRange(params[0]);\n this.updateRange(params[2]);\n};\n\n\n/**\n * CSI Pc; Pt; Pl; Pb; Pr$ x\n * Fill Rectangular Area (DECFRA), VT420 and up.\n * Pc is the character to use.\n * Pt; Pl; Pb; Pr denotes the rectangle.\n * NOTE: xterm doesn't enable this code by default.\n */\nTerminal.prototype.fillRectangle = function(params) {\n var ch = params[0]\n , t = params[1]\n , l = params[2]\n , b = params[3]\n , r = params[4];\n\n var line\n , i;\n\n for (; t < b + 1; t++) {\n line = this.lines[this.ybase + t];\n for (i = l; i < r; i++) {\n line[i] = [line[i][0], String.fromCharCode(ch)];\n }\n }\n\n // this.maxRange();\n this.updateRange(params[1]);\n this.updateRange(params[3]);\n};\n\n\n/**\n * CSI Ps ; Pu ' z\n * Enable Locator Reporting (DECELR).\n * Valid values for the first parameter:\n * Ps = 0 -> Locator disabled (default).\n * Ps = 1 -> Locator enabled.\n * Ps = 2 -> Locator enabled for one report, then disabled.\n * The second parameter specifies the coordinate unit for locator\n * reports.\n * Valid values for the second parameter:\n * Pu = 0 <- or omitted -> default to character cells.\n * Pu = 1 <- device physical pixels.\n * Pu = 2 <- character cells.\n */\nTerminal.prototype.enableLocatorReporting = function(params) {\n var val = params[0] > 0;\n //this.mouseEvents = val;\n //this.decLocator = val;\n};\n\n\n/**\n * CSI Pt; Pl; Pb; Pr$ z\n * Erase Rectangular Area (DECERA), VT400 and up.\n * Pt; Pl; Pb; Pr denotes the rectangle.\n * NOTE: xterm doesn't enable this code by default.\n */\nTerminal.prototype.eraseRectangle = function(params) {\n var t = params[0]\n , l = params[1]\n , b = params[2]\n , r = params[3];\n\n var line\n , i\n , ch;\n\n ch = [this.eraseAttr(), ' ', 1]; // xterm?\n\n for (; t < b + 1; t++) {\n line = this.lines[this.ybase + t];\n for (i = l; i < r; i++) {\n line[i] = ch;\n }\n }\n\n // this.maxRange();\n this.updateRange(params[0]);\n this.updateRange(params[2]);\n};\n\n\n/**\n * CSI P m SP }\n * Insert P s Column(s) (default = 1) (DECIC), VT420 and up.\n * NOTE: xterm doesn't enable this code by default.\n */\nTerminal.prototype.insertColumns = function() {\n var param = params[0]\n , l = this.ybase + this.rows\n , ch = [this.eraseAttr(), ' ', 1] // xterm?\n , i;\n\n while (param--) {\n for (i = this.ybase; i < l; i++) {\n this.lines[i].splice(this.x + 1, 0, ch);\n this.lines[i].pop();\n }\n }\n\n this.maxRange();\n};\n\n\n/**\n * CSI P m SP ~\n * Delete P s Column(s) (default = 1) (DECDC), VT420 and up\n * NOTE: xterm doesn't enable this code by default.\n */\nTerminal.prototype.deleteColumns = function() {\n var param = params[0]\n , l = this.ybase + this.rows\n , ch = [this.eraseAttr(), ' ', 1] // xterm?\n , i;\n\n while (param--) {\n for (i = this.ybase; i < l; i++) {\n this.lines[i].splice(this.x, 1);\n this.lines[i].push(ch);\n }\n }\n\n this.maxRange();\n};\n\n/**\n * Character Sets\n */\n\nTerminal.charsets = {};\n\n// DEC Special Character and Line Drawing Set.\n// 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.\nTerminal.charsets.SCLD = { // (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\nTerminal.charsets.UK = null; // (A\nTerminal.charsets.US = null; // (B (USASCII)\nTerminal.charsets.Dutch = null; // (4\nTerminal.charsets.Finnish = null; // (C or (5\nTerminal.charsets.French = null; // (R\nTerminal.charsets.FrenchCanadian = null; // (Q\nTerminal.charsets.German = null; // (K\nTerminal.charsets.Italian = null; // (Y\nTerminal.charsets.NorwegianDanish = null; // (E or (6\nTerminal.charsets.Spanish = null; // (Z\nTerminal.charsets.Swedish = null; // (H or (7\nTerminal.charsets.Swiss = null; // (=\nTerminal.charsets.ISOLatin = null; // /A\n\n/**\n * Helpers\n */\n\nfunction on(el, type, handler, capture) {\n if (!Array.isArray(el)) {\n el = [el];\n }\n el.forEach(function (element) {\n element.addEventListener(type, handler, capture || false);\n });\n}\n\nfunction off(el, type, handler, capture) {\n el.removeEventListener(type, handler, capture || false);\n}\n\nfunction cancel(ev, force) {\n if (!this.cancelEvents && !force) {\n return;\n }\n ev.preventDefault();\n ev.stopPropagation();\n return false;\n}\n\nfunction inherits(child, parent) {\n function f() {\n this.constructor = child;\n }\n f.prototype = parent.prototype;\n child.prototype = new f;\n}\n\n// if bold is broken, we can't\n// use it in the terminal.\nfunction isBoldBroken(document) {\n var body = document.getElementsByTagName('body')[0];\n var el = document.createElement('span');\n el.innerHTML = 'hello world';\n body.appendChild(el);\n var w1 = el.scrollWidth;\n el.style.fontWeight = 'bold';\n var w2 = el.scrollWidth;\n body.removeChild(el);\n return w1 !== w2;\n}\n\nfunction indexOf(obj, el) {\n var i = obj.length;\n while (i--) {\n if (obj[i] === el) return i;\n }\n return -1;\n}\n\nfunction isThirdLevelShift(term, ev) {\n var thirdLevelKey =\n (term.browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) ||\n (term.browser.isMSWindows && ev.altKey && ev.ctrlKey && !ev.metaKey);\n\n if (ev.type == 'keypress') {\n return thirdLevelKey;\n }\n\n // Don't invoke for arrows, pageDown, home, backspace, etc. (on non-keypress events)\n return thirdLevelKey && (!ev.keyCode || ev.keyCode > 47);\n}\n\nfunction matchColor(r1, g1, b1) {\n var hash = (r1 << 16) | (g1 << 8) | b1;\n\n if (matchColor._cache[hash] != null) {\n return matchColor._cache[hash];\n }\n\n var ldiff = Infinity\n , li = -1\n , i = 0\n , c\n , r2\n , g2\n , b2\n , diff;\n\n for (; i < Terminal.vcolors.length; i++) {\n c = Terminal.vcolors[i];\n r2 = c[0];\n g2 = c[1];\n b2 = c[2];\n\n diff = matchColor.distance(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 matchColor._cache[hash] = li;\n}\n\nmatchColor._cache = {};\n\n// http://stackoverflow.com/questions/1633828\nmatchColor.distance = function(r1, g1, b1, r2, g2, b2) {\n return Math.pow(30 * (r1 - r2), 2)\n + Math.pow(59 * (g1 - g2), 2)\n + Math.pow(11 * (b1 - b2), 2);\n};\n\nfunction each(obj, iter, con) {\n if (obj.forEach) return obj.forEach(iter, con);\n for (var i = 0; i < obj.length; i++) {\n iter.call(con, obj[i], i, obj);\n }\n}\n\nfunction keys(obj) {\n if (Object.keys) return Object.keys(obj);\n var key, keys = [];\n for (key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n keys.push(key);\n }\n }\n return keys;\n}\n\nvar wcwidth = (function(opts) {\n // extracted from https://www.cl.cam.ac.uk/%7Emgk25/ucs/wcwidth.c\n // combining characters\n var COMBINING = [\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 [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) {\n var min = 0;\n var max = COMBINING.length - 1;\n var mid;\n if (ucs < COMBINING[0][0] || ucs > COMBINING[max][1])\n return false;\n while (max >= min) {\n mid = Math.floor((min + max) / 2);\n if (ucs > COMBINING[mid][1])\n min = mid + 1;\n else if (ucs < COMBINING[mid][0])\n max = mid - 1;\n else\n return true;\n }\n return false;\n }\n function wcwidth(ucs) {\n // test for 8-bit control characters\n if (ucs === 0)\n return opts.nul;\n if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))\n return opts.control;\n // binary search in table of non-spacing characters\n if (bisearch(ucs))\n return 0;\n // if we arrive here, ucs is not a combining or C0/C1 control character\n return 1 +\n (\n ucs >= 0x1100 &&\n (\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 (ucs >= 0x20000 && ucs <= 0x2fffd) ||\n (ucs >= 0x30000 && ucs <= 0x3fffd)\n )\n );\n }\n return wcwidth;\n})({nul: 0, control: 0}); // configurable options\n\n/**\n * Expose\n */\n\nTerminal.EventEmitter = EventEmitter;\nTerminal.CompositionHelper = CompositionHelper;\nTerminal.Viewport = Viewport;\nTerminal.inherits = inherits;\n\n/**\n * Adds an event listener to the terminal.\n *\n * @param {string} event The name of the event. TODO: Document all event types\n * @param {function} callback The function to call when the event is triggered.\n */\nTerminal.on = on;\nTerminal.off = off;\nTerminal.cancel = cancel;\n\nmodule.exports = Terminal;\n" - ] -} \ No newline at end of file +{"version":3,"file":"xterm.js","sources":["../src/xterm.js","../src/utils/Generic.js","../src/utils/Browser.js","../src/handlers/Clipboard.ts","../src/Viewport.ts","../src/EventEmitter.js","../src/CompositionHelper.ts","../node_modules/browser-pack/_prelude.js"],"sourcesContent":["/**\n * xterm.js: xterm, in the browser\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 * @license MIT\n */\n\nimport { CompositionHelper } from './CompositionHelper.js';\nimport { EventEmitter } from './EventEmitter.js';\nimport { Viewport } from './Viewport.js';\nimport { rightClickHandler, pasteHandler, copyHandler } from './handlers/Clipboard.js';\nimport * as Browser from './utils/Browser';\nimport * as Keyboard from './utils/Keyboard';\n\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\n// Let it work inside Node.js for automated testing purposes.\nvar document = (typeof window != 'undefined') ? window.document : null;\n\n/**\n * States\n */\nvar normal = 0, escaped = 1, csi = 2, osc = 3, charset = 4, dcs = 5, ignore = 6;\n\n/**\n * Terminal\n */\n\n/**\n * Creates a new `Terminal` object.\n *\n * @param {object} options An object containing a set of options, the available options are:\n * - `cursorBlink` (boolean): Whether the terminal cursor blinks\n * - `cols` (number): The number of columns of the terminal (horizontal size)\n * - `rows` (number): The number of rows of the terminal (vertical size)\n *\n * @public\n * @class Xterm Xterm\n * @alias module:xterm/src/xterm\n */\nfunction Terminal(options) {\n var self = this;\n\n if (!(this instanceof Terminal)) {\n return new Terminal(arguments[0], arguments[1], arguments[2]);\n }\n\n self.browser = Browser;\n self.cancel = Terminal.cancel;\n\n EventEmitter.call(this);\n\n if (typeof options === 'number') {\n options = {\n cols: arguments[0],\n rows: arguments[1],\n handler: arguments[2]\n };\n }\n\n options = options || {};\n\n\n Object.keys(Terminal.defaults).forEach(function(key) {\n if (options[key] == null) {\n options[key] = Terminal.options[key];\n\n if (Terminal[key] !== Terminal.defaults[key]) {\n options[key] = Terminal[key];\n }\n }\n self[key] = options[key];\n });\n\n if (options.colors.length === 8) {\n options.colors = options.colors.concat(Terminal._colors.slice(8));\n } else if (options.colors.length === 16) {\n options.colors = options.colors.concat(Terminal._colors.slice(16));\n } else if (options.colors.length === 10) {\n options.colors = options.colors.slice(0, -2).concat(\n Terminal._colors.slice(8, -2), options.colors.slice(-2));\n } else if (options.colors.length === 18) {\n options.colors = options.colors.concat(\n Terminal._colors.slice(16, -2), options.colors.slice(-2));\n }\n this.colors = options.colors;\n\n this.options = options;\n\n // this.context = options.context || window;\n // this.document = options.document || document;\n this.parent = options.body || options.parent || (\n document ? document.getElementsByTagName('body')[0] : null\n );\n\n this.cols = options.cols || options.geometry[0];\n this.rows = options.rows || options.geometry[1];\n this.geometry = [this.cols, this.rows];\n\n if (options.handler) {\n this.on('data', options.handler);\n }\n\n /**\n * The scroll position of the y cursor, ie. ybase + y = the y position within the entire\n * buffer\n */\n this.ybase = 0;\n\n /**\n * The scroll position of the viewport\n */\n this.ydisp = 0;\n\n /**\n * The cursor's x position after ybase\n */\n this.x = 0;\n\n /**\n * The cursor's y position after ybase\n */\n this.y = 0;\n\n /**\n * Used to debounce the refresh function\n */\n this.isRefreshing = false;\n\n /**\n * Whether there is a full terminal refresh queued\n */\n\n this.cursorState = 0;\n this.cursorHidden = false;\n this.convertEol;\n this.state = 0;\n this.queue = '';\n this.scrollTop = 0;\n this.scrollBottom = this.rows - 1;\n this.customKeydownHandler = 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.normal = null;\n\n // charset\n this.charset = null;\n this.gcharset = null;\n this.glevel = 0;\n this.charsets = [null];\n\n // mouse properties\n this.decLocator;\n this.x10Mouse;\n this.vt200Mouse;\n this.vt300Mouse;\n this.normalMouse;\n this.mouseEvents;\n this.sendFocus;\n this.utfMouse;\n this.sgrMouse;\n this.urxvtMouse;\n\n // misc\n this.element;\n this.children;\n this.refreshStart;\n this.refreshEnd;\n this.savedX;\n this.savedY;\n this.savedCols;\n\n // stream\n this.readable = true;\n this.writable = true;\n\n this.defAttr = (0 << 18) | (257 << 9) | (256 << 0);\n this.curAttr = this.defAttr;\n\n this.params = [];\n this.currentParam = 0;\n this.prefix = '';\n this.postfix = '';\n\n // leftover surrogate high from previous write invocation\n this.surrogate_high = '';\n\n /**\n * An array of all lines in the entire buffer, including the prompt. The lines are array of\n * characters which are 2-length arrays where [0] is an attribute and [1] is the character.\n */\n this.lines = [];\n var i = this.rows;\n while (i--) {\n this.lines.push(this.blankLine());\n }\n\n this.tabs;\n this.setupStops();\n\n // Store if user went browsing history in scrollback\n this.userScrolling = false;\n}\n\ninherits(Terminal, EventEmitter);\n\n/**\n * back_color_erase feature for xterm.\n */\nTerminal.prototype.eraseAttr = function() {\n // if (this.is('screen')) return this.defAttr;\n return (this.defAttr & ~0x1ff) | (this.curAttr & 0x1ff);\n};\n\n/**\n * Colors\n */\n\n// Colors 0-15\nTerminal.tangoColors = [\n // dark:\n '#2e3436',\n '#cc0000',\n '#4e9a06',\n '#c4a000',\n '#3465a4',\n '#75507b',\n '#06989a',\n '#d3d7cf',\n // bright:\n '#555753',\n '#ef2929',\n '#8ae234',\n '#fce94f',\n '#729fcf',\n '#ad7fa8',\n '#34e2e2',\n '#eeeeec'\n];\n\n// Colors 0-15 + 16-255\n// Much thanks to TooTallNate for writing this.\nTerminal.colors = (function() {\n var colors = Terminal.tangoColors.slice()\n , r = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff]\n , i;\n\n // 16-231\n i = 0;\n for (; i < 216; i++) {\n out(r[(i / 36) % 6 | 0], r[(i / 6) % 6 | 0], r[i % 6]);\n }\n\n // 232-255 (grey)\n i = 0;\n for (; i < 24; i++) {\n r = 8 + i * 10;\n out(r, r, r);\n }\n\n function out(r, g, b) {\n colors.push('#' + hex(r) + hex(g) + hex(b));\n }\n\n function hex(c) {\n c = c.toString(16);\n return c.length < 2 ? '0' + c : c;\n }\n\n return colors;\n})();\n\nTerminal._colors = Terminal.colors.slice();\n\nTerminal.vcolors = (function() {\n var out = []\n , colors = Terminal.colors\n , i = 0\n , color;\n\n for (; i < 256; i++) {\n color = parseInt(colors[i].substring(1), 16);\n out.push([\n (color >> 16) & 0xff,\n (color >> 8) & 0xff,\n color & 0xff\n ]);\n }\n\n return out;\n})();\n\n/**\n * Options\n */\n\nTerminal.defaults = {\n colors: Terminal.colors,\n theme: 'default',\n convertEol: false,\n termName: 'xterm',\n geometry: [80, 24],\n cursorBlink: false,\n visualBell: false,\n popOnBell: false,\n scrollback: 1000,\n screenKeys: false,\n debug: false,\n cancelEvents: false\n // programFeatures: false,\n // focusKeys: false,\n};\n\nTerminal.options = {};\n\nTerminal.focus = null;\n\neach(keys(Terminal.defaults), function(key) {\n Terminal[key] = Terminal.defaults[key];\n Terminal.options[key] = Terminal.defaults[key];\n});\n\n/**\n * Focus the terminal. Delegates focus handling to the terminal's DOM element.\n */\nTerminal.prototype.focus = function() {\n return this.textarea.focus();\n};\n\n/**\n * Retrieves an option's value from the terminal.\n * @param {string} key The option key.\n */\nTerminal.prototype.getOption = function(key, value) {\n if (!(key in Terminal.defaults)) {\n throw new Error('No option with key \"' + key + '\"');\n }\n\n if (typeof this.options[key] !== 'undefined') {\n return this.options[key];\n }\n\n return this[key];\n};\n\n/**\n * Sets an option on the terminal.\n * @param {string} key The option key.\n * @param {string} value The option value.\n */\nTerminal.prototype.setOption = function(key, value) {\n if (!(key in Terminal.defaults)) {\n throw new Error('No option with key \"' + key + '\"');\n }\n this[key] = value;\n this.options[key] = value;\n};\n\n/**\n * Binds the desired focus behavior on a given terminal object.\n *\n * @static\n */\nTerminal.bindFocus = function (term) {\n on(term.textarea, 'focus', function (ev) {\n if (term.sendFocus) {\n term.send('\\x1b[I');\n }\n term.element.classList.add('focus');\n term.showCursor();\n Terminal.focus = term;\n term.emit('focus', {terminal: term});\n });\n};\n\n/**\n * Blur the terminal. Delegates blur handling to the terminal's DOM element.\n */\nTerminal.prototype.blur = function() {\n return this.textarea.blur();\n};\n\n/**\n * Binds the desired blur behavior on a given terminal object.\n *\n * @static\n */\nTerminal.bindBlur = function (term) {\n on(term.textarea, 'blur', function (ev) {\n term.refresh(term.y, term.y);\n if (term.sendFocus) {\n term.send('\\x1b[O');\n }\n term.element.classList.remove('focus');\n Terminal.focus = null;\n term.emit('blur', {terminal: term});\n });\n};\n\n/**\n * Initialize default behavior\n */\nTerminal.prototype.initGlobal = function() {\n var term = this;\n\n Terminal.bindKeys(this);\n Terminal.bindFocus(this);\n Terminal.bindBlur(this);\n\n // Bind clipboard functionality\n on(this.element, 'copy', function (ev) {\n copyHandler.call(this, ev, term);\n });\n on(this.textarea, 'paste', function (ev) {\n pasteHandler.call(this, ev, term);\n });\n\n function rightClickHandlerWrapper (ev) {\n rightClickHandler.call(this, ev, term);\n }\n\n if (term.browser.isFirefox) {\n on(this.element, 'mousedown', function (ev) {\n if (ev.button == 2) {\n rightClickHandlerWrapper(ev);\n }\n });\n } else {\n on(this.element, 'contextmenu', rightClickHandlerWrapper);\n }\n};\n\n/**\n * Apply key handling to the terminal\n */\nTerminal.bindKeys = function(term) {\n on(term.element, 'keydown', function(ev) {\n if (document.activeElement != this) {\n return;\n }\n term.keyDown(ev);\n }, true);\n\n on(term.element, 'keypress', function(ev) {\n if (document.activeElement != this) {\n return;\n }\n term.keyPress(ev);\n }, true);\n\n on(term.element, 'keyup', term.focus.bind(term));\n\n on(term.textarea, 'keydown', function(ev) {\n term.keyDown(ev);\n }, true);\n\n on(term.textarea, 'keypress', function(ev) {\n term.keyPress(ev);\n // Truncate the textarea's value, since it is not needed\n this.value = '';\n }, true);\n\n on(term.textarea, 'compositionstart', term.compositionHelper.compositionstart.bind(term.compositionHelper));\n on(term.textarea, 'compositionupdate', term.compositionHelper.compositionupdate.bind(term.compositionHelper));\n on(term.textarea, 'compositionend', term.compositionHelper.compositionend.bind(term.compositionHelper));\n term.on('refresh', term.compositionHelper.updateCompositionElements.bind(term.compositionHelper));\n};\n\n\n/**\n * Insert the given row to the terminal or produce a new one\n * if no row argument is passed. Return the inserted row.\n * @param {HTMLElement} row (optional) The row to append to the terminal.\n */\nTerminal.prototype.insertRow = function (row) {\n if (typeof row != 'object') {\n row = document.createElement('div');\n }\n\n this.rowContainer.appendChild(row);\n this.children.push(row);\n\n return row;\n};\n\n/**\n * Opens the terminal within an element.\n *\n * @param {HTMLElement} parent The element to create the terminal within.\n */\nTerminal.prototype.open = function(parent) {\n var self=this, i=0, div;\n\n this.parent = parent || this.parent;\n\n if (!this.parent) {\n throw new Error('Terminal requires a parent element.');\n }\n\n // Grab global elements\n this.context = this.parent.ownerDocument.defaultView;\n this.document = this.parent.ownerDocument;\n this.body = this.document.getElementsByTagName('body')[0];\n\n //Create main element container\n this.element = this.document.createElement('div');\n this.element.classList.add('terminal');\n this.element.classList.add('xterm');\n this.element.classList.add('xterm-theme-' + this.theme);\n\n this.element.style.height\n this.element.setAttribute('tabindex', 0);\n\n this.viewportElement = document.createElement('div');\n this.viewportElement.classList.add('xterm-viewport');\n this.element.appendChild(this.viewportElement);\n this.viewportScrollArea = document.createElement('div');\n this.viewportScrollArea.classList.add('xterm-scroll-area');\n this.viewportElement.appendChild(this.viewportScrollArea);\n\n // Create the container that will hold the lines of the terminal and then\n // produce the lines the lines.\n this.rowContainer = document.createElement('div');\n this.rowContainer.classList.add('xterm-rows');\n this.element.appendChild(this.rowContainer);\n this.children = [];\n\n // Create the container that will hold helpers like the textarea for\n // capturing DOM Events. Then produce the helpers.\n this.helperContainer = document.createElement('div');\n this.helperContainer.classList.add('xterm-helpers');\n // TODO: This should probably be inserted once it's filled to prevent an additional layout\n this.element.appendChild(this.helperContainer);\n this.textarea = document.createElement('textarea');\n this.textarea.classList.add('xterm-helper-textarea');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.tabIndex = 0;\n this.textarea.addEventListener('focus', function() {\n self.emit('focus', {terminal: self});\n });\n this.textarea.addEventListener('blur', function() {\n self.emit('blur', {terminal: self});\n });\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.charMeasureElement = document.createElement('div');\n this.charMeasureElement.classList.add('xterm-char-measure-element');\n this.charMeasureElement.innerHTML = 'W';\n this.helperContainer.appendChild(this.charMeasureElement);\n\n for (; i < this.rows; i++) {\n this.insertRow();\n }\n this.parent.appendChild(this.element);\n\n this.viewport = new Viewport(this, this.viewportElement, this.viewportScrollArea, this.charMeasureElement);\n\n // Draw the screen.\n this.refresh(0, this.rows - 1);\n\n // Initialize global actions that\n // need to be taken on the document.\n this.initGlobal();\n\n // Ensure there is a Terminal.focus.\n this.focus();\n\n on(this.element, 'click', function() {\n var selection = document.getSelection(),\n collapsed = selection.isCollapsed,\n isRange = typeof collapsed == 'boolean' ? !collapsed : selection.type == 'Range';\n if (!isRange) {\n self.focus();\n }\n });\n\n // Listen for mouse events and translate\n // them into terminal mouse protocols.\n this.bindMouse();\n\n // Figure out whether boldness affects\n // the character width of monospace fonts.\n if (Terminal.brokenBold == null) {\n Terminal.brokenBold = isBoldBroken(this.document);\n }\n\n /**\n * This event is emitted when terminal has completed opening.\n *\n * @event open\n */\n this.emit('open');\n};\n\n\n/**\n * Attempts to load an add-on using CommonJS or RequireJS (whichever is available).\n * @param {string} addon The name of the addon to load\n * @static\n */\nTerminal.loadAddon = function(addon, callback) {\n if (typeof exports === 'object' && typeof module === 'object') {\n // CommonJS\n return require('./addons/' + addon + '/' + addon);\n } else if (typeof define == 'function') {\n // RequireJS\n return require(['./addons/' + addon + '/' + addon], callback);\n } else {\n console.error('Cannot load a module without a CommonJS or RequireJS environment.');\n return false;\n }\n};\n\n\n/**\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 */\nTerminal.prototype.bindMouse = function() {\n var el = this.element, self = this, pressed = 32;\n\n // mouseup, mousedown, wheel\n // left click: ^[[M 3<^[[M#3<\n // wheel up: ^[[M`3>\n function sendButton(ev) {\n var button\n , pos;\n\n // get the xterm-style button\n button = getButton(ev);\n\n // get mouse coordinates\n pos = getCoords(ev);\n if (!pos) return;\n\n sendEvent(button, pos);\n\n switch (ev.overrideType || ev.type) {\n case 'mousedown':\n pressed = button;\n break;\n case 'mouseup':\n // keep it at the left\n // button, just in case.\n pressed = 32;\n break;\n case 'wheel':\n // nothing. don't\n // interfere with\n // `pressed`.\n break;\n }\n }\n\n // motion example of a left click:\n // ^[[M 3<^[[M@4<^[[M@5<^[[M@6<^[[M@7<^[[M#7<\n function sendMove(ev) {\n var button = pressed\n , pos;\n\n pos = getCoords(ev);\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, ch) {\n if (!self.utfMouse) {\n if (ch === 255) return data.push(0);\n if (ch > 127) ch = 127;\n data.push(ch);\n } else {\n if (ch === 2047) return data.push(0);\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, pos) {\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 var data = '\\x1b[24';\n if (button === 0) data += '1';\n else if (button === 1) data += '3';\n else if (button === 2) data += '5';\n else if (button === 3) return;\n else data += '0';\n data += '~[' + pos.x + ',' + pos.y + ']\\r';\n self.send(data);\n return;\n }\n\n if (self.decLocator) {\n // NOTE: Unstable.\n button &= 3;\n pos.x -= 32;\n pos.y -= 32;\n if (button === 0) button = 2;\n else if (button === 1) button = 4;\n else if (button === 2) button = 6;\n else if (button === 3) button = 3;\n self.send('\\x1b['\n + button\n + ';'\n + (button === 3 ? 4 : 0)\n + ';'\n + pos.y\n + ';'\n + pos.x\n + ';'\n + (pos.page || 0)\n + '&w');\n return;\n }\n\n if (self.urxvtMouse) {\n pos.x -= 32;\n pos.y -= 32;\n pos.x++;\n pos.y++;\n self.send('\\x1b[' + button + ';' + pos.x + ';' + pos.y + 'M');\n return;\n }\n\n if (self.sgrMouse) {\n pos.x -= 32;\n pos.y -= 32;\n self.send('\\x1b[<'\n + ((button & 3) === 3 ? button & ~3 : button)\n + ';'\n + pos.x\n + ';'\n + pos.y\n + ((button & 3) === 3 ? 'm' : 'M'));\n return;\n }\n\n var data = [];\n\n encode(data, button);\n encode(data, pos.x);\n encode(data, pos.y);\n\n self.send('\\x1b[M' + String.fromCharCode.apply(String, data));\n }\n\n function getButton(ev) {\n var button\n , shift\n , meta\n , ctrl\n , mod;\n\n // two low bits:\n // 0 = left\n // 1 = middle\n // 2 = right\n // 3 = release\n // wheel up/down:\n // 1, and 2 - with 64 added\n switch (ev.overrideType || ev.type) {\n case 'mousedown':\n button = ev.button != null\n ? +ev.button\n : ev.which != null\n ? ev.which - 1\n : null;\n\n if (self.browser.isMSIE) {\n button = button === 1 ? 0 : button === 4 ? 1 : button;\n }\n break;\n case 'mouseup':\n button = 3;\n break;\n case 'DOMMouseScroll':\n button = ev.detail < 0\n ? 64\n : 65;\n break;\n case 'wheel':\n button = ev.wheelDeltaY > 0\n ? 64\n : 65;\n break;\n }\n\n // next three bits are the modifiers:\n // 4 = shift, 8 = meta, 16 = control\n shift = ev.shiftKey ? 4 : 0;\n meta = ev.metaKey ? 8 : 0;\n ctrl = ev.ctrlKey ? 16 : 0;\n mod = shift | meta | ctrl;\n\n // no mods\n if (self.vt200Mouse) {\n // ctrl only\n mod &= ctrl;\n } else if (!self.normalMouse) {\n mod = 0;\n }\n\n // increment to SP\n button = (32 + (mod << 2)) + button;\n\n return button;\n }\n\n // mouse coordinates measured in cols/rows\n function getCoords(ev) {\n var x, y, w, h, el;\n\n // ignore browsers without pageX for now\n if (ev.pageX == null) return;\n\n x = ev.pageX;\n y = ev.pageY;\n el = self.element;\n\n // should probably check offsetParent\n // but this is more portable\n while (el && el !== self.document.documentElement) {\n x -= el.offsetLeft;\n y -= el.offsetTop;\n el = 'offsetParent' in el\n ? el.offsetParent\n : el.parentNode;\n }\n\n // convert to cols/rows\n w = self.element.clientWidth;\n h = self.element.clientHeight;\n x = Math.ceil((x / w) * self.cols);\n y = Math.ceil((y / h) * self.rows);\n\n // be sure to avoid sending\n // bad positions to the program\n if (x < 0) x = 0;\n if (x > self.cols) x = self.cols;\n if (y < 0) y = 0;\n if (y > self.rows) y = self.rows;\n\n // xterm sends raw bytes and\n // starts at 32 (SP) for each.\n x += 32;\n y += 32;\n\n return {\n x: x,\n y: y,\n type: 'wheel'\n };\n }\n\n on(el, 'mousedown', function(ev) {\n if (!self.mouseEvents) return;\n\n // send the button\n sendButton(ev);\n\n // ensure focus\n self.focus();\n\n // fix for odd bug\n //if (self.vt200Mouse && !self.normalMouse) {\n if (self.vt200Mouse) {\n ev.overrideType = 'mouseup';\n sendButton(ev);\n return self.cancel(ev);\n }\n\n // bind events\n if (self.normalMouse) on(self.document, 'mousemove', sendMove);\n\n // x10 compatibility mode can't send button releases\n if (!self.x10Mouse) {\n on(self.document, 'mouseup', function up(ev) {\n sendButton(ev);\n if (self.normalMouse) off(self.document, 'mousemove', sendMove);\n off(self.document, 'mouseup', up);\n return self.cancel(ev);\n });\n }\n\n return self.cancel(ev);\n });\n\n //if (self.normalMouse) {\n // on(self.document, 'mousemove', sendMove);\n //}\n\n on(el, 'wheel', function(ev) {\n if (!self.mouseEvents) return;\n if (self.x10Mouse\n || self.vt300Mouse\n || self.decLocator) return;\n sendButton(ev);\n return self.cancel(ev);\n });\n\n // allow wheel scrolling in\n // the shell for example\n on(el, 'wheel', function(ev) {\n if (self.mouseEvents) return;\n self.viewport.onWheel(ev);\n return self.cancel(ev);\n });\n};\n\n/**\n * Destroys the terminal.\n */\nTerminal.prototype.destroy = function() {\n this.readable = false;\n this.writable = false;\n this._events = {};\n this.handler = function() {};\n this.write = function() {};\n if (this.element.parentNode) {\n this.element.parentNode.removeChild(this.element);\n }\n //this.emit('close');\n};\n\n\n/**\n * Flags used to render terminal text properly\n */\nTerminal.flags = {\n BOLD: 1,\n UNDERLINE: 2,\n BLINK: 4,\n INVERSE: 8,\n INVISIBLE: 16\n}\n\n/**\n * Refreshes (re-renders) terminal content within two rows (inclusive)\n *\n * Rendering Engine:\n *\n * In the screen buffer, each character is stored as a an array with a character\n * and a 32-bit integer:\n * - First value: a utf-16 character.\n * - Second value:\n * - Next 9 bits: background color (0-511).\n * - Next 9 bits: foreground color (0-511).\n * - Next 14 bits: a mask for misc. flags:\n * - 1=bold\n * - 2=underline\n * - 4=blink\n * - 8=inverse\n * - 16=invisible\n *\n * @param {number} start The row to start from (between 0 and terminal's height terminal - 1)\n * @param {number} end The row to end at (between fromRow and terminal's height terminal - 1)\n * @param {boolean} queue Whether the refresh should ran right now or be queued\n */\nTerminal.prototype.refresh = function(start, end, queue) {\n var self = this;\n\n // queue defaults to true\n queue = (typeof queue == 'undefined') ? true : queue;\n\n /**\n * The refresh queue allows refresh to execute only approximately 30 times a second. For\n * commands that pass a significant amount of output to the write function, this prevents the\n * terminal from maxing out the CPU and making the UI unresponsive. While commands can still\n * run beyond what they do on the terminal, it is far better with a debounce in place as\n * every single terminal manipulation does not need to be constructed in the DOM.\n *\n * A side-effect of this is that it makes ^C to interrupt a process seem more responsive.\n */\n if (queue) {\n // If refresh should be queued, order the refresh and return.\n if (this._refreshIsQueued) {\n // If a refresh has already been queued, just order a full refresh next\n this._fullRefreshNext = true;\n } else {\n setTimeout(function () {\n self.refresh(start, end, false);\n }, 34)\n this._refreshIsQueued = true;\n }\n return;\n }\n\n // If refresh should be run right now (not be queued), release the lock\n this._refreshIsQueued = false;\n\n // If multiple refreshes were requested, make a full refresh.\n if (this._fullRefreshNext) {\n start = 0;\n end = this.rows - 1;\n this._fullRefreshNext = false // reset lock\n }\n\n var x, y, i, line, out, ch, ch_width, width, data, attr, bg, fg, flags, row, parent, focused = document.activeElement;\n\n // If this is a big refresh, remove the terminal rows from the DOM for faster calculations\n if (end - start >= this.rows / 2) {\n parent = this.element.parentNode;\n if (parent) {\n this.element.removeChild(this.rowContainer);\n }\n }\n\n width = this.cols;\n y = start;\n\n if (end >= this.rows.length) {\n this.log('`end` is too large. Most likely a bad CSR.');\n end = this.rows.length - 1;\n }\n\n for (; y <= end; y++) {\n row = y + this.ydisp;\n\n line = this.lines[row];\n out = '';\n\n if (this.y === y - (this.ybase - this.ydisp)\n && this.cursorState\n && !this.cursorHidden) {\n x = this.x;\n } else {\n x = -1;\n }\n\n attr = this.defAttr;\n i = 0;\n\n for (; i < width; i++) {\n data = line[i][0];\n ch = line[i][1];\n ch_width = line[i][2];\n if (!ch_width)\n continue;\n\n if (i === x) data = -1;\n\n if (data !== attr) {\n if (attr !== this.defAttr) {\n out += '';\n }\n if (data !== this.defAttr) {\n if (data === -1) {\n out += '> 9) & 0x1ff;\n flags = data >> 18;\n\n if (flags & Terminal.flags.BOLD) {\n if (!Terminal.brokenBold) {\n classNames.push('xterm-bold');\n }\n // See: XTerm*boldColors\n if (fg < 8) fg += 8;\n }\n\n if (flags & Terminal.flags.UNDERLINE) {\n classNames.push('xterm-underline');\n }\n\n if (flags & Terminal.flags.BLINK) {\n classNames.push('xterm-blink');\n }\n\n // If inverse flag is on, then swap the foreground and background variables.\n if (flags & Terminal.flags.INVERSE) {\n /* One-line variable swap in JavaScript: http://stackoverflow.com/a/16201730 */\n bg = [fg, fg = bg][0];\n // Should inverse just be before the\n // above boldColors effect instead?\n if ((flags & 1) && fg < 8) fg += 8;\n }\n\n if (flags & Terminal.flags.INVISIBLE) {\n classNames.push('xterm-hidden');\n }\n\n /**\n * Weird situation: Invert flag used black foreground and white background results\n * in invalid background color, positioned at the 256 index of the 256 terminal\n * color map. Pin the colors manually in such a case.\n *\n * Source: https://github.com/sourcelair/xterm.js/issues/57\n */\n if (flags & Terminal.flags.INVERSE) {\n if (bg == 257) {\n bg = 15;\n }\n if (fg == 256) {\n fg = 0;\n }\n }\n\n if (bg < 256) {\n classNames.push('xterm-bg-color-' + bg);\n }\n\n if (fg < 256) {\n classNames.push('xterm-color-' + fg);\n }\n\n out += '':\n out += '>';\n break;\n default:\n if (ch <= ' ') {\n out += ' ';\n } else {\n out += ch;\n }\n break;\n }\n\n attr = data;\n }\n\n if (attr !== this.defAttr) {\n out += '';\n }\n\n this.children[y].innerHTML = out;\n }\n\n if (parent) {\n this.element.appendChild(this.rowContainer);\n }\n\n this.emit('refresh', {element: this.element, start: start, end: end});\n};\n\n/**\n * Display the cursor element\n */\nTerminal.prototype.showCursor = function() {\n if (!this.cursorState) {\n this.cursorState = 1;\n this.refresh(this.y, this.y);\n }\n};\n\n/**\n * Scroll the terminal\n */\nTerminal.prototype.scroll = function() {\n var row;\n\n if (++this.ybase === this.scrollback) {\n this.ybase = this.ybase / 2 | 0;\n this.lines = this.lines.slice(-(this.ybase + this.rows) + 1);\n }\n\n if (!this.userScrolling) {\n this.ydisp = this.ybase;\n }\n\n // last line\n row = this.ybase + this.rows - 1;\n\n // subtract the bottom scroll region\n row -= this.rows - 1 - this.scrollBottom;\n\n if (row === this.lines.length) {\n // potential optimization:\n // pushing is faster than splicing\n // when they amount to the same\n // behavior.\n this.lines.push(this.blankLine());\n } else {\n // add our new line\n this.lines.splice(row, 0, this.blankLine());\n }\n\n if (this.scrollTop !== 0) {\n if (this.ybase !== 0) {\n this.ybase--;\n if (!this.userScrolling) {\n this.ydisp = this.ybase;\n }\n }\n this.lines.splice(this.ybase + this.scrollTop, 1);\n }\n\n // this.maxRange();\n this.updateRange(this.scrollTop);\n this.updateRange(this.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.ydisp);\n};\n\n/**\n * Scroll the display of the terminal\n * @param {number} disp The number of lines to scroll down (negatives scroll up).\n * @param {boolean} suppressScrollEvent Don't emit the scroll event as scrollDisp. This is used\n * to avoid unwanted events being handled by the veiwport when the event was triggered from the\n * viewport originally.\n */\nTerminal.prototype.scrollDisp = function(disp, suppressScrollEvent) {\n if (disp < 0) {\n this.userScrolling = true;\n } else if (disp + this.ydisp >= this.ybase) {\n this.userScrolling = false;\n }\n\n this.ydisp += disp;\n\n if (this.ydisp > this.ybase) {\n this.ydisp = this.ybase;\n } else if (this.ydisp < 0) {\n this.ydisp = 0;\n }\n\n if (!suppressScrollEvent) {\n this.emit('scroll', this.ydisp);\n }\n\n this.refresh(0, this.rows - 1);\n};\n\n/**\n * Scroll the display of the terminal by a number of pages.\n * @param {number} pageCount The number of pages to scroll (negative scrolls up).\n */\nTerminal.prototype.scrollPages = function(pageCount) {\n this.scrollDisp(pageCount * (this.rows - 1));\n}\n\n/**\n * Scrolls the display of the terminal to the top.\n */\nTerminal.prototype.scrollToTop = function() {\n this.scrollDisp(-this.ydisp);\n}\n\n/**\n * Scrolls the display of the terminal to the bottom.\n */\nTerminal.prototype.scrollToBottom = function() {\n this.scrollDisp(this.ybase - this.ydisp);\n}\n\n/**\n * Writes text to the terminal.\n * @param {string} text The text to write to the terminal.\n */\nTerminal.prototype.write = function(data) {\n var l = data.length, i = 0, j, cs, ch, code, low, ch_width, row;\n\n this.refreshStart = this.y;\n this.refreshEnd = this.y;\n\n // apply leftover surrogate high from last write\n if (this.surrogate_high) {\n data = this.surrogate_high + data;\n this.surrogate_high = '';\n }\n\n for (; i < l; i++) {\n ch = data[i];\n\n // FIXME: higher chars than 0xa0 are not allowed in escape sequences\n // --> maybe move to default\n code = data.charCodeAt(i);\n if (0xD800 <= code && code <= 0xDBFF) {\n // we got a surrogate high\n // get surrogate low (next 2 bytes)\n low = data.charCodeAt(i+1);\n if (isNaN(low)) {\n // end of data stream, save surrogate high\n this.surrogate_high = ch;\n continue;\n }\n code = ((code - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;\n ch += data.charAt(i+1);\n }\n // surrogate low - already handled above\n if (0xDC00 <= code && code <= 0xDFFF)\n continue;\n\n switch (this.state) {\n case normal:\n switch (ch) {\n case '\\x07':\n this.bell();\n break;\n\n // '\\n', '\\v', '\\f'\n case '\\n':\n case '\\x0b':\n case '\\x0c':\n if (this.convertEol) {\n this.x = 0;\n }\n this.y++;\n if (this.y > this.scrollBottom) {\n this.y--;\n this.scroll();\n }\n break;\n\n // '\\r'\n case '\\r':\n this.x = 0;\n break;\n\n // '\\b'\n case '\\x08':\n if (this.x > 0) {\n this.x--;\n }\n break;\n\n // '\\t'\n case '\\t':\n this.x = this.nextStop();\n break;\n\n // shift out\n case '\\x0e':\n this.setgLevel(1);\n break;\n\n // shift in\n case '\\x0f':\n this.setgLevel(0);\n break;\n\n // '\\e'\n case '\\x1b':\n this.state = escaped;\n break;\n\n default:\n // ' '\n // calculate print space\n // expensive call, therefore we save width in line buffer\n ch_width = wcwidth(code);\n\n if (ch >= ' ') {\n if (this.charset && this.charset[ch]) {\n ch = this.charset[ch];\n }\n\n row = this.y + this.ybase;\n\n // insert combining char in last cell\n // FIXME: needs handling after cursor jumps\n if (!ch_width && this.x) {\n\n // dont overflow left\n if (this.lines[row][this.x-1]) {\n if (!this.lines[row][this.x-1][2]) {\n\n // found empty cell after fullwidth, need to go 2 cells back\n if (this.lines[row][this.x-2])\n this.lines[row][this.x-2][1] += ch;\n\n } else {\n this.lines[row][this.x-1][1] += ch;\n }\n this.updateRange(this.y);\n }\n break;\n }\n\n // goto next line if ch would overflow\n // TODO: needs a global min terminal width of 2\n if (this.x+ch_width-1 >= this.cols) {\n // autowrap - DECAWM\n if (this.wraparoundMode) {\n this.x = 0;\n this.y++;\n if (this.y > this.scrollBottom) {\n this.y--;\n this.scroll();\n }\n } else {\n this.x = this.cols-1;\n if(ch_width===2) // FIXME: check for xterm behavior\n continue;\n }\n }\n row = this.y + this.ybase;\n\n // insert mode: move characters to right\n if (this.insertMode) {\n // do this twice for a fullwidth char\n for (var moves=0; moves Normal Keypad (DECKPNM).\n case '>':\n this.log('Switching back to normal keypad.');\n this.applicationKeypad = false;\n this.viewport.syncScrollArea();\n this.state = normal;\n break;\n\n default:\n this.state = normal;\n this.error('Unknown ESC control: %s.', ch);\n break;\n }\n break;\n\n case charset:\n switch (ch) {\n case '0': // DEC Special Character and Line Drawing Set.\n cs = Terminal.charsets.SCLD;\n break;\n case 'A': // UK\n cs = Terminal.charsets.UK;\n break;\n case 'B': // United States (USASCII).\n cs = Terminal.charsets.US;\n break;\n case '4': // Dutch\n cs = Terminal.charsets.Dutch;\n break;\n case 'C': // Finnish\n case '5':\n cs = Terminal.charsets.Finnish;\n break;\n case 'R': // French\n cs = Terminal.charsets.French;\n break;\n case 'Q': // FrenchCanadian\n cs = Terminal.charsets.FrenchCanadian;\n break;\n case 'K': // German\n cs = Terminal.charsets.German;\n break;\n case 'Y': // Italian\n cs = Terminal.charsets.Italian;\n break;\n case 'E': // NorwegianDanish\n case '6':\n cs = Terminal.charsets.NorwegianDanish;\n break;\n case 'Z': // Spanish\n cs = Terminal.charsets.Spanish;\n break;\n case 'H': // Swedish\n case '7':\n cs = Terminal.charsets.Swedish;\n break;\n case '=': // Swiss\n cs = Terminal.charsets.Swiss;\n break;\n case '/': // ISOLatin (actually /A)\n cs = Terminal.charsets.ISOLatin;\n i++;\n break;\n default: // Default\n cs = Terminal.charsets.US;\n break;\n }\n this.setgCharset(this.gcharset, cs);\n this.gcharset = null;\n this.state = normal;\n break;\n\n case osc:\n // OSC Ps ; Pt ST\n // OSC Ps ; Pt BEL\n // Set Text Parameters.\n if (ch === '\\x1b' || ch === '\\x07') {\n if (ch === '\\x1b') i++;\n\n this.params.push(this.currentParam);\n\n switch (this.params[0]) {\n case 0:\n case 1:\n case 2:\n if (this.params[1]) {\n this.title = this.params[1];\n this.handleTitle(this.title);\n }\n break;\n case 3:\n // set X property\n break;\n case 4:\n case 5:\n // change dynamic colors\n break;\n case 10:\n case 11:\n case 12:\n case 13:\n case 14:\n case 15:\n case 16:\n case 17:\n case 18:\n case 19:\n // change dynamic ui colors\n break;\n case 46:\n // change log file\n break;\n case 50:\n // dynamic font\n break;\n case 51:\n // emacs shell\n break;\n case 52:\n // manipulate selection data\n break;\n case 104:\n case 105:\n case 110:\n case 111:\n case 112:\n case 113:\n case 114:\n case 115:\n case 116:\n case 117:\n case 118:\n // reset colors\n break;\n }\n\n this.params = [];\n this.currentParam = 0;\n this.state = normal;\n } else {\n if (!this.params.length) {\n if (ch >= '0' && ch <= '9') {\n this.currentParam =\n this.currentParam * 10 + ch.charCodeAt(0) - 48;\n } else if (ch === ';') {\n this.params.push(this.currentParam);\n this.currentParam = '';\n }\n } else {\n this.currentParam += ch;\n }\n }\n break;\n\n case csi:\n // '?', '>', '!'\n if (ch === '?' || ch === '>' || ch === '!') {\n this.prefix = ch;\n break;\n }\n\n // 0 - 9\n if (ch >= '0' && ch <= '9') {\n this.currentParam = this.currentParam * 10 + ch.charCodeAt(0) - 48;\n break;\n }\n\n // '$', '\"', ' ', '\\''\n if (ch === '$' || ch === '\"' || ch === ' ' || ch === '\\'') {\n this.postfix = ch;\n break;\n }\n\n this.params.push(this.currentParam);\n this.currentParam = 0;\n\n // ';'\n if (ch === ';') break;\n\n this.state = normal;\n\n switch (ch) {\n // CSI Ps A\n // Cursor Up Ps Times (default = 1) (CUU).\n case 'A':\n this.cursorUp(this.params);\n break;\n\n // CSI Ps B\n // Cursor Down Ps Times (default = 1) (CUD).\n case 'B':\n this.cursorDown(this.params);\n break;\n\n // CSI Ps C\n // Cursor Forward Ps Times (default = 1) (CUF).\n case 'C':\n this.cursorForward(this.params);\n break;\n\n // CSI Ps D\n // Cursor Backward Ps Times (default = 1) (CUB).\n case 'D':\n this.cursorBackward(this.params);\n break;\n\n // CSI Ps ; Ps H\n // Cursor Position [row;column] (default = [1,1]) (CUP).\n case 'H':\n this.cursorPos(this.params);\n break;\n\n // CSI Ps J Erase in Display (ED).\n case 'J':\n this.eraseInDisplay(this.params);\n break;\n\n // CSI Ps K Erase in Line (EL).\n case 'K':\n this.eraseInLine(this.params);\n break;\n\n // CSI Pm m Character Attributes (SGR).\n case 'm':\n if (!this.prefix) {\n this.charAttributes(this.params);\n }\n break;\n\n // CSI Ps n Device Status Report (DSR).\n case 'n':\n if (!this.prefix) {\n this.deviceStatus(this.params);\n }\n break;\n\n /**\n * Additions\n */\n\n // CSI Ps @\n // Insert Ps (Blank) Character(s) (default = 1) (ICH).\n case '@':\n this.insertChars(this.params);\n break;\n\n // CSI Ps E\n // Cursor Next Line Ps Times (default = 1) (CNL).\n case 'E':\n this.cursorNextLine(this.params);\n break;\n\n // CSI Ps F\n // Cursor Preceding Line Ps Times (default = 1) (CNL).\n case 'F':\n this.cursorPrecedingLine(this.params);\n break;\n\n // CSI Ps G\n // Cursor Character Absolute [column] (default = [row,1]) (CHA).\n case 'G':\n this.cursorCharAbsolute(this.params);\n break;\n\n // CSI Ps L\n // Insert Ps Line(s) (default = 1) (IL).\n case 'L':\n this.insertLines(this.params);\n break;\n\n // CSI Ps M\n // Delete Ps Line(s) (default = 1) (DL).\n case 'M':\n this.deleteLines(this.params);\n break;\n\n // CSI Ps P\n // Delete Ps Character(s) (default = 1) (DCH).\n case 'P':\n this.deleteChars(this.params);\n break;\n\n // CSI Ps X\n // Erase Ps Character(s) (default = 1) (ECH).\n case 'X':\n this.eraseChars(this.params);\n break;\n\n // CSI Pm ` Character Position Absolute\n // [column] (default = [row,1]) (HPA).\n case '`':\n this.charPosAbsolute(this.params);\n break;\n\n // 141 61 a * HPR -\n // Horizontal Position Relative\n case 'a':\n this.HPositionRelative(this.params);\n break;\n\n // CSI P s c\n // Send Device Attributes (Primary DA).\n // CSI > P s c\n // Send Device Attributes (Secondary DA)\n case 'c':\n this.sendDeviceAttributes(this.params);\n break;\n\n // CSI Pm d\n // Line Position Absolute [row] (default = [1,column]) (VPA).\n case 'd':\n this.linePosAbsolute(this.params);\n break;\n\n // 145 65 e * VPR - Vertical Position Relative\n case 'e':\n this.VPositionRelative(this.params);\n break;\n\n // CSI Ps ; Ps f\n // Horizontal and Vertical Position [row;column] (default =\n // [1,1]) (HVP).\n case 'f':\n this.HVPosition(this.params);\n break;\n\n // CSI Pm h Set Mode (SM).\n // CSI ? Pm h - mouse escape codes, cursor escape codes\n case 'h':\n this.setMode(this.params);\n break;\n\n // CSI Pm l Reset Mode (RM).\n // CSI ? Pm l\n case 'l':\n this.resetMode(this.params);\n break;\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 case 'r':\n this.setScrollRegion(this.params);\n break;\n\n // CSI s\n // Save cursor (ANSI.SYS).\n case 's':\n this.saveCursor(this.params);\n break;\n\n // CSI u\n // Restore cursor (ANSI.SYS).\n case 'u':\n this.restoreCursor(this.params);\n break;\n\n /**\n * Lesser Used\n */\n\n // CSI Ps I\n // Cursor Forward Tabulation Ps tab stops (default = 1) (CHT).\n case 'I':\n this.cursorForwardTab(this.params);\n break;\n\n // CSI Ps S Scroll up Ps lines (default = 1) (SU).\n case 'S':\n this.scrollUp(this.params);\n break;\n\n // CSI Ps T Scroll down Ps lines (default = 1) (SD).\n // CSI Ps ; Ps ; Ps ; Ps ; Ps T\n // CSI > Ps; Ps T\n case 'T':\n // if (this.prefix === '>') {\n // this.resetTitleModes(this.params);\n // break;\n // }\n // if (this.params.length > 2) {\n // this.initMouseTracking(this.params);\n // break;\n // }\n if (this.params.length < 2 && !this.prefix) {\n this.scrollDown(this.params);\n }\n break;\n\n // CSI Ps Z\n // Cursor Backward Tabulation Ps tab stops (default = 1) (CBT).\n case 'Z':\n this.cursorBackwardTab(this.params);\n break;\n\n // CSI Ps b Repeat the preceding graphic character Ps times (REP).\n case 'b':\n this.repeatPrecedingCharacter(this.params);\n break;\n\n // CSI Ps g Tab Clear (TBC).\n case 'g':\n this.tabClear(this.params);\n break;\n\n // CSI Pm i Media Copy (MC).\n // CSI ? Pm i\n // case 'i':\n // this.mediaCopy(this.params);\n // break;\n\n // CSI Pm m Character Attributes (SGR).\n // CSI > Ps; Ps m\n // case 'm': // duplicate\n // if (this.prefix === '>') {\n // this.setResources(this.params);\n // } else {\n // this.charAttributes(this.params);\n // }\n // break;\n\n // CSI Ps n Device Status Report (DSR).\n // CSI > Ps n\n // case 'n': // duplicate\n // if (this.prefix === '>') {\n // this.disableModifiers(this.params);\n // } else {\n // this.deviceStatus(this.params);\n // }\n // break;\n\n // CSI > Ps p Set pointer mode.\n // CSI ! p Soft terminal reset (DECSTR).\n // CSI Ps$ p\n // Request ANSI mode (DECRQM).\n // CSI ? Ps$ p\n // Request DEC private mode (DECRQM).\n // CSI Ps ; Ps \" p\n case 'p':\n switch (this.prefix) {\n // case '>':\n // this.setPointerMode(this.params);\n // break;\n case '!':\n this.softReset(this.params);\n break;\n // case '?':\n // if (this.postfix === '$') {\n // this.requestPrivateMode(this.params);\n // }\n // break;\n // default:\n // if (this.postfix === '\"') {\n // this.setConformanceLevel(this.params);\n // } else if (this.postfix === '$') {\n // this.requestAnsiMode(this.params);\n // }\n // break;\n }\n break;\n\n // CSI Ps q Load LEDs (DECLL).\n // CSI Ps SP q\n // CSI Ps \" q\n // case 'q':\n // if (this.postfix === ' ') {\n // this.setCursorStyle(this.params);\n // break;\n // }\n // if (this.postfix === '\"') {\n // this.setCharProtectionAttr(this.params);\n // break;\n // }\n // this.loadLEDs(this.params);\n // break;\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 // CSI Pt; Pl; Pb; Pr; Ps$ r\n // case 'r': // duplicate\n // if (this.prefix === '?') {\n // this.restorePrivateValues(this.params);\n // } else if (this.postfix === '$') {\n // this.setAttrInRectangle(this.params);\n // } else {\n // this.setScrollRegion(this.params);\n // }\n // break;\n\n // CSI s Save cursor (ANSI.SYS).\n // CSI ? Pm s\n // case 's': // duplicate\n // if (this.prefix === '?') {\n // this.savePrivateValues(this.params);\n // } else {\n // this.saveCursor(this.params);\n // }\n // break;\n\n // CSI Ps ; Ps ; Ps t\n // CSI Pt; Pl; Pb; Pr; Ps$ t\n // CSI > Ps; Ps t\n // CSI Ps SP t\n // case 't':\n // if (this.postfix === '$') {\n // this.reverseAttrInRectangle(this.params);\n // } else if (this.postfix === ' ') {\n // this.setWarningBellVolume(this.params);\n // } else {\n // if (this.prefix === '>') {\n // this.setTitleModeFeature(this.params);\n // } else {\n // this.manipulateWindow(this.params);\n // }\n // }\n // break;\n\n // CSI u Restore cursor (ANSI.SYS).\n // CSI Ps SP u\n // case 'u': // duplicate\n // if (this.postfix === ' ') {\n // this.setMarginBellVolume(this.params);\n // } else {\n // this.restoreCursor(this.params);\n // }\n // break;\n\n // CSI Pt; Pl; Pb; Pr; Pp; Pt; Pl; Pp$ v\n // case 'v':\n // if (this.postfix === '$') {\n // this.copyRectagle(this.params);\n // }\n // break;\n\n // CSI Pt ; Pl ; Pb ; Pr ' w\n // case 'w':\n // if (this.postfix === '\\'') {\n // this.enableFilterRectangle(this.params);\n // }\n // break;\n\n // CSI Ps x Request Terminal Parameters (DECREQTPARM).\n // CSI Ps x Select Attribute Change Extent (DECSACE).\n // CSI Pc; Pt; Pl; Pb; Pr$ x\n // case 'x':\n // if (this.postfix === '$') {\n // this.fillRectangle(this.params);\n // } else {\n // this.requestParameters(this.params);\n // //this.__(this.params);\n // }\n // break;\n\n // CSI Ps ; Pu ' z\n // CSI Pt; Pl; Pb; Pr$ z\n // case 'z':\n // if (this.postfix === '\\'') {\n // this.enableLocatorReporting(this.params);\n // } else if (this.postfix === '$') {\n // this.eraseRectangle(this.params);\n // }\n // break;\n\n // CSI Pm ' {\n // CSI Pt; Pl; Pb; Pr$ {\n // case '{':\n // if (this.postfix === '\\'') {\n // this.setLocatorEvents(this.params);\n // } else if (this.postfix === '$') {\n // this.selectiveEraseRectangle(this.params);\n // }\n // break;\n\n // CSI Ps ' |\n // case '|':\n // if (this.postfix === '\\'') {\n // this.requestLocatorPosition(this.params);\n // }\n // break;\n\n // CSI P m SP }\n // Insert P s Column(s) (default = 1) (DECIC), VT420 and up.\n // case '}':\n // if (this.postfix === ' ') {\n // this.insertColumns(this.params);\n // }\n // break;\n\n // CSI P m SP ~\n // Delete P s Column(s) (default = 1) (DECDC), VT420 and up\n // case '~':\n // if (this.postfix === ' ') {\n // this.deleteColumns(this.params);\n // }\n // break;\n\n default:\n this.error('Unknown CSI code: %s.', ch);\n break;\n }\n\n this.prefix = '';\n this.postfix = '';\n break;\n\n case dcs:\n if (ch === '\\x1b' || ch === '\\x07') {\n if (ch === '\\x1b') i++;\n\n switch (this.prefix) {\n // User-Defined Keys (DECUDK).\n case '':\n break;\n\n // Request Status String (DECRQSS).\n // test: echo -e '\\eP$q\"p\\e\\\\'\n case '$q':\n var pt = this.currentParam\n , valid = false;\n\n switch (pt) {\n // DECSCA\n case '\"q':\n pt = '0\"q';\n break;\n\n // DECSCL\n case '\"p':\n pt = '61\"p';\n break;\n\n // DECSTBM\n case 'r':\n pt = ''\n + (this.scrollTop + 1)\n + ';'\n + (this.scrollBottom + 1)\n + 'r';\n break;\n\n // SGR\n case 'm':\n pt = '0m';\n break;\n\n default:\n this.error('Unknown DCS Pt: %s.', pt);\n pt = '';\n break;\n }\n\n this.send('\\x1bP' + +valid + '$r' + pt + '\\x1b\\\\');\n break;\n\n // Set Termcap/Terminfo Data (xterm, experimental).\n case '+p':\n break;\n\n // Request Termcap/Terminfo String (xterm, experimental)\n // Regular xterm does not even respond to this sequence.\n // This can cause a small glitch in vim.\n // test: echo -ne '\\eP+q6b64\\e\\\\'\n case '+q':\n var pt = this.currentParam\n , valid = false;\n\n this.send('\\x1bP' + +valid + '+r' + pt + '\\x1b\\\\');\n break;\n\n default:\n this.error('Unknown DCS prefix: %s.', this.prefix);\n break;\n }\n\n this.currentParam = 0;\n this.prefix = '';\n this.state = normal;\n } else if (!this.currentParam) {\n if (!this.prefix && ch !== '$' && ch !== '+') {\n this.currentParam = ch;\n } else if (this.prefix.length === 2) {\n this.currentParam = ch;\n } else {\n this.prefix += ch;\n }\n } else {\n this.currentParam += ch;\n }\n break;\n\n case ignore:\n // For PM and APC.\n if (ch === '\\x1b' || ch === '\\x07') {\n if (ch === '\\x1b') i++;\n this.state = normal;\n }\n break;\n }\n }\n\n this.updateRange(this.y);\n this.refresh(this.refreshStart, this.refreshEnd);\n};\n\n/**\n * Writes text to the terminal, followed by a break line character (\\n).\n * @param {string} text The text to write to the terminal.\n */\nTerminal.prototype.writeln = function(data) {\n this.write(data + '\\r\\n');\n};\n\n/**\n * Attaches a custom keydown handler which is run before keys are processed, giving consumers of\n * xterm.js ultimate control as to what keys should be processed by the terminal and what keys\n * should not.\n * @param {function} customKeydownHandler The custom KeyboardEvent handler to attach. This is a\n * function that takes a KeyboardEvent, allowing consumers to stop propogation and/or prevent\n * the default action. The function returns whether the event should be processed by xterm.js.\n */\nTerminal.prototype.attachCustomKeydownHandler = function(customKeydownHandler) {\n this.customKeydownHandler = customKeydownHandler;\n}\n\n/**\n * Handle a keydown event\n * Key Resources:\n * - https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent\n * @param {KeyboardEvent} ev The keydown event to be handled.\n */\nTerminal.prototype.keyDown = function(ev) {\n if (this.customKeydownHandler && this.customKeydownHandler(ev) === false) {\n return false;\n }\n\n if (!this.compositionHelper.keydown.bind(this.compositionHelper)(ev)) {\n if (this.ybase !== this.ydisp) {\n this.scrollToBottom();\n }\n return false;\n }\n\n var self = this;\n var result = this.evaluateKeyEscapeSequence(ev);\n\n if (result.scrollDisp) {\n this.scrollDisp(result.scrollDisp);\n return this.cancel(ev, true);\n }\n\n if (isThirdLevelShift(this, ev)) {\n return true;\n }\n\n if (result.cancel) {\n // The event is canceled at the end already, is this necessary?\n this.cancel(ev, true);\n }\n\n if (!result.key) {\n return true;\n }\n\n this.emit('keydown', ev);\n this.emit('key', result.key, ev);\n this.showCursor();\n this.handler(result.key);\n\n return this.cancel(ev, true);\n};\n\n/**\n * Returns an object that determines how a KeyboardEvent should be handled. The key of the\n * returned value is the new key code to pass to the PTY.\n *\n * Reference: http://invisible-island.net/xterm/ctlseqs/ctlseqs.html\n * @param {KeyboardEvent} ev The keyboard event to be translated to key escape sequence.\n */\nTerminal.prototype.evaluateKeyEscapeSequence = function(ev) {\n var result = {\n // Whether to cancel event propogation (NOTE: this may not be needed since the event is\n // canceled at the end of keyDown\n cancel: false,\n // The new key even to emit\n key: undefined,\n // The number of characters to scroll, if this is defined it will cancel the event\n scrollDisp: undefined\n };\n var modifiers = ev.shiftKey << 0 | ev.altKey << 1 | ev.ctrlKey << 2 | ev.metaKey << 3;\n switch (ev.keyCode) {\n case 8:\n // backspace\n if (ev.shiftKey) {\n result.key = '\\x08'; // ^H\n break;\n }\n result.key = '\\x7f'; // ^?\n break;\n case 9:\n // tab\n if (ev.shiftKey) {\n result.key = '\\x1b[Z';\n break;\n }\n result.key = '\\t';\n result.cancel = true;\n break;\n case 13:\n // return/enter\n result.key = '\\r';\n result.cancel = true;\n break;\n case 27:\n // escape\n result.key = '\\x1b';\n result.cancel = true;\n break;\n case 37:\n // left-arrow\n if (modifiers) {\n result.key = '\\x1b[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 if (result.key == '\\x1b[1;3D') {\n result.key = '\\x1b[1;5D';\n }\n } else if (this.applicationCursor) {\n result.key = '\\x1bOD';\n } else {\n result.key = '\\x1b[D';\n }\n break;\n case 39:\n // right-arrow\n if (modifiers) {\n result.key = '\\x1b[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 if (result.key == '\\x1b[1;3C') {\n result.key = '\\x1b[1;5C';\n }\n } else if (this.applicationCursor) {\n result.key = '\\x1bOC';\n } else {\n result.key = '\\x1b[C';\n }\n break;\n case 38:\n // up-arrow\n if (modifiers) {\n result.key = '\\x1b[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 == '\\x1b[1;3A') {\n result.key = '\\x1b[1;5A';\n }\n } else if (this.applicationCursor) {\n result.key = '\\x1bOA';\n } else {\n result.key = '\\x1b[A';\n }\n break;\n case 40:\n // down-arrow\n if (modifiers) {\n result.key = '\\x1b[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 == '\\x1b[1;3B') {\n result.key = '\\x1b[1;5B';\n }\n } else if (this.applicationCursor) {\n result.key = '\\x1bOB';\n } else {\n result.key = '\\x1b[B';\n }\n break;\n case 45:\n // insert\n if (!ev.shiftKey && !ev.ctrlKey) {\n // or + are used to\n // copy-paste on some systems.\n result.key = '\\x1b[2~';\n }\n break;\n case 46:\n // delete\n if (modifiers) {\n result.key = '\\x1b[3;' + (modifiers + 1) + '~';\n } else {\n result.key = '\\x1b[3~';\n }\n break;\n case 36:\n // home\n if (modifiers)\n result.key = '\\x1b[1;' + (modifiers + 1) + 'H';\n else if (this.applicationCursor)\n result.key = '\\x1bOH';\n else\n result.key = '\\x1b[H';\n break;\n case 35:\n // end\n if (modifiers)\n result.key = '\\x1b[1;' + (modifiers + 1) + 'F';\n else if (this.applicationCursor)\n result.key = '\\x1bOF';\n else\n result.key = '\\x1b[F';\n break;\n case 33:\n // page up\n if (ev.shiftKey) {\n result.scrollDisp = -(this.rows - 1);\n } else {\n result.key = '\\x1b[5~';\n }\n break;\n case 34:\n // page down\n if (ev.shiftKey) {\n result.scrollDisp = this.rows - 1;\n } else {\n result.key = '\\x1b[6~';\n }\n break;\n case 112:\n // F1-F12\n if (modifiers) {\n result.key = '\\x1b[1;' + (modifiers + 1) + 'P';\n } else {\n result.key = '\\x1bOP';\n }\n break;\n case 113:\n if (modifiers) {\n result.key = '\\x1b[1;' + (modifiers + 1) + 'Q';\n } else {\n result.key = '\\x1bOQ';\n }\n break;\n case 114:\n if (modifiers) {\n result.key = '\\x1b[1;' + (modifiers + 1) + 'R';\n } else {\n result.key = '\\x1bOR';\n }\n break;\n case 115:\n if (modifiers) {\n result.key = '\\x1b[1;' + (modifiers + 1) + 'S';\n } else {\n result.key = '\\x1bOS';\n }\n break;\n case 116:\n if (modifiers) {\n result.key = '\\x1b[15;' + (modifiers + 1) + '~';\n } else {\n result.key = '\\x1b[15~';\n }\n break;\n case 117:\n if (modifiers) {\n result.key = '\\x1b[17;' + (modifiers + 1) + '~';\n } else {\n result.key = '\\x1b[17~';\n }\n break;\n case 118:\n if (modifiers) {\n result.key = '\\x1b[18;' + (modifiers + 1) + '~';\n } else {\n result.key = '\\x1b[18~';\n }\n break;\n case 119:\n if (modifiers) {\n result.key = '\\x1b[19;' + (modifiers + 1) + '~';\n } else {\n result.key = '\\x1b[19~';\n }\n break;\n case 120:\n if (modifiers) {\n result.key = '\\x1b[20;' + (modifiers + 1) + '~';\n } else {\n result.key = '\\x1b[20~';\n }\n break;\n case 121:\n if (modifiers) {\n result.key = '\\x1b[21;' + (modifiers + 1) + '~';\n } else {\n result.key = '\\x1b[21~';\n }\n break;\n case 122:\n if (modifiers) {\n result.key = '\\x1b[23;' + (modifiers + 1) + '~';\n } else {\n result.key = '\\x1b[23~';\n }\n break;\n case 123:\n if (modifiers) {\n result.key = '\\x1b[24;' + (modifiers + 1) + '~';\n } else {\n result.key = '\\x1b[24~';\n }\n break;\n default:\n // a-z and space\n if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) {\n if (ev.keyCode >= 65 && ev.keyCode <= 90) {\n result.key = String.fromCharCode(ev.keyCode - 64);\n } else if (ev.keyCode === 32) {\n // NUL\n result.key = String.fromCharCode(0);\n } else if (ev.keyCode >= 51 && ev.keyCode <= 55) {\n // escape, file sep, group sep, record sep, unit sep\n result.key = String.fromCharCode(ev.keyCode - 51 + 27);\n } else if (ev.keyCode === 56) {\n // delete\n result.key = String.fromCharCode(127);\n } else if (ev.keyCode === 219) {\n // ^[ - Control Sequence Introducer (CSI)\n result.key = String.fromCharCode(27);\n } else if (ev.keyCode === 220) {\n // ^\\ - String Terminator (ST)\n result.key = String.fromCharCode(28);\n } else if (ev.keyCode === 221) {\n // ^] - Operating System Command (OSC)\n result.key = String.fromCharCode(29);\n }\n } else if (!this.browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) {\n // On Mac this is a third level shift. Use instead.\n if (ev.keyCode >= 65 && ev.keyCode <= 90) {\n result.key = '\\x1b' + String.fromCharCode(ev.keyCode + 32);\n } else if (ev.keyCode === 192) {\n result.key = '\\x1b`';\n } else if (ev.keyCode >= 48 && ev.keyCode <= 57) {\n result.key = '\\x1b' + (ev.keyCode - 48);\n }\n }\n break;\n }\n return result;\n};\n\n/**\n * Set the G level of the terminal\n * @param g\n */\nTerminal.prototype.setgLevel = function(g) {\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 */\nTerminal.prototype.setgCharset = function(g, charset) {\n this.charsets[g] = charset;\n if (this.glevel === g) {\n this.charset = charset;\n }\n};\n\n/**\n * Handle a keypress event.\n * Key Resources:\n * - https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent\n * @param {KeyboardEvent} ev The keypress event to be handled.\n */\nTerminal.prototype.keyPress = function(ev) {\n var key;\n\n this.cancel(ev);\n\n if (ev.charCode) {\n key = ev.charCode;\n } else if (ev.which == null) {\n key = ev.keyCode;\n } else if (ev.which !== 0 && ev.charCode !== 0) {\n key = ev.which;\n } else {\n return false;\n }\n\n if (!key || (\n (ev.altKey || ev.ctrlKey || ev.metaKey) && !isThirdLevelShift(this, 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 false;\n};\n\n/**\n * Send data for handling to the terminal\n * @param {string} data\n */\nTerminal.prototype.send = function(data) {\n var self = this;\n\n if (!this.queue) {\n setTimeout(function() {\n self.handler(self.queue);\n self.queue = '';\n }, 1);\n }\n\n this.queue += data;\n};\n\n/**\n * Ring the bell.\n * Note: We could do sweet things with webaudio here\n */\nTerminal.prototype.bell = function() {\n if (!this.visualBell) return;\n var self = this;\n this.element.style.borderColor = 'white';\n setTimeout(function() {\n self.element.style.borderColor = '';\n }, 10);\n if (this.popOnBell) this.focus();\n};\n\n/**\n * Log the current state to the console.\n */\nTerminal.prototype.log = function() {\n if (!this.debug) return;\n if (!this.context.console || !this.context.console.log) return;\n var args = Array.prototype.slice.call(arguments);\n this.context.console.log.apply(this.context.console, args);\n};\n\n/**\n * Log the current state as error to the console.\n */\nTerminal.prototype.error = function() {\n if (!this.debug) return;\n if (!this.context.console || !this.context.console.error) return;\n var args = Array.prototype.slice.call(arguments);\n this.context.console.error.apply(this.context.console, args);\n};\n\n/**\n * Resizes the terminal.\n *\n * @param {number} x The number of columns to resize to.\n * @param {number} y The number of rows to resize to.\n */\nTerminal.prototype.resize = function(x, y) {\n var line\n , el\n , i\n , j\n , ch\n , addToY;\n\n if (x === this.cols && y === this.rows) {\n return;\n }\n\n if (x < 1) x = 1;\n if (y < 1) y = 1;\n\n // resize cols\n j = this.cols;\n if (j < x) {\n ch = [this.defAttr, ' ', 1]; // does xterm use the default attr?\n i = this.lines.length;\n while (i--) {\n while (this.lines[i].length < x) {\n this.lines[i].push(ch);\n }\n }\n } else { // (j > x)\n i = this.lines.length;\n while (i--) {\n while (this.lines[i].length > x) {\n this.lines[i].pop();\n }\n }\n }\n this.setupStops(j);\n this.cols = x;\n\n // resize rows\n j = this.rows;\n addToY = 0;\n if (j < y) {\n el = this.element;\n while (j++ < y) {\n // y is rows, not this.y\n if (this.lines.length < y + 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.blankLine());\n }\n }\n if (this.children.length < y) {\n this.insertRow();\n }\n }\n } else { // (j > y)\n while (j-- > y) {\n if (this.lines.length > y + 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 if (this.children.length > y) {\n el = this.children.shift();\n if (!el) continue;\n el.parentNode.removeChild(el);\n }\n }\n }\n this.rows = y;\n\n // Make sure that the cursor stays on screen\n if (this.y >= y) {\n this.y = y - 1;\n }\n if (addToY) {\n this.y += addToY;\n }\n\n if (this.x >= x) {\n this.x = x - 1;\n }\n\n this.scrollTop = 0;\n this.scrollBottom = y - 1;\n\n this.refresh(0, this.rows - 1);\n\n this.normal = null;\n\n this.geometry = [this.cols, this.rows];\n this.emit('resize', {terminal: this, cols: x, rows: y});\n};\n\n/**\n * Updates the range of rows to refresh\n * @param {number} y The number of rows to refresh next.\n */\nTerminal.prototype.updateRange = function(y) {\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 */\nTerminal.prototype.maxRange = function() {\n this.refreshStart = 0;\n this.refreshEnd = this.rows - 1;\n};\n\n\n\n/**\n * Setup the tab stops.\n * @param {number} i\n */\nTerminal.prototype.setupStops = function(i) {\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.cols; i += 8) {\n this.tabs[i] = true;\n }\n};\n\n\n/**\n * Move the cursor to the previous tab stop from the given position (default is current).\n * @param {number} x The position to move the cursor to the previous tab stop.\n */\nTerminal.prototype.prevStop = function(x) {\n if (x == null) x = this.x;\n while (!this.tabs[--x] && x > 0);\n return x >= this.cols\n ? this.cols - 1\n : x < 0 ? 0 : x;\n};\n\n\n/**\n * Move the cursor one tab stop forward from the given position (default is current).\n * @param {number} x The position to move the cursor one tab stop forward.\n */\nTerminal.prototype.nextStop = function(x) {\n if (x == null) x = this.x;\n while (!this.tabs[++x] && x < this.cols);\n return x >= this.cols\n ? this.cols - 1\n : x < 0 ? 0 : x;\n};\n\n\n/**\n * Erase in the identified line everything from \"x\" to the end of the line (right).\n * @param {number} x The column from which to start erasing to the end of the line.\n * @param {number} y The line in which to operate.\n */\nTerminal.prototype.eraseRight = function(x, y) {\n var line = this.lines[this.ybase + y]\n , ch = [this.eraseAttr(), ' ', 1]; // xterm\n\n\n for (; x < this.cols; x++) {\n line[x] = ch;\n }\n\n this.updateRange(y);\n};\n\n\n\n/**\n * Erase in the identified line everything from \"x\" to the start of the line (left).\n * @param {number} x The column from which to start erasing to the start of the line.\n * @param {number} y The line in which to operate.\n */\nTerminal.prototype.eraseLeft = function(x, y) {\n var line = this.lines[this.ybase + y]\n , ch = [this.eraseAttr(), ' ', 1]; // xterm\n\n x++;\n while (x--) line[x] = ch;\n\n this.updateRange(y);\n};\n\n/**\n * Clears the entire buffer, making the prompt line the new first line.\n */\nTerminal.prototype.clear = function() {\n if (this.ybase === 0 && this.y === 0) {\n // Don't clear if it's already clear\n return;\n }\n this.lines = [this.lines[this.ybase + this.y]];\n this.ydisp = 0;\n this.ybase = 0;\n this.y = 0;\n for (var i = 1; i < this.rows; i++) {\n this.lines.push(this.blankLine());\n }\n this.refresh(0, this.rows - 1);\n this.emit('scroll', this.ydisp);\n};\n\n/**\n * Erase all content in the given line\n * @param {number} y The line to erase all of its contents.\n */\nTerminal.prototype.eraseLine = function(y) {\n this.eraseRight(0, y);\n};\n\n\n/**\n * Return the data array of a blank line/\n * @param {number} cur First bunch of data for each \"blank\" character.\n */\nTerminal.prototype.blankLine = function(cur) {\n var attr = cur\n ? this.eraseAttr()\n : this.defAttr;\n\n var ch = [attr, ' ', 1] // width defaults to 1 halfwidth character\n , line = []\n , i = 0;\n\n for (; i < this.cols; i++) {\n line[i] = ch;\n }\n\n return line;\n};\n\n\n/**\n * If cur return the back color xterm feature attribute. Else return defAttr.\n * @param {object} cur\n */\nTerminal.prototype.ch = function(cur) {\n return cur\n ? [this.eraseAttr(), ' ', 1]\n : [this.defAttr, ' ', 1];\n};\n\n\n/**\n * Evaluate if the current erminal is the given argument.\n * @param {object} term The terminal to evaluate\n */\nTerminal.prototype.is = function(term) {\n var name = this.termName;\n return (name + '').indexOf(term) === 0;\n};\n\n\n/**\n * Emit the 'data' event and populate the given data.\n * @param {string} data The data to populate in the event.\n */\nTerminal.prototype.handler = function(data) {\n // Input is being sent to the terminal, the terminal should focus the prompt.\n if (this.ybase !== this.ydisp) {\n this.scrollToBottom();\n }\n this.emit('data', data);\n};\n\n\n/**\n * Emit the 'title' event and populate the given title.\n * @param {string} title The title to populate in the event.\n */\nTerminal.prototype.handleTitle = function(title) {\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/**\n * ESC\n */\n\n/**\n * ESC D Index (IND is 0x84).\n */\nTerminal.prototype.index = function() {\n this.y++;\n if (this.y > this.scrollBottom) {\n this.y--;\n this.scroll();\n }\n this.state = normal;\n};\n\n\n/**\n * ESC M Reverse Index (RI is 0x8d).\n */\nTerminal.prototype.reverseIndex = function() {\n var j;\n this.y--;\n if (this.y < this.scrollTop) {\n this.y++;\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 this.lines.splice(this.y + this.ybase, 0, this.blankLine(true));\n j = this.rows - 1 - this.scrollBottom;\n this.lines.splice(this.rows - 1 + this.ybase - j + 1, 1);\n // this.maxRange();\n this.updateRange(this.scrollTop);\n this.updateRange(this.scrollBottom);\n }\n this.state = normal;\n};\n\n\n/**\n * ESC c Full Reset (RIS).\n */\nTerminal.prototype.reset = function() {\n this.options.rows = this.rows;\n this.options.cols = this.cols;\n var customKeydownHandler = this.customKeydownHandler;\n Terminal.call(this, this.options);\n this.customKeydownHandler = customKeydownHandler;\n this.refresh(0, this.rows - 1);\n this.viewport.syncScrollArea();\n};\n\n\n/**\n * ESC H Tab Set (HTS is 0x88).\n */\nTerminal.prototype.tabSet = function() {\n this.tabs[this.x] = true;\n this.state = normal;\n};\n\n\n/**\n * CSI\n */\n\n/**\n * CSI Ps A\n * Cursor Up Ps Times (default = 1) (CUU).\n */\nTerminal.prototype.cursorUp = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.y -= param;\n if (this.y < 0) this.y = 0;\n};\n\n\n/**\n * CSI Ps B\n * Cursor Down Ps Times (default = 1) (CUD).\n */\nTerminal.prototype.cursorDown = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.y += param;\n if (this.y >= this.rows) {\n this.y = this.rows - 1;\n }\n};\n\n\n/**\n * CSI Ps C\n * Cursor Forward Ps Times (default = 1) (CUF).\n */\nTerminal.prototype.cursorForward = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.x += param;\n if (this.x >= this.cols) {\n this.x = this.cols - 1;\n }\n};\n\n\n/**\n * CSI Ps D\n * Cursor Backward Ps Times (default = 1) (CUB).\n */\nTerminal.prototype.cursorBackward = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.x -= param;\n if (this.x < 0) this.x = 0;\n};\n\n\n/**\n * CSI Ps ; Ps H\n * Cursor Position [row;column] (default = [1,1]) (CUP).\n */\nTerminal.prototype.cursorPos = function(params) {\n var row, col;\n\n row = 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.rows) {\n row = this.rows - 1;\n }\n\n if (col < 0) {\n col = 0;\n } else if (col >= this.cols) {\n col = this.cols - 1;\n }\n\n this.x = col;\n this.y = row;\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 */\nTerminal.prototype.eraseInDisplay = function(params) {\n var j;\n switch (params[0]) {\n case 0:\n this.eraseRight(this.x, this.y);\n j = this.y + 1;\n for (; j < this.rows; j++) {\n this.eraseLine(j);\n }\n break;\n case 1:\n this.eraseLeft(this.x, this.y);\n j = this.y;\n while (j--) {\n this.eraseLine(j);\n }\n break;\n case 2:\n j = this.rows;\n while (j--) this.eraseLine(j);\n break;\n case 3:\n ; // no saved lines\n break;\n }\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 */\nTerminal.prototype.eraseInLine = function(params) {\n switch (params[0]) {\n case 0:\n this.eraseRight(this.x, this.y);\n break;\n case 1:\n this.eraseLeft(this.x, this.y);\n break;\n case 2:\n this.eraseLine(this.y);\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 = 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 */\nTerminal.prototype.charAttributes = function(params) {\n // Optimize a single SGR0.\n if (params.length === 1 && params[0] === 0) {\n this.curAttr = this.defAttr;\n return;\n }\n\n var l = params.length\n , i = 0\n , flags = this.curAttr >> 18\n , fg = (this.curAttr >> 9) & 0x1ff\n , bg = this.curAttr & 0x1ff\n , p;\n\n for (; i < l; i++) {\n p = params[i];\n if (p >= 30 && p <= 37) {\n // fg color 8\n fg = p - 30;\n } else if (p >= 40 && p <= 47) {\n // bg color 8\n bg = p - 40;\n } else if (p >= 90 && p <= 97) {\n // fg color 16\n p += 8;\n fg = p - 90;\n } else if (p >= 100 && p <= 107) {\n // bg color 16\n p += 8;\n bg = p - 100;\n } else if (p === 0) {\n // default\n flags = this.defAttr >> 18;\n fg = (this.defAttr >> 9) & 0x1ff;\n bg = this.defAttr & 0x1ff;\n // flags = 0;\n // fg = 0x1ff;\n // bg = 0x1ff;\n } else if (p === 1) {\n // bold text\n flags |= 1;\n } else if (p === 4) {\n // underlined text\n flags |= 2;\n } else if (p === 5) {\n // blink\n flags |= 4;\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 |= 8;\n } else if (p === 8) {\n // invisible\n flags |= 16;\n } else if (p === 22) {\n // not bold\n flags &= ~1;\n } else if (p === 24) {\n // not underlined\n flags &= ~2;\n } else if (p === 25) {\n // not blink\n flags &= ~4;\n } else if (p === 27) {\n // not inverse\n flags &= ~8;\n } else if (p === 28) {\n // not invisible\n flags &= ~16;\n } else if (p === 39) {\n // reset fg\n fg = (this.defAttr >> 9) & 0x1ff;\n } else if (p === 49) {\n // reset bg\n bg = this.defAttr & 0x1ff;\n } else if (p === 38) {\n // fg color 256\n if (params[i + 1] === 2) {\n i += 2;\n fg = 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 = matchColor(\n params[i] & 0xff,\n params[i + 1] & 0xff,\n params[i + 2] & 0xff);\n if (bg === -1) bg = 0x1ff;\n i += 2;\n } else if (params[i + 1] === 5) {\n i += 2;\n p = params[i] & 0xff;\n bg = p;\n }\n } else if (p === 100) {\n // reset fg/bg\n fg = (this.defAttr >> 9) & 0x1ff;\n bg = this.defAttr & 0x1ff;\n } else {\n this.error('Unknown SGR attribute: %d.', p);\n }\n }\n\n this.curAttr = (flags << 18) | (fg << 9) | bg;\n};\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 */\nTerminal.prototype.deviceStatus = function(params) {\n if (!this.prefix) {\n switch (params[0]) {\n case 5:\n // status report\n this.send('\\x1b[0n');\n break;\n case 6:\n // cursor position\n this.send('\\x1b['\n + (this.y + 1)\n + ';'\n + (this.x + 1)\n + 'R');\n break;\n }\n } else if (this.prefix === '?') {\n // modern xterm doesnt seem to\n // respond to any of these except ?6, 6, and 5\n switch (params[0]) {\n case 6:\n // cursor position\n this.send('\\x1b[?'\n + (this.y + 1)\n + ';'\n + (this.x + 1)\n + 'R');\n break;\n case 15:\n // no printer\n // this.send('\\x1b[?11n');\n break;\n case 25:\n // dont support user defined keys\n // this.send('\\x1b[?21n');\n break;\n case 26:\n // north american keyboard\n // this.send('\\x1b[?27;1;0;0n');\n break;\n case 53:\n // no dec locator/mouse\n // this.send('\\x1b[?50n');\n break;\n }\n }\n};\n\n\n/**\n * Additions\n */\n\n/**\n * CSI Ps @\n * Insert Ps (Blank) Character(s) (default = 1) (ICH).\n */\nTerminal.prototype.insertChars = function(params) {\n var param, row, j, ch;\n\n param = params[0];\n if (param < 1) param = 1;\n\n row = this.y + this.ybase;\n j = this.x;\n ch = [this.eraseAttr(), ' ', 1]; // xterm\n\n while (param-- && j < this.cols) {\n this.lines[row].splice(j++, 0, ch);\n this.lines[row].pop();\n }\n};\n\n/**\n * CSI Ps E\n * Cursor Next Line Ps Times (default = 1) (CNL).\n * same as CSI Ps B ?\n */\nTerminal.prototype.cursorNextLine = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.y += param;\n if (this.y >= this.rows) {\n this.y = this.rows - 1;\n }\n this.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 */\nTerminal.prototype.cursorPrecedingLine = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.y -= param;\n if (this.y < 0) this.y = 0;\n this.x = 0;\n};\n\n\n/**\n * CSI Ps G\n * Cursor Character Absolute [column] (default = [row,1]) (CHA).\n */\nTerminal.prototype.cursorCharAbsolute = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.x = param - 1;\n};\n\n\n/**\n * CSI Ps L\n * Insert Ps Line(s) (default = 1) (IL).\n */\nTerminal.prototype.insertLines = function(params) {\n var param, row, j;\n\n param = params[0];\n if (param < 1) param = 1;\n row = this.y + this.ybase;\n\n j = this.rows - 1 - this.scrollBottom;\n j = this.rows - 1 + this.ybase - j + 1;\n\n while (param--) {\n // test: echo -e '\\e[44m\\e[1L\\e[0m'\n // blankLine(true) - xterm/linux behavior\n this.lines.splice(row, 0, this.blankLine(true));\n this.lines.splice(j, 1);\n }\n\n // this.maxRange();\n this.updateRange(this.y);\n this.updateRange(this.scrollBottom);\n};\n\n\n/**\n * CSI Ps M\n * Delete Ps Line(s) (default = 1) (DL).\n */\nTerminal.prototype.deleteLines = function(params) {\n var param, row, j;\n\n param = params[0];\n if (param < 1) param = 1;\n row = this.y + this.ybase;\n\n j = this.rows - 1 - this.scrollBottom;\n j = this.rows - 1 + this.ybase - j;\n\n while (param--) {\n // test: echo -e '\\e[44m\\e[1M\\e[0m'\n // blankLine(true) - xterm/linux behavior\n this.lines.splice(j + 1, 0, this.blankLine(true));\n this.lines.splice(row, 1);\n }\n\n // this.maxRange();\n this.updateRange(this.y);\n this.updateRange(this.scrollBottom);\n};\n\n\n/**\n * CSI Ps P\n * Delete Ps Character(s) (default = 1) (DCH).\n */\nTerminal.prototype.deleteChars = function(params) {\n var param, row, ch;\n\n param = params[0];\n if (param < 1) param = 1;\n\n row = this.y + this.ybase;\n ch = [this.eraseAttr(), ' ', 1]; // xterm\n\n while (param--) {\n this.lines[row].splice(this.x, 1);\n this.lines[row].push(ch);\n }\n};\n\n/**\n * CSI Ps X\n * Erase Ps Character(s) (default = 1) (ECH).\n */\nTerminal.prototype.eraseChars = function(params) {\n var param, row, j, ch;\n\n param = params[0];\n if (param < 1) param = 1;\n\n row = this.y + this.ybase;\n j = this.x;\n ch = [this.eraseAttr(), ' ', 1]; // xterm\n\n while (param-- && j < this.cols) {\n this.lines[row][j++] = ch;\n }\n};\n\n/**\n * CSI Pm ` Character Position Absolute\n * [column] (default = [row,1]) (HPA).\n */\nTerminal.prototype.charPosAbsolute = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.x = param - 1;\n if (this.x >= this.cols) {\n this.x = this.cols - 1;\n }\n};\n\n\n/**\n * 141 61 a * HPR -\n * Horizontal Position Relative\n * reuse CSI Ps C ?\n */\nTerminal.prototype.HPositionRelative = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.x += param;\n if (this.x >= this.cols) {\n this.x = this.cols - 1;\n }\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 */\nTerminal.prototype.sendDeviceAttributes = function(params) {\n if (params[0] > 0) return;\n\n if (!this.prefix) {\n if (this.is('xterm')\n || this.is('rxvt-unicode')\n || this.is('screen')) {\n this.send('\\x1b[?1;2c');\n } else if (this.is('linux')) {\n this.send('\\x1b[?6c');\n }\n } else if (this.prefix === '>') {\n // xterm and urxvt\n // seem to spit this\n // out around ~370 times (?).\n if (this.is('xterm')) {\n this.send('\\x1b[>0;276;0c');\n } else if (this.is('rxvt-unicode')) {\n this.send('\\x1b[>85;95;0c');\n } else if (this.is('linux')) {\n // not supported by linux console.\n // linux console echoes parameters.\n this.send(params[0] + 'c');\n } else if (this.is('screen')) {\n this.send('\\x1b[>83;40003;0c');\n }\n }\n};\n\n\n/**\n * CSI Pm d\n * Line Position Absolute [row] (default = [1,column]) (VPA).\n */\nTerminal.prototype.linePosAbsolute = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.y = param - 1;\n if (this.y >= this.rows) {\n this.y = this.rows - 1;\n }\n};\n\n\n/**\n * 145 65 e * VPR - Vertical Position Relative\n * reuse CSI Ps B ?\n */\nTerminal.prototype.VPositionRelative = function(params) {\n var param = params[0];\n if (param < 1) param = 1;\n this.y += param;\n if (this.y >= this.rows) {\n this.y = this.rows - 1;\n }\n};\n\n\n/**\n * CSI Ps ; Ps f\n * Horizontal and Vertical Position [row;column] (default =\n * [1,1]) (HVP).\n */\nTerminal.prototype.HVPosition = function(params) {\n if (params[0] < 1) params[0] = 1;\n if (params[1] < 1) params[1] = 1;\n\n this.y = params[0] - 1;\n if (this.y >= this.rows) {\n this.y = this.rows - 1;\n }\n\n this.x = params[1] - 1;\n if (this.x >= this.cols) {\n this.x = this.cols - 1;\n }\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 */\nTerminal.prototype.setMode = function(params) {\n if (typeof params === 'object') {\n var l = params.length\n , i = 0;\n\n for (; i < l; i++) {\n this.setMode(params[i]);\n }\n\n return;\n }\n\n if (!this.prefix) {\n switch (params) {\n case 4:\n this.insertMode = true;\n break;\n case 20:\n //this.convertEol = true;\n break;\n }\n } else if (this.prefix === '?') {\n switch (params) {\n case 1:\n this.applicationCursor = true;\n break;\n case 2:\n this.setgCharset(0, Terminal.charsets.US);\n this.setgCharset(1, Terminal.charsets.US);\n this.setgCharset(2, Terminal.charsets.US);\n this.setgCharset(3, Terminal.charsets.US);\n // set VT100 mode here\n break;\n case 3: // 132 col mode\n this.savedCols = this.cols;\n this.resize(132, this.rows);\n break;\n case 6:\n this.originMode = true;\n break;\n case 7:\n this.wraparoundMode = true;\n break;\n case 12:\n // this.cursorBlink = true;\n break;\n case 66:\n this.log('Serial port requested application keypad.');\n this.applicationKeypad = true;\n this.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 this.x10Mouse = params === 9;\n this.vt200Mouse = params === 1000;\n this.normalMouse = params > 1000;\n this.mouseEvents = true;\n this.element.style.cursor = 'default';\n this.log('Binding to mouse events.');\n break;\n case 1004: // send focusin/focusout events\n // focusin: ^[[I\n // focusout: ^[[O\n this.sendFocus = true;\n break;\n case 1005: // utf8 ext mode mouse\n this.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.sgrMouse = true;\n // for wide terminals\n // does not add 32 to fields\n // press: ^[[ Keyboard Action Mode (AM).\n * Ps = 4 -> Replace Mode (IRM).\n * Ps = 1 2 -> Send/receive (SRM).\n * Ps = 2 0 -> Normal Linefeed (LNM).\n * CSI ? Pm l\n * DEC Private Mode Reset (DECRST).\n * Ps = 1 -> Normal Cursor Keys (DECCKM).\n * Ps = 2 -> Designate VT52 mode (DECANM).\n * Ps = 3 -> 80 Column Mode (DECCOLM).\n * Ps = 4 -> Jump (Fast) Scroll (DECSCLM).\n * Ps = 5 -> Normal Video (DECSCNM).\n * Ps = 6 -> Normal Cursor Mode (DECOM).\n * Ps = 7 -> No Wraparound Mode (DECAWM).\n * Ps = 8 -> No Auto-repeat Keys (DECARM).\n * Ps = 9 -> Don't send Mouse X & Y on button press.\n * Ps = 1 0 -> Hide toolbar (rxvt).\n * Ps = 1 2 -> Stop Blinking Cursor (att610).\n * Ps = 1 8 -> Don't print form feed (DECPFF).\n * Ps = 1 9 -> Limit print to scrolling region (DECPEX).\n * Ps = 2 5 -> Hide Cursor (DECTCEM).\n * Ps = 3 0 -> Don't show scrollbar (rxvt).\n * Ps = 3 5 -> Disable font-shifting functions (rxvt).\n * Ps = 4 0 -> Disallow 80 -> 132 Mode.\n * Ps = 4 1 -> No more(1) fix (see curses resource).\n * Ps = 4 2 -> Disable Nation Replacement Character sets (DEC-\n * NRCM).\n * Ps = 4 4 -> Turn Off Margin Bell.\n * Ps = 4 5 -> No Reverse-wraparound Mode.\n * Ps = 4 6 -> Stop Logging. (This is normally disabled by a\n * compile-time option).\n * Ps = 4 7 -> Use Normal Screen Buffer.\n * Ps = 6 6 -> Numeric keypad (DECNKM).\n * Ps = 6 7 -> Backarrow key sends delete (DECBKM).\n * Ps = 1 0 0 0 -> Don't send Mouse X & Y on button press and\n * release. See the section Mouse Tracking.\n * Ps = 1 0 0 1 -> Don't use Hilite Mouse Tracking.\n * Ps = 1 0 0 2 -> Don't use Cell Motion Mouse Tracking.\n * Ps = 1 0 0 3 -> Don't use All Motion Mouse Tracking.\n * Ps = 1 0 0 4 -> Don't send FocusIn/FocusOut events.\n * Ps = 1 0 0 5 -> Disable Extended Mouse Mode.\n * Ps = 1 0 1 0 -> Don't scroll to bottom on tty output\n * (rxvt).\n * Ps = 1 0 1 1 -> Don't scroll to bottom on key press (rxvt).\n * Ps = 1 0 3 4 -> Don't interpret \"meta\" key. (This disables\n * the eightBitInput resource).\n * Ps = 1 0 3 5 -> Disable special modifiers for Alt and Num-\n * Lock keys. (This disables the numLock resource).\n * Ps = 1 0 3 6 -> Don't send ESC when Meta modifies a key.\n * (This disables the metaSendsEscape resource).\n * Ps = 1 0 3 7 -> Send VT220 Remove from the editing-keypad\n * Delete key.\n * Ps = 1 0 3 9 -> Don't send ESC when Alt modifies a key.\n * (This disables the altSendsEscape resource).\n * Ps = 1 0 4 0 -> Do not keep selection when not highlighted.\n * (This disables the keepSelection resource).\n * Ps = 1 0 4 1 -> Use the PRIMARY selection. (This disables\n * the selectToClipboard resource).\n * Ps = 1 0 4 2 -> Disable Urgency window manager hint when\n * Control-G is received. (This disables the bellIsUrgent\n * resource).\n * Ps = 1 0 4 3 -> Disable raising of the window when Control-\n * G is received. (This disables the popOnBell resource).\n * Ps = 1 0 4 7 -> Use Normal Screen Buffer, clearing screen\n * first if in the Alternate Screen. (This may be disabled by\n * the titeInhibit resource).\n * Ps = 1 0 4 8 -> Restore cursor as in DECRC. (This may be\n * disabled by the titeInhibit resource).\n * Ps = 1 0 4 9 -> Use Normal Screen Buffer and restore cursor\n * as in DECRC. (This may be disabled by the titeInhibit\n * resource). This combines the effects of the 1 0 4 7 and 1 0\n * 4 8 modes. Use this with terminfo-based applications rather\n * than the 4 7 mode.\n * Ps = 1 0 5 0 -> Reset terminfo/termcap function-key mode.\n * Ps = 1 0 5 1 -> Reset Sun function-key mode.\n * Ps = 1 0 5 2 -> Reset HP function-key mode.\n * Ps = 1 0 5 3 -> Reset SCO function-key mode.\n * Ps = 1 0 6 0 -> Reset legacy keyboard emulation (X11R6).\n * Ps = 1 0 6 1 -> Reset keyboard emulation to Sun/PC style.\n * Ps = 2 0 0 4 -> Reset bracketed paste mode.\n */\nTerminal.prototype.resetMode = function(params) {\n if (typeof params === 'object') {\n var l = params.length\n , i = 0;\n\n for (; i < l; i++) {\n this.resetMode(params[i]);\n }\n\n return;\n }\n\n if (!this.prefix) {\n switch (params) {\n case 4:\n this.insertMode = false;\n break;\n case 20:\n //this.convertEol = false;\n break;\n }\n } else if (this.prefix === '?') {\n switch (params) {\n case 1:\n this.applicationCursor = false;\n break;\n case 3:\n if (this.cols === 132 && this.savedCols) {\n this.resize(this.savedCols, this.rows);\n }\n delete this.savedCols;\n break;\n case 6:\n this.originMode = false;\n break;\n case 7:\n this.wraparoundMode = false;\n break;\n case 12:\n // this.cursorBlink = false;\n break;\n case 66:\n this.log('Switching back to normal keypad.');\n this.applicationKeypad = false;\n this.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.x10Mouse = false;\n this.vt200Mouse = false;\n this.normalMouse = false;\n this.mouseEvents = false;\n this.element.style.cursor = '';\n break;\n case 1004: // send focusin/focusout events\n this.sendFocus = false;\n break;\n case 1005: // utf8 ext mode mouse\n this.utfMouse = false;\n break;\n case 1006: // sgr ext mode mouse\n this.sgrMouse = false;\n break;\n case 1015: // urxvt ext mode mouse\n this.urxvtMouse = false;\n break;\n case 25: // hide cursor\n this.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 if (this.normal) {\n this.lines = this.normal.lines;\n this.ybase = this.normal.ybase;\n this.ydisp = this.normal.ydisp;\n this.x = this.normal.x;\n this.y = this.normal.y;\n this.scrollTop = this.normal.scrollTop;\n this.scrollBottom = this.normal.scrollBottom;\n this.tabs = this.normal.tabs;\n this.normal = null;\n // if (params === 1049) {\n // this.x = this.savedX;\n // this.y = this.savedY;\n // }\n this.refresh(0, this.rows - 1);\n this.showCursor();\n }\n break;\n }\n }\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 */\nTerminal.prototype.setScrollRegion = function(params) {\n if (this.prefix) return;\n this.scrollTop = (params[0] || 1) - 1;\n this.scrollBottom = (params[1] || this.rows) - 1;\n this.x = 0;\n this.y = 0;\n};\n\n\n/**\n * CSI s\n * Save cursor (ANSI.SYS).\n */\nTerminal.prototype.saveCursor = function(params) {\n this.savedX = this.x;\n this.savedY = this.y;\n};\n\n\n/**\n * CSI u\n * Restore cursor (ANSI.SYS).\n */\nTerminal.prototype.restoreCursor = function(params) {\n this.x = this.savedX || 0;\n this.y = this.savedY || 0;\n};\n\n\n/**\n * Lesser Used\n */\n\n/**\n * CSI Ps I\n * Cursor Forward Tabulation Ps tab stops (default = 1) (CHT).\n */\nTerminal.prototype.cursorForwardTab = function(params) {\n var param = params[0] || 1;\n while (param--) {\n this.x = this.nextStop();\n }\n};\n\n\n/**\n * CSI Ps S Scroll up Ps lines (default = 1) (SU).\n */\nTerminal.prototype.scrollUp = function(params) {\n var param = params[0] || 1;\n while (param--) {\n this.lines.splice(this.ybase + this.scrollTop, 1);\n this.lines.splice(this.ybase + this.scrollBottom, 0, this.blankLine());\n }\n // this.maxRange();\n this.updateRange(this.scrollTop);\n this.updateRange(this.scrollBottom);\n};\n\n\n/**\n * CSI Ps T Scroll down Ps lines (default = 1) (SD).\n */\nTerminal.prototype.scrollDown = function(params) {\n var param = params[0] || 1;\n while (param--) {\n this.lines.splice(this.ybase + this.scrollBottom, 1);\n this.lines.splice(this.ybase + this.scrollTop, 0, this.blankLine());\n }\n // this.maxRange();\n this.updateRange(this.scrollTop);\n this.updateRange(this.scrollBottom);\n};\n\n\n/**\n * CSI Ps ; Ps ; Ps ; Ps ; Ps T\n * Initiate highlight mouse tracking. Parameters are\n * [func;startx;starty;firstrow;lastrow]. See the section Mouse\n * Tracking.\n */\nTerminal.prototype.initMouseTracking = function(params) {\n // Relevant: DECSET 1001\n};\n\n\n/**\n * CSI > Ps; Ps T\n * Reset one or more features of the title modes to the default\n * value. Normally, \"reset\" disables the feature. It is possi-\n * ble to disable the ability to reset features by compiling a\n * different default for the title modes into xterm.\n * Ps = 0 -> Do not set window/icon labels using hexadecimal.\n * Ps = 1 -> Do not query window/icon labels using hexadeci-\n * mal.\n * Ps = 2 -> Do not set window/icon labels using UTF-8.\n * Ps = 3 -> Do not query window/icon labels using UTF-8.\n * (See discussion of \"Title Modes\").\n */\nTerminal.prototype.resetTitleModes = function(params) {\n ;\n};\n\n\n/**\n * CSI Ps Z Cursor Backward Tabulation Ps tab stops (default = 1) (CBT).\n */\nTerminal.prototype.cursorBackwardTab = function(params) {\n var param = params[0] || 1;\n while (param--) {\n this.x = this.prevStop();\n }\n};\n\n\n/**\n * CSI Ps b Repeat the preceding graphic character Ps times (REP).\n */\nTerminal.prototype.repeatPrecedingCharacter = function(params) {\n var param = params[0] || 1\n , line = this.lines[this.ybase + this.y]\n , ch = line[this.x - 1] || [this.defAttr, ' ', 1];\n\n while (param--) line[this.x++] = ch;\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 */\nTerminal.prototype.tabClear = function(params) {\n var param = params[0];\n if (param <= 0) {\n delete this.tabs[this.x];\n } else if (param === 3) {\n this.tabs = {};\n }\n};\n\n\n/**\n * CSI Pm i Media Copy (MC).\n * Ps = 0 -> Print screen (default).\n * Ps = 4 -> Turn off printer controller mode.\n * Ps = 5 -> Turn on printer controller mode.\n * CSI ? Pm i\n * Media Copy (MC, DEC-specific).\n * Ps = 1 -> Print line containing cursor.\n * Ps = 4 -> Turn off autoprint mode.\n * Ps = 5 -> Turn on autoprint mode.\n * Ps = 1 0 -> Print composed display, ignores DECPEX.\n * Ps = 1 1 -> Print all pages.\n */\nTerminal.prototype.mediaCopy = function(params) {\n ;\n};\n\n\n/**\n * CSI > Ps; Ps m\n * Set or reset resource-values used by xterm to decide whether\n * to construct escape sequences holding information about the\n * modifiers pressed with a given key. The first parameter iden-\n * tifies the resource to set/reset. The second parameter is the\n * value to assign to the resource. If the second parameter is\n * omitted, the resource is reset to its initial value.\n * Ps = 1 -> modifyCursorKeys.\n * Ps = 2 -> modifyFunctionKeys.\n * Ps = 4 -> modifyOtherKeys.\n * If no parameters are given, all resources are reset to their\n * initial values.\n */\nTerminal.prototype.setResources = function(params) {\n ;\n};\n\n\n/**\n * CSI > Ps n\n * Disable modifiers which may be enabled via the CSI > Ps; Ps m\n * sequence. This corresponds to a resource value of \"-1\", which\n * cannot be set with the other sequence. The parameter identi-\n * fies the resource to be disabled:\n * Ps = 1 -> modifyCursorKeys.\n * Ps = 2 -> modifyFunctionKeys.\n * Ps = 4 -> modifyOtherKeys.\n * If the parameter is omitted, modifyFunctionKeys is disabled.\n * When modifyFunctionKeys is disabled, xterm uses the modifier\n * keys to make an extended sequence of functions rather than\n * adding a parameter to each function key to denote the modi-\n * fiers.\n */\nTerminal.prototype.disableModifiers = function(params) {\n ;\n};\n\n\n/**\n * CSI > Ps p\n * Set resource value pointerMode. This is used by xterm to\n * decide whether to hide the pointer cursor as the user types.\n * Valid values for the parameter:\n * Ps = 0 -> never hide the pointer.\n * Ps = 1 -> hide if the mouse tracking mode is not enabled.\n * Ps = 2 -> always hide the pointer. If no parameter is\n * given, xterm uses the default, which is 1 .\n */\nTerminal.prototype.setPointerMode = function(params) {\n ;\n};\n\n\n/**\n * CSI ! p Soft terminal reset (DECSTR).\n * http://vt100.net/docs/vt220-rm/table4-10.html\n */\nTerminal.prototype.softReset = function(params) {\n this.cursorHidden = false;\n this.insertMode = false;\n this.originMode = false;\n this.wraparoundMode = false; // autowrap\n this.applicationKeypad = false; // ?\n this.viewport.syncScrollArea();\n this.applicationCursor = false;\n this.scrollTop = 0;\n this.scrollBottom = this.rows - 1;\n this.curAttr = this.defAttr;\n this.x = this.y = 0; // ?\n this.charset = null;\n this.glevel = 0; // ??\n this.charsets = [null]; // ??\n};\n\n\n/**\n * CSI Ps$ p\n * Request ANSI mode (DECRQM). For VT300 and up, reply is\n * CSI Ps; Pm$ y\n * where Ps is the mode number as in RM, and Pm is the mode\n * value:\n * 0 - not recognized\n * 1 - set\n * 2 - reset\n * 3 - permanently set\n * 4 - permanently reset\n */\nTerminal.prototype.requestAnsiMode = function(params) {\n ;\n};\n\n\n/**\n * CSI ? Ps$ p\n * Request DEC private mode (DECRQM). For VT300 and up, reply is\n * CSI ? Ps; Pm$ p\n * where Ps is the mode number as in DECSET, Pm is the mode value\n * as in the ANSI DECRQM.\n */\nTerminal.prototype.requestPrivateMode = function(params) {\n ;\n};\n\n\n/**\n * CSI Ps ; Ps \" p\n * Set conformance level (DECSCL). Valid values for the first\n * parameter:\n * Ps = 6 1 -> VT100.\n * Ps = 6 2 -> VT200.\n * Ps = 6 3 -> VT300.\n * Valid values for the second parameter:\n * Ps = 0 -> 8-bit controls.\n * Ps = 1 -> 7-bit controls (always set for VT100).\n * Ps = 2 -> 8-bit controls.\n */\nTerminal.prototype.setConformanceLevel = function(params) {\n ;\n};\n\n\n/**\n * CSI Ps q Load LEDs (DECLL).\n * Ps = 0 -> Clear all LEDS (default).\n * Ps = 1 -> Light Num Lock.\n * Ps = 2 -> Light Caps Lock.\n * Ps = 3 -> Light Scroll Lock.\n * Ps = 2 1 -> Extinguish Num Lock.\n * Ps = 2 2 -> Extinguish Caps Lock.\n * Ps = 2 3 -> Extinguish Scroll Lock.\n */\nTerminal.prototype.loadLEDs = function(params) {\n ;\n};\n\n\n/**\n * CSI Ps SP q\n * 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 */\nTerminal.prototype.setCursorStyle = function(params) {\n ;\n};\n\n\n/**\n * CSI Ps \" q\n * Select character protection attribute (DECSCA). Valid values\n * for the parameter:\n * Ps = 0 -> DECSED and DECSEL can erase (default).\n * Ps = 1 -> DECSED and DECSEL cannot erase.\n * Ps = 2 -> DECSED and DECSEL can erase.\n */\nTerminal.prototype.setCharProtectionAttr = function(params) {\n ;\n};\n\n\n/**\n * CSI ? Pm r\n * Restore DEC Private Mode Values. The value of Ps previously\n * saved is restored. Ps values are the same as for DECSET.\n */\nTerminal.prototype.restorePrivateValues = function(params) {\n ;\n};\n\n\n/**\n * CSI Pt; Pl; Pb; Pr; Ps$ r\n * Change Attributes in Rectangular Area (DECCARA), VT400 and up.\n * Pt; Pl; Pb; Pr denotes the rectangle.\n * Ps denotes the SGR attributes to change: 0, 1, 4, 5, 7.\n * NOTE: xterm doesn't enable this code by default.\n */\nTerminal.prototype.setAttrInRectangle = function(params) {\n var t = params[0]\n , l = params[1]\n , b = params[2]\n , r = params[3]\n , attr = params[4];\n\n var line\n , i;\n\n for (; t < b + 1; t++) {\n line = this.lines[this.ybase + t];\n for (i = l; i < r; i++) {\n line[i] = [attr, line[i][1]];\n }\n }\n\n // this.maxRange();\n this.updateRange(params[0]);\n this.updateRange(params[2]);\n};\n\n\n/**\n * CSI Pc; Pt; Pl; Pb; Pr$ x\n * Fill Rectangular Area (DECFRA), VT420 and up.\n * Pc is the character to use.\n * Pt; Pl; Pb; Pr denotes the rectangle.\n * NOTE: xterm doesn't enable this code by default.\n */\nTerminal.prototype.fillRectangle = function(params) {\n var ch = params[0]\n , t = params[1]\n , l = params[2]\n , b = params[3]\n , r = params[4];\n\n var line\n , i;\n\n for (; t < b + 1; t++) {\n line = this.lines[this.ybase + t];\n for (i = l; i < r; i++) {\n line[i] = [line[i][0], String.fromCharCode(ch)];\n }\n }\n\n // this.maxRange();\n this.updateRange(params[1]);\n this.updateRange(params[3]);\n};\n\n\n/**\n * CSI Ps ; Pu ' z\n * Enable Locator Reporting (DECELR).\n * Valid values for the first parameter:\n * Ps = 0 -> Locator disabled (default).\n * Ps = 1 -> Locator enabled.\n * Ps = 2 -> Locator enabled for one report, then disabled.\n * The second parameter specifies the coordinate unit for locator\n * reports.\n * Valid values for the second parameter:\n * Pu = 0 <- or omitted -> default to character cells.\n * Pu = 1 <- device physical pixels.\n * Pu = 2 <- character cells.\n */\nTerminal.prototype.enableLocatorReporting = function(params) {\n var val = params[0] > 0;\n //this.mouseEvents = val;\n //this.decLocator = val;\n};\n\n\n/**\n * CSI Pt; Pl; Pb; Pr$ z\n * Erase Rectangular Area (DECERA), VT400 and up.\n * Pt; Pl; Pb; Pr denotes the rectangle.\n * NOTE: xterm doesn't enable this code by default.\n */\nTerminal.prototype.eraseRectangle = function(params) {\n var t = params[0]\n , l = params[1]\n , b = params[2]\n , r = params[3];\n\n var line\n , i\n , ch;\n\n ch = [this.eraseAttr(), ' ', 1]; // xterm?\n\n for (; t < b + 1; t++) {\n line = this.lines[this.ybase + t];\n for (i = l; i < r; i++) {\n line[i] = ch;\n }\n }\n\n // this.maxRange();\n this.updateRange(params[0]);\n this.updateRange(params[2]);\n};\n\n\n/**\n * CSI P m SP }\n * Insert P s Column(s) (default = 1) (DECIC), VT420 and up.\n * NOTE: xterm doesn't enable this code by default.\n */\nTerminal.prototype.insertColumns = function() {\n var param = params[0]\n , l = this.ybase + this.rows\n , ch = [this.eraseAttr(), ' ', 1] // xterm?\n , i;\n\n while (param--) {\n for (i = this.ybase; i < l; i++) {\n this.lines[i].splice(this.x + 1, 0, ch);\n this.lines[i].pop();\n }\n }\n\n this.maxRange();\n};\n\n\n/**\n * CSI P m SP ~\n * Delete P s Column(s) (default = 1) (DECDC), VT420 and up\n * NOTE: xterm doesn't enable this code by default.\n */\nTerminal.prototype.deleteColumns = function() {\n var param = params[0]\n , l = this.ybase + this.rows\n , ch = [this.eraseAttr(), ' ', 1] // xterm?\n , i;\n\n while (param--) {\n for (i = this.ybase; i < l; i++) {\n this.lines[i].splice(this.x, 1);\n this.lines[i].push(ch);\n }\n }\n\n this.maxRange();\n};\n\n/**\n * Character Sets\n */\n\nTerminal.charsets = {};\n\n// DEC Special Character and Line Drawing Set.\n// 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.\nTerminal.charsets.SCLD = { // (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\nTerminal.charsets.UK = null; // (A\nTerminal.charsets.US = null; // (B (USASCII)\nTerminal.charsets.Dutch = null; // (4\nTerminal.charsets.Finnish = null; // (C or (5\nTerminal.charsets.French = null; // (R\nTerminal.charsets.FrenchCanadian = null; // (Q\nTerminal.charsets.German = null; // (K\nTerminal.charsets.Italian = null; // (Y\nTerminal.charsets.NorwegianDanish = null; // (E or (6\nTerminal.charsets.Spanish = null; // (Z\nTerminal.charsets.Swedish = null; // (H or (7\nTerminal.charsets.Swiss = null; // (=\nTerminal.charsets.ISOLatin = null; // /A\n\n/**\n * Helpers\n */\n\nfunction on(el, type, handler, capture) {\n if (!Array.isArray(el)) {\n el = [el];\n }\n el.forEach(function (element) {\n element.addEventListener(type, handler, capture || false);\n });\n}\n\nfunction off(el, type, handler, capture) {\n el.removeEventListener(type, handler, capture || false);\n}\n\nfunction cancel(ev, force) {\n if (!this.cancelEvents && !force) {\n return;\n }\n ev.preventDefault();\n ev.stopPropagation();\n return false;\n}\n\nfunction inherits(child, parent) {\n function f() {\n this.constructor = child;\n }\n f.prototype = parent.prototype;\n child.prototype = new f;\n}\n\n// if bold is broken, we can't\n// use it in the terminal.\nfunction isBoldBroken(document) {\n var body = document.getElementsByTagName('body')[0];\n var el = document.createElement('span');\n el.innerHTML = 'hello world';\n body.appendChild(el);\n var w1 = el.scrollWidth;\n el.style.fontWeight = 'bold';\n var w2 = el.scrollWidth;\n body.removeChild(el);\n return w1 !== w2;\n}\n\nfunction indexOf(obj, el) {\n var i = obj.length;\n while (i--) {\n if (obj[i] === el) return i;\n }\n return -1;\n}\n\nfunction isThirdLevelShift(term, ev) {\n var thirdLevelKey =\n (term.browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) ||\n (term.browser.isMSWindows && ev.altKey && ev.ctrlKey && !ev.metaKey);\n\n if (ev.type == 'keypress') {\n return thirdLevelKey;\n }\n\n // Don't invoke for arrows, pageDown, home, backspace, etc. (on non-keypress events)\n return thirdLevelKey && (!ev.keyCode || ev.keyCode > 47);\n}\n\nfunction matchColor(r1, g1, b1) {\n var hash = (r1 << 16) | (g1 << 8) | b1;\n\n if (matchColor._cache[hash] != null) {\n return matchColor._cache[hash];\n }\n\n var ldiff = Infinity\n , li = -1\n , i = 0\n , c\n , r2\n , g2\n , b2\n , diff;\n\n for (; i < Terminal.vcolors.length; i++) {\n c = Terminal.vcolors[i];\n r2 = c[0];\n g2 = c[1];\n b2 = c[2];\n\n diff = matchColor.distance(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 matchColor._cache[hash] = li;\n}\n\nmatchColor._cache = {};\n\n// http://stackoverflow.com/questions/1633828\nmatchColor.distance = function(r1, g1, b1, r2, g2, b2) {\n return Math.pow(30 * (r1 - r2), 2)\n + Math.pow(59 * (g1 - g2), 2)\n + Math.pow(11 * (b1 - b2), 2);\n};\n\nfunction each(obj, iter, con) {\n if (obj.forEach) return obj.forEach(iter, con);\n for (var i = 0; i < obj.length; i++) {\n iter.call(con, obj[i], i, obj);\n }\n}\n\nfunction keys(obj) {\n if (Object.keys) return Object.keys(obj);\n var key, keys = [];\n for (key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n keys.push(key);\n }\n }\n return keys;\n}\n\nvar wcwidth = (function(opts) {\n // extracted from https://www.cl.cam.ac.uk/%7Emgk25/ucs/wcwidth.c\n // combining characters\n var COMBINING = [\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 [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) {\n var min = 0;\n var max = COMBINING.length - 1;\n var mid;\n if (ucs < COMBINING[0][0] || ucs > COMBINING[max][1])\n return false;\n while (max >= min) {\n mid = Math.floor((min + max) / 2);\n if (ucs > COMBINING[mid][1])\n min = mid + 1;\n else if (ucs < COMBINING[mid][0])\n max = mid - 1;\n else\n return true;\n }\n return false;\n }\n function wcwidth(ucs) {\n // test for 8-bit control characters\n if (ucs === 0)\n return opts.nul;\n if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))\n return opts.control;\n // binary search in table of non-spacing characters\n if (bisearch(ucs))\n return 0;\n // if we arrive here, ucs is not a combining or C0/C1 control character\n return 1 +\n (\n ucs >= 0x1100 &&\n (\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 (ucs >= 0x20000 && ucs <= 0x2fffd) ||\n (ucs >= 0x30000 && ucs <= 0x3fffd)\n )\n );\n }\n return wcwidth;\n})({nul: 0, control: 0}); // configurable options\n\n/**\n * Expose\n */\n\nTerminal.EventEmitter = EventEmitter;\nTerminal.inherits = inherits;\n\n/**\n * Adds an event listener to the terminal.\n *\n * @param {string} event The name of the event. TODO: Document all event types\n * @param {function} callback The function to call when the event is triggered.\n */\nTerminal.on = on;\nTerminal.off = off;\nTerminal.cancel = cancel;\n\nmodule.exports = Terminal;\n","/**\n * Generic utilities module with methods that can be helpful at different parts of the code base.\n * @module xterm/utils/Generic\n * @license MIT\n */\n\n/**\n * Return if the given array contains the given element\n * @param {Array} array The array to search for the given element.\n * @param {Object} el The element to look for into the array\n */\nexport let contains = function(arr, el) {\n return arr.indexOf(el) >= 0;\n};\n","/**\n * Attributes and methods to help with identifying the current browser and platform.\n * @module xterm/utils/Browser\n * @license MIT\n */\n\nimport { contains } from './Generic.js';\n\nlet isNode = (typeof navigator == 'undefined') ? true : false;\nlet userAgent = (isNode) ? 'node' : navigator.userAgent;\nlet platform = (isNode) ? 'node' : navigator.platform;\n\nexport let isFirefox = !!~userAgent.indexOf('Firefox');\nexport let 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 let isMac = contains(['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'], platform);\nexport let isIpad = platform === 'iPad';\nexport let isIphone = platform === 'iPhone';\nexport let isMSWindows = contains(['Windows', 'Win16', 'Win32', 'WinCE'], platform);\n","/**\n * Clipboard handler module: exports methods for handling all clipboard-related events in the\n * terminal.\n * @module xterm/handlers/Clipboard\n * @license MIT\n */\n\nimport { ITerminal } from '../Interfaces';\n\n// We are extending the ClipboardEvent interface, since TypeScript has not declared the\n// clientX and clientY properties that we use.\ninterface IClipboardEvent extends ClipboardEvent {\n clientX: number;\n clientY: number;\n}\n\ninterface IWindow extends Window {\n clipboardData?: {\n getData(format: string): string;\n setData(format: string, data: string);\n };\n}\n\ndeclare var window: IWindow;\n\n/**\n * Prepares text copied from terminal selection, to be saved in the clipboard by:\n * 1. stripping all trailing white spaces\n * 2. converting all non-breaking spaces to regular spaces\n * @param {string} text The copied text that needs processing for storing in clipboard\n * @returns {string}\n */\nexport function prepareTextForClipboard(text: string): string {\n let space = String.fromCharCode(32),\n nonBreakingSpace = String.fromCharCode(160),\n allNonBreakingSpaces = new RegExp(nonBreakingSpace, 'g'),\n processedText = text.split('\\n').map(function (line) {\n // Strip all trailing white spaces and convert all non-breaking spaces\n // to regular spaces.\n let processedLine = line.replace(/\\s+$/g, '').replace(allNonBreakingSpaces, space);\n\n return processedLine;\n }).join('\\n');\n\n return processedText;\n}\n\n/**\n * Binds copy functionality to the given terminal.\n * @param {ClipboardEvent} ev The original copy event to be handled\n */\nexport function copyHandler(ev: IClipboardEvent, term: ITerminal) {\n // We cast `window` to `any` type, because TypeScript has not declared the `clipboardData`\n // property that we use below for Internet Explorer.\n let copiedText = window.getSelection().toString(),\n text = prepareTextForClipboard(copiedText);\n\n if (term.browser.isMSIE) {\n window.clipboardData.setData('Text', text);\n } else {\n ev.clipboardData.setData('text/plain', text);\n }\n\n ev.preventDefault(); // Prevent or the original text will be copied.\n}\n\n/**\n * Redirect the clipboard's data to the terminal's input handler.\n * @param {ClipboardEvent} ev The original paste event to be handled\n * @param {Terminal} term The terminal on which to apply the handled paste event\n */\nexport function pasteHandler(ev: IClipboardEvent, term: ITerminal) {\n ev.stopPropagation();\n\n let text: string;\n\n let dispatchPaste = function(text) {\n term.handler(text);\n term.textarea.value = '';\n return 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 * Bind to right-click event and allow right-click copy and paste.\n *\n * **Logic**\n * If text is selected and right-click happens on selected text, then\n * do nothing to allow seamless copying.\n * If no text is selected or right-click is outside of the selection\n * area, then bring the terminal's input below the cursor, in order to\n * trigger the event on the textarea and allow-right click paste, without\n * caring about disappearing selection.\n * @param {ClipboardEvent} ev The original paste event to be handled\n * @param {Terminal} term The terminal on which to apply the handled paste event\n */\nexport function rightClickHandler(ev: IClipboardEvent, term: ITerminal) {\n let s = document.getSelection(),\n selectedText = prepareTextForClipboard(s.toString()),\n clickIsOnSelection = false,\n x = ev.clientX,\n y = ev.clientY;\n\n if (s.rangeCount) {\n let r = s.getRangeAt(0),\n cr = r.getClientRects(),\n i, rect;\n\n for (i=0; i rect.left) && (x < rect.right) &&\n (y > rect.top) && (y < rect.bottom)\n );\n\n if (clickIsOnSelection) {\n break;\n }\n }\n // If we clicked on selection and selection is not a single space,\n // then mark the right click as copy-only. We check for the single\n // space selection, as this can happen when clicking on an  \n // and there is not much pointing in copying a single space.\n if (selectedText.match(/^\\s$/) || !selectedText.length) {\n clickIsOnSelection = false;\n }\n }\n\n // Bring textarea at the cursor position\n if (!clickIsOnSelection) {\n term.textarea.style.position = 'fixed';\n term.textarea.style.width = '20px';\n term.textarea.style.height = '20px';\n term.textarea.style.left = (x - 10) + 'px';\n term.textarea.style.top = (y - 10) + 'px';\n term.textarea.style.zIndex = '1000';\n term.textarea.focus();\n\n // Reset the terminal textarea's styling\n setTimeout(function () {\n term.textarea.style.position = null;\n term.textarea.style.width = null;\n term.textarea.style.height = null;\n term.textarea.style.left = null;\n term.textarea.style.top = null;\n term.textarea.style.zIndex = null;\n }, 4);\n }\n}\n","/**\n * @license MIT\n */\n\nimport { ITerminal } from './Interfaces';\n\n/**\n * Represents the viewport of a terminal, the visible area within the larger buffer of output.\n * Logic for the virtual scroll bar is included in this object.\n */\nexport class Viewport {\n private currentRowHeight: number;\n private lastRecordedBufferLength: number;\n private lastRecordedViewportHeight: number;\n\n /**\n * Creates a new Viewport.\n * @param terminal The terminal this viewport belongs to.\n * @param viewportElement The DOM element acting as the viewport.\n * @param scrollArea The DOM element acting as the scroll area.\n * @param charMeasureElement 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 charMeasureElement: HTMLElement\n ) {\n this.currentRowHeight = 0;\n this.lastRecordedBufferLength = 0;\n this.lastRecordedViewportHeight = 0;\n\n this.terminal.on('scroll', this.syncScrollArea.bind(this));\n this.terminal.on('resize', this.syncScrollArea.bind(this));\n this.viewportElement.addEventListener('scroll', this.onScroll.bind(this));\n\n this.syncScrollArea();\n }\n\n /**\n * Refreshes row height, setting line-height, viewport height and scroll area height if\n * necessary.\n * @param charSize A character size measurement bounding rect object, if it doesn't exist it will\n * be created.\n */\n private refresh(charSize?: ClientRect): void {\n var size = charSize || this.charMeasureElement.getBoundingClientRect();\n if (size.height > 0) {\n var rowHeightChanged = size.height !== this.currentRowHeight;\n if (rowHeightChanged) {\n this.currentRowHeight = size.height;\n this.viewportElement.style.lineHeight = size.height + 'px';\n this.terminal.rowContainer.style.lineHeight = size.height + 'px';\n }\n var viewportHeightChanged = this.lastRecordedViewportHeight !== this.terminal.rows;\n if (rowHeightChanged || viewportHeightChanged) {\n this.lastRecordedViewportHeight = this.terminal.rows;\n this.viewportElement.style.height = size.height * this.terminal.rows + 'px';\n }\n this.scrollArea.style.height = (size.height * this.lastRecordedBufferLength) + 'px';\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.lines.length) {\n // If buffer height changed\n this.lastRecordedBufferLength = this.terminal.lines.length;\n this.refresh();\n } else if (this.lastRecordedViewportHeight !== this.terminal.rows) {\n // If viewport height changed\n this.refresh();\n } else {\n // If size has changed, refresh viewport\n var size = this.charMeasureElement.getBoundingClientRect();\n if (size.height !== this.currentRowHeight) {\n this.refresh(size);\n }\n }\n\n // Sync scrollTop\n var scrollTop = this.terminal.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) {\n var newRow = Math.round(this.viewportElement.scrollTop / this.currentRowHeight);\n var diff = newRow - this.terminal.ydisp;\n this.terminal.scrollDisp(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) {\n if (ev.deltaY === 0) {\n // Do nothing if it's not a vertical scroll event\n return;\n }\n // Fallback to WheelEvent.DOM_DELTA_PIXEL\n var multiplier = 1;\n if (ev.deltaMode === WheelEvent.DOM_DELTA_LINE) {\n multiplier = this.currentRowHeight;\n } else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) {\n multiplier = this.currentRowHeight * this.terminal.rows;\n }\n this.viewportElement.scrollTop += ev.deltaY * multiplier;\n // Prevent the page from scrolling when the terminal scrolls\n ev.preventDefault();\n };\n}\n","/**\n * @license MIT\n */\n\nfunction EventEmitter() {\n this._events = this._events || {};\n}\n\nEventEmitter.prototype.addListener = function(type, listener) {\n this._events[type] = this._events[type] || [];\n this._events[type].push(listener);\n};\n\nEventEmitter.prototype.on = EventEmitter.prototype.addListener;\n\nEventEmitter.prototype.removeListener = function(type, listener) {\n if (!this._events[type]) return;\n\n var obj = this._events[type]\n , i = obj.length;\n\n while (i--) {\n if (obj[i] === listener || obj[i].listener === listener) {\n obj.splice(i, 1);\n return;\n }\n }\n};\n\nEventEmitter.prototype.off = EventEmitter.prototype.removeListener;\n\nEventEmitter.prototype.removeAllListeners = function(type) {\n if (this._events[type]) delete this._events[type];\n};\n\nEventEmitter.prototype.once = function(type, listener) {\n var self = this;\n function on() {\n var args = Array.prototype.slice.call(arguments);\n this.removeListener(type, on);\n return listener.apply(this, args);\n }\n on.listener = listener;\n return this.on(type, on);\n};\n\nEventEmitter.prototype.emit = function(type) {\n if (!this._events[type]) return;\n\n var args = Array.prototype.slice.call(arguments, 1)\n , obj = this._events[type]\n , l = obj.length\n , i = 0;\n\n for (; i < l; i++) {\n obj[i].apply(this, args);\n }\n};\n\nEventEmitter.prototype.listeners = function(type) {\n return this._events[type] = this._events[type] || [];\n};\n\nexport { EventEmitter };\n","/**\n * @license MIT\n */\n\nimport { ITerminal } from './Interfaces';\n\ninterface IPosition {\n start: number;\n end: number;\n}\n\n/**\n * Encapsulates the logic for handling compositionstart, compositionupdate and compositionend\n * events, displaying the in-progress composition to the UI and forwarding the final composition\n * to the handler.\n */\nexport class CompositionHelper {\n /**\n * Whether input composition is currently happening, eg. via a mobile keyboard, speech input or\n * IME. This variable determines whether the compositionText should be displayed on the UI.\n */\n private isComposing: boolean;\n\n /**\n * The position within the input textarea's value of the current composition.\n */\n private compositionPosition: IPosition;;\n\n /**\n * Whether a composition is in the process of being sent, setting this to false will cancel any\n * in-progress composition.\n */\n private isSendingComposition: boolean;\n\n /**\n * Creates a new CompositionHelper.\n * @param textarea The textarea that xterm uses for input.\n * @param compositionView The element to display the in-progress composition in.\n * @param terminal The Terminal to forward the finished composition to.\n */\n constructor(\n private textarea: HTMLTextAreaElement,\n private compositionView: HTMLElement,\n private terminal: ITerminal\n ) {\n this.isComposing = false;\n this.isSendingComposition = false;\n this.compositionPosition = { start: null, end: null };\n }\n\n /**\n * Handles the compositionstart event, activating the composition view.\n */\n public compositionstart() {\n this.isComposing = true;\n this.compositionPosition.start = this.textarea.value.length;\n this.compositionView.textContent = '';\n this.compositionView.classList.add('active');\n }\n\n /**\n * Handles the compositionupdate event, updating the composition view.\n * @param {CompositionEvent} ev The event.\n */\n public compositionupdate(ev: CompositionEvent) {\n this.compositionView.textContent = ev.data;\n this.updateCompositionElements();\n var self = this;\n setTimeout(function() {\n self.compositionPosition.end = self.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() {\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) {\n if (this.isComposing || this.isSendingComposition) {\n if (ev.keyCode === 229) {\n // Continue composing if the keyCode is the \"composition character\"\n return false;\n } else if (ev.keyCode === 16 || ev.keyCode === 17 || ev.keyCode === 18) {\n // Continue composing if the keyCode is a modifier key\n return false;\n } else {\n // Finish composition immediately. This is mainly here for the case where enter is\n // pressed and the handler needs to be triggered before the command is executed.\n this.finalizeComposition(false);\n }\n }\n\n if (ev.keyCode === 229) {\n // If the \"composition character\" is used but gets to this point it means a non-composition\n // character (eg. numbers and punctuation) was pressed when the IME was active.\n this.handleAnyTextareaChanges();\n return false;\n }\n\n return true;\n }\n\n /**\n * Finalizes the composition, resuming regular input actions. This is called when a composition\n * is ending.\n * @param waitForPropogation Whether to wait for events to propogate before sending\n * the input. This should be false if a non-composition keystroke is entered before the\n * compositionend event is triggered, such as enter, so that the composition is send before\n * the command is executed.\n */\n private finalizeComposition(waitForPropogation: boolean) {\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 var 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 var 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 var self = this;\n this.isSendingComposition = true;\n setTimeout(function () {\n // Ensure that the input has not already been sent\n if (self.isSendingComposition) {\n self.isSendingComposition = false;\n var input;\n if (self.isComposing) {\n // Use the end position to get the string if a new composition has started.\n input = self.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 = self.textarea.value.substring(currentCompositionPosition.start);\n }\n self.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() {\n var oldValue = this.textarea.value;\n var self = this;\n setTimeout(function() {\n // Ignore if a composition has started since the timeout\n if (!self.isComposing) {\n var newValue = self.textarea.value;\n var diff = newValue.replace(oldValue, '');\n if (diff.length > 0) {\n self.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) {\n if (!this.isComposing) {\n return;\n }\n var cursor = this.terminal.element.querySelector('.terminal-cursor');\n if (cursor) {\n // Take .xterm-rows offsetTop into account as well in case it's positioned absolutely within\n // the .xterm element.\n var xtermRows = this.terminal.element.querySelector('.xterm-rows');\n var cursorTop = xtermRows.offsetTop + cursor.offsetTop;\n\n this.compositionView.style.left = cursor.offsetLeft + 'px';\n this.compositionView.style.top = cursorTop + 'px';\n this.compositionView.style.height = cursor.offsetHeight + 'px';\n this.compositionView.style.lineHeight = cursor.offsetHeight + 'px';\n // Sync the textarea to the exact position of the composition view so the IME knows where the\n // text is.\n var compositionViewBounds = this.compositionView.getBoundingClientRect();\n this.textarea.style.left = cursor.offsetLeft + '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 if (!dontRecurse) {\n setTimeout(this.updateCompositionElements.bind(this, 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() {\n this.textarea.style.left = '';\n this.textarea.style.top = '';\n };\n}\n","(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o Date: Wed, 7 Dec 2016 18:42:40 +0000 Subject: [PATCH 21/24] Checkout add-ons --- dist/addons/attach/attach.js | 114 ++++++++++++++++++ dist/addons/fit/fit.js | 59 +++++++++ dist/addons/fullscreen/fullscreen.css | 10 ++ dist/addons/fullscreen/fullscreen.js | 50 ++++++++ dist/addons/linkify/linkify.js | 165 ++++++++++++++++++++++++++ dist/addons/terminado/terminado.js | 122 +++++++++++++++++++ 6 files changed, 520 insertions(+) create mode 100644 dist/addons/attach/attach.js create mode 100644 dist/addons/fit/fit.js create mode 100644 dist/addons/fullscreen/fullscreen.css create mode 100644 dist/addons/fullscreen/fullscreen.js create mode 100644 dist/addons/linkify/linkify.js create mode 100644 dist/addons/terminado/terminado.js diff --git a/dist/addons/attach/attach.js b/dist/addons/attach/attach.js new file mode 100644 index 00000000..8cf759ae --- /dev/null +++ b/dist/addons/attach/attach.js @@ -0,0 +1,114 @@ +/** + * Implements the attach method, that attaches the terminal to a WebSocket stream. + * @module xterm/addons/attach/attach + * @license MIT + */ +(function (attach) { + if (typeof exports === 'object' && typeof module === 'object') { + /* + * CommonJS environment + */ + module.exports = attach(require('../../xterm')); + } + else if (typeof define == 'function') { + /* + * Require.js is available + */ + define(['../../xterm'], attach); + } + else { + /* + * Plain browser environment + */ + attach(window.Terminal); + } +})(function (Xterm) { + 'use strict'; + var exports = {}; + /** + * Attaches the given terminal to the given socket. + * + * @param {Xterm} term - The terminal to be attached to the given socket. + * @param {WebSocket} socket - The socket to attach the current terminal. + * @param {boolean} bidirectional - Whether the terminal should send data + * to the socket as well. + * @param {boolean} buffered - Whether the rendering of incoming data + * should happen instantly or at a maximum + * frequency of 1 rendering per 10ms. + */ + exports.attach = function (term, socket, bidirectional, buffered) { + bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional; + term.socket = socket; + term._flushBuffer = function () { + term.write(term._attachSocketBuffer); + term._attachSocketBuffer = null; + clearTimeout(term._attachSocketBufferTimer); + term._attachSocketBufferTimer = null; + }; + term._pushToBuffer = function (data) { + if (term._attachSocketBuffer) { + term._attachSocketBuffer += data; + } + else { + term._attachSocketBuffer = data; + setTimeout(term._flushBuffer, 10); + } + }; + term._getMessage = function (ev) { + if (buffered) { + term._pushToBuffer(ev.data); + } + else { + term.write(ev.data); + } + }; + term._sendData = function (data) { + socket.send(data); + }; + socket.addEventListener('message', term._getMessage); + if (bidirectional) { + term.on('data', term._sendData); + } + socket.addEventListener('close', term.detach.bind(term, socket)); + socket.addEventListener('error', term.detach.bind(term, socket)); + }; + /** + * Detaches the given terminal from the given socket + * + * @param {Xterm} term - The terminal to be detached from the given socket. + * @param {WebSocket} socket - The socket from which to detach the current + * terminal. + */ + exports.detach = function (term, socket) { + term.off('data', term._sendData); + socket = (typeof socket == 'undefined') ? term.socket : socket; + if (socket) { + socket.removeEventListener('message', term._getMessage); + } + delete term.socket; + }; + /** + * Attaches the current terminal to the given socket + * + * @param {WebSocket} socket - The socket to attach the current terminal. + * @param {boolean} bidirectional - Whether the terminal should send data + * to the socket as well. + * @param {boolean} buffered - Whether the rendering of incoming data + * should happen instantly or at a maximum + * frequency of 1 rendering per 10ms. + */ + Xterm.prototype.attach = function (socket, bidirectional, buffered) { + return exports.attach(this, socket, bidirectional, buffered); + }; + /** + * Detaches the current terminal from the given socket. + * + * @param {WebSocket} socket - The socket from which to detach the current + * terminal. + */ + Xterm.prototype.detach = function (socket) { + return exports.detach(this, socket); + }; + return exports; +}); +//# sourceMappingURL=attach.js.map \ No newline at end of file diff --git a/dist/addons/fit/fit.js b/dist/addons/fit/fit.js new file mode 100644 index 00000000..5ba26746 --- /dev/null +++ b/dist/addons/fit/fit.js @@ -0,0 +1,59 @@ +/** + * Fit terminal columns and rows to the dimensions of its DOM element. + * + * ## Approach + * - Rows: Truncate the division of the terminal parent element height by the terminal row height. + * + * - Columns: Truncate the division of the terminal parent element width by the terminal character + * width (apply display: inline at the terminal row and truncate its width with the current + * number of columns). + * @module xterm/addons/fit/fit + * @license MIT + */ +(function (fit) { + if (typeof exports === 'object' && typeof module === 'object') { + /* + * CommonJS environment + */ + module.exports = fit(require('../../xterm')); + } + else if (typeof define == 'function') { + /* + * Require.js is available + */ + define(['../../xterm'], fit); + } + else { + /* + * Plain browser environment + */ + fit(window.Terminal); + } +})(function (Xterm) { + var exports = {}; + exports.proposeGeometry = function (term) { + var parentElementStyle = window.getComputedStyle(term.element.parentElement), parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')), parentElementWidth = parseInt(parentElementStyle.getPropertyValue('width')), elementStyle = window.getComputedStyle(term.element), elementPaddingVer = parseInt(elementStyle.getPropertyValue('padding-top')) + parseInt(elementStyle.getPropertyValue('padding-bottom')), elementPaddingHor = parseInt(elementStyle.getPropertyValue('padding-right')) + parseInt(elementStyle.getPropertyValue('padding-left')), availableHeight = parentElementHeight - elementPaddingVer, availableWidth = parentElementWidth - elementPaddingHor, container = term.rowContainer, subjectRow = term.rowContainer.firstElementChild, contentBuffer = subjectRow.innerHTML, characterHeight, rows, characterWidth, cols, geometry; + subjectRow.style.display = 'inline'; + subjectRow.innerHTML = 'W'; // Common character for measuring width, although on monospace + characterWidth = subjectRow.getBoundingClientRect().width; + subjectRow.style.display = ''; // Revert style before calculating height, since they differ. + characterHeight = parseInt(subjectRow.offsetHeight); + subjectRow.innerHTML = contentBuffer; + rows = parseInt(availableHeight / characterHeight); + cols = parseInt(availableWidth / characterWidth) - 1; + geometry = { cols: cols, rows: rows }; + return geometry; + }; + exports.fit = function (term) { + var geometry = exports.proposeGeometry(term); + term.resize(geometry.cols, geometry.rows); + }; + Xterm.prototype.proposeGeometry = function () { + return exports.proposeGeometry(this); + }; + Xterm.prototype.fit = function () { + return exports.fit(this); + }; + return exports; +}); +//# sourceMappingURL=fit.js.map \ No newline at end of file diff --git a/dist/addons/fullscreen/fullscreen.css b/dist/addons/fullscreen/fullscreen.css new file mode 100644 index 00000000..60e8c511 --- /dev/null +++ b/dist/addons/fullscreen/fullscreen.css @@ -0,0 +1,10 @@ +.xterm.fullscreen { + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + width: auto; + height: auto; + z-index: 255; +} diff --git a/dist/addons/fullscreen/fullscreen.js b/dist/addons/fullscreen/fullscreen.js new file mode 100644 index 00000000..a3227217 --- /dev/null +++ b/dist/addons/fullscreen/fullscreen.js @@ -0,0 +1,50 @@ +/** + * Fullscreen addon for xterm.js + * @module xterm/addons/fullscreen/fullscreen + * @license MIT + */ +(function (fullscreen) { + if (typeof exports === 'object' && typeof module === 'object') { + /* + * CommonJS environment + */ + module.exports = fullscreen(require('../../xterm')); + } + else if (typeof define == 'function') { + /* + * Require.js is available + */ + define(['../../xterm'], fullscreen); + } + else { + /* + * Plain browser environment + */ + fullscreen(window.Terminal); + } +})(function (Xterm) { + var exports = {}; + /** + * Toggle the given terminal's fullscreen mode. + * @param {Xterm} term - The terminal to toggle full screen mode + * @param {boolean} fullscreen - Toggle fullscreen on (true) or off (false) + */ + exports.toggleFullScreen = function (term, fullscreen) { + var fn; + if (typeof fullscreen == 'undefined') { + fn = (term.element.classList.contains('fullscreen')) ? 'remove' : 'add'; + } + else if (!fullscreen) { + fn = 'remove'; + } + else { + fn = 'add'; + } + term.element.classList[fn]('fullscreen'); + }; + Xterm.prototype.toggleFullscreen = function (fullscreen) { + exports.toggleFullScreen(this, fullscreen); + }; + return exports; +}); +//# sourceMappingURL=fullscreen.js.map \ No newline at end of file diff --git a/dist/addons/linkify/linkify.js b/dist/addons/linkify/linkify.js new file mode 100644 index 00000000..d3a6933d --- /dev/null +++ b/dist/addons/linkify/linkify.js @@ -0,0 +1,165 @@ +/** + * Methods for turning URL subscrings in the terminal's content into links (`a` DOM elements). + * @module xterm/addons/linkify/linkify + * @license MIT + */ +(function (linkify) { + if (typeof exports === 'object' && typeof module === 'object') { + /* + * CommonJS environment + */ + module.exports = linkify(require('../../xterm')); + } + else if (typeof define == 'function') { + /* + * Require.js is available + */ + define(['../../xterm'], linkify); + } + else { + /* + * Plain browser environment + */ + linkify(window.Terminal); + } +})(function (Xterm) { + 'use strict'; + var exports = {}, protocolClause = '(https?:\\/\\/)', domainCharacterSet = '[\\da-z\\.-]+', negatedDomainCharacterSet = '[^\\da-z\\.-]+', domainBodyClause = '(' + domainCharacterSet + ')', tldClause = '([a-z\\.]{2,6})', ipClause = '((\\d{1,3}\\.){3}\\d{1,3})', portClause = '(:\\d{1,5})', hostClause = '((' + domainBodyClause + '\\.' + tldClause + ')|' + ipClause + ')' + portClause + '?', pathClause = '(\\/[\\/\\w\\.-]*)*', negatedPathCharacterSet = '[^\\/\\w\\.-]+', bodyClause = hostClause + pathClause, start = '(?:^|' + negatedDomainCharacterSet + ')(', end = ')($|' + negatedPathCharacterSet + ')', lenientUrlClause = start + protocolClause + '?' + bodyClause + end, strictUrlClause = start + protocolClause + bodyClause + end, lenientUrlRegex = new RegExp(lenientUrlClause), strictUrlRegex = new RegExp(strictUrlClause); + /** + * Converts all valid URLs found in the given terminal line into + * hyperlinks. The terminal line can be either the HTML element itself + * or the index of the termina line in the children of the terminal + * rows container. + * + * @param {Xterm} terminal - The terminal that owns the given line. + * @param {number|HTMLDivElement} line - The terminal line that should get + * "linkified". + * @param {boolean} lenient - The regex type that will be used to identify links. If lenient is + * false, the regex requires a protocol clause. Defaults to true. + * @param {string} target - Sets target="" attribute with value provided to links. + * Default doesn't set target attribute + * @emits linkify + * @emits linkify:line + */ + exports.linkifyTerminalLine = function (terminal, line, lenient, target) { + if (typeof line == 'number') { + line = terminal.rowContainer.children[line]; + } + else if (!(line instanceof HTMLDivElement)) { + var message = 'The "line" argument should be either a number'; + message += ' or an HTMLDivElement'; + throw new TypeError(message); + } + if (typeof target === 'undefined') { + target = ''; + } + else { + target = 'target="' + target + '"'; + } + var buffer = document.createElement('span'), nodes = line.childNodes; + for (var j = 0; j < nodes.length; j++) { + var node = nodes[j], match; + /** + * Since we cannot access the TextNode's HTML representation + * from the instance itself, we assign its data as textContent + * to a dummy buffer span, in order to retrieve the TextNode's + * HTML representation from the buffer's innerHTML. + */ + buffer.textContent = node.data; + var nodeHTML = buffer.innerHTML; + /** + * Apply function only on TextNodes + */ + if (node.nodeType != node.TEXT_NODE) { + continue; + } + var url = exports.findLinkMatch(node.data, lenient); + if (!url) { + continue; + } + var startsWithProtocol = new RegExp('^' + protocolClause), urlHasProtocol = url.match(startsWithProtocol), href = (urlHasProtocol) ? url : 'http://' + url, link = '' + url + '', newHTML = nodeHTML.replace(url, link); + line.innerHTML = line.innerHTML.replace(nodeHTML, newHTML); + } + /** + * This event gets emitted when conversion of all URL susbtrings + * to HTML anchor elements (links) has finished, for a specific + * line of the current Xterm instance. + * + * @event linkify:line + */ + terminal.emit('linkify:line', line); + }; + /** + * Finds a link within a block of text. + * + * @param {string} text - The text to search . + * @param {boolean} lenient - Whether to use the lenient search. + * @return {string} A URL. + */ + exports.findLinkMatch = function (text, lenient) { + var match = text.match(lenient ? lenientUrlRegex : strictUrlRegex); + if (!match || match.length === 0) { + return null; + } + return match[1]; + }; + /** + * Converts all valid URLs found in the terminal view into hyperlinks. + * + * @param {Xterm} terminal - The terminal that should get "linkified". + * @param {boolean} lenient - The regex type that will be used to identify links. If lenient is + * false, the regex requires a protocol clause. Defaults to true. + * @param {string} target - Sets target="" attribute with value provided to links. + * Default doesn't set target attribute + * @emits linkify + * @emits linkify:line + */ + exports.linkify = function (terminal, lenient, target) { + var rows = terminal.rowContainer.children; + lenient = (typeof lenient == "boolean") ? lenient : true; + for (var i = 0; i < rows.length; i++) { + var line = rows[i]; + exports.linkifyTerminalLine(terminal, line, lenient, target); + } + /** + * This event gets emitted when conversion of all URL substrings to + * HTML anchor elements (links) has finished for the current Xterm + * instance's view. + * + * @event linkify + */ + terminal.emit('linkify'); + }; + /** + * Extend Xterm prototype. + */ + /** + * Converts all valid URLs found in the current terminal linte into + * hyperlinks. + * + * @memberof Xterm + * @param {number|HTMLDivElement} line - The terminal line that should get + * "linkified". + * @param {boolean} lenient - The regex type that will be used to identify links. If lenient is + * false, the regex requires a protocol clause. Defaults to true. + * @param {string} target - Sets target="" attribute with value provided to links. + * Default doesn't set target attribute + */ + Xterm.prototype.linkifyTerminalLine = function (line, lenient, target) { + return exports.linkifyTerminalLine(this, line, lenient, target); + }; + /** + * Converts all valid URLs found in the current terminal into hyperlinks. + * + * @memberof Xterm + * @param {boolean} lenient - The regex type that will be used to identify links. If lenient is + * false, the regex requires a protocol clause. Defaults to true. + * @param {string} target - Sets target="" attribute with value provided to links. + * Default doesn't set target attribute + */ + Xterm.prototype.linkify = function (lenient, target) { + return exports.linkify(this, lenient, target); + }; + return exports; +}); +//# sourceMappingURL=linkify.js.map \ No newline at end of file diff --git a/dist/addons/terminado/terminado.js b/dist/addons/terminado/terminado.js new file mode 100644 index 00000000..73183a6a --- /dev/null +++ b/dist/addons/terminado/terminado.js @@ -0,0 +1,122 @@ +/** + * This module provides methods for attaching a terminal to a terminado WebSocket stream. + * + * @module xterm/addons/terminado/terminado + * @license MIT + */ +(function (attach) { + if (typeof exports === 'object' && typeof module === 'object') { + /* + * CommonJS environment + */ + module.exports = attach(require('../../xterm')); + } + else if (typeof define == 'function') { + /* + * Require.js is available + */ + define(['../../xterm'], attach); + } + else { + /* + * Plain browser environment + */ + attach(window.Terminal); + } +})(function (Xterm) { + 'use strict'; + var exports = {}; + /** + * Attaches the given terminal to the given socket. + * + * @param {Xterm} term - The terminal to be attached to the given socket. + * @param {WebSocket} socket - The socket to attach the current terminal. + * @param {boolean} bidirectional - Whether the terminal should send data + * to the socket as well. + * @param {boolean} buffered - Whether the rendering of incoming data + * should happen instantly or at a maximum + * frequency of 1 rendering per 10ms. + */ + exports.terminadoAttach = function (term, socket, bidirectional, buffered) { + bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional; + term.socket = socket; + term._flushBuffer = function () { + term.write(term._attachSocketBuffer); + term._attachSocketBuffer = null; + clearTimeout(term._attachSocketBufferTimer); + term._attachSocketBufferTimer = null; + }; + term._pushToBuffer = function (data) { + if (term._attachSocketBuffer) { + term._attachSocketBuffer += data; + } + else { + term._attachSocketBuffer = data; + setTimeout(term._flushBuffer, 10); + } + }; + term._getMessage = function (ev) { + var data = JSON.parse(ev.data); + if (data[0] == "stdout") { + if (buffered) { + term._pushToBuffer(data[1]); + } + else { + term.write(data[1]); + } + } + }; + term._sendData = function (data) { + socket.send(JSON.stringify(['stdin', data])); + }; + term._setSize = function (size) { + socket.send(JSON.stringify(['set_size', size.rows, size.cols])); + }; + socket.addEventListener('message', term._getMessage); + if (bidirectional) { + term.on('data', term._sendData); + } + term.on('resize', term._setSize); + socket.addEventListener('close', term.terminadoDetach.bind(term, socket)); + socket.addEventListener('error', term.terminadoDetach.bind(term, socket)); + }; + /** + * Detaches the given terminal from the given socket + * + * @param {Xterm} term - The terminal to be detached from the given socket. + * @param {WebSocket} socket - The socket from which to detach the current + * terminal. + */ + exports.terminadoDetach = function (term, socket) { + term.off('data', term._sendData); + socket = (typeof socket == 'undefined') ? term.socket : socket; + if (socket) { + socket.removeEventListener('message', term._getMessage); + } + delete term.socket; + }; + /** + * Attaches the current terminal to the given socket + * + * @param {WebSocket} socket - The socket to attach the current terminal. + * @param {boolean} bidirectional - Whether the terminal should send data + * to the socket as well. + * @param {boolean} buffered - Whether the rendering of incoming data + * should happen instantly or at a maximum + * frequency of 1 rendering per 10ms. + */ + Xterm.prototype.terminadoAttach = function (socket, bidirectional, buffered) { + return exports.terminadoAttach(this, socket, bidirectional, buffered); + }; + /** + * Detaches the current terminal from the given socket. + * + * @param {WebSocket} socket - The socket from which to detach the current + * terminal. + */ + Xterm.prototype.terminadoDetach = function (socket) { + return exports.terminadoDetach(this, socket); + }; + return exports; +}); +//# sourceMappingURL=terminado.js.map \ No newline at end of file From 60a59be4d3717c0a97d292ef64a65377d54407e8 Mon Sep 17 00:00:00 2001 From: Paris Kasidiaris Date: Wed, 7 Dec 2016 18:43:03 +0000 Subject: [PATCH 22/24] Bump version to 2.2.1 Signed-off-by: Paris Kasidiaris --- bower.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bower.json b/bower.json index 4bb8b471..c33f4702 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "xterm.js", - "version": "2.2.0", + "version": "2.2.1", "ignore": ["demo", "test", ".gitignore"], "main": [ "dist/xterm.js", diff --git a/package.json b/package.json index 30b90f23..04bc552f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xterm", - "version": "2.2.0", + "version": "2.2.1", "ignore": [ "demo", "test", From a75bafc4ba1a03fa70a38c0be86c023d50f1bf76 Mon Sep 17 00:00:00 2001 From: bottleofwater Date: Fri, 9 Dec 2016 10:52:09 +0100 Subject: [PATCH 23/24] Don't apply the 32 delta when in sgr mode - fix #394 --- src/xterm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xterm.js b/src/xterm.js index 7f1bf63c..dc1c7331 100644 --- a/src/xterm.js +++ b/src/xterm.js @@ -785,7 +785,7 @@ Terminal.prototype.bindMouse = function() { pos.x -= 32; pos.y -= 32; self.send('\x1b[<' - + ((button & 3) === 3 ? button & ~3 : button) + + (((button & 3) === 3 ? button & ~3 : button) - 32) + ';' + pos.x + ';' From e0e6f5e302a86a73554ca1ccd60e038710a49ae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Sat, 10 Dec 2016 14:46:01 +0100 Subject: [PATCH 24/24] Use a fixed size to account for the scrollbar --- src/addons/fit/fit.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/addons/fit/fit.js b/src/addons/fit/fit.js index 7b0ac14f..cacd9202 100644 --- a/src/addons/fit/fit.js +++ b/src/addons/fit/fit.js @@ -34,7 +34,7 @@ exports.proposeGeometry = function (term) { var parentElementStyle = window.getComputedStyle(term.element.parentElement), parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')), - parentElementWidth = parseInt(parentElementStyle.getPropertyValue('width')), + parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')) - 17), elementStyle = window.getComputedStyle(term.element), elementPaddingVer = parseInt(elementStyle.getPropertyValue('padding-top')) + parseInt(elementStyle.getPropertyValue('padding-bottom')), elementPaddingHor = parseInt(elementStyle.getPropertyValue('padding-right')) + parseInt(elementStyle.getPropertyValue('padding-left')), @@ -57,7 +57,7 @@ subjectRow.innerHTML = contentBuffer; rows = parseInt(availableHeight / characterHeight); - cols = parseInt(availableWidth / characterWidth) - 1; + cols = parseInt(availableWidth / characterWidth); geometry = {cols: cols, rows: rows}; return geometry;