From e8bbc3ebd5be2af9162c6fc9894aa41d6e09ce99 Mon Sep 17 00:00:00 2001 From: nuintun Date: Tue, 24 Nov 2015 18:27:50 +0800 Subject: [PATCH] update files --- static/js/terminal/termlib.js | 3308 +++++++++++++++++++++++++++++++++ 1 file changed, 3308 insertions(+) create mode 100644 static/js/terminal/termlib.js diff --git a/static/js/terminal/termlib.js b/static/js/terminal/termlib.js new file mode 100644 index 0000000..f41edf9 --- /dev/null +++ b/static/js/terminal/termlib.js @@ -0,0 +1,3308 @@ +/* + termlib.js - JS-WebTerminal Object v1.66 + + (c) Norbert Landsteiner 2003-2015 + mass:werk - media environments + + + Creates [multiple] Terminal instances. + + Synopsis: + + myTerminal = new Terminal(); + myTerminal.open(); + + overrides any values of object `TerminalDefaults'. + individual values of `id' must be supplied for multiple terminals. + `handler' specifies a function to be called for input handling. + (see `Terminal.prototype.defaultHandler()' and documentation.) + + globals defined in this library: + Terminal (Terminal object) + TerminalDefaults (default configuration) + termDefaultHandler (default command line handler) + TermGlobals (common vars and code for all instances) + termKey (named mappings for special keys) + termDomKeyRef (special key mapping for DOM constants) + + (please see the v. 1.4 history entry on these elements) + + required CSS classes for font definitions: ".term", ".termReverse". + + Compatibilty: + Standard web browsers with a JavaScript implementation compliant to + ECMA-262 2nd edition and support for the anonymous array and object + constructs and the anonymous function construct in the form of + "myfunc=function(x) {}" (c.f. ECMA-262 3rd edion for details). + This comprises almost all current browsers but Konquerer (khtml) and + versions of Apple Safari for Mac OS 10.0-10.28 (Safari 1.0) which + lack support for keyboard events. + v1.5: Dropped support of Netscape 4 (layers) + + License: + This JavaScript-library is free. + Include a visible backlink to in the + embedding web page or application. + The library should always be accompanied by the 'readme.txt' and the + sample HTML-documents. + + Any changes should be commented and must be reflected in `Terminal.version' + in the format: "Version.Subversion (compatibility)". + + Donations: + Donations are welcome: You may support and/or honor the development of + "termlib.js" via PayPal at: + + Disclaimer: + This software is distributed AS IS and in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. The entire risk as to + the quality and performance of the product is borne by the user. No use of + the product is authorized hereunder except under this disclaimer. + + ### The sections above must not be removed. ### + + version 1.01: added Terminal.prototype.resizeTo(x,y) + added Terminal.conf.fontClass (=> configureable class name) + Terminal.prototype.open() now checks for element conf.termDiv + in advance and returns success. + + version 1.02: added support for and Euro sign + (Terminal.conf.printTab, Terminal.conf.printEuro) + and a method to evaluate printable chars: + Terminal.prototype.isPrintable(keycode) + + version 1.03: added global keyboard locking (TermGlobals.keylock) + modified Terminal.prototype.redraw for speed (use of locals) + + version 1.04: modified the key handler to fix a bug with MSIE5/Mac + fixed a bug in TermGlobals.setVisible with older MSIE-alike + browsers without DOM support. + + version 1.05: added config flag historyUnique. + + version 1.06: fixed CTRl+ALT (Windows alt gr) isn't CTRL any more + fixed double backspace bug for Safari; + added TermGlobals.setDisplay for setting style.display props + termlib.js now outputs lower case html (xhtml compatibility) + + version 1.07: added method rebuild() to rebuild with new color settings. + + version 1.1: fixed a bug in 'more' output mode (cursor could be hidden after + quit) + added socket-extension for server-client talk in a separate file + -> "temlib_socket.js" (to be loaded after termlib.js) + (this is a separate file because we break our compatibility + guide lines with this IO/AJAX library.) + + version 1.2 added color support ("%[+-]c()" markup) + moved paste support from sample file to lib + * TermGlobals.insertText( ) + * TermGlobals.importEachLine( ) + * TermGlobals.importMultiLine( ) + + version 1.3 added word wrapping to write() + * activate with myTerm.wrapOn() + * deactivate with myTerm.wrapOff() + use conf.wrapping (boolean) for a global setting + + version 1.4 Terminal is now an entirely self-contained object + Global references to inner objects for backward compatipility: + * TerminalDefaults => Terminal.prototype.Defaults + * termDefaultHandler => Terminal.prototype.defaultHandler + * termKey => Terminal.prototype.globals.termKey + see also: Terminal.prototype.termKey + * TermGlobals => Terminal.prototype.globals + * termDomKeyRef => Terminal.prototype.globals.termDomKeyRef + + So in effect to outside scripts everything remains the same; + no need to rewrite any existing scripts. + You may now use "this.globals" inside any handlers + to refer to the static global object (TermGlobals). + You may also refer to key definitions as "this.termKey.*". + (Please mind that "this.termKey" is a reference to the static object + and not specific to the instance. A change to "this.termKey" will be + by any other instances of Terminal too.) + + Added method TermGlobals.assignStyle() for custom styles & mark up. + + Unified the color mark up: You may now use color codes (decimal or hex) + inside brackets. e.g.: %c(10)DARKRED%c() or %c(a)DARKRED%c() + + Added key repeat for remapped keys (cursor movements etc). + + version 1.41 fixed a bug in the word wrapping regarding write() output, when + the cursor was set with cursorSet() before. + + version 1.42 fixed a bug which caused Opera to delete 2 chars at once. + introduced property Terminal.isOpera (Boolean) + + version 1.43 enhanced the control handler so it also catches ESC if flag closeOnESC + is set to false. fixed a bug with Safari which fired repeated events + for the control handler for TAB if flag printTab was set to false. + + version 1.5 Changed the license. + Dropped support for Netscape 4 (layers). + HTML-elements are now created by document.createElement, if applicable. + Included the formerly separate socket extension in the main library. + Added methods 'backupScreen()' and 'restoreScreen()' to save a screen + and restore it's content from backup. (see the globbing sample). + + version 1.51 Added basic support of ANSI-SGR-sequences. + + version 1.52 Added method swapBackup(), reorganized some of the accompanying files. + + version 1.54 Fixed BACK_SPACE for Chrome, DELETE for Safari/WebKit. + + version 1.55 Fixed dead keys issue for Mac OS (Leapard & later), vowels only. + version 1.56 Fixed new ESC issue for Safari. + version 1.57 Fixed dead keys fix: now only for Safari/Mac, German (de-de). + version 1.59 Dropped dead keys fix, fixed backspace for Safari. + version 1.6 Saved some bytes by discarding traces of ancient condition syntax + Added input mode "fieldMode" + version 1.61 Changes to defaults implementation of the constructor. + version 1.62 Fixed a bug related to AltGr-sequences with IE8+. + version 1.65 Added options for textColor and textBlur. + version 1.66 textBlur accepts also an array of values for multiple text-shadows. + + */ + +var Terminal = function (conf){ + if (typeof conf != 'object') conf = {}; + + for (var i in this.Defaults) { + if (this.Defaults.hasOwnProperty(i)) { + if (typeof conf[i] == 'undefined') conf[i] = this.Defaults[i]; + } + } + + if (typeof conf.handler != 'function') conf.handler = Terminal.prototype.defaultHandler; + + this.conf = conf; + this.setInitValues(); +}; + +Terminal.prototype = { + // prototype definitions (save some 2k on indentation) + version: '1.66 (original)', + Defaults: { + // dimensions + cols: 80, + rows: 24, + // appearance + x: 100, + y: 100, + termDiv: 'termDiv', + bgColor: '#181818', + frameColor: '#555555', + frameWidth: 1, + rowHeight: 15, + blinkDelay: 500, + // css class + fontClass: 'term', + // initial cursor mode + crsrBlinkMode: false, + crsrBlockMode: true, + // key mapping + DELisBS: false, + printTab: true, + printEuro: true, + catchCtrlH: true, + closeOnESC: true, + // prevent consecutive history doublets + historyUnique: false, + // optional id + id: 0, + // strings + ps: '>', + greeting: '%+r Terminal ready. %-r', + // handlers + handler: null, + ctrlHandler: null, + initHandler: null, + exitHandler: null, + wrapping: false, + mapANSI: false, + ANSItrueBlack: false, + textBlur: 0, + textColor: '' + }, + setInitValues: function (){ + this.isSafari = !!(navigator.userAgent.indexOf('Safari') >= 0 || navigator.userAgent.indexOf('WebKit') >= 0); + this.isOpera = !!(window.opera && navigator.userAgent.indexOf('Opera') >= 0); + this.isChrome = !!(navigator.userAgent.indexOf('Chrome/') >= 0 && navigator.userAgent.indexOf('WebKit') >= 0); + this.domAPI = (document && document.createElement) ? true : false; + this.isMac = navigator.userAgent.indexOf('Mac') >= 0; + this.id = this.conf.id; + this.maxLines = this.conf.rows; + this.maxCols = this.conf.cols; + this.termDiv = this.conf.termDiv; + this.crsrBlinkMode = this.conf.crsrBlinkMode; + this.crsrBlockMode = this.conf.crsrBlockMode; + this.blinkDelay = this.conf.blinkDelay; + this.DELisBS = this.conf.DELisBS; + this.printTab = this.conf.printTab; + this.printEuro = this.conf.printEuro; + this.catchCtrlH = this.conf.catchCtrlH; + this.closeOnESC = this.conf.closeOnESC; + this.historyUnique = this.conf.historyUnique; + this.ps = this.conf.ps; + this.closed = false; + this.r = 0; + this.c = 0; + this.charBuf = []; + this.styleBuf = []; + this.scrollBuf = null; + this.blinkBuffer = 0; + this.blinkTimer = null; + this.cursoractive = false; + this.lock = true; + this.insert = false; + this.charMode = false; + this.rawMode = false; + this.lineBuffer = ''; + this.inputChar = 0; + this.lastLine = ''; + this.guiCounter = 0; + this.history = []; + this.histPtr = 0; + this.env = []; + this.buckupBuffer = null; + this.handler = this.conf.handler; + this.wrapping = this.conf.wrapping; + this.mapANSI = this.conf.mapANSI; + this.ANSItrueBlack = this.conf.ANSItrueBlack; + this.ctrlHandler = this.conf.ctrlHandler; + this.initHandler = this.conf.initHandler; + this.exitHandler = this.conf.exitHandler; + this.fieldMode = false; + this.fieldStart = this.fieldEnd = this.fieldC = 0; + + if (typeof this.conf.textBlur === 'object' && this.conf.textBlur.length) { + var a = []; + + for (var i = 0; i < this.conf.textBlur.length; i++) { + var b = Number(this.conf.textBlur[i]); + if (!isNaN(b) && b > 0) a.push(b); + } + + this.textBlur = (a.length) ? a : 0; + } else { + this.textBlur = Number(this.conf.textBlur); + if (isNaN(this.textBlur) || this.textBlur < 0 || this.textBlur > 40) this.textBlur = 0; + } + this.textColor = this.conf.textColor || ''; + }, + defaultHandler: function (){ + this.newLine(); + + if (this.lineBuffer != '') { + this.type('You typed: ' + this.lineBuffer); + this.newLine(); + } + + this.prompt(); + }, + open: function (){ + if (this.termDivReady()) { + if (!this.closed) this._makeTerm(); + + this.init(); + + return true; + } else { + return false; + } + }, + close: function (){ + this.lock = true; + this.cursorOff(); + if (this.exitHandler) this.exitHandler(); + this.globals.setVisible(this.termDiv, 0); + this.closed = true; + }, + init: function (){ + // wait for gui + if (this.guiReady()) { + this.guiCounter = 0; + // clean up at re-entry + if (this.closed) { + this.setInitValues(); + } + + this.clear(); + this.globals.setVisible(this.termDiv, 1); + this.globals.enableKeyboard(this); + + if (this.initHandler) { + this.initHandler(); + } else { + this.write(this.conf.greeting); + this.newLine(); + this.prompt(); + } + } else { + this.guiCounter++; + + if (this.guiCounter > 18000) { + if (confirm('Terminal:\nYour browser hasn\'t responded for more than 2 minutes.\nRetry?')) { + this.guiCounter = 0; + } else { + return; + } + } + + this.globals.termToInitialze = this; + + window.setTimeout('Terminal.prototype.globals.termToInitialze.init()', 200); + } + }, + getRowArray: function (l, v){ + // returns a fresh array of l length initialized with value v + var a = []; + + for (var i = 0; i < l; i++) a[i] = v; + + return a; + }, + wrapOn: function (){ + // activate word wrap, wrapping workes with write() only! + this.wrapping = true; + }, + wrapOff: function (){ + this.wrapping = false; + }, + setTextBlur: function (v){ + var rerender = false; + + if (typeof v === 'object' && v.length) { + var a = []; + + for (var i = 0; i < v.length; i++) { + var b = Number(v[i]); + if (!isNaN(b) && b > 0) a.push(b); + } + + this.textBlur = (a.length) ? a : 0; + + rerender = true; + } else { + v = Number(v); + + if (isNaN(v) || v < 0 || v > 40) v = 0; + + if (v != this.textBlur) { + this.textBlur = v; + rerender = true; + } + } + + if (rerender) { + for (var r = 0, l = this.conf.rows; r < l; r++) this.redraw(r); + } + }, + setTextColor: function (v){ + if (!v) v = ''; + + if (v != this.textColor) { + this.textColor = v; + + for (var r = 0, l = this.conf.rows; r < l; r++) { + this.redraw(r); + } + } + }, + // main output methods + type: function (text, style){ + for (var i = 0; i < text.length; i++) { + var ch = text.charCodeAt(i); + + if (!this.isPrintable(ch)) ch = 94; + + this.charBuf[this.r][this.c] = ch; + this.styleBuf[this.r][this.c] = (style) ? style : 0; + + var last_r = this.r; + + this._incCol(); + + if (this.r != last_r) this.redraw(last_r); + } + + this.redraw(this.r) + }, + write: function (text, usemore){ + var ta; + var opt; + + // write to scroll buffer with markup + // new line = '%n' prepare any strings or arrys first + if (typeof text != 'object') { + if (typeof text != 'string') text = '' + text; + + if (text.indexOf('\n') >= 0) { + ta = text.split('\n'); + text = ta.join('%n'); + } + } + else { + if (text.join) { + text = text.join('%n'); + } else { + text = '' + text; + } + + if (text.indexOf('\n') >= 0) { + ta = text.split('\n'); + text = ta.join('%n'); + } + } + + if (this.mapANSI) text = this.globals.ANSI_map(text, this.ANSItrueBlack); + + this._sbInit(usemore); + + var chunks = text.split('%'); + var esc = (text.charAt(0) != '%'); + var style = 0; + var styleMarkUp = this.globals.termStyleMarkup; + + for (var i = 0; i < chunks.length; i++) { + if (esc) { + if (chunks[i].length > 0) { + this._sbType(chunks[i], style); + } else if (i > 0) { + this._sbType('%', style); + } + + esc = false; + } else { + var func = chunks[i].charAt(0); + + if (chunks[i].length == 0 && i > 0) { + this._sbType('%', style); + + esc = true; + } else if (func == 'n') { + this._sbNewLine(true); + + if (chunks[i].length > 1) this._sbType(chunks[i].substring(1), style); + } + else if (func == '+') { + opt = chunks[i].charAt(1); + + opt = opt.toLowerCase(); + + if (opt == 'p') { + style = 0; + } else if (styleMarkUp[opt]) { + style |= styleMarkUp[opt]; + } + + if (chunks[i].length > 2) this._sbType(chunks[i].substring(2), style); + } + else if (func == '-') { + opt = chunks[i].charAt(1); + opt = opt.toLowerCase(); + + if (opt == 'p') { + style = 0; + } else if (styleMarkUp[opt]) { + style &= ~styleMarkUp[opt]; + } + + if (chunks[i].length > 2) this._sbType(chunks[i].substring(2), style); + } else if (chunks[i].length > 1 && func == 'c') { + var cinfo = this._parseColor(chunks[i].substring(1)); + + style = (style & (~0xfffff0)) | cinfo.style; + + if (cinfo.rest) this._sbType(cinfo.rest, style); + } else if (chunks[i].length > 1 && chunks[i].charAt(0) == 'C' && chunks[i].charAt(1) == 'S') { + this.clear(); + this._sbInit(); + + if (chunks[i].length > 2) this._sbType(chunks[i].substring(2), style); + } else { + if (chunks[i].length > 0) this._sbType(chunks[i], style); + } + } + } + + this._sbOut(); + }, + // parse a color markup + _parseColor: function (chunk){ + var i; + var c; + var sc; + var cl; + var rest = ''; + var style = 0; + + if (chunk.length) { + if (chunk.charAt(0) == '(') { + var clabel = ''; + + for (i = 1; i < chunk.length; i++) { + c = chunk.charAt(i); + + if (c == ')') { + if (chunk.length > i) rest = chunk.substring(i + 1); + break; + } + + clabel += c; + } + + if (clabel) { + if (clabel.charAt(0) == '@') { + sc = this.globals.nsColors[clabel.substring(1).toLowerCase()]; + + if (sc) style = (16 + sc) * 0x100; + } else if (clabel.charAt(0) == '#') { + cl = clabel.substring(1).toLowerCase(); + sc = this.globals.webColors[cl]; + + if (sc) { + style = sc * 0x10000; + } else { + cl = this.globals.webifyColor(cl); + + if (cl) style = this.globals.webColors[cl] * 0x10000; + } + } else if (clabel.length && clabel.length <= 2) { + var isHex = false; + + for (i = 0; i < clabel.length; i++) { + if (this.globals.isHexOnlyChar(clabel.charAt(i))) { + isHex = true; + break; + } + } + + cl = (isHex) ? parseInt(clabel, 16) : parseInt(clabel, 10); + + if (!isNaN(cl) || cl <= 15) { + style = cl * 0x100; + } + } else { + style = this.globals.getColorCode(clabel) * 0x100; + } + } + } else { + c = chunk.charAt(0); + + if (this.globals.isHexChar(c)) { + style = this.globals.hexToNum[c] * 0x100; + rest = chunk.substring(1); + } else { + rest = chunk; + } + } + } + + return { rest: rest, style: style }; + }, + // internal scroll buffer output methods + _sbInit: function (usemore){ + var sb = this.scrollBuf = {}; + var sbl = sb.lines = []; + var sbs = sb.styles = []; + + sb.more = usemore; + sb.line = 0; + sb.status = 0; + sb.r = 0; + sb.c = this.c; + sbl[0] = this.getRowArray(this.conf.cols, 0); + sbs[0] = this.getRowArray(this.conf.cols, 0); + + for (var i = 0; i < this.c; i++) { + sbl[0][i] = this.charBuf[this.r][i]; + sbs[0][i] = this.styleBuf[this.r][i]; + } + }, + _sbType: function (text, style){ + // type to scroll buffer + var sb = this.scrollBuf; + + for (var i = 0; i < text.length; i++) { + var ch = text.charCodeAt(i); + + if (!this.isPrintable(ch)) ch = 94; + + sb.lines[sb.r][sb.c] = ch; + sb.styles[sb.r][sb.c++] = (style) ? style : 0; + + if (sb.c >= this.maxCols) this._sbNewLine(); + } + }, + _sbNewLine: function (forced){ + var sb = this.scrollBuf; + + if (this.wrapping && forced) { + sb.lines[sb.r][sb.c] = 10; + sb.lines[sb.r].length = sb.c + 1; + } + + sb.r++; + sb.c = 0; + sb.lines[sb.r] = this.getRowArray(this.conf.cols, 0); + sb.styles[sb.r] = this.getRowArray(this.conf.cols, 0); + }, + _sbWrap: function (){ + // create a temp wrap buffer wb and scan for words/wrap-chars + // then re-asign lines & styles to scrollBuf + var wb = {}; + + wb.lines = []; + wb.styles = []; + wb.lines[0] = this.getRowArray(this.conf.cols, 0); + wb.styles[0] = this.getRowArray(this.conf.cols, 0); + wb.r = 0; + wb.c = 0; + + var sb = this.scrollBuf; + var sbl = sb.lines; + var sbs = sb.styles; + var ch; + var st; + var wrap; + var lc; + var ls; + var l = this.c; + var lastR = 0; + var lastC = 0; + + wb.cBreak = false; + + for (var r = 0; r < sbl.length; r++) { + lc = sbl[r]; + ls = sbs[r]; + + for (var c = 0; c < lc.length; c++) { + ch = lc[c]; + st = ls[c]; + + if (ch) { + wrap = this.globals.wrapChars[ch]; + + if (ch == 10) wrap = 1; + + if (wrap) { + if (wrap == 2) { + l++; + } else if (wrap == 4) { + l++; + lc[c] = 45; + } + + this._wbOut(wb, lastR, lastC, l); + + if (ch == 10) { + this._wbIncLine(wb); + } else if (wrap == 1 && wb.c < this.maxCols) { + wb.lines[wb.r][wb.c] = ch; + wb.styles[wb.r][wb.c++] = st; + + if (wb.c >= this.maxCols) this._wbIncLine(wb); + } + + if (wrap == 3) { + lastR = r; + lastC = c; + l = 1; + } else { + l = 0; + lastR = r; + lastC = c + 1; + if (lastC == lc.length) { + lastR++; + lastC = 0; + } + + if (wrap == 4) wb.cBreak = true; + } + } else { + l++; + } + } + } + } + + if (l) { + if (wb.cBreak && wb.c != 0) wb.c--; + + this._wbOut(wb, lastR, lastC, l); + } + + sb.lines = wb.lines; + sb.styles = wb.styles; + sb.r = wb.r; + sb.c = wb.c; + }, + _wbOut: function (wb, br, bc, l){ + // copy a word (of l length from br/bc) to wrap buffer wb + var sb = this.scrollBuf; + var sbl = sb.lines; + var sbs = sb.styles; + var ofs = 0; + var lc; + var ls; + var i; + + if (l + wb.c > this.maxCols) { + if (l < this.maxCols) { + this._wbIncLine(wb); + } else { + var i0 = 0; + + ofs = this.maxCols - wb.c; + lc = sbl[br]; + ls = sbs[br]; + + while (true) { + for (i = i0; i < ofs; i++) { + wb.lines[wb.r][wb.c] = lc[bc]; + wb.styles[wb.r][wb.c++] = ls[bc++]; + + if (bc == sbl[br].length) { + bc = 0; + br++; + lc = sbl[br]; + ls = sbs[br]; + } + } + + this._wbIncLine(wb); + + if (l - ofs < this.maxCols) break; + i0 = ofs; + ofs += this.maxCols; + } + } + } else if (wb.cBreak) { + wb.c--; + } + + lc = sbl[br]; + ls = sbs[br]; + + for (i = ofs; i < l; i++) { + wb.lines[wb.r][wb.c] = lc[bc]; + wb.styles[wb.r][wb.c++] = ls[bc++]; + + if (bc == sbl[br].length) { + bc = 0; + br++; + lc = sbl[br]; + ls = sbs[br]; + } + } + + wb.cBreak = false; + }, + _wbIncLine: function (wb){ + // create a new line in temp buffer + wb.r++; + wb.c = 0; + wb.lines[wb.r] = this.getRowArray(this.conf.cols, 0); + wb.styles[wb.r] = this.getRowArray(this.conf.cols, 0); + }, + _sbOut: function (){ + var sb = this.scrollBuf; + + if (this.wrapping && !sb.status) this._sbWrap(); + + var i; + var r; + var ofs; + var sbl = sb.lines; + var sbs = sb.styles; + var tcb = this.charBuf; + var tsb = this.styleBuf; + var ml = this.maxLines; + var buflen = sbl.length; + + if (sb.more) { + if (sb.status) { + if (this.inputChar == this.globals.lcMoreKeyAbort) { + this.r = ml - 1; + this.c = 0; + tcb[this.r] = this.getRowArray(this.conf.cols, 0); + tsb[this.r] = this.getRowArray(this.conf.cols, 0); + + this.redraw(this.r); + + this.handler = sb.handler; + this.charMode = false; + this.inputChar = 0; + this.scrollBuf = null; + + this.prompt(); + + return; + } else if (this.inputChar == this.globals.lcMoreKeyContinue) { + this.clear(); + } else { + return; + } + } else { + if (this.r >= ml - 1) this.clear(); + } + } + + if (this.r + buflen - sb.line <= ml) { + for (i = sb.line; i < buflen; i++) { + r = this.r + i - sb.line; + + tcb[r] = sbl[i]; + tsb[r] = sbs[i]; + + this.redraw(r); + } + + this.r += sb.r - sb.line; + this.c = sb.c; + + if (sb.more) { + if (sb.status) this.handler = sb.handler; + + this.charMode = false; + this.inputChar = 0; + this.scrollBuf = null; + + this.prompt(); + + return; + } + } + else if (sb.more) { + ml--; + + if (sb.status == 0) { + sb.handler = this.handler; + this.handler = this._sbOut; + this.charMode = true; + sb.status = 1; + } + + if (this.r) { + ofs = ml - this.r; + + for (i = sb.line; i < ofs; i++) { + r = this.r + i - sb.line; + tcb[r] = sbl[i]; + tsb[r] = sbs[i]; + + this.redraw(r); + } + } + else { + ofs = sb.line + ml; + + for (i = sb.line; i < ofs; i++) { + r = this.r + i - sb.line; + tcb[r] = sbl[i]; + tsb[r] = sbs[i]; + + this.redraw(r); + } + } + + sb.line = ofs; + this.r = ml; + this.c = 0; + this.type(this.globals.lcMorePrompt1, this.globals.lcMorePromtp1Style); + this.type(this.globals.lcMorePrompt2, this.globals.lcMorePrompt2Style); + this.lock = false; + + return; + } + else if (buflen >= ml) { + ofs = buflen - ml; + + for (i = 0; i < ml; i++) { + r = ofs + i; + tcb[i] = sbl[r]; + tsb[i] = sbs[r]; + + this.redraw(i); + } + + this.r = ml - 1; + this.c = sb.c; + } + else { + var dr = ml - buflen; + + ofs = this.r - dr; + + for (i = 0; i < dr; i++) { + r = ofs + i; + + for (var c = 0; c < this.maxCols; c++) { + tcb[i][c] = tcb[r][c]; + tsb[i][c] = tsb[r][c]; + } + + this.redraw(i); + } + + for (i = 0; i < buflen; i++) { + r = dr + i; + tcb[r] = sbl[i]; + tsb[r] = sbs[i]; + + this.redraw(r); + } + + this.r = ml - 1; + this.c = sb.c; + } + + this.scrollBuf = null; + }, + + // basic console output + typeAt: function (r, c, text, style){ + var tr1 = this.r; + var tc1 = this.c; + + this.cursorSet(r, c); + + for (var i = 0; i < text.length; i++) { + var ch = text.charCodeAt(i); + + if (!this.isPrintable(ch)) ch = 94; + + this.charBuf[this.r][this.c] = ch; + this.styleBuf[this.r][this.c] = (style) ? style : 0; + + var last_r = this.r; + + this._incCol(); + + if (this.r != last_r) this.redraw(last_r); + } + + this.redraw(this.r); + + this.r = tr1; + this.c = tc1; + }, + statusLine: function (text, style, offset){ + var ch, r; + + style = (style && !isNaN(style)) ? parseInt(style) & 15 : 0; + + if (offset && offset > 0) { + r = this.conf.rows - offset; + } else { + r = this.conf.rows - 1; + } + + for (var i = 0; i < this.conf.cols; i++) { + if (i < text.length) { + ch = text.charCodeAt(i); + if (!this.isPrintable(ch)) ch = 94; + } else { + ch = 0; + } + + this.charBuf[r][i] = ch; + this.styleBuf[r][i] = style; + } + + this.redraw(r); + }, + printRowFromString: function (r, text, style){ + var ch; + + style = (style && !isNaN(style)) ? parseInt(style) & 15 : 0; + + if (r >= 0 && r < this.maxLines) { + if (typeof text != 'string') text = '' + text; + + for (var i = 0; i < this.conf.cols; i++) { + if (i < text.length) { + ch = text.charCodeAt(i); + if (!this.isPrintable(ch)) ch = 94; + } else { + ch = 0; + } + + this.charBuf[r][i] = ch; + this.styleBuf[r][i] = style; + } + + this.redraw(r); + } + }, + setChar: function (ch, r, c, style){ + this.charBuf[r][c] = ch; + this.styleBuf[r][c] = (style) ? style : 0; + + this.redraw(r); + }, + newLine: function (){ + this.c = 0; + + this._incRow(); + }, + // internal methods for output + _charOut: function (ch, style){ + this.charBuf[this.r][this.c] = ch; + this.styleBuf[this.r][this.c] = (style) ? style : 0; + + this.redraw(this.r); + this._incCol(); + }, + _incCol: function (){ + this.c++; + + if (this.c >= this.maxCols) { + this.c = 0; + this._incRow(); + } + }, + _incRow: function (){ + this.r++; + + if (this.r >= this.maxLines) { + this._scrollLines(0, this.maxLines); + this.r = this.maxLines - 1; + } + }, + _scrollLines: function (start, end){ + start++; + + var rt; + + for (var ri = start; ri < end; ri++) { + rt = ri - 1; + this.charBuf[rt] = this.charBuf[ri]; + this.styleBuf[rt] = this.styleBuf[ri]; + } + + // clear last line + rt = end - 1; + this.charBuf[rt] = this.getRowArray(this.conf.cols, 0); + this.styleBuf[rt] = this.getRowArray(this.conf.cols, 0); + + this.redraw(rt); + + for (var r = end - 1; r >= start; r--) this.redraw(r - 1); + }, + // control methods + clear: function (){ + this.cursorOff(); + + this.insert = false; + + for (var ri = 0; ri < this.maxLines; ri++) { + this.charBuf[ri] = this.getRowArray(this.conf.cols, 0); + this.styleBuf[ri] = this.getRowArray(this.conf.cols, 0); + this.redraw(ri); + } + + this.r = 0; + this.c = 0; + }, + reset: function (){ + if (this.lock) return; + + this.lock = true; + this.rawMode = false; + this.charMode = false; + this.maxLines = this.conf.rows; + this.maxCols = this.conf.cols; + this.lastLine = ''; + this.lineBuffer = ''; + this.inputChar = 0; + + this.clear(); + }, + prompt: function (){ + this.lock = true; + + if (this.c > 0) this.newLine(); + + this.type(this.ps); + this._charOut(1); + + this.lock = false; + + this.cursorOn(); + }, + isPrintable: function (ch, unicodePage1only){ + if (this.wrapping && this.globals.wrapChars[ch] == 4) return true; + + if (unicodePage1only && ch > 255) { + return (ch == this.termKey.EURO && this.printEuro) ? true : false; + } + + return ( + (ch >= 32 && ch != this.termKey.DEL) || + (this.printTab && ch == this.termKey.TAB) + ); + }, + // cursor methods + cursorSet: function (r, c){ + var crsron = this.cursoractive; + + if (crsron) this.cursorOff(); + + this.r = r % this.maxLines; + this.c = c % this.maxCols; + + this._cursorReset(crsron); + }, + cursorOn: function (){ + if (this.blinkTimer) clearTimeout(this.blinkTimer); + + this.blinkBuffer = this.styleBuf[this.r][this.c]; + + this._cursorBlink(); + + this.cursoractive = true; + }, + cursorOff: function (){ + if (this.blinkTimer) clearTimeout(this.blinkTimer); + + if (this.cursoractive) { + this.styleBuf[this.r][this.c] = this.blinkBuffer; + + this.redraw(this.r); + + this.cursoractive = false; + } + }, + cursorLeft: function (){ + var crsron = this.cursoractive; + + if (crsron) this.cursorOff(); + + var r = this.r; + var c = this.c; + + if (c > 0) { + c--; + } else if (r > 0) { + c = this.maxCols - 1; + r--; + } + + if (this.isPrintable(this.charBuf[r][c])) { + this.r = r; + this.c = c; + } + + this.insert = true; + + this._cursorReset(crsron); + }, + cursorRight: function (){ + var crsron = this.cursoractive; + + if (crsron) this.cursorOff(); + + var r = this.r; + var c = this.c; + + if (c < this.maxCols - 1) { + c++; + } else if (r < this.maxLines - 1) { + c = 0; + r++; + } + + if (!this.isPrintable(this.charBuf[r][c])) { + this.insert = false; + } + + if (this.isPrintable(this.charBuf[this.r][this.c])) { + this.r = r; + this.c = c; + } + + this._cursorReset(crsron); + }, + backspace: function (){ + var crsron = this.cursoractive; + + if (crsron) this.cursorOff(); + + var r = this.r; + var c = this.c; + + if (c > 0) { + c--; + } else if (r > 0) { + c = this.maxCols - 1; + r--; + } + + if (this.isPrintable(this.charBuf[r][c])) { + this._scrollLeft(r, c); + this.r = r; + this.c = c; + } + + this._cursorReset(crsron); + }, + fwdDelete: function (){ + var crsron = this.cursoractive; + + if (crsron) this.cursorOff(); + + if (this.isPrintable(this.charBuf[this.r][this.c])) { + this._scrollLeft(this.r, this.c); + + if (!this.isPrintable(this.charBuf[this.r][this.c])) this.insert = false; + } + + this._cursorReset(crsron); + }, + _cursorReset: function (crsron){ + if (crsron) { + this.cursorOn(); + } else { + this.blinkBuffer = this.styleBuf[this.r][this.c]; + } + }, + _cursorBlink: function (){ + if (this.blinkTimer) clearTimeout(this.blinkTimer); + + if (this == this.globals.activeTerm) { + if (this.crsrBlockMode) { + this.styleBuf[this.r][this.c] = (this.styleBuf[this.r][this.c] & 1) ? + this.styleBuf[this.r][this.c] & 0xfffffe : this.styleBuf[this.r][this.c] | 1; + } else { + this.styleBuf[this.r][this.c] = (this.styleBuf[this.r][this.c] & 2) ? + this.styleBuf[this.r][this.c] & 0xffffd : this.styleBuf[this.r][this.c] | 2; + } + + this.redraw(this.r); + } + + if (this.crsrBlinkMode) { + this.blinkTimer = setTimeout('Terminal.prototype.globals.activeTerm._cursorBlink()', this.blinkDelay); + } + }, + _scrollLeft: function (r, c){ + var rows = []; + + rows[0] = r; + + while (this.isPrintable(this.charBuf[r][c])) { + var ri = r; + var ci = c + 1; + + if (ci == this.maxCols) { + if (ri < this.maxLines - 1) { + ci = 0; + ri++; + rows[rows.length] = ri; + } else { + break; + } + } + + this.charBuf[r][c] = this.charBuf[ri][ci]; + this.styleBuf[r][c] = this.styleBuf[ri][ci]; + c = ci; + r = ri; + } + + if (this.charBuf[r][c] != 0) this.charBuf[r][c] = 0; + + for (var i = 0; i < rows.length; i++) this.redraw(rows[i]); + }, + _scrollRight: function (r, c){ + var rows = []; + var end = this._getLineEnd(r, c); + var ri = end[0]; + var ci = end[1]; + + if (ci == this.maxCols - 1 && ri == this.maxLines - 1) { + if (r == 0) return; + + this._scrollLines(0, this.maxLines); + + this.r--; + r--; + ri--; + } + + rows[r] = 1; + + while (this.isPrintable(this.charBuf[ri][ci])) { + var rt = ri; + var ct = ci + 1; + + if (ct == this.maxCols) { + ct = 0; + rt++; + rows[rt] = 1; + } + + this.charBuf[rt][ct] = this.charBuf[ri][ci]; + this.styleBuf[rt][ct] = this.styleBuf[ri][ci]; + + if (ri == r && ci == c) break; + + ci--; + + if (ci < 0) { + ci = this.maxCols - 1; + ri--; + rows[ri] = 1; + } + } + + for (var i = r; i < this.maxLines; i++) { + if (rows[i]) this.redraw(i); + } + }, + _getLineEnd: function (r, c){ + if (!this.isPrintable(this.charBuf[r][c])) { + c--; + + if (c < 0) { + if (r > 0) { + r--; + c = this.maxCols - 1; + } else { + c = 0; + } + } + } + + if (this.isPrintable(this.charBuf[r][c])) { + while (true) { + var ri = r; + var ci = c + 1; + + if (ci == this.maxCols) { + if (ri < this.maxLines - 1) { + ri++; + ci = 0; + } else { + break; + } + } + + if (!this.isPrintable(this.charBuf[ri][ci])) break; + + c = ci; + r = ri; + } + } + + return [r, c]; + }, + _getLineStart: function (r, c){ + // not used by now, just in case anyone needs this ... + var ci, ri; + + if (!this.isPrintable(this.charBuf[r][c])) { + ci = c - 1; + ri = r; + + if (ci < 0) { + if (ri == 0) return [0, 0]; + + ci = this.maxCols - 1; + ri--; + } + + if (!this.isPrintable(this.charBuf[ri][ci])) { + return [r, c]; + } else { + r = ri; + c = ci; + } + } + + while (true) { + ri = r; + ci = c - 1; + + if (ci < 0) { + if (ri == 0) break; + + ci = this.maxCols - 1; + ri--; + } + + if (!this.isPrintable(this.charBuf[ri][ci])) break; + + r = ri; + c = ci; + } + + return [r, c]; + }, + _getLine: function (adjustCrsrPos){ + var end = this._getLineEnd(this.r, this.c); + var r = end[0]; + var c = end[1]; + + if (adjustCrsrPos && (this.r != r || this.c != c + 1)) { + this.r = r; + this.c = c + 1; + + if (this.c >= this.maxCols) this.c = this.maxCols - 1; + } + + var line = []; + + while (this.isPrintable(this.charBuf[r][c])) { + line[line.length] = String.fromCharCode(this.charBuf[r][c]); + + if (c > 0) { + c--; + } else if (r > 0) { + c = this.maxCols - 1; + r--; + } else { + break; + } + } + + line.reverse(); + + return line.join(''); + }, + _clearLine: function (){ + var end = this._getLineEnd(this.r, this.c); + var r = end[0]; + var c = end[1]; + + while (this.isPrintable(this.charBuf[r][c])) { + this.charBuf[r][c] = 0; + + if (c > 0) { + c--; + } else if (r > 0) { + this.redraw(r); + + c = this.maxCols - 1; + r--; + } else { + break; + } + } + + if (r != end[0]) this.redraw(r); + + c++; + + this.cursorSet(r, c); + + this.insert = false; + }, + // backup/restore screen & state + backupScreen: function (){ + var backup = this.backupBuffer = {}; + var rl = this.conf.rows; + var cl = this.conf.cols; + + backup.cbuf = new Array(rl); + backup.sbuf = new Array(rl); + backup.maxCols = this.maxCols; + backup.maxLines = this.maxLines; + backup.r = this.r; + backup.c = this.c; + backup.charMode = this.charMode; + backup.rawMode = this.rawMode; + backup.handler = this.handler; + backup.ctrlHandler = this.ctrlHandler; + backup.cursoractive = this.cursoractive; + backup.crsrBlinkMode = this.crsrBlinkMode; + backup.crsrBlockMode = this.crsrBlockMode; + backup.blinkDelay = this.blinkDelay; + backup.DELisBS = this.DELisBS; + backup.printTab = this.printTab; + backup.printEuro = this.printEuro; + backup.catchCtrlH = this.catchCtrlH; + backup.closeOnESC = this.closeOnESC; + backup.historyUnique = this.historyUnique; + backup.ps = this.ps; + backup.lineBuffer = this.lineBuffer; + backup.inputChar = this.inputChar; + backup.lastLine = this.lastLine; + backup.historyLength = this.history.length; + backup.histPtr = this.histPtr; + backup.wrapping = this.wrapping; + backup.mapANSI = this.mapANSI; + backup.ANSItrueBlack = this.ANSItrueBlack; + + if (this.cursoractive) this.cursorOff(); + + for (var r = 0; r < rl; r++) { + var cbr = this.charBuf[r]; + var sbr = this.styleBuf[r]; + var tcbr = backup.cbuf[r] = new Array(cl); + var tsbr = backup.sbuf[r] = new Array(cl); + + for (var c = 0; c < cl; c++) { + tcbr[c] = cbr[c]; + tsbr[c] = sbr[c]; + } + } + }, + restoreScreen: function (){ + var backup = this.backupBuffer; + + if (!backup) return; + + var rl = this.conf.rows; + + for (var r = 0; r < rl; r++) { + this.charBuf[r] = backup.cbuf[r]; + this.styleBuf[r] = backup.sbuf[r]; + + this.redraw(r); + } + + this.maxCols = backup.maxCols; + this.maxLines = backup.maxLines; + this.r = backup.r; + this.c = backup.c; + this.charMode = backup.charMode; + this.rawMode = backup.rawMode; + this.handler = backup.handler; + this.ctrlHandler = backup.ctrlHandler; + this.cursoractive = backup.cursoractive; + this.crsrBlinkMode = backup.crsrBlinkMode; + this.crsrBlockMode = backup.crsrBlockMode; + this.blinkDelay = backup.blinkDelay; + this.DELisBS = backup.DELisBS; + this.printTab = backup.printTab; + this.printEuro = backup.printEuro; + this.catchCtrlH = backup.catchCtrlH; + this.closeOnESC = backup.closeOnESC; + this.historyUnique = backup.historyUnique; + this.ps = backup.ps; + this.lineBuffer = backup.lineBuffer; + this.inputChar = backup.inputChar; + this.lastLine = backup.lastLine; + + if (this.history.length > backup.historyLength) { + this.history.length = backup.historyLength; + this.histPtr = backup.histPtr; + } + + this.wrapping = backup.wrapping; + this.mapANSI = backup.mapANSI; + this.ANSItrueBlack = backup.ANSItrueBlack; + + if (this.cursoractive) this.cursorOn(); + + this.backupBuffer = null; + }, + swapBackup: function (){ + // swap current state and backup buffer (e.g.: toggle do/undo) + var backup = this.backupBuffer; + + this.backupScreen(); + + if (backup) { + var backup2 = this.backupBuffer; + + this.backupBuffer = backup; + + this.restoreScreen(); + + this.backupBuffer = backup2; + } + }, + // simple markup escaping + escapeMarkup: function (t){ + return t.replace(/%/g, '%%'); + }, + // field mode + enterFieldMode: function (start, end, style){ + this.cursorOff(); + + if (start === undefined || start < 0) start = this.c; + + if (end === undefined || end < start || end > this.maxCols) end = this.maxCols; + + if (!style) style = 0; + + this.fieldStart = start; + this.fieldEnd = end; + this.fieldStyle = style; + this.fieldC = 0; + this.lastLine = ''; + this.fieldMode = true; + this.rawMode = this.charMode = false; + + if (style & 1) { + this._crsrWasBlockMode = this.crsrBlockMode; + this._crsrWasBlinkMode = this.crsrBlinkMode; + this.crsrBlockMode = false; + this.crsrBlinkMode = true; + } + + this.drawField(); + this.lock = false; + }, + exitFieldMode: function (){ + this.drawField(true); + + this.fieldMode = false; + this.c = this.fieldEnd; + + if (this.c == this.maxLine) this.newLine(); + + this.lock = true; + }, + drawField: function (isfinal){ + this.cursorOff(); + + if (isfinal) this.fieldC = 0; + + var fl = this.fieldEnd - this.fieldStart; + + if (this.fieldC == this.lastLine.length) fl--; + + var ofs = this.fieldC - fl; + + if (ofs < 0) ofs = 0; + + var line = (ofs) ? this.lastLine.substring(ofs) : this.lastLine; + var sb = this.styleBuf[this.r]; + var cb = this.charBuf[this.r]; + var max = line.length; + + for (var i = this.fieldStart, k = 0; i < this.fieldEnd; i++, k++) { + sb[i] = this.fieldStyle; + cb[i] = (k < max) ? line.charCodeAt(k) : 0; + } + + this.redraw(this.r); + + if (isfinal) { + if (this.fieldStyle & 1) { + this.crsrBlockMode = this._crsrWasBlockMode; + this.crsrBlinkMode = this._crsrWasBlinkMode; + + delete this._crsrWasBlockMode; + delete this._crsrWasBlinkMode; + } + } else { + this.c = this.fieldStart + this.fieldC - ofs; + + this.cursorOn(); + } + }, + // keyboard focus + focus: function (){ + this.globals.setFocus(this); + }, + // a inner reference (just for comfort) to be mapped to Terminal.prototype.globals.termKey + termKey: null, + // GUI related methods + _makeTerm: function (rebuild){ + var c; + var r; + var rstr = ''; + var divPrefix = this.termDiv + '_r'; + + if (this.domAPI) { + // if applicable we're using createElement + this.globals.hasSubDivs = false; + var row, table, tbody, ptd, table2, tbody2, tr, td, node; + + table = document.createElement('table'); + + table.setAttribute('border', 0); + table.setAttribute('cellSpacing', 0); + table.setAttribute('cellPadding', this.conf.frameWidth); + + tbody = document.createElement('tbody'); + + table.appendChild(tbody); + + row = document.createElement('tr'); + + tbody.appendChild(row); + + ptd = document.createElement('td'); + ptd.style.backgroundColor = this.conf.frameColor; + + row.appendChild(ptd); + + table2 = document.createElement('table'); + + table2.setAttribute('border', 0); + table2.setAttribute('cellSpacing', 0); + table2.setAttribute('cellPadding', 2); + + tbody2 = document.createElement('tbody'); + + table2.appendChild(tbody2); + + tr = document.createElement('tr'); + + tbody2.appendChild(tr); + + td = document.createElement('td'); + td.style.backgroundColor = this.conf.bgColor; + + tr.appendChild(td); + ptd.appendChild(table2); + + ptd = td; + table2 = document.createElement('table'); + + table2.setAttribute('border', 0); + table2.setAttribute('cellSpacing', 0); + table2.setAttribute('cellPadding', 0); + + tbody2 = document.createElement('tbody'); + + table2.appendChild(tbody2); + + for (c = 0; c < this.conf.cols; c++) rstr += ' '; + + for (r = 0; r < this.conf.rows; r++) { + tr = document.createElement('tr'); + td = document.createElement('td'); + td.id = divPrefix + r; + td.style.height = td.style.minHeight = td.style.maxHeight = this.conf.rowHeight; + td.style.whiteSpace = 'nowrap'; + td.className = this.conf.fontClass; + td.innerHTML = rstr; + + tr.appendChild(td); + tbody2.appendChild(tr); + } + + ptd.appendChild(table2); + + node = document.getElementById(this.termDiv); + + while (node.hasChildNodes()) node.removeChild(node.firstChild); + + node.appendChild(table); + } else { + // legacy code + this.globals.hasSubDivs = (navigator.userAgent.indexOf('Gecko') < 0); + + var s = ''; + var bgColorAttribute = (this.conf.bgColor && (this.conf.bgColor !== 'none' + || this.conf.bgColor != 'transparent')) ? ' bgcolor="' + this.conf.bgColor + '"' : ''; + var frameColorAttribute = (this.conf.frameColor && (this.conf.frameColor !== 'none' + || this.conf.frameColor != 'transparent')) ? ' bgcolor="' + this.conf.frameColor + '"' : ''; + + s += '\n'; + s += '
\n'; + + for (c = 0; c < this.conf.cols; c++) rstr += ' '; + + for (r = 0; r < this.conf.rows; r++) { + var termid = (this.globals.hasSubDivs) ? '' : ' id="' + divPrefix + r + '"'; + + s += '
' + rstr + '<\/td><\/tr>\n'; + } + + s += '<\/table><\/td><\/tr>\n'; + s += '<\/table><\/td><\/tr>\n'; + s += '<\/table>\n'; + + var termOffset = 2 + this.conf.frameWidth; + + if (this.globals.hasSubDivs) { + for (var r = 0; r < this.conf.rows; r++) { + s += '
<\/div>\n'; + } + + this.globals.termStringStart = '
'; + this.globals.termStringEnd = '<\/td><\/tr><\/table>'; + } + + this.globals.writeElement(this.termDiv, s); + } + + if (!rebuild) { + this.globals.setElementXY(this.termDiv, this.conf.x, this.conf.y); + this.globals.setVisible(this.termDiv, 1); + } + }, + rebuild: function (){ + // check for bounds and array lengths + var c; + var r; + var rl = this.conf.rows; + var cl = this.conf.cols; + + for (r = 0; r < rl; r++) { + var cbr = this.charBuf[r]; + + if (!cbr) { + this.charBuf[r] = this.getRowArray(cl, 0); + this.styleBuf[r] = this.getRowArray(cl, 0); + } else if (cbr.length < cl) { + for (c = cbr.length; c < cl; c++) { + this.charBuf[r][c] = 0; + this.styleBuf[r][c] = 0; + } + } + } + + var resetcrsr = false; + + if (this.r >= rl) { + r = rl - 1; + resetcrsr = true; + } + + if (this.c >= cl) { + c = cl - 1; + resetcrsr = true; + } + + if (resetcrsr && this.cursoractive) this.cursorOn(); + + // and actually rebuild + this._makeTerm(true); + + for (r = 0; r < rl; r++) { + this.redraw(r); + } + + // clear backup buffer to prevent errors + this.backupBuffer = null; + }, + moveTo: function (x, y){ + this.globals.setElementXY(this.termDiv, x, y); + }, + resizeTo: function (x, y){ + if (this.termDivReady()) { + x = parseInt(x, 10); + y = parseInt(y, 10); + + if (isNaN(x) || isNaN(y) || x < 4 || y < 2) return false; + + this.maxCols = this.conf.cols = x; + this.maxLines = this.conf.rows = y; + + this._makeTerm(); + this.clear(); + + return true; + } else { + return false; + } + }, + redraw: function (r){ + var k; + var st; + var s = this.globals.termStringStart; + var curStyle = 0; + var tstls = this.globals.termStyles; + var tscls = this.globals.termStyleClose; + var tsopn = this.globals.termStyleOpen; + var tspcl = this.globals.termSpecials; + var tclrs = this.globals.colorCodes; + var tnclrs = this.globals.nsColorCodes; + var twclrs = this.globals.webColorCodes; + var t_cb = this.charBuf; + var t_sb = this.styleBuf; + var blur = this.textBlur; + var clr = ''; + var textColor = this.textColor || ''; + + for (var i = 0; i < this.conf.cols; i++) { + var c = t_cb[r][i]; + var cs = t_sb[r][i]; + + if (cs != curStyle || (i == 0 && textColor)) { + if (curStyle) { + if (curStyle & 0xffff00) s += ''; + + for (k = tstls.length - 1; k >= 0; k--) { + st = tstls[k]; + + if (curStyle & st) s += tscls[st]; + } + } + + curStyle = cs; + + for (k = 0; k < tstls.length; k++) { + st = tstls[k]; + + if (curStyle & st) s += tsopn[st]; + } + + clr = textColor; + + if (curStyle & 0xff00) { + var cc = (curStyle & 0xff00) >>> 8; + + clr = (cc < 16) ? tclrs[cc] : '#' + tnclrs[cc - 16]; + } else if (curStyle & 0xff0000) { + clr = '#' + twclrs[(curStyle & 0xff0000) >>> 16]; + } + + if (clr) { + if (curStyle & 1) { + s += ''; + } else if (typeof blur === 'object') { + s += ''; + } else if (blur) { + s += ''; + } else { + s += ''; + } + } + } + + s += (tspcl[c]) ? tspcl[c] : String.fromCharCode(c); + } + + if (curStyle > 0) { + if (curStyle & 0xffff00) s += ''; + + for (k = tstls.length - 1; k >= 0; k--) { + st = tstls[k]; + + if (curStyle & st) s += tscls[st]; + } + } + + s += this.globals.termStringEnd; + + this.globals.writeElement(this.termDiv + '_r' + r, s); + }, + guiReady: function (){ + var ready = true; + + if (this.globals.guiElementsReady(this.termDiv)) { + for (var r = 0; r < this.conf.rows; r++) { + if (this.globals.guiElementsReady(this.termDiv + '_r' + r) == false) { + ready = false; + break; + } + } + } else { + ready = false; + } + + return ready; + }, + termDivReady: function (){ + if (document.getElementById) { + return (document.getElementById(this.termDiv)) ? true : false; + } else if (document.all) { + return (document.all[this.termDiv]) ? true : false; + } else { + return false; + } + }, + getDimensions: function (){ + var object; + var w = 0; + var h = 0; + var d = this.termDiv; + + if (document.getElementById) { + object = document.getElementById(d); + + if (object && object.firstChild) { + w = parseInt(object.firstChild.offsetWidth, 10); + h = parseInt(object.firstChild.offsetHeight, 10); + } else if (object && object.children && object.children[0]) { + w = parseInt(object.children[0].offsetWidth, 10); + h = parseInt(object.children[0].offsetHeight, 10); + } + } else if (document.all) { + object = document.all[d]; + + if (object && object.children && object.children[0]) { + w = parseInt(object.children[0].offsetWidth, 10); + h = parseInt(object.children[0].offsetHeight, 10); + } + } + + return { width: w, height: h }; + }, + // global store for static data and methods (former "TermGlobals") + globals: { + termToInitialze: null, + activeTerm: null, + kbdEnabled: false, + keylock: false, + keyRepeatDelay1: 450, // initial delay + keyRepeatDelay2: 100, // consecutive delays + keyRepeatTimer: null, + lcMorePrompt1: ' -- MORE -- ', + lcMorePromtp1Style: 1, + lcMorePrompt2: ' (Type: space to continue, \'q\' to quit)', + lcMorePrompt2Style: 0, + lcMoreKeyAbort: 113, + lcMoreKeyContinue: 32, + // initialize global data structs + _initGlobals: function (){ + var tg = Terminal.prototype.globals; + + tg._extendMissingStringMethods(); + tg._initWebColors(); + tg._initDomKeyRef(); + + Terminal.prototype.termKey = tg.termKey; + }, + // hex support (don't rely on generic support like Number.toString(16)) + getHexChar: function (c){ + var tg = Terminal.prototype.globals; + + if (tg.isHexChar(c)) return tg.hexToNum[c]; + + return -1; + }, + isHexChar: function (c){ + return !!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); + }, + isHexOnlyChar: function (c){ + return !!((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); + }, + hexToNum: { + '0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, + '8': 8, '9': 9, 'a': 10, 'b': 11, 'c': 12, 'd': 13, 'e': 14, 'f': 15, + 'A': 10, 'B': 11, 'C': 12, 'D': 13, 'E': 14, 'F': 15 + }, + // data for color support + webColors: [], + webColorCodes: [''], + colors: { + // ANSI bright (bold) color set + black: 1, + red: 2, + green: 3, + yellow: 4, + blue: 5, + magenta: 6, + cyan: 7, + white: 8, + // dark color set + grey: 9, + red2: 10, + green2: 11, + yellow2: 12, + blue2: 13, + magenta2: 14, + cyan2: 15, + // synonyms + red1: 2, + green1: 3, + yellow1: 4, + blue1: 5, + magenta1: 6, + cyan1: 7, + gray: 9, + darkred: 10, + darkgreen: 11, + darkyellow: 12, + darkblue: 13, + darkmagenta: 14, + darkcyan: 15, + // default color + 'default': 0, + clear: 0 + }, + colorCodes: [ + '', '#000000', '#ff0000', '#00ff00', '#ffff00', '#0066ff', '#ff00ff', '#00ffff', '#ffffff', + '#808080', '#990000', '#009900', '#999900', '#003399', '#990099', '#009999' + ], + nsColors: { + 'aliceblue': 1, 'antiquewhite': 2, 'aqua': 3, 'aquamarine': 4, + 'azure': 5, 'beige': 6, 'black': 7, 'blue': 8, + 'blueviolet': 9, 'brown': 10, 'burlywood': 11, 'cadetblue': 12, + 'chartreuse': 13, 'chocolate': 14, 'coral': 15, 'cornflowerblue': 16, + 'cornsilk': 17, 'crimson': 18, 'darkblue': 19, 'darkcyan': 20, + 'darkgoldenrod': 21, 'darkgray': 22, 'darkgreen': 23, 'darkkhaki': 24, + 'darkmagenta': 25, 'darkolivegreen': 26, 'darkorange': 27, 'darkorchid': 28, + 'darkred': 29, 'darksalmon': 30, 'darkseagreen': 31, 'darkslateblue': 32, + 'darkslategray': 33, 'darkturquoise': 34, 'darkviolet': 35, 'deeppink': 36, + 'deepskyblue': 37, 'dimgray': 38, 'dodgerblue': 39, 'firebrick': 40, + 'floralwhite': 41, 'forestgreen': 42, 'fuchsia': 43, 'gainsboro': 44, + 'ghostwhite': 45, 'gold': 46, 'goldenrod': 47, 'gray': 48, + 'green': 49, 'greenyellow': 50, 'honeydew': 51, 'hotpink': 52, + 'indianred': 53, 'indigo': 54, 'ivory': 55, 'khaki': 56, + 'lavender': 57, 'lavenderblush': 58, 'lawngreen': 59, 'lemonchiffon': 60, + 'lightblue': 61, 'lightcoral': 62, 'lightcyan': 63, 'lightgoldenrodyellow': 64, + 'lightgreen': 65, 'lightgrey': 66, 'lightpink': 67, 'lightsalmon': 68, + 'lightseagreen': 69, 'lightskyblue': 70, 'lightslategray': 71, 'lightsteelblue': 72, + 'lightyellow': 73, 'lime': 74, 'limegreen': 75, 'linen': 76, + 'maroon': 77, 'mediumaquamarine': 78, 'mediumblue': 79, 'mediumorchid': 80, + 'mediumpurple': 81, 'mediumseagreen': 82, 'mediumslateblue': 83, 'mediumspringgreen': 84, + 'mediumturquoise': 85, 'mediumvioletred': 86, 'midnightblue': 87, 'mintcream': 88, + 'mistyrose': 89, 'moccasin': 90, 'navajowhite': 91, 'navy': 92, + 'oldlace': 93, 'olive': 94, 'olivedrab': 95, 'orange': 96, + 'orangered': 97, 'orchid': 98, 'palegoldenrod': 99, 'palegreen': 100, + 'paleturquoise': 101, 'palevioletred': 102, 'papayawhip': 103, 'peachpuff': 104, + 'peru': 105, 'pink': 106, 'plum': 107, 'powderblue': 108, + 'purple': 109, 'red': 110, 'rosybrown': 111, 'royalblue': 112, + 'saddlebrown': 113, 'salmon': 114, 'sandybrown': 115, 'seagreen': 116, + 'seashell': 117, 'sienna': 118, 'silver': 119, 'skyblue': 120, + 'slateblue': 121, 'slategray': 122, 'snow': 123, 'springgreen': 124, + 'steelblue': 125, 'tan': 126, 'teal': 127, 'thistle': 128, + 'tomato': 129, 'turquoise': 130, 'violet': 131, 'wheat': 132, + 'white': 133, 'whitesmoke': 134, 'yellow': 135, 'yellowgreen': 136 + }, + nsColorCodes: [ + '', + 'f0f8ff', 'faebd7', '00ffff', '7fffd4', + 'f0ffff', 'f5f5dc', '000000', '0000ff', + '8a2be2', 'a52a2a', 'deb887', '5f9ea0', + '7fff00', 'd2691e', 'ff7f50', '6495ed', + 'fff8dc', 'dc143c', '00008b', '008b8b', + 'b8860b', 'a9a9a9', '006400', 'bdb76b', + '8b008b', '556b2f', 'ff8c00', '9932cc', + '8b0000', 'e9967a', '8fbc8f', '483d8b', + '2f4f4f', '00ced1', '9400d3', 'ff1493', + '00bfff', '696969', '1e90ff', 'b22222', + 'fffaf0', '228b22', 'ff00ff', 'dcdcdc', + 'f8f8ff', 'ffd700', 'daa520', '808080', + '008000', 'adff2f', 'f0fff0', 'ff69b4', + 'cd5c5c', '4b0082', 'fffff0', 'f0e68c', + 'e6e6fa', 'fff0f5', '7cfc00', 'fffacd', + 'add8e6', 'f08080', 'e0ffff', 'fafad2', + '90ee90', 'd3d3d3', 'ffb6c1', 'ffa07a', + '20b2aa', '87cefa', '778899', 'b0c4de', + 'ffffe0', '00ff00', '32cd32', 'faf0e6', + '800000', '66cdaa', '0000cd', 'ba55d3', + '9370db', '3cb371', '7b68ee', '00fa9a', + '48d1cc', 'c71585', '191970', 'f5fffa', + 'ffe4e1', 'ffe4b5', 'ffdead', '000080', + 'fdf5e6', '808000', '6b8e23', 'ffa500', + 'ff4500', 'da70d6', 'eee8aa', '98fb98', + 'afeeee', 'db7093', 'ffefd5', 'ffdab9', + 'cd853f', 'ffc0cb', 'dda0dd', 'b0e0e6', + '800080', 'ff0000', 'bc8f8f', '4169e1', + '8b4513', 'fa8072', 'f4a460', '2e8b57', + 'fff5ee', 'a0522d', 'c0c0c0', '87ceeb', + '6a5acd', '708090', 'fffafa', '00ff7f', + '4682b4', 'd2b48c', '008080', 'd8bfd8', + 'ff6347', '40e0d0', 'ee82ee', 'f5deb3', + 'ffffff', 'f5f5f5', 'ffff00', '9acd32' + ], + _webSwatchChars: ['0', '3', '6', '9', 'c', 'f'], + _initWebColors: function (){ + // generate long and short web color ref + var tg = Terminal.prototype.globals; + var wn = tg.webColors; + var cc = tg.webColorCodes; + var n = 1; + var a, b, c, al, bl, bs, cl; + + for (var i = 0; i < 6; i++) { + a = tg._webSwatchChars[i]; + al = a + a; + + for (var j = 0; j < 6; j++) { + b = tg._webSwatchChars[j]; + bl = al + b + b; + bs = a + b; + + for (var k = 0; k < 6; k++) { + c = tg._webSwatchChars[k]; + cl = bl + c + c; + wn[bs + c] = wn[cl] = n; + cc[n] = cl; + n++; + } + } + } + }, + webifyColor: function (s){ + var i; + var a; + var c = ''; + // return nearest web color in 3 digit format + // (do without RegExp for compatibility) + var tg = Terminal.prototype.globals; + + if (s.length == 6) { + for (i = 0; i < 6; i += 2) { + a = s.charAt(i); + + var b = s.charAt(i + 1); + + if (tg.isHexChar(a) && tg.isHexChar(b)) { + c += tg._webSwatchChars[Math.round(parseInt(a + b, 16) / 255 * 5)]; + } else { + return ''; + } + } + + return c; + } else if (s.length == 3) { + for (i = 0; i < 3; i++) { + a = s.charAt(i); + + if (tg.isHexChar(a)) { + c += tg._webSwatchChars[Math.round(parseInt(a, 16) / 15 * 5)]; + } else { + return ''; + } + } + + return c; + } else { + return ''; + } + }, + // public methods for color support + setColor: function (label, value){ + var n; + var tg = Terminal.prototype.globals; + + if (typeof label == 'number' && label >= 1 && label <= 15) { + tg.colorCodes[label] = value; + } else if (typeof label == 'string') { + label = label.toLowerCase(); + + if (label.length == 1 && tg.isHexChar(label)) { + n = tg.hexToNum[label]; + + if (n) tg.colorCodes[n] = value; + } + else if (typeof tg.colors[label] != 'undefined') { + n = tg.colors[label]; + + if (n) tg.colorCodes[n] = value; + } + } + }, + getColorString: function (label){ + var tg = Terminal.prototype.globals; + + if (typeof label == 'number' && label >= 0 && label <= 15) { + return tg.colorCodes[label]; + } else if (typeof label == 'string') { + label = label.toLowerCase(); + + if (label.length == 1 && tg.isHexChar(label)) { + return tg.colorCodes[tg.hexToNum[label]]; + } else if (typeof tg.colors[label] != 'undefined') { + return tg.colorCodes[tg.colors[label]]; + } + } + + return ''; + }, + getColorCode: function (label){ + var tg = Terminal.prototype.globals; + + if (typeof label == 'number' && label >= 0 && label <= 15) { + return label; + } else if (typeof label == 'string') { + label = label.toLowerCase(); + + if (label.length == 1 && tg.isHexChar(label)) { + return parseInt(label, 16); + } else if (typeof tg.colors[label] != 'undefined') { + return tg.colors[label]; + } + } + + return 0; + }, + // import/paste methods (methods return success) + insertText: function (text){ + // auto-types a given string to the active terminal + // returns success (false indicates a lock or no active terminal) + var tg = Terminal.prototype.globals; + var termRef = tg.activeTerm; + + if (!termRef || termRef.closed || tg.keylock + || termRef.lock || termRef.charMode || termRef.fieldMode) return false; + + // terminal open and unlocked, so type the text + for (var i = 0; i < text.length; i++) { + tg.keyHandler({ which: text.charCodeAt(i), _remapped: true }); + } + + return true; + }, + importEachLine: function (text){ + // import multiple lines of text per line each and execs + // returns success (false indicates a lock or no active terminal) + var tg = Terminal.prototype.globals; + var termRef = tg.activeTerm; + + if (!termRef || termRef.closed || tg.keylock + || termRef.lock || termRef.charMode || termRef.fieldMode) return false; + + // clear the current command line + termRef.cursorOff(); + termRef._clearLine(); + + // normalize line breaks + text = text.replace(/\r\n?/g, '\n'); + // split lines and auto-type the text + var t = text.split('\n'); + + for (var i = 0; i < t.length; i++) { + for (var k = 0; k < t[i].length; k++) { + tg.keyHandler({ which: t[i].charCodeAt(k), _remapped: true }); + } + + tg.keyHandler({ which: term.termKey.CR, _remapped: true }); + } + + return true; + }, + importMultiLine: function (text){ + // importing multi-line text as single input with "\n" in lineBuffer + var tg = Terminal.prototype.globals; + var termRef = tg.activeTerm; + + if (!termRef || termRef.closed || tg.keylock + || termRef.lock || termRef.charMode || termRef.fieldMode) return false; + + // lock and clear the line + termRef.lock = true; + + termRef.cursorOff(); + termRef._clearLine(); + // normalize linebreaks and echo the text linewise + text = text.replace(/\r\n?/g, '\n'); + + var lines = text.split('\n'); + + for (var i = 0; i < lines.length; i++) { + termRef.type(lines[i]); + + if (i < lines.length - 1) termRef.newLine(); + } + + // fake ; + // (no history entry for this) + termRef.lineBuffer = text; + termRef.lastLine = ''; + termRef.inputChar = 0; + termRef.handler(); + + return true; + }, + // text related service functions + normalize: function (n, m){ + var s = '' + n; + + while (s.length < m) s = '0' + s; + + return s; + }, + fillLeft: function (t, n){ + if (typeof t != 'string') t = '' + t; + + while (t.length < n) t = ' ' + t; + + return t; + }, + center: function (t, l){ + var s = ''; + + for (var i = t.length; i < l; i += 2) s += ' '; + + return s + t; + }, + // simple substitute for String.replace() + stringReplace: function (s1, s2, t){ + var l1 = s1.length; + var l2 = s2.length; + var ofs = t.indexOf(s1); + + while (ofs >= 0) { + t = t.substring(0, ofs) + s2 + t.substring(ofs + l1); + ofs = t.indexOf(s1, ofs + l2); + } + + return t; + }, + // config data for text wrap + wrapChars: { + // keys: charCode + // values: 1 = white space, 2 = wrap after, 3 = wrap before, 4 = conditional word break + 9: 1, // tab + 10: 1, // new line - don't change this (used internally)!!! + 12: 4, // form feed (use this for conditional word breaks) + 13: 1, // cr + 32: 1, // blank + 40: 3, // ( + 45: 2, // dash/hyphen + 61: 2, // = + 91: 3, // [ + 94: 3, // caret (non-printing chars) + 123: 3 // { + }, + // keyboard methods & controls + setFocus: function (termref){ + Terminal.prototype.globals.activeTerm = termref; + Terminal.prototype.globals.clearRepeatTimer(); + }, + termKey: { + // codes of special keys + 'NUL': 0x00, + 'SOH': 0x01, + 'STX': 0x02, + 'ETX': 0x03, + 'EOT': 0x04, + 'ENQ': 0x05, + 'ACK': 0x06, + 'BEL': 0x07, + 'BS': 0x08, + 'BACKSPACE': 0x08, + 'HT': 0x09, + 'TAB': 0x09, + 'LF': 0x0A, + 'VT': 0x0B, + 'FF': 0x0C, + 'CR': 0x0D, + 'SO': 0x0E, + 'SI': 0x0F, + 'DLE': 0x10, + 'DC1': 0x11, + 'DC2': 0x12, + 'DC3': 0x13, + 'DC4': 0x14, + 'NAK': 0x15, + 'SYN': 0x16, + 'ETB': 0x17, + 'CAN': 0x18, + 'EM': 0x19, + 'SUB': 0x1A, + 'ESC': 0x1B, + 'IS4': 0x1C, + 'IS3': 0x1D, + 'IS2': 0x1E, + 'IS1': 0x1F, + 'DEL': 0x7F, + // other specials + 'EURO': 0x20AC, + // cursor mapping + 'LEFT': 0x1C, + 'RIGHT': 0x1D, + 'UP': 0x1E, + 'DOWN': 0x1F + }, + // map some DOM_VK_* properties to values defined in termKey + termDomKeyRef: {}, + _domKeyMappingData: { + 'LEFT': 'LEFT', + 'RIGHT': 'RIGHT', + 'UP': 'UP', + 'DOWN': 'DOWN', + 'BACK_SPACE': 'BS', + 'RETURN': 'CR', + 'ENTER': 'CR', + 'ESCAPE': 'ESC', + 'DELETE': 'DEL', + 'TAB': 'TAB' + }, + _initDomKeyRef: function (){ + var tg = Terminal.prototype.globals; + var m = tg._domKeyMappingData; + var r = tg.termDomKeyRef; + var k = tg.termKey; + + for (var i in m) { + if (m.hasOwnProperty(i)) { + r['DOM_VK_' + i] = k[m[i]]; + } + } + }, + registerEvent: function (element, eventType, handler, capture){ + if (element.addEventListener) { + element.addEventListener(eventType.toLowerCase(), handler, capture); + } else { + var et = eventType.toUpperCase(); + + if (window.Event && window.Event[et] && element.captureEvents) element.captureEvents(Event[et]); + + element['on' + eventType.toLowerCase()] = handler; + } + }, + releaseEvent: function (element, eventType, handler, capture){ + if (element.removeEventListener) { + element.removeEventListener(eventType.toLowerCase(), handler, capture); + } else { + var et = eventType.toUpperCase(); + + if (window.Event && window.Event[et] && element.releaseEvents) element.releaseEvents(Event[et]); + + et = 'on' + eventType.toLowerCase(); + + if (element[et] && element[et] == handler) element.et = null; + } + }, + + enableKeyboard: function (term){ + var tg = Terminal.prototype.globals; + + if (!tg.kbdEnabled) { + tg.registerEvent(document, 'keypress', tg.keyHandler, true); + tg.registerEvent(document, 'keydown', tg.keyFix, true); + tg.registerEvent(document, 'keyup', tg.clearRepeatTimer, true); + + tg.kbdEnabled = true; + } + + tg.activeTerm = term; + }, + disableKeyboard: function (term){ + var tg = Terminal.prototype.globals; + + if (tg.kbdEnabled) { + tg.releaseEvent(document, 'keypress', tg.keyHandler, true); + tg.releaseEvent(document, 'keydown', tg.keyFix, true); + tg.releaseEvent(document, 'keyup', tg.clearRepeatTimer, true); + + tg.kbdEnabled = false; + } + + tg.activeTerm = null; + }, + // remap some special key mappings on keydown + keyFix: function (e){ + var tg = Terminal.prototype.globals; + var term = tg.activeTerm; + var ch; + + if (tg.keylock || term.lock) return true; + + if (window.event) { + if (!e) e = window.event; + + ch = e.keyCode; + + if (e.DOM_VK_UP) { + for (var i in tg.termDomKeyRef) { + if (tg.termDomKeyRef.hasOwnProperty(i)) { + if (e[i] && ch == e[i]) { + tg.keyHandler({ which: tg.termDomKeyRef[i], _remapped: true, _repeat: ch == 0x1B }); + + if (e.preventDefault) e.preventDefault(); + + if (e.stopPropagation) e.stopPropagation(); + + e.cancelBubble = true; + + return false; + } + } + } + + e.cancelBubble = false; + + return true; + } else { + // no DOM support + var termKey = term.termKey; + var keyHandler = tg.keyHandler; + + if (ch == 8 && !term.isOpera) { + keyHandler({ which: termKey.BS, _remapped: true, _repeat: true }); + } else if (ch == 9) { + keyHandler({ + which: termKey.TAB, + _remapped: true, + _repeat: (term.printTab) ? false : true + }); + } else if (ch == 27) { + keyHandler({ + which: termKey.ESC, + _remapped: true, + _repeat: (term.printTab) ? false : true + }); + } else if (ch == 37) { + keyHandler({ which: termKey.LEFT, _remapped: true, _repeat: true }); + } else if (ch == 39) { + keyHandler({ which: termKey.RIGHT, _remapped: true, _repeat: true }); + } else if (ch == 38) { + keyHandler({ which: termKey.UP, _remapped: true, _repeat: true }); + } else if (ch == 40) { + keyHandler({ which: termKey.DOWN, _remapped: true, _repeat: true }); + } else if (ch == 127 || ch == 46) { + keyHandler({ which: termKey.DEL, _remapped: true, _repeat: true }); + } else if (ch >= 57373 && ch <= 57376) { + if (ch == 57373) { + keyHandler({ which: termKey.UP, _remapped: true, _repeat: true }); + } else if (ch == 57374) { + keyHandler({ which: termKey.DOWN, _remapped: true, _repeat: true }); + } else if (ch == 57375) { + keyHandler({ which: termKey.LEFT, _remapped: true, _repeat: true }); + } else if (ch == 57376) { + keyHandler({ which: termKey.RIGHT, _remapped: true, _repeat: true }); + } + } else { + e.cancelBubble = false; + + return true; + } + + if (e.preventDefault) e.preventDefault(); + + if (e.stopPropagation) e.stopPropagation(); + + e.cancelBubble = true; + + return false; + } + } + }, + clearRepeatTimer: function (e){ + var tg = Terminal.prototype.globals; + + if (tg.keyRepeatTimer) { + clearTimeout(tg.keyRepeatTimer); + + tg.keyRepeatTimer = null; + } + }, + doKeyRepeat: function (ch){ + Terminal.prototype.globals.keyHandler({ which: ch, _remapped: true, _repeated: true }) + }, + keyHandler: function (e){ + var tg = Terminal.prototype.globals; + var term = tg.activeTerm; + + if (tg.keylock || term.lock || term.isMac && e && e.metaKey) return true; + + if (window.event) { + if (window.event.preventDefault) window.event.preventDefault(); + + if (window.event.stopPropagation) window.event.stopPropagation(); + } else if (e) { + if (e.preventDefault) e.preventDefault(); + + if (e.stopPropagation) e.stopPropagation(); + } + + var ch; + var ctrl = false; + var shft = false; + var remapped = false; + var termKey = term.termKey; + var keyRepeat = 0; + + if (e) { + ch = e.which; + ctrl = ((e.ctrlKey && !e.altKey) || e.modifiers == 2); + shft = (e.shiftKey || e.modifiers == 4); + + if (e._remapped) { + remapped = true; + + if (window.event) { + //ctrl=(ctrl || window.event.ctrlKey); + ctrl = (ctrl || (window.event.ctrlKey && !window.event.altKey)); + shft = (shft || window.event.shiftKey); + } + } + + if (e._repeated) { + keyRepeat = 2; + } else if (e._repeat) { + keyRepeat = 1; + } + } else if (window.event) { + ch = window.event.keyCode; + //ctrl=(window.event.ctrlKey); + ctrl = (window.event.ctrlKey && !window.event.altKey); // allow alt gr == ctrl alt + shft = (window.event.shiftKey); + + if (window.event._repeated) { + keyRepeat = 2; + } else if (window.event._repeat) { + keyRepeat = 1; + } + } else { + return true; + } + + if (ch == '' && remapped == false) { + // map specials + if (e == null) e = window.event; + + if (e.charCode == 0 && e.keyCode) { + if (e.DOM_VK_UP) { + var dkr = tg.termDomKeyRef; + + for (var i in dkr) { + if (dkr.hasOwnProperty(i)) { + if (e[i] && e.keyCode == e[i]) { + ch = dkr[i]; + break; + } + } + } + } else { + // NS4 + if (e.keyCode == 28) { ch = termKey.LEFT; } + else if (e.keyCode == 29) { ch = termKey.RIGHT; } + else if (e.keyCode == 30) { ch = termKey.UP; } + else if (e.keyCode == 31) { ch = termKey.DOWN; } + // Mozilla alike but no DOM support + else if (e.keyCode == 37) { ch = termKey.LEFT; } + else if (e.keyCode == 39) { ch = termKey.RIGHT; } + else if (e.keyCode == 38) { ch = termKey.UP; } + else if (e.keyCode == 40) { ch = termKey.DOWN; } + // just to have the TAB mapping here too + else if (e.keyCode == 9) { ch = termKey.TAB; } + } + } + } + + // leave on unicode private use area (might be function key etc) + if ((ch >= 0xE000) && (ch <= 0xF8FF)) return; + + if (keyRepeat) { + tg.clearRepeatTimer(); + + tg.keyRepeatTimer = window.setTimeout( + 'Terminal.prototype.globals.doKeyRepeat(' + ch + ')', + (keyRepeat == 1) ? tg.keyRepeatDelay1 : tg.keyRepeatDelay2 + ); + } + + // key actions + if (term.charMode) { + term.insert = false; + term.inputChar = ch; + term.lineBuffer = ''; + term.handler(); + + if (ch <= 32 && window.event) window.event.cancelBubble = true; + + return false; + } + + if (!ctrl) { + // special keys + if (ch == termKey.CR) { + term.lock = true; + + term.cursorOff(); + + term.insert = false; + + if (term.rawMode) { + term.lineBuffer = term.lastLine; + } else if (term.fieldMode) { + term.lineBuffer = term.lastLine; + term.exitFieldMode(); + } else { + term.lineBuffer = term._getLine(true); + + if ( + term.lineBuffer != '' && + (!term.historyUnique || term.history.length == 0 || + term.lineBuffer != term.history[term.history.length - 1]) + ) { + term.history[term.history.length] = term.lineBuffer; + } + + term.histPtr = term.history.length; + } + + term.lastLine = ''; + term.inputChar = 0; + term.handler(); + + if (window.event) window.event.cancelBubble = true; + + return false; + } else if (term.fieldMode) { + if (ch == termKey.ESC) { + term.lineBuffer = term.lastLine = ''; + term.exitFieldMode(); + term.lastLine = ''; + term.inputChar = 0; + term.handler(); + + if (window.event) window.event.cancelBubble = true; + + return false; + } else if (ch == termKey.LEFT) { + if (term.fieldC > 0) term.fieldC--; + } else if (ch == termKey.RIGHT) { + if (term.fieldC < term.lastLine.length) term.fieldC++; + } else if (ch == termKey.BS) { + if (term.fieldC > 0) { + term.lastLine = term.lastLine.substring(0, term.fieldC - 1) + term.lastLine.substring(term.fieldC); + term.fieldC--; + } + } else if (ch == termKey.DEL) { + if (term.fieldC < term.lastLine.length) { + term.lastLine = term.lastLine.substring(0, term.fieldC) + term.lastLine.substring(term.fieldC + 1); + } + } else if (ch >= 32) { + term.lastLine = term.lastLine.substring(0, term.fieldC) + String.fromCharCode(ch) + + term.lastLine.substring(term.fieldC); + term.fieldC++; + } + + term.drawField(); + + return false; + } else if (ch == termKey.ESC && term.conf.closeOnESC) { + term.close(); + + if (window.event) window.event.cancelBubble = true; + + return false; + } + + if (ch < 32 && term.rawMode) { + if (window.event) window.event.cancelBubble = true; + + return false; + } else { + if (ch == termKey.LEFT) { + term.cursorLeft(); + + if (window.event) window.event.cancelBubble = true; + + return false; + } else if (ch == termKey.RIGHT) { + term.cursorRight(); + + if (window.event) window.event.cancelBubble = true; + + return false; + } else if (ch == termKey.UP) { + term.cursorOff(); + + if (term.histPtr == term.history.length) term.lastLine = term._getLine(); + + term._clearLine(); + + if (term.history.length && term.histPtr >= 0) { + if (term.histPtr > 0) term.histPtr--; + + term.type(term.history[term.histPtr]); + } else if (term.lastLine) { + term.type(term.lastLine); + } + + term.cursorOn(); + + if (window.event) window.event.cancelBubble = true; + + return false; + } else if (ch == termKey.DOWN) { + term.cursorOff(); + + if (term.histPtr == term.history.length) term.lastLine = term._getLine(); + term._clearLine(); + + if (term.history.length && term.histPtr <= term.history.length) { + if (term.histPtr < term.history.length) term.histPtr++; + + if (term.histPtr < term.history.length) { + term.type(term.history[term.histPtr]); + } else if (term.lastLine) { + term.type(term.lastLine); + } + } else if (term.lastLine) { + term.type(term.lastLine); + } + + term.cursorOn(); + + if (window.event) window.event.cancelBubble = true; + + return false; + } else if (ch == termKey.BS) { + term.backspace(); + + if (window.event) window.event.cancelBubble = true; + + return false; + } else if (ch == termKey.DEL) { + if (term.DELisBS) { + term.backspace(); + } else { + term.fwdDelete(); + } + + if (window.event) window.event.cancelBubble = true; + + return false; + } + } + } + + if (term.rawMode) { + if (term.isPrintable(ch)) { + term.lastLine += String.fromCharCode(ch); + } + + if (ch == 32 && window.event) { + window.event.cancelBubble = true; + } else if (window.opera && window.event) { + window.event.cancelBubble = true; + } + + return false; + } else { + if (term.conf.catchCtrlH && (ch == termKey.BS || (ctrl && ch == 72))) { + // catch ^H + term.backspace(); + + if (window.event) window.event.cancelBubble = true; + + return false; + } else if (term.ctrlHandler && (ch < 32 || (ctrl && term.isPrintable(ch, true)))) { + if ((ch >= 65 && ch <= 96) || ch == 63) { + // remap canonical + if (ch == 63) { + ch = 31; + } else { + ch -= 64; + } + } + + term.inputChar = ch; + term.ctrlHandler(); + + if (window.event) window.event.cancelBubble = true; + + return false; + } else if (ctrl || !term.isPrintable(ch, true)) { + if (window.event) window.event.cancelBubble = true; + + return false; + } else if (term.isPrintable(ch, true)) { + if (term.blinkTimer) clearTimeout(term.blinkTimer); + + if (term.insert) { + term.cursorOff(); + term._scrollRight(term.r, term.c); + } + + term._charOut(ch); + term.cursorOn(); + + if (ch == 32 && window.event) { + window.event.cancelBubble = true; + } else if (window.opera && window.event) { + window.event.cancelBubble = true; + } + + return false; + } + } + + return true; + }, + // gui mappings + hasSubDivs: false, + termStringStart: '', + termStringEnd: '', + termSpecials: { + // special HTML escapes + 0: ' ', + 1: ' ', + 9: ' ', + 32: ' ', + 34: '"', + 38: '&', + 60: '<', + 62: '>', + 127: '◊', + 0x20AC: '€' + }, + // extensive list of max 8 styles (2^n, n<16) + termStyles: [1, 2, 4, 8, 16], + // style markup: one letter keys, reserved keys: "p" (plain), "c" (color) + termStyleMarkup: { + 'r': 1, + 'u': 2, + 'i': 4, + 's': 8, + 'b': 16 // map "b" to 16 (italics) for ANSI mapping + }, + // mappings for styles (heading HTML) + termStyleOpen: { + 1: '', + 2: '', + 4: '', + 8: '', + 16: '' + }, + // mapping for styles (trailing HTML) + termStyleClose: { + 1: '<\/span>', + 2: '<\/u>', + 4: '<\/i>', + 8: '<\/strike>', + 16: '' + }, + // method to install custom styles + assignStyle: function (styleCode, markup, htmlOpen, htmlClose){ + var i; + var tg = Terminal.prototype.globals; + + // check params + if (!styleCode || isNaN(styleCode)) { + if (styleCode >= 256) { + alert('termlib.js:\nCould not assign style.\n' + s + ' is not a valid power of 2 between 0 and 256.'); + + return; + } + } + + var s = styleCode & 0xff; + var matched = false; + + for (i = 0; i < 8; i++) { + if ((s >>> i) & 1) { + if (matched) { + alert('termlib.js:\nCould not assign style code.\n' + s + ' is not a power of 2!'); + return; + } + matched = true; + } + } + + if (!matched) { + alert('termlib.js:\nCould not assign style code.\n' + s + ' is not a valid power of 2 between 0 and 256.'); + + return; + } + + markup = String(markup).toLowerCase(); + + if (markup == 'c' || markup == 'p') { + alert('termlib.js:\nCould not assign mark up.\n"' + markup + '" is a reserved code.'); + + return; + } + + if (markup.length > 1) { + alert('termlib.js:\nCould not assign mark up.\n"' + markup + '" is not a single letter code.'); + + return; + } + + var exists = false; + + for (i = 0; i < tg.termStyles.length; i++) { + if (tg.termStyles[i] == s) { + exists = true; + break; + } + } + + if (exists) { + var m = tg.termStyleMarkup[markup]; + + if (m && m != s) { + alert('termlib.js:\nCould not assign mark up.\n"' + markup + '" is already in use.'); + + return; + } + } else { + if (tg.termStyleMarkup[markup]) { + alert('termlib.js:\nCould not assign mark up.\n"' + markup + '" is already in use.'); + + return; + } + + tg.termStyles[tg.termStyles.length] = s; + } + + // install properties + tg.termStyleMarkup[markup] = s; + tg.termStyleOpen[s] = htmlOpen; + tg.termStyleClose[s] = htmlClose; + }, + // ANSI output mapping (styles & fg colors only) + ANSI_regexp: /(\x1b\[|x9b)([0-9;]+?)([a-zA-Z])/g, // CSI ( = 0x1b+"[" or 0x9b ) + params + letter + ANIS_SGR_codes: { + '0': '%+p', + '1': '%+b', + '3': '%+i', + '4': '%+u', + '7': '%+r', + '9': '%+s', + '21': '%+u', + '22': '%-b', + '23': '%-i', + '24': '%-u', + '27': '%-r', + '29': '%-s', + '30': '%c(0)', // using default fg color for black (black: "%c(1)") + '31': '%c(a)', + '32': '%c(b)', + '33': '%c(c)', + '34': '%c(d)', + '35': '%c(e)', + '36': '%c(f)', + '37': '%c(#999)', + '39': '%c(0)', + '90': '%c(9)', + '91': '%c(2)', + '92': '%c(3)', + '93': '%c(4)', + '94': '%c(5)', + '95': '%c(6)', + '96': '%c(7)', + '97': '%c(8)', + '99': '%c(0)', + 'trueBlack': '%c(1)' + }, + ANSI_map: function (t, trueBlack){ + // transform simple ANSI SGR codes to internal markup + var tg = Terminal.prototype.globals; + + tg.ANSI_regexp.lastIndex = 0; + + return t.replace( + tg.ANSI_regexp, + function (str, p1, p2, p3, offset, s){ + return tg.ANSI_replace(p2, p3, trueBlack); + } + ); + }, + /** + * @return {string} + */ + ANSI_replace: function (p, cmd, trueBlack){ + var tg = Terminal.prototype.globals; + + if (cmd == 'm') { + if (p == '') { + return tg.ANIS_SGR_codes[0]; + } else if (trueBlack && p == '30') { + return tg.ANIS_SGR_codes.trueBlack; + } else if (tg.ANIS_SGR_codes[p]) { + return tg.ANIS_SGR_codes[p]; + } + } + + return ''; + }, + // basic DHTML dynamics and browser abstraction + writeElement: function (e, t){ + if (document.getElementById) { + var element = document.getElementById(e); + + element.innerHTML = t; + } else if (document.all) { + document.all[e].innerHTML = t; + } + }, + setElementXY: function (d, x, y){ + if (document.getElementById) { + var element = document.getElementById(d); + + element.style.left = x + 'px'; + element.style.top = y + 'px'; + } else if (document.all) { + document.all[d].style.left = x + 'px'; + document.all[d].style.top = y + 'px'; + } + }, + setVisible: function (d, v){ + if (document.getElementById) { + var element = document.getElementById(d); + + element.style.visibility = (v) ? 'visible' : 'hidden'; + } else if (document.all) { + document.all[d].style.visibility = (v) ? 'visible' : 'hidden'; + } + }, + setDisplay: function (d, v){ + if (document.getElementById) { + var element = document.getElementById(d); + + element.style.display = v; + } + else if (document.all) { + document.all[d].style.display = v; + } + }, + guiElementsReady: function (e){ + if (document.getElementById) { + return (document.getElementById(e)) ? true : false; + } else if (document.all) { + return (document.all[e]) ? true : false; + } else { + return false; + } + }, + // constructor mods (MSIE fixes) + _termString_makeKeyref: function (){ + var tg = Terminal.prototype.globals; + var termString_keyref = tg.termString_keyref = []; + var termString_keycoderef = tg.termString_keycoderef = []; + var hex = ['A', 'B', 'C', 'D', 'E', 'F']; + + for (var i = 0; i <= 15; i++) { + var high = (i < 10) ? i : hex[i - 10]; + + for (var k = 0; k <= 15; k++) { + var low = (k < 10) ? k : hex[k - 10]; + var cc = i * 16 + k; + + if (cc >= 32) { + var cs = unescape("%" + high + low); + + termString_keyref[cc] = cs; + termString_keycoderef[cs] = cc; + } + } + } + }, + _extendMissingStringMethods: function (){ + if (!String.fromCharCode || !String.prototype.charCodeAt) { + Terminal.prototype.globals._termString_makeKeyref(); + } + + if (!String.fromCharCode) { + String.fromCharCode = function (cc){ + return (cc != null) ? Terminal.prototype.globals.termString_keyref[cc] : ''; + }; + } + + if (!String.prototype.charCodeAt) { + String.prototype.charCodeAt = function (n){ + var cs = this.charAt(n); + + return (Terminal.prototype.globals.termString_keycoderef[cs]) ? + Terminal.prototype.globals.termString_keycoderef[cs] : 0; + }; + } + } + // end of Terminal.prototype.globals + } + // end of Terminal.prototype +}; + +// initialize global data +Terminal.prototype.globals._initGlobals(); +// global entities for backward compatibility with termlib 1.x applications +var TerminalDefaults = Terminal.prototype.Defaults; +var termDefaultHandler = Terminal.prototype.defaultHandler; +var TermGlobals = Terminal.prototype.globals; +var termKey = Terminal.prototype.globals.termKey; +var termDomKeyRef = Terminal.prototype.globals.termDomKeyRef; +// eof \ No newline at end of file