/**1* term.js - an xterm emulator2* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)3* https://github.com/chjj/term.js4*5* Permission is hereby granted, free of charge, to any person obtaining a copy6* of this software and associated documentation files (the "Software"), to deal7* in the Software without restriction, including without limitation the rights8* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell9* copies of the Software, and to permit persons to whom the Software is10* furnished to do so, subject to the following conditions:11*12* The above copyright notice and this permission notice shall be included in13* all copies or substantial portions of the Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE18* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER19* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,20* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN21* THE SOFTWARE.22*23* Originally forked from (with the author's permission):24* Fabrice Bellard's javascript vt100 for jslinux:25* http://bellard.org/jslinux/26* Copyright (c) 2011 Fabrice Bellard27* The original design remains. The terminal itself28* has been extended to include xterm CSI codes, among29* other features.30*/3132;(function() {3334/**35* Terminal Emulation References:36* http://vt100.net/37* http://invisible-island.net/xterm/ctlseqs/ctlseqs.txt38* http://invisible-island.net/xterm/ctlseqs/ctlseqs.html39* http://invisible-island.net/vttest/40* http://www.inwap.com/pdp10/ansicode.txt41* http://linux.die.net/man/4/console_codes42* http://linux.die.net/man/7/urxvt43*/4445'use strict';4647/**48* Shared49*/5051var window = this52, document = this.document;5354/**55* EventEmitter56*/5758function EventEmitter() {59this._events = this._events || {};60}6162EventEmitter.prototype.addListener = function(type, listener) {63this._events[type] = this._events[type] || [];64this._events[type].push(listener);65};6667EventEmitter.prototype.on = EventEmitter.prototype.addListener;6869EventEmitter.prototype.removeListener = function(type, listener) {70if (!this._events[type]) return;7172var obj = this._events[type]73, i = obj.length;7475while (i--) {76if (obj[i] === listener || obj[i].listener === listener) {77obj.splice(i, 1);78return;79}80}81};8283EventEmitter.prototype.off = EventEmitter.prototype.removeListener;8485EventEmitter.prototype.removeAllListeners = function(type) {86if (this._events[type]) delete this._events[type];87};8889EventEmitter.prototype.once = function(type, listener) {90function on() {91var args = Array.prototype.slice.call(arguments);92this.removeListener(type, on);93return listener.apply(this, args);94}95on.listener = listener;96return this.on(type, on);97};9899EventEmitter.prototype.emit = function(type) {100if (!this._events[type]) return;101102var args = Array.prototype.slice.call(arguments, 1)103, obj = this._events[type]104, l = obj.length105, i = 0;106107for (; i < l; i++) {108obj[i].apply(this, args);109}110};111112EventEmitter.prototype.listeners = function(type) {113return this._events[type] = this._events[type] || [];114};115116/**117* States118*/119120var normal = 0121, escaped = 1122, csi = 2123, osc = 3124, charset = 4125, dcs = 5126, ignore = 6;127128/**129* Terminal130*/131132function Terminal(options) {133var self = this;134135if (!(this instanceof Terminal)) {136return new Terminal(arguments[0], arguments[1], arguments[2]);137}138139EventEmitter.call(this);140141if (typeof options === 'number') {142options = {143cols: arguments[0],144rows: arguments[1],145handler: arguments[2]146};147}148149options = options || {};150151each(keys(Terminal.defaults), function(key) {152if (options[key] == null) {153options[key] = Terminal.options[key];154// Legacy:155if (Terminal[key] !== Terminal.defaults[key]) {156options[key] = Terminal[key];157}158}159self[key] = options[key];160});161162if (options.colors.length === 8) {163options.colors = options.colors.concat(Terminal._colors.slice(8));164} else if (options.colors.length === 16) {165options.colors = options.colors.concat(Terminal._colors.slice(16));166} else if (options.colors.length === 10) {167options.colors = options.colors.slice(0, -2).concat(168Terminal._colors.slice(8, -2), options.colors.slice(-2));169} else if (options.colors.length === 18) {170options.colors = options.colors.concat(171Terminal._colors.slice(16, -2), options.colors.slice(-2));172}173this.colors = options.colors;174175this.options = options;176177// this.context = options.context || window;178// this.document = options.document || document;179this.parent = options.body || options.parent180|| (document ? document.getElementsByTagName('body')[0] : null);181182this.cols = options.cols || options.geometry[0];183this.rows = options.rows || options.geometry[1];184185if (options.handler) {186this.on('data', options.handler);187}188189this.ybase = 0;190this.ydisp = 0;191this.x = 0;192this.y = 0;193this.cursorState = 0;194this.cursorHidden = false;195this.convertEol;196this.state = 0;197this.queue = '';198this.scrollTop = 0;199this.scrollBottom = this.rows - 1;200201// modes202this.applicationKeypad = false;203this.applicationCursor = false;204this.originMode = false;205this.insertMode = false;206this.wraparoundMode = false;207this.normal = null;208209// select modes210this.prefixMode = false;211this.selectMode = false;212this.visualMode = false;213this.searchMode = false;214this.searchDown;215this.entry = '';216this.entryPrefix = 'Search: ';217this._real;218this._selected;219this._textarea;220221// charset222this.charset = null;223this.gcharset = null;224this.glevel = 0;225this.charsets = [null];226227// mouse properties228this.decLocator;229this.x10Mouse;230this.vt200Mouse;231this.vt300Mouse;232this.normalMouse;233this.mouseEvents;234this.sendFocus;235this.utfMouse;236this.sgrMouse;237this.urxvtMouse;238239// misc240this.element;241this.children;242this.refreshStart;243this.refreshEnd;244this.savedX;245this.savedY;246this.savedCols;247248// stream249this.readable = true;250this.writable = true;251252this.defAttr = (0 << 18) | (257 << 9) | (256 << 0);253this.curAttr = this.defAttr;254255this.params = [];256this.currentParam = 0;257this.prefix = '';258this.postfix = '';259260this.lines = [];261var i = this.rows;262while (i--) {263this.lines.push(this.blankLine());264}265266this.tabs;267this.setupStops();268}269270inherits(Terminal, EventEmitter);271272// back_color_erase feature for xterm.273Terminal.prototype.eraseAttr = function() {274// if (this.is('screen')) return this.defAttr;275return (this.defAttr & ~0x1ff) | (this.curAttr & 0x1ff);276};277278/**279* Colors280*/281282// Colors 0-15283Terminal.tangoColors = [284// dark:285'#2e3436',286'#cc0000',287'#4e9a06',288'#c4a000',289'#3465a4',290'#75507b',291'#06989a',292'#d3d7cf',293// bright:294'#555753',295'#ef2929',296'#8ae234',297'#fce94f',298'#729fcf',299'#ad7fa8',300'#34e2e2',301'#eeeeec'302];303304Terminal.xtermColors = [305// dark:306'#000000', // black307'#cd0000', // red3308'#00cd00', // green3309'#cdcd00', // yellow3310'#0000ee', // blue2311'#cd00cd', // magenta3312'#00cdcd', // cyan3313'#e5e5e5', // gray90314// bright:315'#7f7f7f', // gray50316'#ff0000', // red317'#00ff00', // green318'#ffff00', // yellow319'#5c5cff', // rgb:5c/5c/ff320'#ff00ff', // magenta321'#00ffff', // cyan322'#ffffff' // white323];324325// Colors 0-15 + 16-255326// Much thanks to TooTallNate for writing this.327Terminal.colors = (function() {328var colors = Terminal.tangoColors.slice()329, r = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff]330, i;331332// 16-231333i = 0;334for (; i < 216; i++) {335out(r[(i / 36) % 6 | 0], r[(i / 6) % 6 | 0], r[i % 6]);336}337338// 232-255 (grey)339i = 0;340for (; i < 24; i++) {341r = 8 + i * 10;342out(r, r, r);343}344345function out(r, g, b) {346colors.push('#' + hex(r) + hex(g) + hex(b));347}348349function hex(c) {350c = c.toString(16);351return c.length < 2 ? '0' + c : c;352}353354return colors;355})();356357// Default BG/FG358Terminal.colors[256] = '#000000';359Terminal.colors[257] = '#f0f0f0';360361Terminal._colors = Terminal.colors.slice();362363Terminal.vcolors = (function() {364var out = []365, colors = Terminal.colors366, i = 0367, color;368369for (; i < 256; i++) {370color = parseInt(colors[i].substring(1), 16);371out.push([372(color >> 16) & 0xff,373(color >> 8) & 0xff,374color & 0xff375]);376}377378return out;379})();380381/**382* Options383*/384385Terminal.defaults = {386colors: Terminal.colors,387convertEol: false,388termName: 'xterm',389geometry: [80, 24],390cursorBlink: true,391visualBell: false,392popOnBell: false,393scrollback: 1000,394screenKeys: false,395debug: false,396useStyle: false397// programFeatures: false,398// focusKeys: false,399};400401Terminal.options = {};402403each(keys(Terminal.defaults), function(key) {404Terminal[key] = Terminal.defaults[key];405Terminal.options[key] = Terminal.defaults[key];406});407408/**409* Focused Terminal410*/411412Terminal.focus = null;413414Terminal.prototype.focus = function() {415if (Terminal.focus === this) return;416417if (Terminal.focus) {418Terminal.focus.blur();419}420421if (this.sendFocus) this.send('\x1b[I');422this.showCursor();423424// try {425// this.element.focus();426// } catch (e) {427// ;428// }429430// this.emit('focus');431432Terminal.focus = this;433};434435Terminal.prototype.blur = function() {436if (Terminal.focus !== this) return;437438this.cursorState = 0;439this.refresh(this.y, this.y);440if (this.sendFocus) this.send('\x1b[O');441442// try {443// this.element.blur();444// } catch (e) {445// ;446// }447448// this.emit('blur');449450Terminal.focus = null;451};452453/**454* Initialize global behavior455*/456457Terminal.prototype.initGlobal = function() {458var document = this.document;459460Terminal._boundDocs = Terminal._boundDocs || [];461if (~indexOf(Terminal._boundDocs, document)) {462return;463}464Terminal._boundDocs.push(document);465466Terminal.bindPaste(document);467468Terminal.bindKeys(document);469470Terminal.bindCopy(document);471472if (this.isIpad || this.isIphone) {473Terminal.fixIpad(document);474}475476if (this.useStyle) {477Terminal.insertStyle(document, this.colors[256], this.colors[257]);478}479};480481/**482* Bind to paste event483*/484485Terminal.bindPaste = function(document) {486// This seems to work well for ctrl-V and middle-click,487// even without the contentEditable workaround.488var window = document.defaultView;489on(window, 'paste', function(ev) {490var term = Terminal.focus;491if (!term) return;492if (ev.clipboardData) {493term.send(ev.clipboardData.getData('text/plain'));494} else if (term.context.clipboardData) {495term.send(term.context.clipboardData.getData('Text'));496}497// Not necessary. Do it anyway for good measure.498term.element.contentEditable = 'inherit';499return cancel(ev);500});501};502503/**504* Global Events for key handling505*/506507Terminal.bindKeys = function(document) {508// We should only need to check `target === body` below,509// but we can check everything for good measure.510on(document, 'keydown', function(ev) {511if (!Terminal.focus) return;512var target = ev.target || ev.srcElement;513if (!target) return;514if (target === Terminal.focus.element515|| target === Terminal.focus.context516|| target === Terminal.focus.document517|| target === Terminal.focus.body518|| target === Terminal._textarea519|| target === Terminal.focus.parent) {520return Terminal.focus.keyDown(ev);521}522}, true);523524on(document, 'keypress', function(ev) {525if (!Terminal.focus) return;526var target = ev.target || ev.srcElement;527if (!target) return;528if (target === Terminal.focus.element529|| target === Terminal.focus.context530|| target === Terminal.focus.document531|| target === Terminal.focus.body532|| target === Terminal._textarea533|| target === Terminal.focus.parent) {534return Terminal.focus.keyPress(ev);535}536}, true);537538// If we click somewhere other than a539// terminal, unfocus the terminal.540on(document, 'mousedown', function(ev) {541if (!Terminal.focus) return;542543var el = ev.target || ev.srcElement;544if (!el) return;545546do {547if (el === Terminal.focus.element) return;548} while (el = el.parentNode);549550Terminal.focus.blur();551});552};553554/**555* Copy Selection w/ Ctrl-C (Select Mode)556*/557558Terminal.bindCopy = function(document) {559var window = document.defaultView;560561// if (!('onbeforecopy' in document)) {562// // Copies to *only* the clipboard.563// on(window, 'copy', function fn(ev) {564// var term = Terminal.focus;565// if (!term) return;566// if (!term._selected) return;567// var text = term.grabText(568// term._selected.x1, term._selected.x2,569// term._selected.y1, term._selected.y2);570// term.emit('copy', text);571// ev.clipboardData.setData('text/plain', text);572// });573// return;574// }575576// Copies to primary selection *and* clipboard.577// NOTE: This may work better on capture phase,578// or using the `beforecopy` event.579on(window, 'copy', function(ev) {580var term = Terminal.focus;581if (!term) return;582if (!term._selected) return;583var textarea = term.getCopyTextarea();584var text = term.grabText(585term._selected.x1, term._selected.x2,586term._selected.y1, term._selected.y2);587term.emit('copy', text);588textarea.focus();589textarea.textContent = text;590textarea.value = text;591textarea.setSelectionRange(0, text.length);592setTimeout(function() {593term.element.focus();594term.focus();595}, 1);596});597};598599/**600* Fix iPad - no idea if this works601*/602603Terminal.fixIpad = function(document) {604var textarea = document.createElement('textarea');605textarea.style.position = 'absolute';606textarea.style.left = '-32000px';607textarea.style.top = '-32000px';608textarea.style.width = '0px';609textarea.style.height = '0px';610textarea.style.opacity = '0';611textarea.style.backgroundColor = 'transparent';612textarea.style.borderStyle = 'none';613textarea.style.outlineStyle = 'none';614textarea.autocapitalize = 'none';615textarea.autocorrect = 'off';616617document.getElementsByTagName('body')[0].appendChild(textarea);618619Terminal._textarea = textarea;620621setTimeout(function() {622textarea.focus();623}, 1000);624};625626/**627* Insert a default style628*/629630Terminal.insertStyle = function(document, bg, fg) {631var style = document.getElementById('term-style');632if (style) return;633634var head = document.getElementsByTagName('head')[0];635if (!head) return;636637var style = document.createElement('style');638style.id = 'term-style';639640// textContent doesn't work well with IE for <style> elements.641style.innerHTML = ''642+ '.terminal {\n'643+ ' float: left;\n'644+ ' border: ' + bg + ' solid 5px;\n'645+ ' font-family: "DejaVu Sans Mono", "Liberation Mono", monospace;\n'646+ ' font-size: 11px;\n'647+ ' color: ' + fg + ';\n'648+ ' background: ' + bg + ';\n'649+ '}\n'650+ '\n'651+ '.terminal-cursor {\n'652+ ' color: ' + bg + ';\n'653+ ' background: ' + fg + ';\n'654+ '}\n';655656// var out = '';657// each(Terminal.colors, function(color, i) {658// if (i === 256) {659// out += '\n.term-bg-color-default { background-color: ' + color + '; }';660// }661// if (i === 257) {662// out += '\n.term-fg-color-default { color: ' + color + '; }';663// }664// out += '\n.term-bg-color-' + i + ' { background-color: ' + color + '; }';665// out += '\n.term-fg-color-' + i + ' { color: ' + color + '; }';666// });667// style.innerHTML += out + '\n';668669head.insertBefore(style, head.firstChild);670};671672/**673* Open Terminal674*/675676Terminal.prototype.open = function(parent) {677var self = this678, i = 0679, div;680681this.parent = parent || this.parent;682683if (!this.parent) {684throw new Error('Terminal requires a parent element.');685}686687// Grab global elements.688this.context = this.parent.ownerDocument.defaultView;689this.document = this.parent.ownerDocument;690this.body = this.document.getElementsByTagName('body')[0];691692// Parse user-agent strings.693if (this.context.navigator && this.context.navigator.userAgent) {694this.isMac = !!~this.context.navigator.userAgent.indexOf('Mac');695this.isIpad = !!~this.context.navigator.userAgent.indexOf('iPad');696this.isIphone = !!~this.context.navigator.userAgent.indexOf('iPhone');697this.isMSIE = !!~this.context.navigator.userAgent.indexOf('MSIE');698}699700// Create our main terminal element.701this.element = this.document.createElement('div');702this.element.className = 'terminal';703this.element.style.outline = 'none';704this.element.setAttribute('tabindex', 0);705this.element.style.backgroundColor = this.colors[256];706this.element.style.color = this.colors[257];707708// Create the lines for our terminal.709this.children = [];710for (; i < this.rows; i++) {711div = this.document.createElement('div');712this.element.appendChild(div);713this.children.push(div);714}715this.parent.appendChild(this.element);716717// Draw the screen.718this.refresh(0, this.rows - 1);719720// Initialize global actions that721// need to be taken on the document.722this.initGlobal();723724// Ensure there is a Terminal.focus.725this.focus();726727// Start blinking the cursor.728this.startBlink();729730// Bind to DOM events related731// to focus and paste behavior.732on(this.element, 'focus', function() {733self.focus();734if (self.isIpad || self.isIphone) {735Terminal._textarea.focus();736}737});738739// This causes slightly funky behavior.740// on(this.element, 'blur', function() {741// self.blur();742// });743744on(this.element, 'mousedown', function() {745self.focus();746});747748// Clickable paste workaround, using contentEditable.749// This probably shouldn't work,750// ... but it does. Firefox's paste751// event seems to only work for textareas?752on(this.element, 'mousedown', function(ev) {753var button = ev.button != null754? +ev.button755: ev.which != null756? ev.which - 1757: null;758759// Does IE9 do this?760if (self.isMSIE) {761button = button === 1 ? 0 : button === 4 ? 1 : button;762}763764if (button !== 2) return;765766self.element.contentEditable = 'true';767setTimeout(function() {768self.element.contentEditable = 'inherit'; // 'false';769}, 1);770}, true);771772// Listen for mouse events and translate773// them into terminal mouse protocols.774this.bindMouse();775776// Figure out whether boldness affects777// the character width of monospace fonts.778if (Terminal.brokenBold == null) {779Terminal.brokenBold = isBoldBroken(this.document);780}781782// this.emit('open');783784// This can be useful for pasting,785// as well as the iPad fix.786setTimeout(function() {787self.element.focus();788}, 100);789};790791// XTerm mouse events792// http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#Mouse%20Tracking793// To better understand these794// the xterm code is very helpful:795// Relevant files:796// button.c, charproc.c, misc.c797// Relevant functions in xterm/button.c:798// BtnCode, EmitButtonCode, EditorButton, SendMousePosition799Terminal.prototype.bindMouse = function() {800var el = this.element801, self = this802, pressed = 32;803804var wheelEvent = 'onmousewheel' in this.context805? 'mousewheel'806: 'DOMMouseScroll';807808// mouseup, mousedown, mousewheel809// left click: ^[[M 3<^[[M#3<810// mousewheel up: ^[[M`3>811function sendButton(ev) {812var button813, pos;814815// get the xterm-style button816button = getButton(ev);817818// get mouse coordinates819pos = getCoords(ev);820if (!pos) return;821822sendEvent(button, pos);823824switch (ev.type) {825case 'mousedown':826pressed = button;827break;828case 'mouseup':829// keep it at the left830// button, just in case.831pressed = 32;832break;833case wheelEvent:834// nothing. don't835// interfere with836// `pressed`.837break;838}839}840841// motion example of a left click:842// ^[[M 3<^[[M@4<^[[M@5<^[[M@6<^[[M@7<^[[M#7<843function sendMove(ev) {844var button = pressed845, pos;846847pos = getCoords(ev);848if (!pos) return;849850// buttons marked as motions851// are incremented by 32852button += 32;853854sendEvent(button, pos);855}856857// encode button and858// position to characters859function encode(data, ch) {860if (!self.utfMouse) {861if (ch === 255) return data.push(0);862if (ch > 127) ch = 127;863data.push(ch);864} else {865if (ch === 2047) return data.push(0);866if (ch < 127) {867data.push(ch);868} else {869if (ch > 2047) ch = 2047;870data.push(0xC0 | (ch >> 6));871data.push(0x80 | (ch & 0x3F));872}873}874}875876// send a mouse event:877// regular/utf8: ^[[M Cb Cx Cy878// urxvt: ^[[ Cb ; Cx ; Cy M879// sgr: ^[[ Cb ; Cx ; Cy M/m880// vt300: ^[[ 24(1/3/5)~ [ Cx , Cy ] \r881// locator: CSI P e ; P b ; P r ; P c ; P p & w882function sendEvent(button, pos) {883// self.emit('mouse', {884// x: pos.x - 32,885// y: pos.x - 32,886// button: button887// });888889if (self.vt300Mouse) {890// NOTE: Unstable.891// http://www.vt100.net/docs/vt3xx-gp/chapter15.html892button &= 3;893pos.x -= 32;894pos.y -= 32;895var data = '\x1b[24';896if (button === 0) data += '1';897else if (button === 1) data += '3';898else if (button === 2) data += '5';899else if (button === 3) return;900else data += '0';901data += '~[' + pos.x + ',' + pos.y + ']\r';902self.send(data);903return;904}905906if (self.decLocator) {907// NOTE: Unstable.908button &= 3;909pos.x -= 32;910pos.y -= 32;911if (button === 0) button = 2;912else if (button === 1) button = 4;913else if (button === 2) button = 6;914else if (button === 3) button = 3;915self.send('\x1b['916+ button917+ ';'918+ (button === 3 ? 4 : 0)919+ ';'920+ pos.y921+ ';'922+ pos.x923+ ';'924+ (pos.page || 0)925+ '&w');926return;927}928929if (self.urxvtMouse) {930pos.x -= 32;931pos.y -= 32;932pos.x++;933pos.y++;934self.send('\x1b[' + button + ';' + pos.x + ';' + pos.y + 'M');935return;936}937938if (self.sgrMouse) {939pos.x -= 32;940pos.y -= 32;941self.send('\x1b[<'942+ ((button & 3) === 3 ? button & ~3 : button)943+ ';'944+ pos.x945+ ';'946+ pos.y947+ ((button & 3) === 3 ? 'm' : 'M'));948return;949}950951var data = [];952953encode(data, button);954encode(data, pos.x);955encode(data, pos.y);956957self.send('\x1b[M' + String.fromCharCode.apply(String, data));958}959960function getButton(ev) {961var button962, shift963, meta964, ctrl965, mod;966967// two low bits:968// 0 = left969// 1 = middle970// 2 = right971// 3 = release972// wheel up/down:973// 1, and 2 - with 64 added974switch (ev.type) {975case 'mousedown':976button = ev.button != null977? +ev.button978: ev.which != null979? ev.which - 1980: null;981982if (self.isMSIE) {983button = button === 1 ? 0 : button === 4 ? 1 : button;984}985break;986case 'mouseup':987button = 3;988break;989case 'DOMMouseScroll':990button = ev.detail < 0991? 64992: 65;993break;994case 'mousewheel':995button = ev.wheelDeltaY > 0996? 64997: 65;998break;999}10001001// next three bits are the modifiers:1002// 4 = shift, 8 = meta, 16 = control1003shift = ev.shiftKey ? 4 : 0;1004meta = ev.metaKey ? 8 : 0;1005ctrl = ev.ctrlKey ? 16 : 0;1006mod = shift | meta | ctrl;10071008// no mods1009if (self.vt200Mouse) {1010// ctrl only1011mod &= ctrl;1012} else if (!self.normalMouse) {1013mod = 0;1014}10151016// increment to SP1017button = (32 + (mod << 2)) + button;10181019return button;1020}10211022// mouse coordinates measured in cols/rows1023function getCoords(ev) {1024var x, y, w, h, el;10251026// ignore browsers without pageX for now1027if (ev.pageX == null) return;10281029x = ev.pageX;1030y = ev.pageY;1031el = self.element;10321033// should probably check offsetParent1034// but this is more portable1035while (el && el !== self.document.documentElement) {1036x -= el.offsetLeft;1037y -= el.offsetTop;1038el = 'offsetParent' in el1039? el.offsetParent1040: el.parentNode;1041}10421043// convert to cols/rows1044w = self.element.clientWidth;1045h = self.element.clientHeight;1046x = Math.round((x / w) * self.cols);1047y = Math.round((y / h) * self.rows);10481049// be sure to avoid sending1050// bad positions to the program1051if (x < 0) x = 0;1052if (x > self.cols) x = self.cols;1053if (y < 0) y = 0;1054if (y > self.rows) y = self.rows;10551056// xterm sends raw bytes and1057// starts at 32 (SP) for each.1058x += 32;1059y += 32;10601061return {1062x: x,1063y: y,1064type: ev.type === wheelEvent1065? 'mousewheel'1066: ev.type1067};1068}10691070on(el, 'mousedown', function(ev) {1071if (!self.mouseEvents) return;10721073// send the button1074sendButton(ev);10751076// ensure focus1077self.focus();10781079// fix for odd bug1080//if (self.vt200Mouse && !self.normalMouse) {1081if (self.vt200Mouse) {1082sendButton({ __proto__: ev, type: 'mouseup' });1083return cancel(ev);1084}10851086// bind events1087if (self.normalMouse) on(self.document, 'mousemove', sendMove);10881089// x10 compatibility mode can't send button releases1090if (!self.x10Mouse) {1091on(self.document, 'mouseup', function up(ev) {1092sendButton(ev);1093if (self.normalMouse) off(self.document, 'mousemove', sendMove);1094off(self.document, 'mouseup', up);1095return cancel(ev);1096});1097}10981099return cancel(ev);1100});11011102//if (self.normalMouse) {1103// on(self.document, 'mousemove', sendMove);1104//}11051106on(el, wheelEvent, function(ev) {1107if (!self.mouseEvents) return;1108if (self.x10Mouse1109|| self.vt300Mouse1110|| self.decLocator) return;1111sendButton(ev);1112return cancel(ev);1113});11141115// allow mousewheel scrolling in1116// the shell for example1117on(el, wheelEvent, function(ev) {1118if (self.mouseEvents) return;1119if (self.applicationKeypad) return;1120if (ev.type === 'DOMMouseScroll') {1121self.scrollDisp(ev.detail < 0 ? -5 : 5);1122} else {1123self.scrollDisp(ev.wheelDeltaY > 0 ? -5 : 5);1124}1125return cancel(ev);1126});1127};11281129/**1130* Destroy Terminal1131*/11321133Terminal.prototype.destroy = function() {1134this.readable = false;1135this.writable = false;1136this._events = {};1137this.handler = function() {};1138this.write = function() {};1139if (this.element.parentNode) {1140this.element.parentNode.removeChild(this.element);1141}1142//this.emit('close');1143};11441145/**1146* Rendering Engine1147*/11481149// In the screen buffer, each character1150// is stored as a an array with a character1151// and a 32-bit integer.1152// First value: a utf-16 character.1153// Second value:1154// Next 9 bits: background color (0-511).1155// Next 9 bits: foreground color (0-511).1156// Next 14 bits: a mask for misc. flags:1157// 1=bold, 2=underline, 4=blink, 8=inverse, 16=invisible11581159Terminal.prototype.refresh = function(start, end) {1160var x1161, y1162, i1163, line1164, out1165, ch1166, width1167, data1168, attr1169, bg1170, fg1171, flags1172, row1173, parent;11741175if (end - start >= this.rows / 2) {1176parent = this.element.parentNode;1177if (parent) parent.removeChild(this.element);1178}11791180width = this.cols;1181y = start;11821183if (end >= this.lines.length) {1184this.log('`end` is too large. Most likely a bad CSR.');1185end = this.lines.length - 1;1186}11871188for (; y <= end; y++) {1189row = y + this.ydisp;11901191line = this.lines[row];1192out = '';11931194if (y === this.y1195&& this.cursorState1196&& (this.ydisp === this.ybase || this.selectMode)1197&& !this.cursorHidden) {1198x = this.x;1199} else {1200x = -1;1201}12021203attr = this.defAttr;1204i = 0;12051206for (; i < width; i++) {1207data = line[i][0];1208ch = line[i][1];12091210if (i === x) data = -1;12111212if (data !== attr) {1213if (attr !== this.defAttr) {1214out += '</span>';1215}1216if (data !== this.defAttr) {1217if (data === -1) {1218out += '<span class="reverse-video terminal-cursor">';1219} else {1220out += '<span style="';12211222bg = data & 0x1ff;1223fg = (data >> 9) & 0x1ff;1224flags = data >> 18;12251226// bold1227if (flags & 1) {1228if (!Terminal.brokenBold) {1229out += 'font-weight:bold;';1230}1231// See: XTerm*boldColors1232if (fg < 8) fg += 8;1233}12341235// underline1236if (flags & 2) {1237out += 'text-decoration:underline;';1238}12391240// blink1241if (flags & 4) {1242if (flags & 2) {1243out = out.slice(0, -1);1244out += ' blink;';1245} else {1246out += 'text-decoration:blink;';1247}1248}12491250// inverse1251if (flags & 8) {1252bg = (data >> 9) & 0x1ff;1253fg = data & 0x1ff;1254// Should inverse just be before the1255// above boldColors effect instead?1256if ((flags & 1) && fg < 8) fg += 8;1257}12581259// invisible1260if (flags & 16) {1261out += 'visibility:hidden;';1262}12631264// out += '" class="'1265// + 'term-bg-color-' + bg1266// + ' '1267// + 'term-fg-color-' + fg1268// + '">';12691270if (bg !== 256) {1271out += 'background-color:'1272+ this.colors[bg]1273+ ';';1274}12751276if (fg !== 257) {1277out += 'color:'1278+ this.colors[fg]1279+ ';';1280}12811282out += '">';1283}1284}1285}12861287switch (ch) {1288case '&':1289out += '&';1290break;1291case '<':1292out += '<';1293break;1294case '>':1295out += '>';1296break;1297default:1298if (ch <= ' ') {1299out += ' ';1300} else {1301if (isWide(ch)) i++;1302out += ch;1303}1304break;1305}13061307attr = data;1308}13091310if (attr !== this.defAttr) {1311out += '</span>';1312}13131314this.children[y].innerHTML = out;1315}13161317if (parent) parent.appendChild(this.element);1318};13191320Terminal.prototype._cursorBlink = function() {1321if (Terminal.focus !== this) return;1322this.cursorState ^= 1;1323this.refresh(this.y, this.y);1324};13251326Terminal.prototype.showCursor = function() {1327if (!this.cursorState) {1328this.cursorState = 1;1329this.refresh(this.y, this.y);1330} else {1331// Temporarily disabled:1332// this.refreshBlink();1333}1334};13351336Terminal.prototype.startBlink = function() {1337if (!this.cursorBlink) return;1338var self = this;1339this._blinker = function() {1340self._cursorBlink();1341};1342this._blink = setInterval(this._blinker, 500);1343};13441345Terminal.prototype.refreshBlink = function() {1346if (!this.cursorBlink) return;1347clearInterval(this._blink);1348this._blink = setInterval(this._blinker, 500);1349};13501351Terminal.prototype.scroll = function() {1352var row;13531354if (++this.ybase === this.scrollback) {1355this.ybase = this.ybase / 2 | 0;1356this.lines = this.lines.slice(-(this.ybase + this.rows) + 1);1357}13581359this.ydisp = this.ybase;13601361// last line1362row = this.ybase + this.rows - 1;13631364// subtract the bottom scroll region1365row -= this.rows - 1 - this.scrollBottom;13661367if (row === this.lines.length) {1368// potential optimization:1369// pushing is faster than splicing1370// when they amount to the same1371// behavior.1372this.lines.push(this.blankLine());1373} else {1374// add our new line1375this.lines.splice(row, 0, this.blankLine());1376}13771378if (this.scrollTop !== 0) {1379if (this.ybase !== 0) {1380this.ybase--;1381this.ydisp = this.ybase;1382}1383this.lines.splice(this.ybase + this.scrollTop, 1);1384}13851386// this.maxRange();1387this.updateRange(this.scrollTop);1388this.updateRange(this.scrollBottom);1389};13901391Terminal.prototype.scrollDisp = function(disp) {1392this.ydisp += disp;13931394if (this.ydisp > this.ybase) {1395this.ydisp = this.ybase;1396} else if (this.ydisp < 0) {1397this.ydisp = 0;1398}13991400this.refresh(0, this.rows - 1);1401};14021403Terminal.prototype.write = function(data) {1404var l = data.length1405, i = 01406, j1407, cs1408, ch;14091410this.refreshStart = this.y;1411this.refreshEnd = this.y;14121413if (this.ybase !== this.ydisp) {1414this.ydisp = this.ybase;1415this.maxRange();1416}14171418// this.log(JSON.stringify(data.replace(/\x1b/g, '^[')));14191420for (; i < l; i++) {1421ch = data[i];1422switch (this.state) {1423case normal:1424switch (ch) {1425// '\0'1426// case '\0':1427// case '\200':1428// break;14291430// '\a'1431case '\x07':1432this.bell();1433break;14341435// '\n', '\v', '\f'1436case '\n':1437case '\x0b':1438case '\x0c':1439if (this.convertEol) {1440this.x = 0;1441}1442// TODO: Implement eat_newline_glitch.1443// if (this.realX >= this.cols) break;1444// this.realX = 0;1445this.y++;1446if (this.y > this.scrollBottom) {1447this.y--;1448this.scroll();1449}1450break;14511452// '\r'1453case '\r':1454this.x = 0;1455break;14561457// '\b'1458case '\x08':1459if (this.x > 0) {1460this.x--;1461}1462break;14631464// '\t'1465case '\t':1466this.x = this.nextStop();1467break;14681469// shift out1470case '\x0e':1471this.setgLevel(1);1472break;14731474// shift in1475case '\x0f':1476this.setgLevel(0);1477break;14781479// '\e'1480case '\x1b':1481this.state = escaped;1482break;14831484default:1485// ' '1486if (ch >= ' ') {1487if (this.charset && this.charset[ch]) {1488ch = this.charset[ch];1489}14901491if (this.x >= this.cols) {1492this.x = 0;1493this.y++;1494if (this.y > this.scrollBottom) {1495this.y--;1496this.scroll();1497}1498}14991500this.lines[this.y + this.ybase][this.x] = [this.curAttr, ch];1501this.x++;1502this.updateRange(this.y);15031504if (isWide(ch)) {1505j = this.y + this.ybase;1506if (this.cols < 2 || this.x >= this.cols) {1507this.lines[j][this.x - 1] = [this.curAttr, ' '];1508break;1509}1510this.lines[j][this.x] = [this.curAttr, ' '];1511this.x++;1512}1513}1514break;1515}1516break;1517case escaped:1518switch (ch) {1519// ESC [ Control Sequence Introducer ( CSI is 0x9b).1520case '[':1521this.params = [];1522this.currentParam = 0;1523this.state = csi;1524break;15251526// ESC ] Operating System Command ( OSC is 0x9d).1527case ']':1528this.params = [];1529this.currentParam = 0;1530this.state = osc;1531break;15321533// ESC P Device Control String ( DCS is 0x90).1534case 'P':1535this.params = [];1536this.currentParam = 0;1537this.state = dcs;1538break;15391540// ESC _ Application Program Command ( APC is 0x9f).1541case '_':1542this.state = ignore;1543break;15441545// ESC ^ Privacy Message ( PM is 0x9e).1546case '^':1547this.state = ignore;1548break;15491550// ESC c Full Reset (RIS).1551case 'c':1552this.reset();1553break;15541555// ESC E Next Line ( NEL is 0x85).1556// ESC D Index ( IND is 0x84).1557case 'E':1558this.x = 0;1559;1560case 'D':1561this.index();1562break;15631564// ESC M Reverse Index ( RI is 0x8d).1565case 'M':1566this.reverseIndex();1567break;15681569// ESC % Select default/utf-8 character set.1570// @ = default, G = utf-81571case '%':1572//this.charset = null;1573this.setgLevel(0);1574this.setgCharset(0, Terminal.charsets.US);1575this.state = normal;1576i++;1577break;15781579// ESC (,),*,+,-,. Designate G0-G2 Character Set.1580case '(': // <-- this seems to get all the attention1581case ')':1582case '*':1583case '+':1584case '-':1585case '.':1586switch (ch) {1587case '(':1588this.gcharset = 0;1589break;1590case ')':1591this.gcharset = 1;1592break;1593case '*':1594this.gcharset = 2;1595break;1596case '+':1597this.gcharset = 3;1598break;1599case '-':1600this.gcharset = 1;1601break;1602case '.':1603this.gcharset = 2;1604break;1605}1606this.state = charset;1607break;16081609// Designate G3 Character Set (VT300).1610// A = ISO Latin-1 Supplemental.1611// Not implemented.1612case '/':1613this.gcharset = 3;1614this.state = charset;1615i--;1616break;16171618// ESC N1619// Single Shift Select of G2 Character Set1620// ( SS2 is 0x8e). This affects next character only.1621case 'N':1622break;1623// ESC O1624// Single Shift Select of G3 Character Set1625// ( SS3 is 0x8f). This affects next character only.1626case 'O':1627break;1628// ESC n1629// Invoke the G2 Character Set as GL (LS2).1630case 'n':1631this.setgLevel(2);1632break;1633// ESC o1634// Invoke the G3 Character Set as GL (LS3).1635case 'o':1636this.setgLevel(3);1637break;1638// ESC |1639// Invoke the G3 Character Set as GR (LS3R).1640case '|':1641this.setgLevel(3);1642break;1643// ESC }1644// Invoke the G2 Character Set as GR (LS2R).1645case '}':1646this.setgLevel(2);1647break;1648// ESC ~1649// Invoke the G1 Character Set as GR (LS1R).1650case '~':1651this.setgLevel(1);1652break;16531654// ESC 7 Save Cursor (DECSC).1655case '7':1656this.saveCursor();1657this.state = normal;1658break;16591660// ESC 8 Restore Cursor (DECRC).1661case '8':1662this.restoreCursor();1663this.state = normal;1664break;16651666// ESC # 3 DEC line height/width1667case '#':1668this.state = normal;1669i++;1670break;16711672// ESC H Tab Set (HTS is 0x88).1673case 'H':1674this.tabSet();1675break;16761677// ESC = Application Keypad (DECPAM).1678case '=':1679this.log('Serial port requested application keypad.');1680this.applicationKeypad = true;1681this.state = normal;1682break;16831684// ESC > Normal Keypad (DECPNM).1685case '>':1686this.log('Switching back to normal keypad.');1687this.applicationKeypad = false;1688this.state = normal;1689break;16901691default:1692this.state = normal;1693this.error('Unknown ESC control: %s.', ch);1694break;1695}1696break;16971698case charset:1699switch (ch) {1700case '0': // DEC Special Character and Line Drawing Set.1701cs = Terminal.charsets.SCLD;1702break;1703case 'A': // UK1704cs = Terminal.charsets.UK;1705break;1706case 'B': // United States (USASCII).1707cs = Terminal.charsets.US;1708break;1709case '4': // Dutch1710cs = Terminal.charsets.Dutch;1711break;1712case 'C': // Finnish1713case '5':1714cs = Terminal.charsets.Finnish;1715break;1716case 'R': // French1717cs = Terminal.charsets.French;1718break;1719case 'Q': // FrenchCanadian1720cs = Terminal.charsets.FrenchCanadian;1721break;1722case 'K': // German1723cs = Terminal.charsets.German;1724break;1725case 'Y': // Italian1726cs = Terminal.charsets.Italian;1727break;1728case 'E': // NorwegianDanish1729case '6':1730cs = Terminal.charsets.NorwegianDanish;1731break;1732case 'Z': // Spanish1733cs = Terminal.charsets.Spanish;1734break;1735case 'H': // Swedish1736case '7':1737cs = Terminal.charsets.Swedish;1738break;1739case '=': // Swiss1740cs = Terminal.charsets.Swiss;1741break;1742case '/': // ISOLatin (actually /A)1743cs = Terminal.charsets.ISOLatin;1744i++;1745break;1746default: // Default1747cs = Terminal.charsets.US;1748break;1749}1750this.setgCharset(this.gcharset, cs);1751this.gcharset = null;1752this.state = normal;1753break;17541755case osc:1756// OSC Ps ; Pt ST1757// OSC Ps ; Pt BEL1758// Set Text Parameters.1759if (ch === '\x1b' || ch === '\x07') {1760if (ch === '\x1b') i++;17611762this.params.push(this.currentParam);17631764switch (this.params[0]) {1765case 0:1766case 1:1767case 2:1768if (this.params[1]) {1769this.title = this.params[1];1770this.handleTitle(this.title);1771}1772break;1773case 3:1774// set X property1775break;1776case 4:1777case 5:1778// change dynamic colors1779break;1780case 10:1781case 11:1782case 12:1783case 13:1784case 14:1785case 15:1786case 16:1787case 17:1788case 18:1789case 19:1790// change dynamic ui colors1791break;1792case 46:1793// change log file1794break;1795case 50:1796// dynamic font1797break;1798case 51:1799// emacs shell1800break;1801case 52:1802// manipulate selection data1803break;1804case 104:1805case 105:1806case 110:1807case 111:1808case 112:1809case 113:1810case 114:1811case 115:1812case 116:1813case 117:1814case 118:1815// reset colors1816break;1817}18181819this.params = [];1820this.currentParam = 0;1821this.state = normal;1822} else {1823if (!this.params.length) {1824if (ch >= '0' && ch <= '9') {1825this.currentParam =1826this.currentParam * 10 + ch.charCodeAt(0) - 48;1827} else if (ch === ';') {1828this.params.push(this.currentParam);1829this.currentParam = '';1830}1831} else {1832this.currentParam += ch;1833}1834}1835break;18361837case csi:1838// '?', '>', '!'1839if (ch === '?' || ch === '>' || ch === '!') {1840this.prefix = ch;1841break;1842}18431844// 0 - 91845if (ch >= '0' && ch <= '9') {1846this.currentParam = this.currentParam * 10 + ch.charCodeAt(0) - 48;1847break;1848}18491850// '$', '"', ' ', '\''1851if (ch === '$' || ch === '"' || ch === ' ' || ch === '\'') {1852this.postfix = ch;1853break;1854}18551856this.params.push(this.currentParam);1857this.currentParam = 0;18581859// ';'1860if (ch === ';') break;18611862this.state = normal;18631864switch (ch) {1865// CSI Ps A1866// Cursor Up Ps Times (default = 1) (CUU).1867case 'A':1868this.cursorUp(this.params);1869break;18701871// CSI Ps B1872// Cursor Down Ps Times (default = 1) (CUD).1873case 'B':1874this.cursorDown(this.params);1875break;18761877// CSI Ps C1878// Cursor Forward Ps Times (default = 1) (CUF).1879case 'C':1880this.cursorForward(this.params);1881break;18821883// CSI Ps D1884// Cursor Backward Ps Times (default = 1) (CUB).1885case 'D':1886this.cursorBackward(this.params);1887break;18881889// CSI Ps ; Ps H1890// Cursor Position [row;column] (default = [1,1]) (CUP).1891case 'H':1892this.cursorPos(this.params);1893break;18941895// CSI Ps J Erase in Display (ED).1896case 'J':1897this.eraseInDisplay(this.params);1898break;18991900// CSI Ps K Erase in Line (EL).1901case 'K':1902this.eraseInLine(this.params);1903break;19041905// CSI Pm m Character Attributes (SGR).1906case 'm':1907if (!this.prefix) {1908this.charAttributes(this.params);1909}1910break;19111912// CSI Ps n Device Status Report (DSR).1913case 'n':1914if (!this.prefix) {1915this.deviceStatus(this.params);1916}1917break;19181919/**1920* Additions1921*/19221923// CSI Ps @1924// Insert Ps (Blank) Character(s) (default = 1) (ICH).1925case '@':1926this.insertChars(this.params);1927break;19281929// CSI Ps E1930// Cursor Next Line Ps Times (default = 1) (CNL).1931case 'E':1932this.cursorNextLine(this.params);1933break;19341935// CSI Ps F1936// Cursor Preceding Line Ps Times (default = 1) (CNL).1937case 'F':1938this.cursorPrecedingLine(this.params);1939break;19401941// CSI Ps G1942// Cursor Character Absolute [column] (default = [row,1]) (CHA).1943case 'G':1944this.cursorCharAbsolute(this.params);1945break;19461947// CSI Ps L1948// Insert Ps Line(s) (default = 1) (IL).1949case 'L':1950this.insertLines(this.params);1951break;19521953// CSI Ps M1954// Delete Ps Line(s) (default = 1) (DL).1955case 'M':1956this.deleteLines(this.params);1957break;19581959// CSI Ps P1960// Delete Ps Character(s) (default = 1) (DCH).1961case 'P':1962this.deleteChars(this.params);1963break;19641965// CSI Ps X1966// Erase Ps Character(s) (default = 1) (ECH).1967case 'X':1968this.eraseChars(this.params);1969break;19701971// CSI Pm ` Character Position Absolute1972// [column] (default = [row,1]) (HPA).1973case '`':1974this.charPosAbsolute(this.params);1975break;19761977// 141 61 a * HPR -1978// Horizontal Position Relative1979case 'a':1980this.HPositionRelative(this.params);1981break;19821983// CSI P s c1984// Send Device Attributes (Primary DA).1985// CSI > P s c1986// Send Device Attributes (Secondary DA)1987case 'c':1988this.sendDeviceAttributes(this.params);1989break;19901991// CSI Pm d1992// Line Position Absolute [row] (default = [1,column]) (VPA).1993case 'd':1994this.linePosAbsolute(this.params);1995break;19961997// 145 65 e * VPR - Vertical Position Relative1998case 'e':1999this.VPositionRelative(this.params);2000break;20012002// CSI Ps ; Ps f2003// Horizontal and Vertical Position [row;column] (default =2004// [1,1]) (HVP).2005case 'f':2006this.HVPosition(this.params);2007break;20082009// CSI Pm h Set Mode (SM).2010// CSI ? Pm h - mouse escape codes, cursor escape codes2011case 'h':2012this.setMode(this.params);2013break;20142015// CSI Pm l Reset Mode (RM).2016// CSI ? Pm l2017case 'l':2018this.resetMode(this.params);2019break;20202021// CSI Ps ; Ps r2022// Set Scrolling Region [top;bottom] (default = full size of win-2023// dow) (DECSTBM).2024// CSI ? Pm r2025case 'r':2026this.setScrollRegion(this.params);2027break;20282029// CSI s2030// Save cursor (ANSI.SYS).2031case 's':2032this.saveCursor(this.params);2033break;20342035// CSI u2036// Restore cursor (ANSI.SYS).2037case 'u':2038this.restoreCursor(this.params);2039break;20402041/**2042* Lesser Used2043*/20442045// CSI Ps I2046// Cursor Forward Tabulation Ps tab stops (default = 1) (CHT).2047case 'I':2048this.cursorForwardTab(this.params);2049break;20502051// CSI Ps S Scroll up Ps lines (default = 1) (SU).2052case 'S':2053this.scrollUp(this.params);2054break;20552056// CSI Ps T Scroll down Ps lines (default = 1) (SD).2057// CSI Ps ; Ps ; Ps ; Ps ; Ps T2058// CSI > Ps; Ps T2059case 'T':2060// if (this.prefix === '>') {2061// this.resetTitleModes(this.params);2062// break;2063// }2064// if (this.params.length > 2) {2065// this.initMouseTracking(this.params);2066// break;2067// }2068if (this.params.length < 2 && !this.prefix) {2069this.scrollDown(this.params);2070}2071break;20722073// CSI Ps Z2074// Cursor Backward Tabulation Ps tab stops (default = 1) (CBT).2075case 'Z':2076this.cursorBackwardTab(this.params);2077break;20782079// CSI Ps b Repeat the preceding graphic character Ps times (REP).2080case 'b':2081this.repeatPrecedingCharacter(this.params);2082break;20832084// CSI Ps g Tab Clear (TBC).2085case 'g':2086this.tabClear(this.params);2087break;20882089// CSI Pm i Media Copy (MC).2090// CSI ? Pm i2091// case 'i':2092// this.mediaCopy(this.params);2093// break;20942095// CSI Pm m Character Attributes (SGR).2096// CSI > Ps; Ps m2097// case 'm': // duplicate2098// if (this.prefix === '>') {2099// this.setResources(this.params);2100// } else {2101// this.charAttributes(this.params);2102// }2103// break;21042105// CSI Ps n Device Status Report (DSR).2106// CSI > Ps n2107// case 'n': // duplicate2108// if (this.prefix === '>') {2109// this.disableModifiers(this.params);2110// } else {2111// this.deviceStatus(this.params);2112// }2113// break;21142115// CSI > Ps p Set pointer mode.2116// CSI ! p Soft terminal reset (DECSTR).2117// CSI Ps$ p2118// Request ANSI mode (DECRQM).2119// CSI ? Ps$ p2120// Request DEC private mode (DECRQM).2121// CSI Ps ; Ps " p2122case 'p':2123switch (this.prefix) {2124// case '>':2125// this.setPointerMode(this.params);2126// break;2127case '!':2128this.softReset(this.params);2129break;2130// case '?':2131// if (this.postfix === '$') {2132// this.requestPrivateMode(this.params);2133// }2134// break;2135// default:2136// if (this.postfix === '"') {2137// this.setConformanceLevel(this.params);2138// } else if (this.postfix === '$') {2139// this.requestAnsiMode(this.params);2140// }2141// break;2142}2143break;21442145// CSI Ps q Load LEDs (DECLL).2146// CSI Ps SP q2147// CSI Ps " q2148// case 'q':2149// if (this.postfix === ' ') {2150// this.setCursorStyle(this.params);2151// break;2152// }2153// if (this.postfix === '"') {2154// this.setCharProtectionAttr(this.params);2155// break;2156// }2157// this.loadLEDs(this.params);2158// break;21592160// CSI Ps ; Ps r2161// Set Scrolling Region [top;bottom] (default = full size of win-2162// dow) (DECSTBM).2163// CSI ? Pm r2164// CSI Pt; Pl; Pb; Pr; Ps$ r2165// case 'r': // duplicate2166// if (this.prefix === '?') {2167// this.restorePrivateValues(this.params);2168// } else if (this.postfix === '$') {2169// this.setAttrInRectangle(this.params);2170// } else {2171// this.setScrollRegion(this.params);2172// }2173// break;21742175// CSI s Save cursor (ANSI.SYS).2176// CSI ? Pm s2177// case 's': // duplicate2178// if (this.prefix === '?') {2179// this.savePrivateValues(this.params);2180// } else {2181// this.saveCursor(this.params);2182// }2183// break;21842185// CSI Ps ; Ps ; Ps t2186// CSI Pt; Pl; Pb; Pr; Ps$ t2187// CSI > Ps; Ps t2188// CSI Ps SP t2189// case 't':2190// if (this.postfix === '$') {2191// this.reverseAttrInRectangle(this.params);2192// } else if (this.postfix === ' ') {2193// this.setWarningBellVolume(this.params);2194// } else {2195// if (this.prefix === '>') {2196// this.setTitleModeFeature(this.params);2197// } else {2198// this.manipulateWindow(this.params);2199// }2200// }2201// break;22022203// CSI u Restore cursor (ANSI.SYS).2204// CSI Ps SP u2205// case 'u': // duplicate2206// if (this.postfix === ' ') {2207// this.setMarginBellVolume(this.params);2208// } else {2209// this.restoreCursor(this.params);2210// }2211// break;22122213// CSI Pt; Pl; Pb; Pr; Pp; Pt; Pl; Pp$ v2214// case 'v':2215// if (this.postfix === '$') {2216// this.copyRectagle(this.params);2217// }2218// break;22192220// CSI Pt ; Pl ; Pb ; Pr ' w2221// case 'w':2222// if (this.postfix === '\'') {2223// this.enableFilterRectangle(this.params);2224// }2225// break;22262227// CSI Ps x Request Terminal Parameters (DECREQTPARM).2228// CSI Ps x Select Attribute Change Extent (DECSACE).2229// CSI Pc; Pt; Pl; Pb; Pr$ x2230// case 'x':2231// if (this.postfix === '$') {2232// this.fillRectangle(this.params);2233// } else {2234// this.requestParameters(this.params);2235// //this.__(this.params);2236// }2237// break;22382239// CSI Ps ; Pu ' z2240// CSI Pt; Pl; Pb; Pr$ z2241// case 'z':2242// if (this.postfix === '\'') {2243// this.enableLocatorReporting(this.params);2244// } else if (this.postfix === '$') {2245// this.eraseRectangle(this.params);2246// }2247// break;22482249// CSI Pm ' {2250// CSI Pt; Pl; Pb; Pr$ {2251// case '{':2252// if (this.postfix === '\'') {2253// this.setLocatorEvents(this.params);2254// } else if (this.postfix === '$') {2255// this.selectiveEraseRectangle(this.params);2256// }2257// break;22582259// CSI Ps ' |2260// case '|':2261// if (this.postfix === '\'') {2262// this.requestLocatorPosition(this.params);2263// }2264// break;22652266// CSI P m SP }2267// Insert P s Column(s) (default = 1) (DECIC), VT420 and up.2268// case '}':2269// if (this.postfix === ' ') {2270// this.insertColumns(this.params);2271// }2272// break;22732274// CSI P m SP ~2275// Delete P s Column(s) (default = 1) (DECDC), VT420 and up2276// case '~':2277// if (this.postfix === ' ') {2278// this.deleteColumns(this.params);2279// }2280// break;22812282default:2283this.error('Unknown CSI code: %s.', ch);2284break;2285}22862287this.prefix = '';2288this.postfix = '';2289break;22902291case dcs:2292if (ch === '\x1b' || ch === '\x07') {2293if (ch === '\x1b') i++;22942295switch (this.prefix) {2296// User-Defined Keys (DECUDK).2297case '':2298break;22992300// Request Status String (DECRQSS).2301// test: echo -e '\eP$q"p\e\\'2302case '$q':2303var pt = this.currentParam2304, valid = false;23052306switch (pt) {2307// DECSCA2308case '"q':2309pt = '0"q';2310break;23112312// DECSCL2313case '"p':2314pt = '61"p';2315break;23162317// DECSTBM2318case 'r':2319pt = ''2320+ (this.scrollTop + 1)2321+ ';'2322+ (this.scrollBottom + 1)2323+ 'r';2324break;23252326// SGR2327case 'm':2328pt = '0m';2329break;23302331default:2332this.error('Unknown DCS Pt: %s.', pt);2333pt = '';2334break;2335}23362337this.send('\x1bP' + +valid + '$r' + pt + '\x1b\\');2338break;23392340// Set Termcap/Terminfo Data (xterm, experimental).2341case '+p':2342break;23432344// Request Termcap/Terminfo String (xterm, experimental)2345// Regular xterm does not even respond to this sequence.2346// This can cause a small glitch in vim.2347// test: echo -ne '\eP+q6b64\e\\'2348case '+q':2349var pt = this.currentParam2350, valid = false;23512352this.send('\x1bP' + +valid + '+r' + pt + '\x1b\\');2353break;23542355default:2356this.error('Unknown DCS prefix: %s.', this.prefix);2357break;2358}23592360this.currentParam = 0;2361this.prefix = '';2362this.state = normal;2363} else if (!this.currentParam) {2364if (!this.prefix && ch !== '$' && ch !== '+') {2365this.currentParam = ch;2366} else if (this.prefix.length === 2) {2367this.currentParam = ch;2368} else {2369this.prefix += ch;2370}2371} else {2372this.currentParam += ch;2373}2374break;23752376case ignore:2377// For PM and APC.2378if (ch === '\x1b' || ch === '\x07') {2379if (ch === '\x1b') i++;2380this.state = normal;2381}2382break;2383}2384}23852386this.updateRange(this.y);2387this.refresh(this.refreshStart, this.refreshEnd);2388};23892390Terminal.prototype.writeln = function(data) {2391this.write(data + '\r\n');2392};23932394// Key Resources:2395// https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent2396Terminal.prototype.keyDown = function(ev) {2397var self = this2398, key;23992400switch (ev.keyCode) {2401// backspace2402case 8:2403if (ev.shiftKey) {2404key = '\x08'; // ^H2405break;2406}2407key = '\x7f'; // ^?2408break;2409// tab2410case 9:2411if (ev.shiftKey) {2412key = '\x1b[Z';2413break;2414}2415key = '\t';2416break;2417// return/enter2418case 13:2419key = '\r';2420break;2421// escape2422case 27:2423key = '\x1b';2424break;2425// left-arrow2426case 37:2427if (this.applicationCursor) {2428key = '\x1bOD'; // SS3 as ^[O for 7-bit2429//key = '\x8fD'; // SS3 as 0x8f for 8-bit2430break;2431}2432key = '\x1b[D';2433break;2434// right-arrow2435case 39:2436if (this.applicationCursor) {2437key = '\x1bOC';2438break;2439}2440key = '\x1b[C';2441break;2442// up-arrow2443case 38:2444if (this.applicationCursor) {2445key = '\x1bOA';2446break;2447}2448if (ev.ctrlKey) {2449this.scrollDisp(-1);2450return cancel(ev);2451} else {2452key = '\x1b[A';2453}2454break;2455// down-arrow2456case 40:2457if (this.applicationCursor) {2458key = '\x1bOB';2459break;2460}2461if (ev.ctrlKey) {2462this.scrollDisp(1);2463return cancel(ev);2464} else {2465key = '\x1b[B';2466}2467break;2468// delete2469case 46:2470key = '\x1b[3~';2471break;2472// insert2473case 45:2474key = '\x1b[2~';2475break;2476// home2477case 36:2478if (this.applicationKeypad) {2479key = '\x1bOH';2480break;2481}2482key = '\x1bOH';2483break;2484// end2485case 35:2486if (this.applicationKeypad) {2487key = '\x1bOF';2488break;2489}2490key = '\x1bOF';2491break;2492// page up2493case 33:2494if (ev.shiftKey) {2495this.scrollDisp(-(this.rows - 1));2496return cancel(ev);2497} else {2498key = '\x1b[5~';2499}2500break;2501// page down2502case 34:2503if (ev.shiftKey) {2504this.scrollDisp(this.rows - 1);2505return cancel(ev);2506} else {2507key = '\x1b[6~';2508}2509break;2510// F12511case 112:2512key = '\x1bOP';2513break;2514// F22515case 113:2516key = '\x1bOQ';2517break;2518// F32519case 114:2520key = '\x1bOR';2521break;2522// F42523case 115:2524key = '\x1bOS';2525break;2526// F52527case 116:2528key = '\x1b[15~';2529break;2530// F62531case 117:2532key = '\x1b[17~';2533break;2534// F72535case 118:2536key = '\x1b[18~';2537break;2538// F82539case 119:2540key = '\x1b[19~';2541break;2542// F92543case 120:2544key = '\x1b[20~';2545break;2546// F102547case 121:2548key = '\x1b[21~';2549break;2550// F112551case 122:2552key = '\x1b[23~';2553break;2554// F122555case 123:2556key = '\x1b[24~';2557break;2558default:2559// a-z and space2560if (ev.ctrlKey) {2561if (ev.keyCode >= 65 && ev.keyCode <= 90) {2562// Ctrl-A2563if (this.screenKeys) {2564if (!this.prefixMode && !this.selectMode && ev.keyCode === 65) {2565this.enterPrefix();2566return cancel(ev);2567}2568}2569// Ctrl-V2570if (this.prefixMode && ev.keyCode === 86) {2571this.leavePrefix();2572return;2573}2574// Ctrl-C2575if ((this.prefixMode || this.selectMode) && ev.keyCode === 67) {2576if (this.visualMode) {2577setTimeout(function() {2578self.leaveVisual();2579}, 1);2580}2581return;2582}2583key = String.fromCharCode(ev.keyCode - 64);2584} else if (ev.keyCode === 32) {2585// NUL2586key = String.fromCharCode(0);2587} else if (ev.keyCode >= 51 && ev.keyCode <= 55) {2588// escape, file sep, group sep, record sep, unit sep2589key = String.fromCharCode(ev.keyCode - 51 + 27);2590} else if (ev.keyCode === 56) {2591// delete2592key = String.fromCharCode(127);2593} else if (ev.keyCode === 219) {2594// ^[ - escape2595key = String.fromCharCode(27);2596} else if (ev.keyCode === 221) {2597// ^] - group sep2598key = String.fromCharCode(29);2599}2600} else if ((!this.isMac && ev.altKey) || (this.isMac && ev.metaKey)) {2601if (ev.keyCode >= 65 && ev.keyCode <= 90) {2602key = '\x1b' + String.fromCharCode(ev.keyCode + 32);2603} else if (ev.keyCode === 192) {2604key = '\x1b`';2605} else if (ev.keyCode >= 48 && ev.keyCode <= 57) {2606key = '\x1b' + (ev.keyCode - 48);2607}2608}2609break;2610}26112612if (!key) return true;26132614if (this.prefixMode) {2615this.leavePrefix();2616return cancel(ev);2617}26182619if (this.selectMode) {2620this.keySelect(ev, key);2621return cancel(ev);2622}26232624this.emit('keydown', ev);2625this.emit('key', key, ev);26262627this.showCursor();2628this.handler(key);26292630return cancel(ev);2631};26322633Terminal.prototype.setgLevel = function(g) {2634this.glevel = g;2635this.charset = this.charsets[g];2636};26372638Terminal.prototype.setgCharset = function(g, charset) {2639this.charsets[g] = charset;2640if (this.glevel === g) {2641this.charset = charset;2642}2643};26442645Terminal.prototype.keyPress = function(ev) {2646var key;26472648cancel(ev);26492650if (ev.charCode) {2651key = ev.charCode;2652} else if (ev.which == null) {2653key = ev.keyCode;2654} else if (ev.which !== 0 && ev.charCode !== 0) {2655key = ev.which;2656} else {2657return false;2658}26592660if (!key || ev.ctrlKey || ev.altKey || ev.metaKey) return false;26612662key = String.fromCharCode(key);26632664if (this.prefixMode) {2665this.leavePrefix();2666this.keyPrefix(ev, key);2667return false;2668}26692670if (this.selectMode) {2671this.keySelect(ev, key);2672return false;2673}26742675this.emit('keypress', key, ev);2676this.emit('key', key, ev);26772678this.showCursor();2679this.handler(key);26802681return false;2682};26832684Terminal.prototype.send = function(data) {2685var self = this;26862687if (!this.queue) {2688setTimeout(function() {2689self.handler(self.queue);2690self.queue = '';2691}, 1);2692}26932694this.queue += data;2695};26962697Terminal.prototype.bell = function() {2698if (!this.visualBell) return;2699var self = this;2700this.element.style.borderColor = 'white';2701setTimeout(function() {2702self.element.style.borderColor = '';2703}, 10);2704if (this.popOnBell) this.focus();2705};27062707Terminal.prototype.log = function() {2708if (!this.debug) return;2709if (!this.context.console || !this.context.console.log) return;2710var args = Array.prototype.slice.call(arguments);2711this.context.console.log.apply(this.context.console, args);2712};27132714Terminal.prototype.error = function() {2715if (!this.debug) return;2716if (!this.context.console || !this.context.console.error) return;2717var args = Array.prototype.slice.call(arguments);2718this.context.console.error.apply(this.context.console, args);2719};27202721Terminal.prototype.resize = function(x, y) {2722var line2723, el2724, i2725, j2726, ch;27272728if (x < 1) x = 1;2729if (y < 1) y = 1;27302731// resize cols2732j = this.cols;2733if (j < x) {2734ch = [this.defAttr, ' ']; // does xterm use the default attr?2735i = this.lines.length;2736while (i--) {2737while (this.lines[i].length < x) {2738this.lines[i].push(ch);2739}2740}2741} else if (j > x) {2742i = this.lines.length;2743while (i--) {2744while (this.lines[i].length > x) {2745this.lines[i].pop();2746}2747}2748}2749this.setupStops(j);2750this.cols = x;27512752// resize rows2753j = this.rows;2754if (j < y) {2755el = this.element;2756while (j++ < y) {2757if (this.lines.length < y + this.ybase) {2758this.lines.push(this.blankLine());2759}2760if (this.children.length < y) {2761line = this.document.createElement('div');2762el.appendChild(line);2763this.children.push(line);2764}2765}2766} else if (j > y) {2767while (j-- > y) {2768if (this.lines.length > y + this.ybase) {2769this.lines.pop();2770}2771if (this.children.length > y) {2772el = this.children.pop();2773if (!el) continue;2774el.parentNode.removeChild(el);2775}2776}2777}2778this.rows = y;27792780// make sure the cursor stays on screen2781if (this.y >= y) this.y = y - 1;2782if (this.x >= x) this.x = x - 1;27832784this.scrollTop = 0;2785this.scrollBottom = y - 1;27862787this.refresh(0, this.rows - 1);27882789// it's a real nightmare trying2790// to resize the original2791// screen buffer. just set it2792// to null for now.2793this.normal = null;2794};27952796Terminal.prototype.updateRange = function(y) {2797if (y < this.refreshStart) this.refreshStart = y;2798if (y > this.refreshEnd) this.refreshEnd = y;2799// if (y > this.refreshEnd) {2800// this.refreshEnd = y;2801// if (y > this.rows - 1) {2802// this.refreshEnd = this.rows - 1;2803// }2804// }2805};28062807Terminal.prototype.maxRange = function() {2808this.refreshStart = 0;2809this.refreshEnd = this.rows - 1;2810};28112812Terminal.prototype.setupStops = function(i) {2813if (i != null) {2814if (!this.tabs[i]) {2815i = this.prevStop(i);2816}2817} else {2818this.tabs = {};2819i = 0;2820}28212822for (; i < this.cols; i += 8) {2823this.tabs[i] = true;2824}2825};28262827Terminal.prototype.prevStop = function(x) {2828if (x == null) x = this.x;2829while (!this.tabs[--x] && x > 0);2830return x >= this.cols2831? this.cols - 12832: x < 0 ? 0 : x;2833};28342835Terminal.prototype.nextStop = function(x) {2836if (x == null) x = this.x;2837while (!this.tabs[++x] && x < this.cols);2838return x >= this.cols2839? this.cols - 12840: x < 0 ? 0 : x;2841};28422843Terminal.prototype.eraseRight = function(x, y) {2844var line = this.lines[this.ybase + y]2845, ch = [this.eraseAttr(), ' ']; // xterm284628472848for (; x < this.cols; x++) {2849line[x] = ch;2850}28512852this.updateRange(y);2853};28542855Terminal.prototype.eraseLeft = function(x, y) {2856var line = this.lines[this.ybase + y]2857, ch = [this.eraseAttr(), ' ']; // xterm28582859x++;2860while (x--) line[x] = ch;28612862this.updateRange(y);2863};28642865Terminal.prototype.eraseLine = function(y) {2866this.eraseRight(0, y);2867};28682869Terminal.prototype.blankLine = function(cur) {2870var attr = cur2871? this.eraseAttr()2872: this.defAttr;28732874var ch = [attr, ' ']2875, line = []2876, i = 0;28772878for (; i < this.cols; i++) {2879line[i] = ch;2880}28812882return line;2883};28842885Terminal.prototype.ch = function(cur) {2886return cur2887? [this.eraseAttr(), ' ']2888: [this.defAttr, ' '];2889};28902891Terminal.prototype.is = function(term) {2892var name = this.termName;2893return (name + '').indexOf(term) === 0;2894};28952896Terminal.prototype.handler = function(data) {2897this.emit('data', data);2898};28992900Terminal.prototype.handleTitle = function(title) {2901this.emit('title', title);2902};29032904/**2905* ESC2906*/29072908// ESC D Index (IND is 0x84).2909Terminal.prototype.index = function() {2910this.y++;2911if (this.y > this.scrollBottom) {2912this.y--;2913this.scroll();2914}2915this.state = normal;2916};29172918// ESC M Reverse Index (RI is 0x8d).2919Terminal.prototype.reverseIndex = function() {2920var j;2921this.y--;2922if (this.y < this.scrollTop) {2923this.y++;2924// possibly move the code below to term.reverseScroll();2925// test: echo -ne '\e[1;1H\e[44m\eM\e[0m'2926// blankLine(true) is xterm/linux behavior2927this.lines.splice(this.y + this.ybase, 0, this.blankLine(true));2928j = this.rows - 1 - this.scrollBottom;2929this.lines.splice(this.rows - 1 + this.ybase - j + 1, 1);2930// this.maxRange();2931this.updateRange(this.scrollTop);2932this.updateRange(this.scrollBottom);2933}2934this.state = normal;2935};29362937// ESC c Full Reset (RIS).2938Terminal.prototype.reset = function() {2939this.options.rows = this.rows;2940this.options.cols = this.cols;2941Terminal.call(this, this.options);2942this.refresh(0, this.rows - 1);2943};29442945// ESC H Tab Set (HTS is 0x88).2946Terminal.prototype.tabSet = function() {2947this.tabs[this.x] = true;2948this.state = normal;2949};29502951/**2952* CSI2953*/29542955// CSI Ps A2956// Cursor Up Ps Times (default = 1) (CUU).2957Terminal.prototype.cursorUp = function(params) {2958var param = params[0];2959if (param < 1) param = 1;2960this.y -= param;2961if (this.y < 0) this.y = 0;2962};29632964// CSI Ps B2965// Cursor Down Ps Times (default = 1) (CUD).2966Terminal.prototype.cursorDown = function(params) {2967var param = params[0];2968if (param < 1) param = 1;2969this.y += param;2970if (this.y >= this.rows) {2971this.y = this.rows - 1;2972}2973};29742975// CSI Ps C2976// Cursor Forward Ps Times (default = 1) (CUF).2977Terminal.prototype.cursorForward = function(params) {2978var param = params[0];2979if (param < 1) param = 1;2980this.x += param;2981if (this.x >= this.cols) {2982this.x = this.cols - 1;2983}2984};29852986// CSI Ps D2987// Cursor Backward Ps Times (default = 1) (CUB).2988Terminal.prototype.cursorBackward = function(params) {2989var param = params[0];2990if (param < 1) param = 1;2991this.x -= param;2992if (this.x < 0) this.x = 0;2993};29942995// CSI Ps ; Ps H2996// Cursor Position [row;column] (default = [1,1]) (CUP).2997Terminal.prototype.cursorPos = function(params) {2998var row, col;29993000row = params[0] - 1;30013002if (params.length >= 2) {3003col = params[1] - 1;3004} else {3005col = 0;3006}30073008if (row < 0) {3009row = 0;3010} else if (row >= this.rows) {3011row = this.rows - 1;3012}30133014if (col < 0) {3015col = 0;3016} else if (col >= this.cols) {3017col = this.cols - 1;3018}30193020this.x = col;3021this.y = row;3022};30233024// CSI Ps J Erase in Display (ED).3025// Ps = 0 -> Erase Below (default).3026// Ps = 1 -> Erase Above.3027// Ps = 2 -> Erase All.3028// Ps = 3 -> Erase Saved Lines (xterm).3029// CSI ? Ps J3030// Erase in Display (DECSED).3031// Ps = 0 -> Selective Erase Below (default).3032// Ps = 1 -> Selective Erase Above.3033// Ps = 2 -> Selective Erase All.3034Terminal.prototype.eraseInDisplay = function(params) {3035var j;3036switch (params[0]) {3037case 0:3038this.eraseRight(this.x, this.y);3039j = this.y + 1;3040for (; j < this.rows; j++) {3041this.eraseLine(j);3042}3043break;3044case 1:3045this.eraseLeft(this.x, this.y);3046j = this.y;3047while (j--) {3048this.eraseLine(j);3049}3050break;3051case 2:3052j = this.rows;3053while (j--) this.eraseLine(j);3054break;3055case 3:3056; // no saved lines3057break;3058}3059};30603061// CSI Ps K Erase in Line (EL).3062// Ps = 0 -> Erase to Right (default).3063// Ps = 1 -> Erase to Left.3064// Ps = 2 -> Erase All.3065// CSI ? Ps K3066// Erase in Line (DECSEL).3067// Ps = 0 -> Selective Erase to Right (default).3068// Ps = 1 -> Selective Erase to Left.3069// Ps = 2 -> Selective Erase All.3070Terminal.prototype.eraseInLine = function(params) {3071switch (params[0]) {3072case 0:3073this.eraseRight(this.x, this.y);3074break;3075case 1:3076this.eraseLeft(this.x, this.y);3077break;3078case 2:3079this.eraseLine(this.y);3080break;3081}3082};30833084// CSI Pm m Character Attributes (SGR).3085// Ps = 0 -> Normal (default).3086// Ps = 1 -> Bold.3087// Ps = 4 -> Underlined.3088// Ps = 5 -> Blink (appears as Bold).3089// Ps = 7 -> Inverse.3090// Ps = 8 -> Invisible, i.e., hidden (VT300).3091// Ps = 2 2 -> Normal (neither bold nor faint).3092// Ps = 2 4 -> Not underlined.3093// Ps = 2 5 -> Steady (not blinking).3094// Ps = 2 7 -> Positive (not inverse).3095// Ps = 2 8 -> Visible, i.e., not hidden (VT300).3096// Ps = 3 0 -> Set foreground color to Black.3097// Ps = 3 1 -> Set foreground color to Red.3098// Ps = 3 2 -> Set foreground color to Green.3099// Ps = 3 3 -> Set foreground color to Yellow.3100// Ps = 3 4 -> Set foreground color to Blue.3101// Ps = 3 5 -> Set foreground color to Magenta.3102// Ps = 3 6 -> Set foreground color to Cyan.3103// Ps = 3 7 -> Set foreground color to White.3104// Ps = 3 9 -> Set foreground color to default (original).3105// Ps = 4 0 -> Set background color to Black.3106// Ps = 4 1 -> Set background color to Red.3107// Ps = 4 2 -> Set background color to Green.3108// Ps = 4 3 -> Set background color to Yellow.3109// Ps = 4 4 -> Set background color to Blue.3110// Ps = 4 5 -> Set background color to Magenta.3111// Ps = 4 6 -> Set background color to Cyan.3112// Ps = 4 7 -> Set background color to White.3113// Ps = 4 9 -> Set background color to default (original).31143115// If 16-color support is compiled, the following apply. Assume3116// that xterm's resources are set so that the ISO color codes are3117// the first 8 of a set of 16. Then the aixterm colors are the3118// bright versions of the ISO colors:3119// Ps = 9 0 -> Set foreground color to Black.3120// Ps = 9 1 -> Set foreground color to Red.3121// Ps = 9 2 -> Set foreground color to Green.3122// Ps = 9 3 -> Set foreground color to Yellow.3123// Ps = 9 4 -> Set foreground color to Blue.3124// Ps = 9 5 -> Set foreground color to Magenta.3125// Ps = 9 6 -> Set foreground color to Cyan.3126// Ps = 9 7 -> Set foreground color to White.3127// Ps = 1 0 0 -> Set background color to Black.3128// Ps = 1 0 1 -> Set background color to Red.3129// Ps = 1 0 2 -> Set background color to Green.3130// Ps = 1 0 3 -> Set background color to Yellow.3131// Ps = 1 0 4 -> Set background color to Blue.3132// Ps = 1 0 5 -> Set background color to Magenta.3133// Ps = 1 0 6 -> Set background color to Cyan.3134// Ps = 1 0 7 -> Set background color to White.31353136// If xterm is compiled with the 16-color support disabled, it3137// supports the following, from rxvt:3138// Ps = 1 0 0 -> Set foreground and background color to3139// default.31403141// If 88- or 256-color support is compiled, the following apply.3142// Ps = 3 8 ; 5 ; Ps -> Set foreground color to the second3143// Ps.3144// Ps = 4 8 ; 5 ; Ps -> Set background color to the second3145// Ps.3146Terminal.prototype.charAttributes = function(params) {3147// Optimize a single SGR0.3148if (params.length === 1 && params[0] === 0) {3149this.curAttr = this.defAttr;3150return;3151}31523153var l = params.length3154, i = 03155, flags = this.curAttr >> 183156, fg = (this.curAttr >> 9) & 0x1ff3157, bg = this.curAttr & 0x1ff3158, p;31593160for (; i < l; i++) {3161p = params[i];3162if (p >= 30 && p <= 37) {3163// fg color 83164fg = p - 30;3165} else if (p >= 40 && p <= 47) {3166// bg color 83167bg = p - 40;3168} else if (p >= 90 && p <= 97) {3169// fg color 163170p += 8;3171fg = p - 90;3172} else if (p >= 100 && p <= 107) {3173// bg color 163174p += 8;3175bg = p - 100;3176} else if (p === 0) {3177// default3178flags = this.defAttr >> 18;3179fg = (this.defAttr >> 9) & 0x1ff;3180bg = this.defAttr & 0x1ff;3181// flags = 0;3182// fg = 0x1ff;3183// bg = 0x1ff;3184} else if (p === 1) {3185// bold text3186flags |= 1;3187} else if (p === 4) {3188// underlined text3189flags |= 2;3190} else if (p === 5) {3191// blink3192flags |= 4;3193} else if (p === 7) {3194// inverse and positive3195// test with: echo -e '\e[31m\e[42mhello\e[7mworld\e[27mhi\e[m'3196flags |= 8;3197} else if (p === 8) {3198// invisible3199flags |= 16;3200} else if (p === 22) {3201// not bold3202flags &= ~1;3203} else if (p === 24) {3204// not underlined3205flags &= ~2;3206} else if (p === 25) {3207// not blink3208flags &= ~4;3209} else if (p === 27) {3210// not inverse3211flags &= ~8;3212} else if (p === 28) {3213// not invisible3214flags &= ~16;3215} else if (p === 39) {3216// reset fg3217fg = (this.defAttr >> 9) & 0x1ff;3218} else if (p === 49) {3219// reset bg3220bg = this.defAttr & 0x1ff;3221} else if (p === 38) {3222// fg color 2563223if (params[i + 1] === 2) {3224i += 2;3225fg = matchColor(3226params[i] & 0xff,3227params[i + 1] & 0xff,3228params[i + 2] & 0xff);3229if (fg === -1) fg = 0x1ff;3230i += 2;3231} else if (params[i + 1] === 5) {3232i += 2;3233p = params[i] & 0xff;3234fg = p;3235}3236} else if (p === 48) {3237// bg color 2563238if (params[i + 1] === 2) {3239i += 2;3240bg = matchColor(3241params[i] & 0xff,3242params[i + 1] & 0xff,3243params[i + 2] & 0xff);3244if (bg === -1) bg = 0x1ff;3245i += 2;3246} else if (params[i + 1] === 5) {3247i += 2;3248p = params[i] & 0xff;3249bg = p;3250}3251} else if (p === 100) {3252// reset fg/bg3253fg = (this.defAttr >> 9) & 0x1ff;3254bg = this.defAttr & 0x1ff;3255} else {3256this.error('Unknown SGR attribute: %d.', p);3257}3258}32593260this.curAttr = (flags << 18) | (fg << 9) | bg;3261};32623263// CSI Ps n Device Status Report (DSR).3264// Ps = 5 -> Status Report. Result (``OK'') is3265// CSI 0 n3266// Ps = 6 -> Report Cursor Position (CPR) [row;column].3267// Result is3268// CSI r ; c R3269// CSI ? Ps n3270// Device Status Report (DSR, DEC-specific).3271// Ps = 6 -> Report Cursor Position (CPR) [row;column] as CSI3272// ? r ; c R (assumes page is zero).3273// Ps = 1 5 -> Report Printer status as CSI ? 1 0 n (ready).3274// or CSI ? 1 1 n (not ready).3275// Ps = 2 5 -> Report UDK status as CSI ? 2 0 n (unlocked)3276// or CSI ? 2 1 n (locked).3277// Ps = 2 6 -> Report Keyboard status as3278// CSI ? 2 7 ; 1 ; 0 ; 0 n (North American).3279// The last two parameters apply to VT400 & up, and denote key-3280// board ready and LK01 respectively.3281// Ps = 5 3 -> Report Locator status as3282// CSI ? 5 3 n Locator available, if compiled-in, or3283// CSI ? 5 0 n No Locator, if not.3284Terminal.prototype.deviceStatus = function(params) {3285if (!this.prefix) {3286switch (params[0]) {3287case 5:3288// status report3289this.send('\x1b[0n');3290break;3291case 6:3292// cursor position3293this.send('\x1b['3294+ (this.y + 1)3295+ ';'3296+ (this.x + 1)3297+ 'R');3298break;3299}3300} else if (this.prefix === '?') {3301// modern xterm doesnt seem to3302// respond to any of these except ?6, 6, and 53303switch (params[0]) {3304case 6:3305// cursor position3306this.send('\x1b[?'3307+ (this.y + 1)3308+ ';'3309+ (this.x + 1)3310+ 'R');3311break;3312case 15:3313// no printer3314// this.send('\x1b[?11n');3315break;3316case 25:3317// dont support user defined keys3318// this.send('\x1b[?21n');3319break;3320case 26:3321// north american keyboard3322// this.send('\x1b[?27;1;0;0n');3323break;3324case 53:3325// no dec locator/mouse3326// this.send('\x1b[?50n');3327break;3328}3329}3330};33313332/**3333* Additions3334*/33353336// CSI Ps @3337// Insert Ps (Blank) Character(s) (default = 1) (ICH).3338Terminal.prototype.insertChars = function(params) {3339var param, row, j, ch;33403341param = params[0];3342if (param < 1) param = 1;33433344row = this.y + this.ybase;3345j = this.x;3346ch = [this.eraseAttr(), ' ']; // xterm33473348while (param-- && j < this.cols) {3349this.lines[row].splice(j++, 0, ch);3350this.lines[row].pop();3351}3352};33533354// CSI Ps E3355// Cursor Next Line Ps Times (default = 1) (CNL).3356// same as CSI Ps B ?3357Terminal.prototype.cursorNextLine = function(params) {3358var param = params[0];3359if (param < 1) param = 1;3360this.y += param;3361if (this.y >= this.rows) {3362this.y = this.rows - 1;3363}3364this.x = 0;3365};33663367// CSI Ps F3368// Cursor Preceding Line Ps Times (default = 1) (CNL).3369// reuse CSI Ps A ?3370Terminal.prototype.cursorPrecedingLine = function(params) {3371var param = params[0];3372if (param < 1) param = 1;3373this.y -= param;3374if (this.y < 0) this.y = 0;3375this.x = 0;3376};33773378// CSI Ps G3379// Cursor Character Absolute [column] (default = [row,1]) (CHA).3380Terminal.prototype.cursorCharAbsolute = function(params) {3381var param = params[0];3382if (param < 1) param = 1;3383this.x = param - 1;3384};33853386// CSI Ps L3387// Insert Ps Line(s) (default = 1) (IL).3388Terminal.prototype.insertLines = function(params) {3389var param, row, j;33903391param = params[0];3392if (param < 1) param = 1;3393row = this.y + this.ybase;33943395j = this.rows - 1 - this.scrollBottom;3396j = this.rows - 1 + this.ybase - j + 1;33973398while (param--) {3399// test: echo -e '\e[44m\e[1L\e[0m'3400// blankLine(true) - xterm/linux behavior3401this.lines.splice(row, 0, this.blankLine(true));3402this.lines.splice(j, 1);3403}34043405// this.maxRange();3406this.updateRange(this.y);3407this.updateRange(this.scrollBottom);3408};34093410// CSI Ps M3411// Delete Ps Line(s) (default = 1) (DL).3412Terminal.prototype.deleteLines = function(params) {3413var param, row, j;34143415param = params[0];3416if (param < 1) param = 1;3417row = this.y + this.ybase;34183419j = this.rows - 1 - this.scrollBottom;3420j = this.rows - 1 + this.ybase - j;34213422while (param--) {3423// test: echo -e '\e[44m\e[1M\e[0m'3424// blankLine(true) - xterm/linux behavior3425this.lines.splice(j + 1, 0, this.blankLine(true));3426this.lines.splice(row, 1);3427}34283429// this.maxRange();3430this.updateRange(this.y);3431this.updateRange(this.scrollBottom);3432};34333434// CSI Ps P3435// Delete Ps Character(s) (default = 1) (DCH).3436Terminal.prototype.deleteChars = function(params) {3437var param, row, ch;34383439param = params[0];3440if (param < 1) param = 1;34413442row = this.y + this.ybase;3443ch = [this.eraseAttr(), ' ']; // xterm34443445while (param--) {3446this.lines[row].splice(this.x, 1);3447this.lines[row].push(ch);3448}3449};34503451// CSI Ps X3452// Erase Ps Character(s) (default = 1) (ECH).3453Terminal.prototype.eraseChars = function(params) {3454var param, row, j, ch;34553456param = params[0];3457if (param < 1) param = 1;34583459row = this.y + this.ybase;3460j = this.x;3461ch = [this.eraseAttr(), ' ']; // xterm34623463while (param-- && j < this.cols) {3464this.lines[row][j++] = ch;3465}3466};34673468// CSI Pm ` Character Position Absolute3469// [column] (default = [row,1]) (HPA).3470Terminal.prototype.charPosAbsolute = function(params) {3471var param = params[0];3472if (param < 1) param = 1;3473this.x = param - 1;3474if (this.x >= this.cols) {3475this.x = this.cols - 1;3476}3477};34783479// 141 61 a * HPR -3480// Horizontal Position Relative3481// reuse CSI Ps C ?3482Terminal.prototype.HPositionRelative = function(params) {3483var param = params[0];3484if (param < 1) param = 1;3485this.x += param;3486if (this.x >= this.cols) {3487this.x = this.cols - 1;3488}3489};34903491// CSI Ps c Send Device Attributes (Primary DA).3492// Ps = 0 or omitted -> request attributes from terminal. The3493// response depends on the decTerminalID resource setting.3494// -> CSI ? 1 ; 2 c (``VT100 with Advanced Video Option'')3495// -> CSI ? 1 ; 0 c (``VT101 with No Options'')3496// -> CSI ? 6 c (``VT102'')3497// -> CSI ? 6 0 ; 1 ; 2 ; 6 ; 8 ; 9 ; 1 5 ; c (``VT220'')3498// The VT100-style response parameters do not mean anything by3499// themselves. VT220 parameters do, telling the host what fea-3500// tures the terminal supports:3501// Ps = 1 -> 132-columns.3502// Ps = 2 -> Printer.3503// Ps = 6 -> Selective erase.3504// Ps = 8 -> User-defined keys.3505// Ps = 9 -> National replacement character sets.3506// Ps = 1 5 -> Technical characters.3507// Ps = 2 2 -> ANSI color, e.g., VT525.3508// Ps = 2 9 -> ANSI text locator (i.e., DEC Locator mode).3509// CSI > Ps c3510// Send Device Attributes (Secondary DA).3511// Ps = 0 or omitted -> request the terminal's identification3512// code. The response depends on the decTerminalID resource set-3513// ting. It should apply only to VT220 and up, but xterm extends3514// this to VT100.3515// -> CSI > Pp ; Pv ; Pc c3516// where Pp denotes the terminal type3517// Pp = 0 -> ``VT100''.3518// Pp = 1 -> ``VT220''.3519// and Pv is the firmware version (for xterm, this was originally3520// the XFree86 patch number, starting with 95). In a DEC termi-3521// nal, Pc indicates the ROM cartridge registration number and is3522// always zero.3523// More information:3524// xterm/charproc.c - line 2012, for more information.3525// vim responds with ^[[?0c or ^[[?1c after the terminal's response (?)3526Terminal.prototype.sendDeviceAttributes = function(params) {3527if (params[0] > 0) return;35283529if (!this.prefix) {3530if (this.is('xterm')3531|| this.is('rxvt-unicode')3532|| this.is('screen')) {3533this.send('\x1b[?1;2c');3534} else if (this.is('linux')) {3535this.send('\x1b[?6c');3536}3537} else if (this.prefix === '>') {3538// xterm and urxvt3539// seem to spit this3540// out around ~370 times (?).3541if (this.is('xterm')) {3542this.send('\x1b[>0;276;0c');3543} else if (this.is('rxvt-unicode')) {3544this.send('\x1b[>85;95;0c');3545} else if (this.is('linux')) {3546// not supported by linux console.3547// linux console echoes parameters.3548this.send(params[0] + 'c');3549} else if (this.is('screen')) {3550this.send('\x1b[>83;40003;0c');3551}3552}3553};35543555// CSI Pm d3556// Line Position Absolute [row] (default = [1,column]) (VPA).3557Terminal.prototype.linePosAbsolute = function(params) {3558var param = params[0];3559if (param < 1) param = 1;3560this.y = param - 1;3561if (this.y >= this.rows) {3562this.y = this.rows - 1;3563}3564};35653566// 145 65 e * VPR - Vertical Position Relative3567// reuse CSI Ps B ?3568Terminal.prototype.VPositionRelative = function(params) {3569var param = params[0];3570if (param < 1) param = 1;3571this.y += param;3572if (this.y >= this.rows) {3573this.y = this.rows - 1;3574}3575};35763577// CSI Ps ; Ps f3578// Horizontal and Vertical Position [row;column] (default =3579// [1,1]) (HVP).3580Terminal.prototype.HVPosition = function(params) {3581if (params[0] < 1) params[0] = 1;3582if (params[1] < 1) params[1] = 1;35833584this.y = params[0] - 1;3585if (this.y >= this.rows) {3586this.y = this.rows - 1;3587}35883589this.x = params[1] - 1;3590if (this.x >= this.cols) {3591this.x = this.cols - 1;3592}3593};35943595// CSI Pm h Set Mode (SM).3596// Ps = 2 -> Keyboard Action Mode (AM).3597// Ps = 4 -> Insert Mode (IRM).3598// Ps = 1 2 -> Send/receive (SRM).3599// Ps = 2 0 -> Automatic Newline (LNM).3600// CSI ? Pm h3601// DEC Private Mode Set (DECSET).3602// Ps = 1 -> Application Cursor Keys (DECCKM).3603// Ps = 2 -> Designate USASCII for character sets G0-G33604// (DECANM), and set VT100 mode.3605// Ps = 3 -> 132 Column Mode (DECCOLM).3606// Ps = 4 -> Smooth (Slow) Scroll (DECSCLM).3607// Ps = 5 -> Reverse Video (DECSCNM).3608// Ps = 6 -> Origin Mode (DECOM).3609// Ps = 7 -> Wraparound Mode (DECAWM).3610// Ps = 8 -> Auto-repeat Keys (DECARM).3611// Ps = 9 -> Send Mouse X & Y on button press. See the sec-3612// tion Mouse Tracking.3613// Ps = 1 0 -> Show toolbar (rxvt).3614// Ps = 1 2 -> Start Blinking Cursor (att610).3615// Ps = 1 8 -> Print form feed (DECPFF).3616// Ps = 1 9 -> Set print extent to full screen (DECPEX).3617// Ps = 2 5 -> Show Cursor (DECTCEM).3618// Ps = 3 0 -> Show scrollbar (rxvt).3619// Ps = 3 5 -> Enable font-shifting functions (rxvt).3620// Ps = 3 8 -> Enter Tektronix Mode (DECTEK).3621// Ps = 4 0 -> Allow 80 -> 132 Mode.3622// Ps = 4 1 -> more(1) fix (see curses resource).3623// Ps = 4 2 -> Enable Nation Replacement Character sets (DECN-3624// RCM).3625// Ps = 4 4 -> Turn On Margin Bell.3626// Ps = 4 5 -> Reverse-wraparound Mode.3627// Ps = 4 6 -> Start Logging. This is normally disabled by a3628// compile-time option.3629// Ps = 4 7 -> Use Alternate Screen Buffer. (This may be dis-3630// abled by the titeInhibit resource).3631// Ps = 6 6 -> Application keypad (DECNKM).3632// Ps = 6 7 -> Backarrow key sends backspace (DECBKM).3633// Ps = 1 0 0 0 -> Send Mouse X & Y on button press and3634// release. See the section Mouse Tracking.3635// Ps = 1 0 0 1 -> Use Hilite Mouse Tracking.3636// Ps = 1 0 0 2 -> Use Cell Motion Mouse Tracking.3637// Ps = 1 0 0 3 -> Use All Motion Mouse Tracking.3638// Ps = 1 0 0 4 -> Send FocusIn/FocusOut events.3639// Ps = 1 0 0 5 -> Enable Extended Mouse Mode.3640// Ps = 1 0 1 0 -> Scroll to bottom on tty output (rxvt).3641// Ps = 1 0 1 1 -> Scroll to bottom on key press (rxvt).3642// Ps = 1 0 3 4 -> Interpret "meta" key, sets eighth bit.3643// (enables the eightBitInput resource).3644// Ps = 1 0 3 5 -> Enable special modifiers for Alt and Num-3645// Lock keys. (This enables the numLock resource).3646// Ps = 1 0 3 6 -> Send ESC when Meta modifies a key. (This3647// enables the metaSendsEscape resource).3648// Ps = 1 0 3 7 -> Send DEL from the editing-keypad Delete3649// key.3650// Ps = 1 0 3 9 -> Send ESC when Alt modifies a key. (This3651// enables the altSendsEscape resource).3652// Ps = 1 0 4 0 -> Keep selection even if not highlighted.3653// (This enables the keepSelection resource).3654// Ps = 1 0 4 1 -> Use the CLIPBOARD selection. (This enables3655// the selectToClipboard resource).3656// Ps = 1 0 4 2 -> Enable Urgency window manager hint when3657// Control-G is received. (This enables the bellIsUrgent3658// resource).3659// Ps = 1 0 4 3 -> Enable raising of the window when Control-G3660// is received. (enables the popOnBell resource).3661// Ps = 1 0 4 7 -> Use Alternate Screen Buffer. (This may be3662// disabled by the titeInhibit resource).3663// Ps = 1 0 4 8 -> Save cursor as in DECSC. (This may be dis-3664// abled by the titeInhibit resource).3665// Ps = 1 0 4 9 -> Save cursor as in DECSC and use Alternate3666// Screen Buffer, clearing it first. (This may be disabled by3667// the titeInhibit resource). This combines the effects of the 13668// 0 4 7 and 1 0 4 8 modes. Use this with terminfo-based3669// applications rather than the 4 7 mode.3670// Ps = 1 0 5 0 -> Set terminfo/termcap function-key mode.3671// Ps = 1 0 5 1 -> Set Sun function-key mode.3672// Ps = 1 0 5 2 -> Set HP function-key mode.3673// Ps = 1 0 5 3 -> Set SCO function-key mode.3674// Ps = 1 0 6 0 -> Set legacy keyboard emulation (X11R6).3675// Ps = 1 0 6 1 -> Set VT220 keyboard emulation.3676// Ps = 2 0 0 4 -> Set bracketed paste mode.3677// Modes:3678// http://vt100.net/docs/vt220-rm/chapter4.html3679Terminal.prototype.setMode = function(params) {3680if (typeof params === 'object') {3681var l = params.length3682, i = 0;36833684for (; i < l; i++) {3685this.setMode(params[i]);3686}36873688return;3689}36903691if (!this.prefix) {3692switch (params) {3693case 4:3694this.insertMode = true;3695break;3696case 20:3697//this.convertEol = true;3698break;3699}3700} else if (this.prefix === '?') {3701switch (params) {3702case 1:3703this.applicationCursor = true;3704break;3705case 2:3706this.setgCharset(0, Terminal.charsets.US);3707this.setgCharset(1, Terminal.charsets.US);3708this.setgCharset(2, Terminal.charsets.US);3709this.setgCharset(3, Terminal.charsets.US);3710// set VT100 mode here3711break;3712case 3: // 132 col mode3713this.savedCols = this.cols;3714this.resize(132, this.rows);3715break;3716case 6:3717this.originMode = true;3718break;3719case 7:3720this.wraparoundMode = true;3721break;3722case 12:3723// this.cursorBlink = true;3724break;3725case 66:3726this.log('Serial port requested application keypad.');3727this.applicationKeypad = true;3728break;3729case 9: // X10 Mouse3730// no release, no motion, no wheel, no modifiers.3731case 1000: // vt200 mouse3732// no motion.3733// no modifiers, except control on the wheel.3734case 1002: // button event mouse3735case 1003: // any event mouse3736// any event - sends motion events,3737// even if there is no button held down.3738this.x10Mouse = params === 9;3739this.vt200Mouse = params === 1000;3740this.normalMouse = params > 1000;3741this.mouseEvents = true;3742this.element.style.cursor = 'default';3743this.log('Binding to mouse events.');3744break;3745case 1004: // send focusin/focusout events3746// focusin: ^[[I3747// focusout: ^[[O3748this.sendFocus = true;3749break;3750case 1005: // utf8 ext mode mouse3751this.utfMouse = true;3752// for wide terminals3753// simply encodes large values as utf8 characters3754break;3755case 1006: // sgr ext mode mouse3756this.sgrMouse = true;3757// for wide terminals3758// does not add 32 to fields3759// press: ^[[<b;x;yM3760// release: ^[[<b;x;ym3761break;3762case 1015: // urxvt ext mode mouse3763this.urxvtMouse = true;3764// for wide terminals3765// numbers for fields3766// press: ^[[b;x;yM3767// motion: ^[[b;x;yT3768break;3769case 25: // show cursor3770this.cursorHidden = false;3771break;3772case 1049: // alt screen buffer cursor3773//this.saveCursor();3774; // FALL-THROUGH3775case 47: // alt screen buffer3776case 1047: // alt screen buffer3777if (!this.normal) {3778var normal = {3779lines: this.lines,3780ybase: this.ybase,3781ydisp: this.ydisp,3782x: this.x,3783y: this.y,3784scrollTop: this.scrollTop,3785scrollBottom: this.scrollBottom,3786tabs: this.tabs3787// XXX save charset(s) here?3788// charset: this.charset,3789// glevel: this.glevel,3790// charsets: this.charsets3791};3792this.reset();3793this.normal = normal;3794this.showCursor();3795}3796break;3797}3798}3799};38003801// CSI Pm l Reset Mode (RM).3802// Ps = 2 -> Keyboard Action Mode (AM).3803// Ps = 4 -> Replace Mode (IRM).3804// Ps = 1 2 -> Send/receive (SRM).3805// Ps = 2 0 -> Normal Linefeed (LNM).3806// CSI ? Pm l3807// DEC Private Mode Reset (DECRST).3808// Ps = 1 -> Normal Cursor Keys (DECCKM).3809// Ps = 2 -> Designate VT52 mode (DECANM).3810// Ps = 3 -> 80 Column Mode (DECCOLM).3811// Ps = 4 -> Jump (Fast) Scroll (DECSCLM).3812// Ps = 5 -> Normal Video (DECSCNM).3813// Ps = 6 -> Normal Cursor Mode (DECOM).3814// Ps = 7 -> No Wraparound Mode (DECAWM).3815// Ps = 8 -> No Auto-repeat Keys (DECARM).3816// Ps = 9 -> Don't send Mouse X & Y on button press.3817// Ps = 1 0 -> Hide toolbar (rxvt).3818// Ps = 1 2 -> Stop Blinking Cursor (att610).3819// Ps = 1 8 -> Don't print form feed (DECPFF).3820// Ps = 1 9 -> Limit print to scrolling region (DECPEX).3821// Ps = 2 5 -> Hide Cursor (DECTCEM).3822// Ps = 3 0 -> Don't show scrollbar (rxvt).3823// Ps = 3 5 -> Disable font-shifting functions (rxvt).3824// Ps = 4 0 -> Disallow 80 -> 132 Mode.3825// Ps = 4 1 -> No more(1) fix (see curses resource).3826// Ps = 4 2 -> Disable Nation Replacement Character sets (DEC-3827// NRCM).3828// Ps = 4 4 -> Turn Off Margin Bell.3829// Ps = 4 5 -> No Reverse-wraparound Mode.3830// Ps = 4 6 -> Stop Logging. (This is normally disabled by a3831// compile-time option).3832// Ps = 4 7 -> Use Normal Screen Buffer.3833// Ps = 6 6 -> Numeric keypad (DECNKM).3834// Ps = 6 7 -> Backarrow key sends delete (DECBKM).3835// Ps = 1 0 0 0 -> Don't send Mouse X & Y on button press and3836// release. See the section Mouse Tracking.3837// Ps = 1 0 0 1 -> Don't use Hilite Mouse Tracking.3838// Ps = 1 0 0 2 -> Don't use Cell Motion Mouse Tracking.3839// Ps = 1 0 0 3 -> Don't use All Motion Mouse Tracking.3840// Ps = 1 0 0 4 -> Don't send FocusIn/FocusOut events.3841// Ps = 1 0 0 5 -> Disable Extended Mouse Mode.3842// Ps = 1 0 1 0 -> Don't scroll to bottom on tty output3843// (rxvt).3844// Ps = 1 0 1 1 -> Don't scroll to bottom on key press (rxvt).3845// Ps = 1 0 3 4 -> Don't interpret "meta" key. (This disables3846// the eightBitInput resource).3847// Ps = 1 0 3 5 -> Disable special modifiers for Alt and Num-3848// Lock keys. (This disables the numLock resource).3849// Ps = 1 0 3 6 -> Don't send ESC when Meta modifies a key.3850// (This disables the metaSendsEscape resource).3851// Ps = 1 0 3 7 -> Send VT220 Remove from the editing-keypad3852// Delete key.3853// Ps = 1 0 3 9 -> Don't send ESC when Alt modifies a key.3854// (This disables the altSendsEscape resource).3855// Ps = 1 0 4 0 -> Do not keep selection when not highlighted.3856// (This disables the keepSelection resource).3857// Ps = 1 0 4 1 -> Use the PRIMARY selection. (This disables3858// the selectToClipboard resource).3859// Ps = 1 0 4 2 -> Disable Urgency window manager hint when3860// Control-G is received. (This disables the bellIsUrgent3861// resource).3862// Ps = 1 0 4 3 -> Disable raising of the window when Control-3863// G is received. (This disables the popOnBell resource).3864// Ps = 1 0 4 7 -> Use Normal Screen Buffer, clearing screen3865// first if in the Alternate Screen. (This may be disabled by3866// the titeInhibit resource).3867// Ps = 1 0 4 8 -> Restore cursor as in DECRC. (This may be3868// disabled by the titeInhibit resource).3869// Ps = 1 0 4 9 -> Use Normal Screen Buffer and restore cursor3870// as in DECRC. (This may be disabled by the titeInhibit3871// resource). This combines the effects of the 1 0 4 7 and 1 03872// 4 8 modes. Use this with terminfo-based applications rather3873// than the 4 7 mode.3874// Ps = 1 0 5 0 -> Reset terminfo/termcap function-key mode.3875// Ps = 1 0 5 1 -> Reset Sun function-key mode.3876// Ps = 1 0 5 2 -> Reset HP function-key mode.3877// Ps = 1 0 5 3 -> Reset SCO function-key mode.3878// Ps = 1 0 6 0 -> Reset legacy keyboard emulation (X11R6).3879// Ps = 1 0 6 1 -> Reset keyboard emulation to Sun/PC style.3880// Ps = 2 0 0 4 -> Reset bracketed paste mode.3881Terminal.prototype.resetMode = function(params) {3882if (typeof params === 'object') {3883var l = params.length3884, i = 0;38853886for (; i < l; i++) {3887this.resetMode(params[i]);3888}38893890return;3891}38923893if (!this.prefix) {3894switch (params) {3895case 4:3896this.insertMode = false;3897break;3898case 20:3899//this.convertEol = false;3900break;3901}3902} else if (this.prefix === '?') {3903switch (params) {3904case 1:3905this.applicationCursor = false;3906break;3907case 3:3908if (this.cols === 132 && this.savedCols) {3909this.resize(this.savedCols, this.rows);3910}3911delete this.savedCols;3912break;3913case 6:3914this.originMode = false;3915break;3916case 7:3917this.wraparoundMode = false;3918break;3919case 12:3920// this.cursorBlink = false;3921break;3922case 66:3923this.log('Switching back to normal keypad.');3924this.applicationKeypad = false;3925break;3926case 9: // X10 Mouse3927case 1000: // vt200 mouse3928case 1002: // button event mouse3929case 1003: // any event mouse3930this.x10Mouse = false;3931this.vt200Mouse = false;3932this.normalMouse = false;3933this.mouseEvents = false;3934this.element.style.cursor = '';3935break;3936case 1004: // send focusin/focusout events3937this.sendFocus = false;3938break;3939case 1005: // utf8 ext mode mouse3940this.utfMouse = false;3941break;3942case 1006: // sgr ext mode mouse3943this.sgrMouse = false;3944break;3945case 1015: // urxvt ext mode mouse3946this.urxvtMouse = false;3947break;3948case 25: // hide cursor3949this.cursorHidden = true;3950break;3951case 1049: // alt screen buffer cursor3952; // FALL-THROUGH3953case 47: // normal screen buffer3954case 1047: // normal screen buffer - clearing it first3955if (this.normal) {3956this.lines = this.normal.lines;3957this.ybase = this.normal.ybase;3958this.ydisp = this.normal.ydisp;3959this.x = this.normal.x;3960this.y = this.normal.y;3961this.scrollTop = this.normal.scrollTop;3962this.scrollBottom = this.normal.scrollBottom;3963this.tabs = this.normal.tabs;3964this.normal = null;3965// if (params === 1049) {3966// this.x = this.savedX;3967// this.y = this.savedY;3968// }3969this.refresh(0, this.rows - 1);3970this.showCursor();3971}3972break;3973}3974}3975};39763977// CSI Ps ; Ps r3978// Set Scrolling Region [top;bottom] (default = full size of win-3979// dow) (DECSTBM).3980// CSI ? Pm r3981Terminal.prototype.setScrollRegion = function(params) {3982if (this.prefix) return;3983this.scrollTop = (params[0] || 1) - 1;3984this.scrollBottom = (params[1] || this.rows) - 1;3985this.x = 0;3986this.y = 0;3987};39883989// CSI s3990// Save cursor (ANSI.SYS).3991Terminal.prototype.saveCursor = function(params) {3992this.savedX = this.x;3993this.savedY = this.y;3994};39953996// CSI u3997// Restore cursor (ANSI.SYS).3998Terminal.prototype.restoreCursor = function(params) {3999this.x = this.savedX || 0;4000this.y = this.savedY || 0;4001};40024003/**4004* Lesser Used4005*/40064007// CSI Ps I4008// Cursor Forward Tabulation Ps tab stops (default = 1) (CHT).4009Terminal.prototype.cursorForwardTab = function(params) {4010var param = params[0] || 1;4011while (param--) {4012this.x = this.nextStop();4013}4014};40154016// CSI Ps S Scroll up Ps lines (default = 1) (SU).4017Terminal.prototype.scrollUp = function(params) {4018var param = params[0] || 1;4019while (param--) {4020this.lines.splice(this.ybase + this.scrollTop, 1);4021this.lines.splice(this.ybase + this.scrollBottom, 0, this.blankLine());4022}4023// this.maxRange();4024this.updateRange(this.scrollTop);4025this.updateRange(this.scrollBottom);4026};40274028// CSI Ps T Scroll down Ps lines (default = 1) (SD).4029Terminal.prototype.scrollDown = function(params) {4030var param = params[0] || 1;4031while (param--) {4032this.lines.splice(this.ybase + this.scrollBottom, 1);4033this.lines.splice(this.ybase + this.scrollTop, 0, this.blankLine());4034}4035// this.maxRange();4036this.updateRange(this.scrollTop);4037this.updateRange(this.scrollBottom);4038};40394040// CSI Ps ; Ps ; Ps ; Ps ; Ps T4041// Initiate highlight mouse tracking. Parameters are4042// [func;startx;starty;firstrow;lastrow]. See the section Mouse4043// Tracking.4044Terminal.prototype.initMouseTracking = function(params) {4045// Relevant: DECSET 10014046};40474048// CSI > Ps; Ps T4049// Reset one or more features of the title modes to the default4050// value. Normally, "reset" disables the feature. It is possi-4051// ble to disable the ability to reset features by compiling a4052// different default for the title modes into xterm.4053// Ps = 0 -> Do not set window/icon labels using hexadecimal.4054// Ps = 1 -> Do not query window/icon labels using hexadeci-4055// mal.4056// Ps = 2 -> Do not set window/icon labels using UTF-8.4057// Ps = 3 -> Do not query window/icon labels using UTF-8.4058// (See discussion of "Title Modes").4059Terminal.prototype.resetTitleModes = function(params) {4060;4061};40624063// CSI Ps Z Cursor Backward Tabulation Ps tab stops (default = 1) (CBT).4064Terminal.prototype.cursorBackwardTab = function(params) {4065var param = params[0] || 1;4066while (param--) {4067this.x = this.prevStop();4068}4069};40704071// CSI Ps b Repeat the preceding graphic character Ps times (REP).4072Terminal.prototype.repeatPrecedingCharacter = function(params) {4073var param = params[0] || 14074, line = this.lines[this.ybase + this.y]4075, ch = line[this.x - 1] || [this.defAttr, ' '];40764077while (param--) line[this.x++] = ch;4078};40794080// CSI Ps g Tab Clear (TBC).4081// Ps = 0 -> Clear Current Column (default).4082// Ps = 3 -> Clear All.4083// Potentially:4084// Ps = 2 -> Clear Stops on Line.4085// http://vt100.net/annarbor/aaa-ug/section6.html4086Terminal.prototype.tabClear = function(params) {4087var param = params[0];4088if (param <= 0) {4089delete this.tabs[this.x];4090} else if (param === 3) {4091this.tabs = {};4092}4093};40944095// CSI Pm i Media Copy (MC).4096// Ps = 0 -> Print screen (default).4097// Ps = 4 -> Turn off printer controller mode.4098// Ps = 5 -> Turn on printer controller mode.4099// CSI ? Pm i4100// Media Copy (MC, DEC-specific).4101// Ps = 1 -> Print line containing cursor.4102// Ps = 4 -> Turn off autoprint mode.4103// Ps = 5 -> Turn on autoprint mode.4104// Ps = 1 0 -> Print composed display, ignores DECPEX.4105// Ps = 1 1 -> Print all pages.4106Terminal.prototype.mediaCopy = function(params) {4107;4108};41094110// CSI > Ps; Ps m4111// Set or reset resource-values used by xterm to decide whether4112// to construct escape sequences holding information about the4113// modifiers pressed with a given key. The first parameter iden-4114// tifies the resource to set/reset. The second parameter is the4115// value to assign to the resource. If the second parameter is4116// omitted, the resource is reset to its initial value.4117// Ps = 1 -> modifyCursorKeys.4118// Ps = 2 -> modifyFunctionKeys.4119// Ps = 4 -> modifyOtherKeys.4120// If no parameters are given, all resources are reset to their4121// initial values.4122Terminal.prototype.setResources = function(params) {4123;4124};41254126// CSI > Ps n4127// Disable modifiers which may be enabled via the CSI > Ps; Ps m4128// sequence. This corresponds to a resource value of "-1", which4129// cannot be set with the other sequence. The parameter identi-4130// fies the resource to be disabled:4131// Ps = 1 -> modifyCursorKeys.4132// Ps = 2 -> modifyFunctionKeys.4133// Ps = 4 -> modifyOtherKeys.4134// If the parameter is omitted, modifyFunctionKeys is disabled.4135// When modifyFunctionKeys is disabled, xterm uses the modifier4136// keys to make an extended sequence of functions rather than4137// adding a parameter to each function key to denote the modi-4138// fiers.4139Terminal.prototype.disableModifiers = function(params) {4140;4141};41424143// CSI > Ps p4144// Set resource value pointerMode. This is used by xterm to4145// decide whether to hide the pointer cursor as the user types.4146// Valid values for the parameter:4147// Ps = 0 -> never hide the pointer.4148// Ps = 1 -> hide if the mouse tracking mode is not enabled.4149// Ps = 2 -> always hide the pointer. If no parameter is4150// given, xterm uses the default, which is 1 .4151Terminal.prototype.setPointerMode = function(params) {4152;4153};41544155// CSI ! p Soft terminal reset (DECSTR).4156// http://vt100.net/docs/vt220-rm/table4-10.html4157Terminal.prototype.softReset = function(params) {4158this.cursorHidden = false;4159this.insertMode = false;4160this.originMode = false;4161this.wraparoundMode = false; // autowrap4162this.applicationKeypad = false; // ?4163this.applicationCursor = false;4164this.scrollTop = 0;4165this.scrollBottom = this.rows - 1;4166this.curAttr = this.defAttr;4167this.x = this.y = 0; // ?4168this.charset = null;4169this.glevel = 0; // ??4170this.charsets = [null]; // ??4171};41724173// CSI Ps$ p4174// Request ANSI mode (DECRQM). For VT300 and up, reply is4175// CSI Ps; Pm$ y4176// where Ps is the mode number as in RM, and Pm is the mode4177// value:4178// 0 - not recognized4179// 1 - set4180// 2 - reset4181// 3 - permanently set4182// 4 - permanently reset4183Terminal.prototype.requestAnsiMode = function(params) {4184;4185};41864187// CSI ? Ps$ p4188// Request DEC private mode (DECRQM). For VT300 and up, reply is4189// CSI ? Ps; Pm$ p4190// where Ps is the mode number as in DECSET, Pm is the mode value4191// as in the ANSI DECRQM.4192Terminal.prototype.requestPrivateMode = function(params) {4193;4194};41954196// CSI Ps ; Ps " p4197// Set conformance level (DECSCL). Valid values for the first4198// parameter:4199// Ps = 6 1 -> VT100.4200// Ps = 6 2 -> VT200.4201// Ps = 6 3 -> VT300.4202// Valid values for the second parameter:4203// Ps = 0 -> 8-bit controls.4204// Ps = 1 -> 7-bit controls (always set for VT100).4205// Ps = 2 -> 8-bit controls.4206Terminal.prototype.setConformanceLevel = function(params) {4207;4208};42094210// CSI Ps q Load LEDs (DECLL).4211// Ps = 0 -> Clear all LEDS (default).4212// Ps = 1 -> Light Num Lock.4213// Ps = 2 -> Light Caps Lock.4214// Ps = 3 -> Light Scroll Lock.4215// Ps = 2 1 -> Extinguish Num Lock.4216// Ps = 2 2 -> Extinguish Caps Lock.4217// Ps = 2 3 -> Extinguish Scroll Lock.4218Terminal.prototype.loadLEDs = function(params) {4219;4220};42214222// CSI Ps SP q4223// Set cursor style (DECSCUSR, VT520).4224// Ps = 0 -> blinking block.4225// Ps = 1 -> blinking block (default).4226// Ps = 2 -> steady block.4227// Ps = 3 -> blinking underline.4228// Ps = 4 -> steady underline.4229Terminal.prototype.setCursorStyle = function(params) {4230;4231};42324233// CSI Ps " q4234// Select character protection attribute (DECSCA). Valid values4235// for the parameter:4236// Ps = 0 -> DECSED and DECSEL can erase (default).4237// Ps = 1 -> DECSED and DECSEL cannot erase.4238// Ps = 2 -> DECSED and DECSEL can erase.4239Terminal.prototype.setCharProtectionAttr = function(params) {4240;4241};42424243// CSI ? Pm r4244// Restore DEC Private Mode Values. The value of Ps previously4245// saved is restored. Ps values are the same as for DECSET.4246Terminal.prototype.restorePrivateValues = function(params) {4247;4248};42494250// CSI Pt; Pl; Pb; Pr; Ps$ r4251// Change Attributes in Rectangular Area (DECCARA), VT400 and up.4252// Pt; Pl; Pb; Pr denotes the rectangle.4253// Ps denotes the SGR attributes to change: 0, 1, 4, 5, 7.4254// NOTE: xterm doesn't enable this code by default.4255Terminal.prototype.setAttrInRectangle = function(params) {4256var t = params[0]4257, l = params[1]4258, b = params[2]4259, r = params[3]4260, attr = params[4];42614262var line4263, i;42644265for (; t < b + 1; t++) {4266line = this.lines[this.ybase + t];4267for (i = l; i < r; i++) {4268line[i] = [attr, line[i][1]];4269}4270}42714272// this.maxRange();4273this.updateRange(params[0]);4274this.updateRange(params[2]);4275};42764277// CSI ? Pm s4278// Save DEC Private Mode Values. Ps values are the same as for4279// DECSET.4280Terminal.prototype.savePrivateValues = function(params) {4281;4282};42834284// CSI Ps ; Ps ; Ps t4285// Window manipulation (from dtterm, as well as extensions).4286// These controls may be disabled using the allowWindowOps4287// resource. Valid values for the first (and any additional4288// parameters) are:4289// Ps = 1 -> De-iconify window.4290// Ps = 2 -> Iconify window.4291// Ps = 3 ; x ; y -> Move window to [x, y].4292// Ps = 4 ; height ; width -> Resize the xterm window to4293// height and width in pixels.4294// Ps = 5 -> Raise the xterm window to the front of the stack-4295// ing order.4296// Ps = 6 -> Lower the xterm window to the bottom of the4297// stacking order.4298// Ps = 7 -> Refresh the xterm window.4299// Ps = 8 ; height ; width -> Resize the text area to4300// [height;width] in characters.4301// Ps = 9 ; 0 -> Restore maximized window.4302// Ps = 9 ; 1 -> Maximize window (i.e., resize to screen4303// size).4304// Ps = 1 0 ; 0 -> Undo full-screen mode.4305// Ps = 1 0 ; 1 -> Change to full-screen.4306// Ps = 1 1 -> Report xterm window state. If the xterm window4307// is open (non-iconified), it returns CSI 1 t . If the xterm4308// window is iconified, it returns CSI 2 t .4309// Ps = 1 3 -> Report xterm window position. Result is CSI 34310// ; x ; y t4311// Ps = 1 4 -> Report xterm window in pixels. Result is CSI4312// 4 ; height ; width t4313// Ps = 1 8 -> Report the size of the text area in characters.4314// Result is CSI 8 ; height ; width t4315// Ps = 1 9 -> Report the size of the screen in characters.4316// Result is CSI 9 ; height ; width t4317// Ps = 2 0 -> Report xterm window's icon label. Result is4318// OSC L label ST4319// Ps = 2 1 -> Report xterm window's title. Result is OSC l4320// label ST4321// Ps = 2 2 ; 0 -> Save xterm icon and window title on4322// stack.4323// Ps = 2 2 ; 1 -> Save xterm icon title on stack.4324// Ps = 2 2 ; 2 -> Save xterm window title on stack.4325// Ps = 2 3 ; 0 -> Restore xterm icon and window title from4326// stack.4327// Ps = 2 3 ; 1 -> Restore xterm icon title from stack.4328// Ps = 2 3 ; 2 -> Restore xterm window title from stack.4329// Ps >= 2 4 -> Resize to Ps lines (DECSLPP).4330Terminal.prototype.manipulateWindow = function(params) {4331;4332};43334334// CSI Pt; Pl; Pb; Pr; Ps$ t4335// Reverse Attributes in Rectangular Area (DECRARA), VT400 and4336// up.4337// Pt; Pl; Pb; Pr denotes the rectangle.4338// Ps denotes the attributes to reverse, i.e., 1, 4, 5, 7.4339// NOTE: xterm doesn't enable this code by default.4340Terminal.prototype.reverseAttrInRectangle = function(params) {4341;4342};43434344// CSI > Ps; Ps t4345// Set one or more features of the title modes. Each parameter4346// enables a single feature.4347// Ps = 0 -> Set window/icon labels using hexadecimal.4348// Ps = 1 -> Query window/icon labels using hexadecimal.4349// Ps = 2 -> Set window/icon labels using UTF-8.4350// Ps = 3 -> Query window/icon labels using UTF-8. (See dis-4351// cussion of "Title Modes")4352Terminal.prototype.setTitleModeFeature = function(params) {4353;4354};43554356// CSI Ps SP t4357// Set warning-bell volume (DECSWBV, VT520).4358// Ps = 0 or 1 -> off.4359// Ps = 2 , 3 or 4 -> low.4360// Ps = 5 , 6 , 7 , or 8 -> high.4361Terminal.prototype.setWarningBellVolume = function(params) {4362;4363};43644365// CSI Ps SP u4366// Set margin-bell volume (DECSMBV, VT520).4367// Ps = 1 -> off.4368// Ps = 2 , 3 or 4 -> low.4369// Ps = 0 , 5 , 6 , 7 , or 8 -> high.4370Terminal.prototype.setMarginBellVolume = function(params) {4371;4372};43734374// CSI Pt; Pl; Pb; Pr; Pp; Pt; Pl; Pp$ v4375// Copy Rectangular Area (DECCRA, VT400 and up).4376// Pt; Pl; Pb; Pr denotes the rectangle.4377// Pp denotes the source page.4378// Pt; Pl denotes the target location.4379// Pp denotes the target page.4380// NOTE: xterm doesn't enable this code by default.4381Terminal.prototype.copyRectangle = function(params) {4382;4383};43844385// CSI Pt ; Pl ; Pb ; Pr ' w4386// Enable Filter Rectangle (DECEFR), VT420 and up.4387// Parameters are [top;left;bottom;right].4388// Defines the coordinates of a filter rectangle and activates4389// it. Anytime the locator is detected outside of the filter4390// rectangle, an outside rectangle event is generated and the4391// rectangle is disabled. Filter rectangles are always treated4392// as "one-shot" events. Any parameters that are omitted default4393// to the current locator position. If all parameters are omit-4394// ted, any locator motion will be reported. DECELR always can-4395// cels any prevous rectangle definition.4396Terminal.prototype.enableFilterRectangle = function(params) {4397;4398};43994400// CSI Ps x Request Terminal Parameters (DECREQTPARM).4401// if Ps is a "0" (default) or "1", and xterm is emulating VT100,4402// the control sequence elicits a response of the same form whose4403// parameters describe the terminal:4404// Ps -> the given Ps incremented by 2.4405// Pn = 1 <- no parity.4406// Pn = 1 <- eight bits.4407// Pn = 1 <- 2 8 transmit 38.4k baud.4408// Pn = 1 <- 2 8 receive 38.4k baud.4409// Pn = 1 <- clock multiplier.4410// Pn = 0 <- STP flags.4411Terminal.prototype.requestParameters = function(params) {4412;4413};44144415// CSI Ps x Select Attribute Change Extent (DECSACE).4416// Ps = 0 -> from start to end position, wrapped.4417// Ps = 1 -> from start to end position, wrapped.4418// Ps = 2 -> rectangle (exact).4419Terminal.prototype.selectChangeExtent = function(params) {4420;4421};44224423// CSI Pc; Pt; Pl; Pb; Pr$ x4424// Fill Rectangular Area (DECFRA), VT420 and up.4425// Pc is the character to use.4426// Pt; Pl; Pb; Pr denotes the rectangle.4427// NOTE: xterm doesn't enable this code by default.4428Terminal.prototype.fillRectangle = function(params) {4429var ch = params[0]4430, t = params[1]4431, l = params[2]4432, b = params[3]4433, r = params[4];44344435var line4436, i;44374438for (; t < b + 1; t++) {4439line = this.lines[this.ybase + t];4440for (i = l; i < r; i++) {4441line[i] = [line[i][0], String.fromCharCode(ch)];4442}4443}44444445// this.maxRange();4446this.updateRange(params[1]);4447this.updateRange(params[3]);4448};44494450// CSI Ps ; Pu ' z4451// Enable Locator Reporting (DECELR).4452// Valid values for the first parameter:4453// Ps = 0 -> Locator disabled (default).4454// Ps = 1 -> Locator enabled.4455// Ps = 2 -> Locator enabled for one report, then disabled.4456// The second parameter specifies the coordinate unit for locator4457// reports.4458// Valid values for the second parameter:4459// Pu = 0 <- or omitted -> default to character cells.4460// Pu = 1 <- device physical pixels.4461// Pu = 2 <- character cells.4462Terminal.prototype.enableLocatorReporting = function(params) {4463var val = params[0] > 0;4464//this.mouseEvents = val;4465//this.decLocator = val;4466};44674468// CSI Pt; Pl; Pb; Pr$ z4469// Erase Rectangular Area (DECERA), VT400 and up.4470// Pt; Pl; Pb; Pr denotes the rectangle.4471// NOTE: xterm doesn't enable this code by default.4472Terminal.prototype.eraseRectangle = function(params) {4473var t = params[0]4474, l = params[1]4475, b = params[2]4476, r = params[3];44774478var line4479, i4480, ch;44814482ch = [this.eraseAttr(), ' ']; // xterm?44834484for (; t < b + 1; t++) {4485line = this.lines[this.ybase + t];4486for (i = l; i < r; i++) {4487line[i] = ch;4488}4489}44904491// this.maxRange();4492this.updateRange(params[0]);4493this.updateRange(params[2]);4494};44954496// CSI Pm ' {4497// Select Locator Events (DECSLE).4498// Valid values for the first (and any additional parameters)4499// are:4500// Ps = 0 -> only respond to explicit host requests (DECRQLP).4501// (This is default). It also cancels any filter4502// rectangle.4503// Ps = 1 -> report button down transitions.4504// Ps = 2 -> do not report button down transitions.4505// Ps = 3 -> report button up transitions.4506// Ps = 4 -> do not report button up transitions.4507Terminal.prototype.setLocatorEvents = function(params) {4508;4509};45104511// CSI Pt; Pl; Pb; Pr$ {4512// Selective Erase Rectangular Area (DECSERA), VT400 and up.4513// Pt; Pl; Pb; Pr denotes the rectangle.4514Terminal.prototype.selectiveEraseRectangle = function(params) {4515;4516};45174518// CSI Ps ' |4519// Request Locator Position (DECRQLP).4520// Valid values for the parameter are:4521// Ps = 0 , 1 or omitted -> transmit a single DECLRP locator4522// report.45234524// If Locator Reporting has been enabled by a DECELR, xterm will4525// respond with a DECLRP Locator Report. This report is also4526// generated on button up and down events if they have been4527// enabled with a DECSLE, or when the locator is detected outside4528// of a filter rectangle, if filter rectangles have been enabled4529// with a DECEFR.45304531// -> CSI Pe ; Pb ; Pr ; Pc ; Pp & w45324533// Parameters are [event;button;row;column;page].4534// Valid values for the event:4535// Pe = 0 -> locator unavailable - no other parameters sent.4536// Pe = 1 -> request - xterm received a DECRQLP.4537// Pe = 2 -> left button down.4538// Pe = 3 -> left button up.4539// Pe = 4 -> middle button down.4540// Pe = 5 -> middle button up.4541// Pe = 6 -> right button down.4542// Pe = 7 -> right button up.4543// Pe = 8 -> M4 button down.4544// Pe = 9 -> M4 button up.4545// Pe = 1 0 -> locator outside filter rectangle.4546// ``button'' parameter is a bitmask indicating which buttons are4547// pressed:4548// Pb = 0 <- no buttons down.4549// Pb & 1 <- right button down.4550// Pb & 2 <- middle button down.4551// Pb & 4 <- left button down.4552// Pb & 8 <- M4 button down.4553// ``row'' and ``column'' parameters are the coordinates of the4554// locator position in the xterm window, encoded as ASCII deci-4555// mal.4556// The ``page'' parameter is not used by xterm, and will be omit-4557// ted.4558Terminal.prototype.requestLocatorPosition = function(params) {4559;4560};45614562// CSI P m SP }4563// Insert P s Column(s) (default = 1) (DECIC), VT420 and up.4564// NOTE: xterm doesn't enable this code by default.4565Terminal.prototype.insertColumns = function() {4566var param = params[0]4567, l = this.ybase + this.rows4568, ch = [this.eraseAttr(), ' '] // xterm?4569, i;45704571while (param--) {4572for (i = this.ybase; i < l; i++) {4573this.lines[i].splice(this.x + 1, 0, ch);4574this.lines[i].pop();4575}4576}45774578this.maxRange();4579};45804581// CSI P m SP ~4582// Delete P s Column(s) (default = 1) (DECDC), VT420 and up4583// NOTE: xterm doesn't enable this code by default.4584Terminal.prototype.deleteColumns = function() {4585var param = params[0]4586, l = this.ybase + this.rows4587, ch = [this.eraseAttr(), ' '] // xterm?4588, i;45894590while (param--) {4591for (i = this.ybase; i < l; i++) {4592this.lines[i].splice(this.x, 1);4593this.lines[i].push(ch);4594}4595}45964597this.maxRange();4598};45994600/**4601* Prefix/Select/Visual/Search Modes4602*/46034604Terminal.prototype.enterPrefix = function() {4605this.prefixMode = true;4606};46074608Terminal.prototype.leavePrefix = function() {4609this.prefixMode = false;4610};46114612Terminal.prototype.enterSelect = function() {4613this._real = {4614x: this.x,4615y: this.y,4616ydisp: this.ydisp,4617ybase: this.ybase,4618cursorHidden: this.cursorHidden,4619lines: this.copyBuffer(this.lines),4620write: this.write4621};4622this.write = function() {};4623this.selectMode = true;4624this.visualMode = false;4625this.cursorHidden = false;4626this.refresh(this.y, this.y);4627};46284629Terminal.prototype.leaveSelect = function() {4630this.x = this._real.x;4631this.y = this._real.y;4632this.ydisp = this._real.ydisp;4633this.ybase = this._real.ybase;4634this.cursorHidden = this._real.cursorHidden;4635this.lines = this._real.lines;4636this.write = this._real.write;4637delete this._real;4638this.selectMode = false;4639this.visualMode = false;4640this.refresh(0, this.rows - 1);4641};46424643Terminal.prototype.enterVisual = function() {4644this._real.preVisual = this.copyBuffer(this.lines);4645this.selectText(this.x, this.x, this.ydisp + this.y, this.ydisp + this.y);4646this.visualMode = true;4647};46484649Terminal.prototype.leaveVisual = function() {4650this.lines = this._real.preVisual;4651delete this._real.preVisual;4652delete this._selected;4653this.visualMode = false;4654this.refresh(0, this.rows - 1);4655};46564657Terminal.prototype.enterSearch = function(down) {4658this.entry = '';4659this.searchMode = true;4660this.searchDown = down;4661this._real.preSearch = this.copyBuffer(this.lines);4662this._real.preSearchX = this.x;4663this._real.preSearchY = this.y;46644665var bottom = this.ydisp + this.rows - 1;4666for (var i = 0; i < this.entryPrefix.length; i++) {4667//this.lines[bottom][i][0] = (this.defAttr & ~0x1ff) | 4;4668//this.lines[bottom][i][1] = this.entryPrefix[i];4669this.lines[bottom][i] = [4670(this.defAttr & ~0x1ff) | 4,4671this.entryPrefix[i]4672];4673}46744675this.y = this.rows - 1;4676this.x = this.entryPrefix.length;46774678this.refresh(this.rows - 1, this.rows - 1);4679};46804681Terminal.prototype.leaveSearch = function() {4682this.searchMode = false;46834684if (this._real.preSearch) {4685this.lines = this._real.preSearch;4686this.x = this._real.preSearchX;4687this.y = this._real.preSearchY;4688delete this._real.preSearch;4689delete this._real.preSearchX;4690delete this._real.preSearchY;4691}46924693this.refresh(this.rows - 1, this.rows - 1);4694};46954696Terminal.prototype.copyBuffer = function(lines) {4697var lines = lines || this.lines4698, out = [];46994700for (var y = 0; y < lines.length; y++) {4701out[y] = [];4702for (var x = 0; x < lines[y].length; x++) {4703out[y][x] = [lines[y][x][0], lines[y][x][1]];4704}4705}47064707return out;4708};47094710Terminal.prototype.getCopyTextarea = function(text) {4711var textarea = this._copyTextarea4712, document = this.document;47134714if (!textarea) {4715textarea = document.createElement('textarea');4716textarea.style.position = 'absolute';4717textarea.style.left = '-32000px';4718textarea.style.top = '-32000px';4719textarea.style.width = '0px';4720textarea.style.height = '0px';4721textarea.style.opacity = '0';4722textarea.style.backgroundColor = 'transparent';4723textarea.style.borderStyle = 'none';4724textarea.style.outlineStyle = 'none';47254726document.getElementsByTagName('body')[0].appendChild(textarea);47274728this._copyTextarea = textarea;4729}47304731return textarea;4732};47334734// NOTE: Only works for primary selection on X11.4735// Non-X11 users should use Ctrl-C instead.4736Terminal.prototype.copyText = function(text) {4737var self = this4738, textarea = this.getCopyTextarea();47394740this.emit('copy', text);47414742textarea.focus();4743textarea.textContent = text;4744textarea.value = text;4745textarea.setSelectionRange(0, text.length);47464747setTimeout(function() {4748self.element.focus();4749self.focus();4750}, 1);4751};47524753Terminal.prototype.selectText = function(x1, x2, y1, y2) {4754var ox14755, ox24756, oy14757, oy24758, tmp4759, x4760, y4761, xl4762, attr;47634764if (this._selected) {4765ox1 = this._selected.x1;4766ox2 = this._selected.x2;4767oy1 = this._selected.y1;4768oy2 = this._selected.y2;47694770if (oy2 < oy1) {4771tmp = ox2;4772ox2 = ox1;4773ox1 = tmp;4774tmp = oy2;4775oy2 = oy1;4776oy1 = tmp;4777}47784779if (ox2 < ox1 && oy1 === oy2) {4780tmp = ox2;4781ox2 = ox1;4782ox1 = tmp;4783}47844785for (y = oy1; y <= oy2; y++) {4786x = 0;4787xl = this.cols - 1;4788if (y === oy1) {4789x = ox1;4790}4791if (y === oy2) {4792xl = ox2;4793}4794for (; x <= xl; x++) {4795if (this.lines[y][x].old != null) {4796//this.lines[y][x][0] = this.lines[y][x].old;4797//delete this.lines[y][x].old;4798attr = this.lines[y][x].old;4799delete this.lines[y][x].old;4800this.lines[y][x] = [attr, this.lines[y][x][1]];4801}4802}4803}48044805y1 = this._selected.y1;4806x1 = this._selected.x1;4807}48084809y1 = Math.max(y1, 0);4810y1 = Math.min(y1, this.ydisp + this.rows - 1);48114812y2 = Math.max(y2, 0);4813y2 = Math.min(y2, this.ydisp + this.rows - 1);48144815this._selected = { x1: x1, x2: x2, y1: y1, y2: y2 };48164817if (y2 < y1) {4818tmp = x2;4819x2 = x1;4820x1 = tmp;4821tmp = y2;4822y2 = y1;4823y1 = tmp;4824}48254826if (x2 < x1 && y1 === y2) {4827tmp = x2;4828x2 = x1;4829x1 = tmp;4830}48314832for (y = y1; y <= y2; y++) {4833x = 0;4834xl = this.cols - 1;4835if (y === y1) {4836x = x1;4837}4838if (y === y2) {4839xl = x2;4840}4841for (; x <= xl; x++) {4842//this.lines[y][x].old = this.lines[y][x][0];4843//this.lines[y][x][0] &= ~0x1ff;4844//this.lines[y][x][0] |= (0x1ff << 9) | 4;4845attr = this.lines[y][x][0];4846this.lines[y][x] = [4847(attr & ~0x1ff) | ((0x1ff << 9) | 4),4848this.lines[y][x][1]4849];4850this.lines[y][x].old = attr;4851}4852}48534854y1 = y1 - this.ydisp;4855y2 = y2 - this.ydisp;48564857y1 = Math.max(y1, 0);4858y1 = Math.min(y1, this.rows - 1);48594860y2 = Math.max(y2, 0);4861y2 = Math.min(y2, this.rows - 1);48624863//this.refresh(y1, y2);4864this.refresh(0, this.rows - 1);4865};48664867Terminal.prototype.grabText = function(x1, x2, y1, y2) {4868var out = ''4869, buf = ''4870, ch4871, x4872, y4873, xl4874, tmp;48754876if (y2 < y1) {4877tmp = x2;4878x2 = x1;4879x1 = tmp;4880tmp = y2;4881y2 = y1;4882y1 = tmp;4883}48844885if (x2 < x1 && y1 === y2) {4886tmp = x2;4887x2 = x1;4888x1 = tmp;4889}48904891for (y = y1; y <= y2; y++) {4892x = 0;4893xl = this.cols - 1;4894if (y === y1) {4895x = x1;4896}4897if (y === y2) {4898xl = x2;4899}4900for (; x <= xl; x++) {4901ch = this.lines[y][x][1];4902if (ch === ' ') {4903buf += ch;4904continue;4905}4906if (buf) {4907out += buf;4908buf = '';4909}4910out += ch;4911if (isWide(ch)) x++;4912}4913buf = '';4914out += '\n';4915}49164917// If we're not at the end of the4918// line, don't add a newline.4919for (x = x2, y = y2; x < this.cols; x++) {4920if (this.lines[y][x][1] !== ' ') {4921out = out.slice(0, -1);4922break;4923}4924}49254926return out;4927};49284929Terminal.prototype.keyPrefix = function(ev, key) {4930if (key === 'k' || key === '&') {4931this.destroy();4932} else if (key === 'p' || key === ']') {4933this.emit('request paste');4934} else if (key === 'c') {4935this.emit('request create');4936} else if (key >= '0' && key <= '9') {4937key = +key - 1;4938if (!~key) key = 9;4939this.emit('request term', key);4940} else if (key === 'n') {4941this.emit('request term next');4942} else if (key === 'P') {4943this.emit('request term previous');4944} else if (key === ':') {4945this.emit('request command mode');4946} else if (key === '[') {4947this.enterSelect();4948}4949};49504951Terminal.prototype.keySelect = function(ev, key) {4952this.showCursor();49534954if (this.searchMode || key === 'n' || key === 'N') {4955return this.keySearch(ev, key);4956}49574958if (key === '\x04') { // ctrl-d4959var y = this.ydisp + this.y;4960if (this.ydisp === this.ybase) {4961// Mimic vim behavior4962this.y = Math.min(this.y + (this.rows - 1) / 2 | 0, this.rows - 1);4963this.refresh(0, this.rows - 1);4964} else {4965this.scrollDisp((this.rows - 1) / 2 | 0);4966}4967if (this.visualMode) {4968this.selectText(this.x, this.x, y, this.ydisp + this.y);4969}4970return;4971}49724973if (key === '\x15') { // ctrl-u4974var y = this.ydisp + this.y;4975if (this.ydisp === 0) {4976// Mimic vim behavior4977this.y = Math.max(this.y - (this.rows - 1) / 2 | 0, 0);4978this.refresh(0, this.rows - 1);4979} else {4980this.scrollDisp(-(this.rows - 1) / 2 | 0);4981}4982if (this.visualMode) {4983this.selectText(this.x, this.x, y, this.ydisp + this.y);4984}4985return;4986}49874988if (key === '\x06') { // ctrl-f4989var y = this.ydisp + this.y;4990this.scrollDisp(this.rows - 1);4991if (this.visualMode) {4992this.selectText(this.x, this.x, y, this.ydisp + this.y);4993}4994return;4995}49964997if (key === '\x02') { // ctrl-b4998var y = this.ydisp + this.y;4999this.scrollDisp(-(this.rows - 1));5000if (this.visualMode) {5001this.selectText(this.x, this.x, y, this.ydisp + this.y);5002}5003return;5004}50055006if (key === 'k' || key === '\x1b[A') {5007var y = this.ydisp + this.y;5008this.y--;5009if (this.y < 0) {5010this.y = 0;5011this.scrollDisp(-1);5012}5013if (this.visualMode) {5014this.selectText(this.x, this.x, y, this.ydisp + this.y);5015} else {5016this.refresh(this.y, this.y + 1);5017}5018return;5019}50205021if (key === 'j' || key === '\x1b[B') {5022var y = this.ydisp + this.y;5023this.y++;5024if (this.y >= this.rows) {5025this.y = this.rows - 1;5026this.scrollDisp(1);5027}5028if (this.visualMode) {5029this.selectText(this.x, this.x, y, this.ydisp + this.y);5030} else {5031this.refresh(this.y - 1, this.y);5032}5033return;5034}50355036if (key === 'h' || key === '\x1b[D') {5037var x = this.x;5038this.x--;5039if (this.x < 0) {5040this.x = 0;5041}5042if (this.visualMode) {5043this.selectText(x, this.x, this.ydisp + this.y, this.ydisp + this.y);5044} else {5045this.refresh(this.y, this.y);5046}5047return;5048}50495050if (key === 'l' || key === '\x1b[C') {5051var x = this.x;5052this.x++;5053if (this.x >= this.cols) {5054this.x = this.cols - 1;5055}5056if (this.visualMode) {5057this.selectText(x, this.x, this.ydisp + this.y, this.ydisp + this.y);5058} else {5059this.refresh(this.y, this.y);5060}5061return;5062}50635064if (key === 'v' || key === ' ') {5065if (!this.visualMode) {5066this.enterVisual();5067} else {5068this.leaveVisual();5069}5070return;5071}50725073if (key === 'y') {5074if (this.visualMode) {5075var text = this.grabText(5076this._selected.x1, this._selected.x2,5077this._selected.y1, this._selected.y2);5078this.copyText(text);5079this.leaveVisual();5080// this.leaveSelect();5081}5082return;5083}50845085if (key === 'q' || key === '\x1b') {5086if (this.visualMode) {5087this.leaveVisual();5088} else {5089this.leaveSelect();5090}5091return;5092}50935094if (key === 'w' || key === 'W') {5095var ox = this.x;5096var oy = this.y;5097var oyd = this.ydisp;50985099var x = this.x;5100var y = this.y;5101var yb = this.ydisp;5102var saw_space = false;51035104for (;;) {5105var line = this.lines[yb + y];5106while (x < this.cols) {5107if (line[x][1] <= ' ') {5108saw_space = true;5109} else if (saw_space) {5110break;5111}5112x++;5113}5114if (x >= this.cols) x = this.cols - 1;5115if (x === this.cols - 1 && line[x][1] <= ' ') {5116x = 0;5117if (++y >= this.rows) {5118y--;5119if (++yb > this.ybase) {5120yb = this.ybase;5121x = this.x;5122break;5123}5124}5125continue;5126}5127break;5128}51295130this.x = x, this.y = y;5131this.scrollDisp(-this.ydisp + yb);51325133if (this.visualMode) {5134this.selectText(ox, this.x, oy + oyd, this.ydisp + this.y);5135}5136return;5137}51385139if (key === 'b' || key === 'B') {5140var ox = this.x;5141var oy = this.y;5142var oyd = this.ydisp;51435144var x = this.x;5145var y = this.y;5146var yb = this.ydisp;51475148for (;;) {5149var line = this.lines[yb + y];5150var saw_space = x > 0 && line[x][1] > ' ' && line[x - 1][1] > ' ';5151while (x >= 0) {5152if (line[x][1] <= ' ') {5153if (saw_space && (x + 1 < this.cols && line[x + 1][1] > ' ')) {5154x++;5155break;5156} else {5157saw_space = true;5158}5159}5160x--;5161}5162if (x < 0) x = 0;5163if (x === 0 && (line[x][1] <= ' ' || !saw_space)) {5164x = this.cols - 1;5165if (--y < 0) {5166y++;5167if (--yb < 0) {5168yb++;5169x = 0;5170break;5171}5172}5173continue;5174}5175break;5176}51775178this.x = x, this.y = y;5179this.scrollDisp(-this.ydisp + yb);51805181if (this.visualMode) {5182this.selectText(ox, this.x, oy + oyd, this.ydisp + this.y);5183}5184return;5185}51865187if (key === 'e' || key === 'E') {5188var x = this.x + 1;5189var y = this.y;5190var yb = this.ydisp;5191if (x >= this.cols) x--;51925193for (;;) {5194var line = this.lines[yb + y];5195while (x < this.cols) {5196if (line[x][1] <= ' ') {5197x++;5198} else {5199break;5200}5201}5202while (x < this.cols) {5203if (line[x][1] <= ' ') {5204if (x - 1 >= 0 && line[x - 1][1] > ' ') {5205x--;5206break;5207}5208}5209x++;5210}5211if (x >= this.cols) x = this.cols - 1;5212if (x === this.cols - 1 && line[x][1] <= ' ') {5213x = 0;5214if (++y >= this.rows) {5215y--;5216if (++yb > this.ybase) {5217yb = this.ybase;5218break;5219}5220}5221continue;5222}5223break;5224}52255226this.x = x, this.y = y;5227this.scrollDisp(-this.ydisp + yb);52285229if (this.visualMode) {5230this.selectText(ox, this.x, oy + oyd, this.ydisp + this.y);5231}5232return;5233}52345235if (key === '^' || key === '0') {5236var ox = this.x;52375238if (key === '0') {5239this.x = 0;5240} else if (key === '^') {5241var line = this.lines[this.ydisp + this.y];5242var x = 0;5243while (x < this.cols) {5244if (line[x][1] > ' ') {5245break;5246}5247x++;5248}5249if (x >= this.cols) x = this.cols - 1;5250this.x = x;5251}52525253if (this.visualMode) {5254this.selectText(ox, this.x, this.ydisp + this.y, this.ydisp + this.y);5255} else {5256this.refresh(this.y, this.y);5257}5258return;5259}52605261if (key === '$') {5262var ox = this.x;5263var line = this.lines[this.ydisp + this.y];5264var x = this.cols - 1;5265while (x >= 0) {5266if (line[x][1] > ' ') {5267if (this.visualMode && x < this.cols - 1) x++;5268break;5269}5270x--;5271}5272if (x < 0) x = 0;5273this.x = x;5274if (this.visualMode) {5275this.selectText(ox, this.x, this.ydisp + this.y, this.ydisp + this.y);5276} else {5277this.refresh(this.y, this.y);5278}5279return;5280}52815282if (key === 'g' || key === 'G') {5283var ox = this.x;5284var oy = this.y;5285var oyd = this.ydisp;5286if (key === 'g') {5287this.x = 0, this.y = 0;5288this.scrollDisp(-this.ydisp);5289} else if (key === 'G') {5290this.x = 0, this.y = this.rows - 1;5291this.scrollDisp(this.ybase);5292}5293if (this.visualMode) {5294this.selectText(ox, this.x, oy + oyd, this.ydisp + this.y);5295}5296return;5297}52985299if (key === 'H' || key === 'M' || key === 'L') {5300var ox = this.x;5301var oy = this.y;5302if (key === 'H') {5303this.x = 0, this.y = 0;5304} else if (key === 'M') {5305this.x = 0, this.y = this.rows / 2 | 0;5306} else if (key === 'L') {5307this.x = 0, this.y = this.rows - 1;5308}5309if (this.visualMode) {5310this.selectText(ox, this.x, this.ydisp + oy, this.ydisp + this.y);5311} else {5312this.refresh(oy, oy);5313this.refresh(this.y, this.y);5314}5315return;5316}53175318if (key === '{' || key === '}') {5319var ox = this.x;5320var oy = this.y;5321var oyd = this.ydisp;53225323var line;5324var saw_full = false;5325var found = false;5326var first_is_space = -1;5327var y = this.y + (key === '{' ? -1 : 1);5328var yb = this.ydisp;5329var i;53305331if (key === '{') {5332if (y < 0) {5333y++;5334if (yb > 0) yb--;5335}5336} else if (key === '}') {5337if (y >= this.rows) {5338y--;5339if (yb < this.ybase) yb++;5340}5341}53425343for (;;) {5344line = this.lines[yb + y];53455346for (i = 0; i < this.cols; i++) {5347if (line[i][1] > ' ') {5348if (first_is_space === -1) {5349first_is_space = 0;5350}5351saw_full = true;5352break;5353} else if (i === this.cols - 1) {5354if (first_is_space === -1) {5355first_is_space = 1;5356} else if (first_is_space === 0) {5357found = true;5358} else if (first_is_space === 1) {5359if (saw_full) found = true;5360}5361break;5362}5363}53645365if (found) break;53665367if (key === '{') {5368y--;5369if (y < 0) {5370y++;5371if (yb > 0) yb--;5372else break;5373}5374} else if (key === '}') {5375y++;5376if (y >= this.rows) {5377y--;5378if (yb < this.ybase) yb++;5379else break;5380}5381}5382}53835384if (!found) {5385if (key === '{') {5386y = 0;5387yb = 0;5388} else if (key === '}') {5389y = this.rows - 1;5390yb = this.ybase;5391}5392}53935394this.x = 0, this.y = y;5395this.scrollDisp(-this.ydisp + yb);53965397if (this.visualMode) {5398this.selectText(ox, this.x, oy + oyd, this.ydisp + this.y);5399}5400return;5401}54025403if (key === '/' || key === '?') {5404if (!this.visualMode) {5405this.enterSearch(key === '/');5406}5407return;5408}54095410return false;5411};54125413Terminal.prototype.keySearch = function(ev, key) {5414if (key === '\x1b') {5415this.leaveSearch();5416return;5417}54185419if (key === '\r' || (!this.searchMode && (key === 'n' || key === 'N'))) {5420this.leaveSearch();54215422var entry = this.entry;54235424if (!entry) {5425this.refresh(0, this.rows - 1);5426return;5427}54285429var ox = this.x;5430var oy = this.y;5431var oyd = this.ydisp;54325433var line;5434var found = false;5435var wrapped = false;5436var x = this.x + 1;5437var y = this.ydisp + this.y;5438var yb, i;5439var up = key === 'N'5440? this.searchDown5441: !this.searchDown;54425443for (;;) {5444line = this.lines[y];54455446while (x < this.cols) {5447for (i = 0; i < entry.length; i++) {5448if (x + i >= this.cols) break;5449if (line[x + i][1] !== entry[i]) {5450break;5451} else if (line[x + i][1] === entry[i] && i === entry.length - 1) {5452found = true;5453break;5454}5455}5456if (found) break;5457x += i + 1;5458}5459if (found) break;54605461x = 0;54625463if (!up) {5464y++;5465if (y > this.ybase + this.rows - 1) {5466if (wrapped) break;5467// this.setMessage('Search wrapped. Continuing at TOP.');5468wrapped = true;5469y = 0;5470}5471} else {5472y--;5473if (y < 0) {5474if (wrapped) break;5475// this.setMessage('Search wrapped. Continuing at BOTTOM.');5476wrapped = true;5477y = this.ybase + this.rows - 1;5478}5479}5480}54815482if (found) {5483if (y - this.ybase < 0) {5484yb = y;5485y = 0;5486if (yb > this.ybase) {5487y = yb - this.ybase;5488yb = this.ybase;5489}5490} else {5491yb = this.ybase;5492y -= this.ybase;5493}54945495this.x = x, this.y = y;5496this.scrollDisp(-this.ydisp + yb);54975498if (this.visualMode) {5499this.selectText(ox, this.x, oy + oyd, this.ydisp + this.y);5500}5501return;5502}55035504// this.setMessage("No matches found.");5505this.refresh(0, this.rows - 1);55065507return;5508}55095510if (key === '\b' || key === '\x7f') {5511if (this.entry.length === 0) return;5512var bottom = this.ydisp + this.rows - 1;5513this.entry = this.entry.slice(0, -1);5514var i = this.entryPrefix.length + this.entry.length;5515//this.lines[bottom][i][1] = ' ';5516this.lines[bottom][i] = [5517this.lines[bottom][i][0],5518' '5519];5520this.x--;5521this.refresh(this.rows - 1, this.rows - 1);5522this.refresh(this.y, this.y);5523return;5524}55255526if (key.length === 1 && key >= ' ' && key <= '~') {5527var bottom = this.ydisp + this.rows - 1;5528this.entry += key;5529var i = this.entryPrefix.length + this.entry.length - 1;5530//this.lines[bottom][i][0] = (this.defAttr & ~0x1ff) | 4;5531//this.lines[bottom][i][1] = key;5532this.lines[bottom][i] = [5533(this.defAttr & ~0x1ff) | 4,5534key5535];5536this.x++;5537this.refresh(this.rows - 1, this.rows - 1);5538this.refresh(this.y, this.y);5539return;5540}55415542return false;5543};55445545/**5546* Character Sets5547*/55485549Terminal.charsets = {};55505551// DEC Special Character and Line Drawing Set.5552// http://vt100.net/docs/vt102-ug/table5-13.html5553// A lot of curses apps use this if they see TERM=xterm.5554// testing: echo -e '\e(0a\e(B'5555// The xterm output sometimes seems to conflict with the5556// reference above. xterm seems in line with the reference5557// when running vttest however.5558// The table below now uses xterm's output from vttest.5559Terminal.charsets.SCLD = { // (05560'`': '\u25c6', // '◆'5561'a': '\u2592', // '▒'5562'b': '\u0009', // '\t'5563'c': '\u000c', // '\f'5564'd': '\u000d', // '\r'5565'e': '\u000a', // '\n'5566'f': '\u00b0', // '°'5567'g': '\u00b1', // '±'5568'h': '\u2424', // '\u2424' (NL)5569'i': '\u000b', // '\v'5570'j': '\u2518', // '┘'5571'k': '\u2510', // '┐'5572'l': '\u250c', // '┌'5573'm': '\u2514', // '└'5574'n': '\u253c', // '┼'5575'o': '\u23ba', // '⎺'5576'p': '\u23bb', // '⎻'5577'q': '\u2500', // '─'5578'r': '\u23bc', // '⎼'5579's': '\u23bd', // '⎽'5580't': '\u251c', // '├'5581'u': '\u2524', // '┤'5582'v': '\u2534', // '┴'5583'w': '\u252c', // '┬'5584'x': '\u2502', // '│'5585'y': '\u2264', // '≤'5586'z': '\u2265', // '≥'5587'{': '\u03c0', // 'π'5588'|': '\u2260', // '≠'5589'}': '\u00a3', // '£'5590'~': '\u00b7' // '·'5591};55925593Terminal.charsets.UK = null; // (A5594Terminal.charsets.US = null; // (B (USASCII)5595Terminal.charsets.Dutch = null; // (45596Terminal.charsets.Finnish = null; // (C or (55597Terminal.charsets.French = null; // (R5598Terminal.charsets.FrenchCanadian = null; // (Q5599Terminal.charsets.German = null; // (K5600Terminal.charsets.Italian = null; // (Y5601Terminal.charsets.NorwegianDanish = null; // (E or (65602Terminal.charsets.Spanish = null; // (Z5603Terminal.charsets.Swedish = null; // (H or (75604Terminal.charsets.Swiss = null; // (=5605Terminal.charsets.ISOLatin = null; // /A56065607/**5608* Helpers5609*/56105611function on(el, type, handler, capture) {5612el.addEventListener(type, handler, capture || false);5613}56145615function off(el, type, handler, capture) {5616el.removeEventListener(type, handler, capture || false);5617}56185619function cancel(ev) {5620if (ev.preventDefault) ev.preventDefault();5621ev.returnValue = false;5622if (ev.stopPropagation) ev.stopPropagation();5623ev.cancelBubble = true;5624return false;5625}56265627function inherits(child, parent) {5628function f() {5629this.constructor = child;5630}5631f.prototype = parent.prototype;5632child.prototype = new f;5633}56345635// if bold is broken, we can't5636// use it in the terminal.5637function isBoldBroken(document) {5638var body = document.getElementsByTagName('body')[0];5639var el = document.createElement('span');5640el.innerHTML = 'hello world';5641body.appendChild(el);5642var w1 = el.scrollWidth;5643el.style.fontWeight = 'bold';5644var w2 = el.scrollWidth;5645body.removeChild(el);5646return w1 !== w2;5647}56485649var String = this.String;5650var setTimeout = this.setTimeout;5651var setInterval = this.setInterval;56525653function indexOf(obj, el) {5654var i = obj.length;5655while (i--) {5656if (obj[i] === el) return i;5657}5658return -1;5659}56605661function isWide(ch) {5662if (ch <= '\uff00') return false;5663return (ch >= '\uff01' && ch <= '\uffbe')5664|| (ch >= '\uffc2' && ch <= '\uffc7')5665|| (ch >= '\uffca' && ch <= '\uffcf')5666|| (ch >= '\uffd2' && ch <= '\uffd7')5667|| (ch >= '\uffda' && ch <= '\uffdc')5668|| (ch >= '\uffe0' && ch <= '\uffe6')5669|| (ch >= '\uffe8' && ch <= '\uffee');5670}56715672function matchColor(r1, g1, b1) {5673var hash = (r1 << 16) | (g1 << 8) | b1;56745675if (matchColor._cache[hash] != null) {5676return matchColor._cache[hash];5677}56785679var ldiff = Infinity5680, li = -15681, i = 05682, c5683, r25684, g25685, b25686, diff;56875688for (; i < Terminal.vcolors.length; i++) {5689c = Terminal.vcolors[i];5690r2 = c[0];5691g2 = c[1];5692b2 = c[2];56935694diff = matchColor.distance(r1, g1, b1, r2, g2, b2);56955696if (diff === 0) {5697li = i;5698break;5699}57005701if (diff < ldiff) {5702ldiff = diff;5703li = i;5704}5705}57065707return matchColor._cache[hash] = li;5708}57095710matchColor._cache = {};57115712// http://stackoverflow.com/questions/16338285713matchColor.distance = function(r1, g1, b1, r2, g2, b2) {5714return Math.pow(30 * (r1 - r2), 2)5715+ Math.pow(59 * (g1 - g2), 2)5716+ Math.pow(11 * (b1 - b2), 2);5717};57185719function each(obj, iter, con) {5720if (obj.forEach) return obj.forEach(iter, con);5721for (var i = 0; i < obj.length; i++) {5722iter.call(con, obj[i], i, obj);5723}5724}57255726function keys(obj) {5727if (Object.keys) return Object.keys(obj);5728var key, keys = [];5729for (key in obj) {5730if (Object.prototype.hasOwnProperty.call(obj, key)) {5731keys.push(key);5732}5733}5734return keys;5735}57365737/**5738* Expose5739*/57405741Terminal.EventEmitter = EventEmitter;5742Terminal.inherits = inherits;5743Terminal.on = on;5744Terminal.off = off;5745Terminal.cancel = cancel;57465747if (typeof module !== 'undefined') {5748module.exports = Terminal;5749} else {5750this.Terminal = Terminal;5751}57525753}).call(function() {5754return this || (typeof window !== 'undefined' ? window : global);5755}());575657575758