* @license MIT
*/
-import { CompositionHelper } from './CompositionHelper.js';
-import { EventEmitter } from './EventEmitter.js';
-import { Viewport } from './Viewport.js';
-import { rightClickHandler, pasteHandler, copyHandler } from './handlers/Clipboard.js';
-import { CircularList } from './utils/CircularList.js';
+import { CompositionHelper } from './CompositionHelper';
+import { EventEmitter } from './EventEmitter';
+import { Viewport } from './Viewport';
+import { rightClickHandler, pasteHandler, copyHandler } from './handlers/Clipboard';
+import { CircularList } from './utils/CircularList';
import { C0 } from './EscapeSequences';
import { InputHandler } from './InputHandler';
import { Parser } from './Parser';
-import { CharMeasure } from './utils/CharMeasure.js';
+import { Renderer } from './Renderer';
+import { CharMeasure } from './utils/CharMeasure';
import * as Browser from './utils/Browser';
import * as Keyboard from './utils/Keyboard';
import { CHARSETS } from './Charsets';
// Let it work inside Node.js for automated testing purposes.
var document = (typeof window != 'undefined') ? window.document : null;
-/**
- * States
- */
-var normal = 0, escaped = 1, csi = 2, osc = 3, charset = 4, dcs = 5, ignore = 6;
-
/**
* The amount of write requests to queue before sending an XOFF signal to the
* pty process. This number must be small in order for ^C and similar sequences
*/
var WRITE_BATCH_SIZE = 300;
-/**
- * The maximum number of refresh frames to skip when the write buffer is non-
- * empty. Note that these frames may be intermingled with frames that are
- * skipped via requestAnimationFrame's mechanism.
- */
-var MAX_REFRESH_FRAME_SKIP = 5;
-
/**
* Terminal
*/
*/
this.y = 0;
- /** A queue of the rows to be refreshed */
- this.refreshRowsQueue = [];
-
this.cursorState = 0;
this.cursorHidden = false;
this.convertEol;
this.inputHandler = new InputHandler(this);
this.parser = new Parser(this.inputHandler, this);
+ // Reuse renderer if the Terminal is being recreated via a Terminal.reset call.
+ this.renderer = this.renderer || null;
// user input states
this.writeBuffer = [];
this.writeInProgress = false;
- this.refreshFramesSkipped = 0;
/**
* Whether _xterm.js_ sent XOFF in order to catch up with the pty process.
termName: 'xterm',
geometry: [80, 24],
cursorBlink: false,
+ cursorStyle: 'block',
visualBell: false,
popOnBell: false,
scrollback: 1000,
screenKeys: false,
debug: false,
cancelEvents: false,
- disableStdin: false
+ disableStdin: false,
+ useFlowControl: false,
+ tabStopWidth: 8
// programFeatures: false,
// focusKeys: false,
};
if (!(key in Terminal.defaults)) {
throw new Error('No option with key "' + key + '"');
}
+ switch (key) {
+ case 'scrollback':
+ if (this.options[key] !== value) {
+ if (this.lines.length > value) {
+ const amountToTrim = this.lines.length - value;
+ const needsRefresh = (this.ydisp - amountToTrim < 0);
+ this.lines.trimStart(amountToTrim);
+ this.ybase = Math.max(this.ybase - amountToTrim, 0);
+ this.ydisp = Math.max(this.ydisp - amountToTrim, 0);
+ if (needsRefresh) {
+ this.refresh(0, this.rows - 1);
+ }
+ }
+ this.lines.maxLength = value;
+ this.viewport.syncScrollArea();
+ }
+ break;
+ }
this[key] = value;
this.options[key] = value;
+ switch (key) {
+ case 'cursorBlink': this.element.classList.toggle('xterm-cursor-blink', value); break;
+ case 'cursorStyle':
+ // Style 'block' applies with no class
+ this.element.classList.toggle(`xterm-cursor-style-underline`, value === 'underline');
+ this.element.classList.toggle(`xterm-cursor-style-bar`, value === 'bar');
+ break;
+ case 'tabStopWidth': this.setupStops(); break;
+ }
};
/**
*/
Terminal.bindBlur = function (term) {
on(term.textarea, 'blur', function (ev) {
- term.queueRefresh(term.y, term.y);
+ term.refresh(term.y, term.y);
if (term.sendFocus) {
term.send(C0.ESC + '[O');
}
term.keyPress(ev);
}, true);
- on(term.element, 'keyup', term.focus.bind(term));
+ on(term.element, 'keyup', function(ev) {
+ if (!wasMondifierKeyOnlyEvent(ev)) {
+ term.focus(term);
+ }
+ }, true);
on(term.textarea, 'keydown', function(ev) {
term.keyDown(ev);
this.element.classList.add('terminal');
this.element.classList.add('xterm');
this.element.classList.add('xterm-theme-' + this.theme);
+ this.element.classList.toggle('xterm-cursor-blink', this.options.cursorBlink);
this.element.style.height
this.element.setAttribute('tabindex', 0);
}
this.parent.appendChild(this.element);
- this.charMeasure = new CharMeasure(this.rowContainer);
+ this.charMeasure = new CharMeasure(this.helperContainer);
this.charMeasure.on('charsizechanged', function () {
self.updateCharSizeCSS();
});
this.charMeasure.measure();
this.viewport = new Viewport(this, this.viewportElement, this.viewportScrollArea, this.charMeasure);
+ this.renderer = new Renderer(this);
// Setup loop that draws to screen
- this.queueRefresh(0, this.rows - 1);
- this.refreshLoop();
+ this.refresh(0, this.rows - 1);
// Initialize global actions that
// need to be taken on the document.
// them into terminal mouse protocols.
this.bindMouse();
- // Figure out whether boldness affects
- // the character width of monospace fonts.
- if (Terminal.brokenBold == null) {
- Terminal.brokenBold = isBoldBroken(this.document);
- }
-
/**
* This event is emitted when terminal has completed opening.
*
this._events = {};
this.handler = function() {};
this.write = function() {};
- if (this.element.parentNode) {
+ if (this.element && this.element.parentNode) {
this.element.parentNode.removeChild(this.element);
}
//this.emit('close');
};
-
-/**
- * Flags used to render terminal text properly
- */
-Terminal.flags = {
- BOLD: 1,
- UNDERLINE: 2,
- BLINK: 4,
- INVERSE: 8,
- INVISIBLE: 16
-}
-
-/**
- * Queues a refresh between two rows (inclusive), to be done on next animation
- * frame.
- * @param {number} start The start row.
- * @param {number} end The end row.
- */
-Terminal.prototype.queueRefresh = function(start, end) {
- this.refreshRowsQueue.push({ start: start, end: end });
-}
-
-/**
- * Performs the refresh loop callback, calling refresh only if a refresh is
- * necessary before queueing up the next one.
- */
-Terminal.prototype.refreshLoop = function() {
- // Don't refresh if there were no row changes
- if (this.refreshRowsQueue.length > 0) {
- // Skip MAX_REFRESH_FRAME_SKIP frames if the writeBuffer is non-empty as it
- // will need to be immediately refreshed anyway. This saves a lot of
- // rendering time as the viewport DOM does not need to be refreshed, no
- // scroll events, no layouts, etc.
- var skipFrame = this.writeBuffer.length > 0 && this.refreshFramesSkipped++ <= MAX_REFRESH_FRAME_SKIP;
-
- if (!skipFrame) {
- this.refreshFramesSkipped = 0;
- var start;
- var end;
- if (this.refreshRowsQueue.length > 4) {
- // Just do a full refresh when 5+ refreshes are queued
- start = 0;
- end = this.rows - 1;
- } else {
- // Get start and end rows that need refreshing
- start = this.refreshRowsQueue[0].start;
- end = this.refreshRowsQueue[0].end;
- for (var i = 1; i < this.refreshRowsQueue.length; i++) {
- if (this.refreshRowsQueue[i].start < start) {
- start = this.refreshRowsQueue[i].start;
- }
- if (this.refreshRowsQueue[i].end > end) {
- end = this.refreshRowsQueue[i].end;
- }
- }
- }
- this.refreshRowsQueue = [];
- this.refresh(start, end);
- }
- }
- window.requestAnimationFrame(this.refreshLoop.bind(this));
-}
-
/**
- * Refreshes (re-renders) terminal content within two rows (inclusive)
- *
- * Rendering Engine:
- *
- * In the screen buffer, each character is stored as a an array with a character
- * and a 32-bit integer:
- * - First value: a utf-16 character.
- * - Second value:
- * - Next 9 bits: background color (0-511).
- * - Next 9 bits: foreground color (0-511).
- * - Next 14 bits: a mask for misc. flags:
- * - 1=bold
- * - 2=underline
- * - 4=blink
- * - 8=inverse
- * - 16=invisible
- *
+ * Tells the renderer to refresh terminal content between two rows (inclusive) at the next
+ * opportunity.
* @param {number} start The row to start from (between 0 and terminal's height terminal - 1)
* @param {number} end The row to end at (between fromRow and terminal's height terminal - 1)
*/
Terminal.prototype.refresh = function(start, end) {
- var self = this;
-
- var x, y, i, line, out, ch, ch_width, width, data, attr, bg, fg, flags, row, parent, focused = document.activeElement;
-
- // If this is a big refresh, remove the terminal rows from the DOM for faster calculations
- if (end - start >= this.rows / 2) {
- parent = this.element.parentNode;
- if (parent) {
- this.element.removeChild(this.rowContainer);
- }
- }
-
- width = this.cols;
- y = start;
-
- if (end >= this.rows.length) {
- this.log('`end` is too large. Most likely a bad CSR.');
- end = this.rows.length - 1;
- }
-
- for (; y <= end; y++) {
- row = y + this.ydisp;
-
- line = this.lines.get(row);
- out = '';
-
- if (this.y === y - (this.ybase - this.ydisp)
- && this.cursorState
- && !this.cursorHidden) {
- x = this.x;
- } else {
- x = -1;
- }
-
- attr = this.defAttr;
- i = 0;
-
- for (; i < width; i++) {
- data = line[i][0];
- ch = line[i][1];
- ch_width = line[i][2];
- if (!ch_width)
- continue;
-
- if (i === x) data = -1;
-
- if (data !== attr) {
- if (attr !== this.defAttr) {
- out += '</span>';
- }
- if (data !== this.defAttr) {
- if (data === -1) {
- out += '<span class="reverse-video terminal-cursor';
- if (this.cursorBlink) {
- out += ' blinking';
- }
- out += '">';
- } else {
- var classNames = [];
-
- bg = data & 0x1ff;
- fg = (data >> 9) & 0x1ff;
- flags = data >> 18;
-
- if (flags & Terminal.flags.BOLD) {
- if (!Terminal.brokenBold) {
- classNames.push('xterm-bold');
- }
- // See: XTerm*boldColors
- if (fg < 8) fg += 8;
- }
-
- if (flags & Terminal.flags.UNDERLINE) {
- classNames.push('xterm-underline');
- }
-
- if (flags & Terminal.flags.BLINK) {
- classNames.push('xterm-blink');
- }
-
- // If inverse flag is on, then swap the foreground and background variables.
- if (flags & Terminal.flags.INVERSE) {
- /* One-line variable swap in JavaScript: http://stackoverflow.com/a/16201730 */
- bg = [fg, fg = bg][0];
- // Should inverse just be before the
- // above boldColors effect instead?
- if ((flags & 1) && fg < 8) fg += 8;
- }
-
- if (flags & Terminal.flags.INVISIBLE) {
- classNames.push('xterm-hidden');
- }
-
- /**
- * Weird situation: Invert flag used black foreground and white background results
- * in invalid background color, positioned at the 256 index of the 256 terminal
- * color map. Pin the colors manually in such a case.
- *
- * Source: https://github.com/sourcelair/xterm.js/issues/57
- */
- if (flags & Terminal.flags.INVERSE) {
- if (bg == 257) {
- bg = 15;
- }
- if (fg == 256) {
- fg = 0;
- }
- }
-
- if (bg < 256) {
- classNames.push('xterm-bg-color-' + bg);
- }
-
- if (fg < 256) {
- classNames.push('xterm-color-' + fg);
- }
-
- out += '<span';
- if (classNames.length) {
- out += ' class="' + classNames.join(' ') + '"';
- }
- out += '>';
- }
- }
- }
-
- if (ch_width === 2) {
- out += '<span class="xterm-wide-char">';
- }
- switch (ch) {
- case '&':
- out += '&';
- break;
- case '<':
- out += '<';
- break;
- case '>':
- out += '>';
- break;
- default:
- if (ch <= ' ') {
- out += ' ';
- } else {
- out += ch;
- }
- break;
- }
- if (ch_width === 2) {
- out += '</span>';
- }
-
- attr = data;
- }
-
- if (attr !== this.defAttr) {
- out += '</span>';
- }
-
- this.children[y].innerHTML = out;
+ if (this.renderer) {
+ this.renderer.queueRefresh(start, end);
}
-
- if (parent) {
- this.element.appendChild(this.rowContainer);
- }
-
- this.emit('refresh', {element: this.element, start: start, end: end});
};
/**
Terminal.prototype.showCursor = function() {
if (!this.cursorState) {
this.cursorState = 1;
- this.queueRefresh(this.y, this.y);
+ this.refresh(this.y, this.y);
}
};
this.emit('scroll', this.ydisp);
}
- this.queueRefresh(0, this.rows - 1);
+ this.refresh(0, this.rows - 1);
};
/**
// Send XOFF to pause the pty process if the write buffer becomes too large so
// xterm.js can catch up before more data is sent. This is necessary in order
// to keep signals such as ^C responsive.
- if (!this.xoffSentToCatchUp && this.writeBuffer.length >= WRITE_BUFFER_PAUSE_THRESHOLD) {
+ if (this.options.useFlowControl && !this.xoffSentToCatchUp && this.writeBuffer.length >= WRITE_BUFFER_PAUSE_THRESHOLD) {
// XOFF - stop pty pipe
// XON will be triggered by emulator before processing data chunk
this.send(C0.DC3);
this.parser.parse(data);
this.updateRange(this.y);
- this.queueRefresh(this.refreshStart, this.refreshEnd);
+ this.refresh(this.refreshStart, this.refreshEnd);
}
if (this.writeBuffer.length > 0) {
// Allow renderer to catch up before processing the next batch
* @param {number} y The number of rows to resize to.
*/
Terminal.prototype.resize = function(x, y) {
+ if (isNaN(x) || isNaN(y)) {
+ return;
+ }
+
var line
, el
, i
}
}
}
- this.setupStops(j);
this.cols = x;
+ this.setupStops(this.cols);
// resize rows
j = this.rows;
this.charMeasure.measure();
- this.queueRefresh(0, this.rows - 1);
+ this.refresh(0, this.rows - 1);
this.normal = null;
i = 0;
}
- for (; i < this.cols; i += 8) {
+ for (; i < this.cols; i += this.getOption('tabStopWidth')) {
this.tabs[i] = true;
}
};
* @param {number} y The line in which to operate.
*/
Terminal.prototype.eraseRight = function(x, y) {
- var line = this.lines.get(this.ybase + y)
- , ch = [this.eraseAttr(), ' ', 1]; // xterm
-
-
+ var line = this.lines.get(this.ybase + y);
+ if (!line) {
+ return;
+ }
+ var ch = [this.eraseAttr(), ' ', 1]; // xterm
for (; x < this.cols; x++) {
line[x] = ch;
}
-
this.updateRange(y);
};
* @param {number} y The line in which to operate.
*/
Terminal.prototype.eraseLeft = function(x, y) {
- var line = this.lines.get(this.ybase + y)
- , ch = [this.eraseAttr(), ' ', 1]; // xterm
-
+ var line = this.lines.get(this.ybase + y);
+ if (!line) {
+ return;
+ }
+ var ch = [this.eraseAttr(), ' ', 1]; // xterm
x++;
- while (x--) line[x] = ch;
-
+ while (x--) {
+ line[x] = ch;
+ }
this.updateRange(y);
};
for (var i = 1; i < this.rows; i++) {
this.lines.push(this.blankLine());
}
- this.queueRefresh(0, this.rows - 1);
+ this.refresh(0, this.rows - 1);
this.emit('scroll', this.ydisp);
};
this.y--;
this.scroll();
}
+ // If the end of the line is hit, prevent this action from wrapping around to the next line.
+ if (this.x >= this.cols) {
+ this.x--;
+ }
};
var customKeydownHandler = this.customKeydownHandler;
Terminal.call(this, this.options);
this.customKeydownHandler = customKeydownHandler;
- this.queueRefresh(0, this.rows - 1);
+ this.refresh(0, this.rows - 1);
this.viewport.syncScrollArea();
};
this.tabs[this.x] = true;
};
-
-/**
- * CSI
- */
-
-
-/**
- * Additions
- */
-
-
-/**
- * Lesser Used
- */
-
-
-
-/**
- * CSI Ps S Scroll up Ps lines (default = 1) (SU).
- */
-Terminal.prototype.scrollUp = function(params) {
- var param = params[0] || 1;
- while (param--) {
- this.lines.splice(this.ybase + this.scrollTop, 1);
- this.lines.splice(this.ybase + this.scrollBottom, 0, this.blankLine());
- }
- // this.maxRange();
- this.updateRange(this.scrollTop);
- this.updateRange(this.scrollBottom);
-};
-
-
-/**
- * CSI Ps T Scroll down Ps lines (default = 1) (SD).
- */
-Terminal.prototype.scrollDown = function(params) {
- var param = params[0] || 1;
- while (param--) {
- this.lines.splice(this.ybase + this.scrollBottom, 1);
- this.lines.splice(this.ybase + this.scrollTop, 0, this.blankLine());
- }
- // this.maxRange();
- this.updateRange(this.scrollTop);
- this.updateRange(this.scrollBottom);
-};
-
-
-/**
- * CSI Ps ; Ps ; Ps ; Ps ; Ps T
- * Initiate highlight mouse tracking. Parameters are
- * [func;startx;starty;firstrow;lastrow]. See the section Mouse
- * Tracking.
- */
-Terminal.prototype.initMouseTracking = function(params) {
- // Relevant: DECSET 1001
-};
-
-
-/**
- * CSI > Ps; Ps T
- * Reset one or more features of the title modes to the default
- * value. Normally, "reset" disables the feature. It is possi-
- * ble to disable the ability to reset features by compiling a
- * different default for the title modes into xterm.
- * Ps = 0 -> Do not set window/icon labels using hexadecimal.
- * Ps = 1 -> Do not query window/icon labels using hexadeci-
- * mal.
- * Ps = 2 -> Do not set window/icon labels using UTF-8.
- * Ps = 3 -> Do not query window/icon labels using UTF-8.
- * (See discussion of "Title Modes").
- */
-Terminal.prototype.resetTitleModes = function(params) {
- ;
-};
-
-
-/**
- * CSI Ps Z Cursor Backward Tabulation Ps tab stops (default = 1) (CBT).
- */
-Terminal.prototype.cursorBackwardTab = function(params) {
- var param = params[0] || 1;
- while (param--) {
- this.x = this.prevStop();
- }
-};
-
-
-/**
- * CSI Ps b Repeat the preceding graphic character Ps times (REP).
- */
-Terminal.prototype.repeatPrecedingCharacter = function(params) {
- var param = params[0] || 1
- , line = this.lines.get(this.ybase + this.y)
- , ch = line[this.x - 1] || [this.defAttr, ' ', 1];
-
- while (param--) line[this.x++] = ch;
-};
-
-
-/**
- * CSI Ps g Tab Clear (TBC).
- * Ps = 0 -> Clear Current Column (default).
- * Ps = 3 -> Clear All.
- * Potentially:
- * Ps = 2 -> Clear Stops on Line.
- * http://vt100.net/annarbor/aaa-ug/section6.html
- */
-Terminal.prototype.tabClear = function(params) {
- var param = params[0];
- if (param <= 0) {
- delete this.tabs[this.x];
- } else if (param === 3) {
- this.tabs = {};
- }
-};
-
-
-/**
- * CSI Pm i Media Copy (MC).
- * Ps = 0 -> Print screen (default).
- * Ps = 4 -> Turn off printer controller mode.
- * Ps = 5 -> Turn on printer controller mode.
- * CSI ? Pm i
- * Media Copy (MC, DEC-specific).
- * Ps = 1 -> Print line containing cursor.
- * Ps = 4 -> Turn off autoprint mode.
- * Ps = 5 -> Turn on autoprint mode.
- * Ps = 1 0 -> Print composed display, ignores DECPEX.
- * Ps = 1 1 -> Print all pages.
- */
-Terminal.prototype.mediaCopy = function(params) {
- ;
-};
-
-
-/**
- * CSI > Ps; Ps m
- * Set or reset resource-values used by xterm to decide whether
- * to construct escape sequences holding information about the
- * modifiers pressed with a given key. The first parameter iden-
- * tifies the resource to set/reset. The second parameter is the
- * value to assign to the resource. If the second parameter is
- * omitted, the resource is reset to its initial value.
- * Ps = 1 -> modifyCursorKeys.
- * Ps = 2 -> modifyFunctionKeys.
- * Ps = 4 -> modifyOtherKeys.
- * If no parameters are given, all resources are reset to their
- * initial values.
- */
-Terminal.prototype.setResources = function(params) {
- ;
-};
-
-
-/**
- * CSI > Ps n
- * Disable modifiers which may be enabled via the CSI > Ps; Ps m
- * sequence. This corresponds to a resource value of "-1", which
- * cannot be set with the other sequence. The parameter identi-
- * fies the resource to be disabled:
- * Ps = 1 -> modifyCursorKeys.
- * Ps = 2 -> modifyFunctionKeys.
- * Ps = 4 -> modifyOtherKeys.
- * If the parameter is omitted, modifyFunctionKeys is disabled.
- * When modifyFunctionKeys is disabled, xterm uses the modifier
- * keys to make an extended sequence of functions rather than
- * adding a parameter to each function key to denote the modi-
- * fiers.
- */
-Terminal.prototype.disableModifiers = function(params) {
- ;
-};
-
-
-/**
- * CSI > Ps p
- * Set resource value pointerMode. This is used by xterm to
- * decide whether to hide the pointer cursor as the user types.
- * Valid values for the parameter:
- * Ps = 0 -> never hide the pointer.
- * Ps = 1 -> hide if the mouse tracking mode is not enabled.
- * Ps = 2 -> always hide the pointer. If no parameter is
- * given, xterm uses the default, which is 1 .
- */
-Terminal.prototype.setPointerMode = function(params) {
- ;
-};
-
-
-/**
- * CSI ! p Soft terminal reset (DECSTR).
- * http://vt100.net/docs/vt220-rm/table4-10.html
- */
-Terminal.prototype.softReset = function(params) {
- this.cursorHidden = false;
- this.insertMode = false;
- this.originMode = false;
- this.wraparoundMode = false; // autowrap
- this.applicationKeypad = false; // ?
- this.viewport.syncScrollArea();
- this.applicationCursor = false;
- this.scrollTop = 0;
- this.scrollBottom = this.rows - 1;
- this.curAttr = this.defAttr;
- this.x = this.y = 0; // ?
- this.charset = null;
- this.glevel = 0; // ??
- this.charsets = [null]; // ??
-};
-
-
-/**
- * CSI Ps$ p
- * Request ANSI mode (DECRQM). For VT300 and up, reply is
- * CSI Ps; Pm$ y
- * where Ps is the mode number as in RM, and Pm is the mode
- * value:
- * 0 - not recognized
- * 1 - set
- * 2 - reset
- * 3 - permanently set
- * 4 - permanently reset
- */
-Terminal.prototype.requestAnsiMode = function(params) {
- ;
-};
-
-
-/**
- * CSI ? Ps$ p
- * Request DEC private mode (DECRQM). For VT300 and up, reply is
- * CSI ? Ps; Pm$ p
- * where Ps is the mode number as in DECSET, Pm is the mode value
- * as in the ANSI DECRQM.
- */
-Terminal.prototype.requestPrivateMode = function(params) {
- ;
-};
-
-
-/**
- * CSI Ps ; Ps " p
- * Set conformance level (DECSCL). Valid values for the first
- * parameter:
- * Ps = 6 1 -> VT100.
- * Ps = 6 2 -> VT200.
- * Ps = 6 3 -> VT300.
- * Valid values for the second parameter:
- * Ps = 0 -> 8-bit controls.
- * Ps = 1 -> 7-bit controls (always set for VT100).
- * Ps = 2 -> 8-bit controls.
- */
-Terminal.prototype.setConformanceLevel = function(params) {
- ;
-};
-
-
-/**
- * CSI Ps q Load LEDs (DECLL).
- * Ps = 0 -> Clear all LEDS (default).
- * Ps = 1 -> Light Num Lock.
- * Ps = 2 -> Light Caps Lock.
- * Ps = 3 -> Light Scroll Lock.
- * Ps = 2 1 -> Extinguish Num Lock.
- * Ps = 2 2 -> Extinguish Caps Lock.
- * Ps = 2 3 -> Extinguish Scroll Lock.
- */
-Terminal.prototype.loadLEDs = function(params) {
- ;
-};
-
-
-/**
- * CSI Ps SP q
- * Set cursor style (DECSCUSR, VT520).
- * Ps = 0 -> blinking block.
- * Ps = 1 -> blinking block (default).
- * Ps = 2 -> steady block.
- * Ps = 3 -> blinking underline.
- * Ps = 4 -> steady underline.
- */
-Terminal.prototype.setCursorStyle = function(params) {
- ;
-};
-
-
-/**
- * CSI Ps " q
- * Select character protection attribute (DECSCA). Valid values
- * for the parameter:
- * Ps = 0 -> DECSED and DECSEL can erase (default).
- * Ps = 1 -> DECSED and DECSEL cannot erase.
- * Ps = 2 -> DECSED and DECSEL can erase.
- */
-Terminal.prototype.setCharProtectionAttr = function(params) {
- ;
-};
-
-
-/**
- * CSI ? Pm r
- * Restore DEC Private Mode Values. The value of Ps previously
- * saved is restored. Ps values are the same as for DECSET.
- */
-Terminal.prototype.restorePrivateValues = function(params) {
- ;
-};
-
-
-/**
- * CSI Pt; Pl; Pb; Pr; Ps$ r
- * Change Attributes in Rectangular Area (DECCARA), VT400 and up.
- * Pt; Pl; Pb; Pr denotes the rectangle.
- * Ps denotes the SGR attributes to change: 0, 1, 4, 5, 7.
- * NOTE: xterm doesn't enable this code by default.
- */
-Terminal.prototype.setAttrInRectangle = function(params) {
- var t = params[0]
- , l = params[1]
- , b = params[2]
- , r = params[3]
- , attr = params[4];
-
- var line
- , i;
-
- for (; t < b + 1; t++) {
- line = this.lines.get(this.ybase + t);
- for (i = l; i < r; i++) {
- line[i] = [attr, line[i][1]];
- }
- }
-
- // this.maxRange();
- this.updateRange(params[0]);
- this.updateRange(params[2]);
-};
-
-
-/**
- * CSI Pc; Pt; Pl; Pb; Pr$ x
- * Fill Rectangular Area (DECFRA), VT420 and up.
- * Pc is the character to use.
- * Pt; Pl; Pb; Pr denotes the rectangle.
- * NOTE: xterm doesn't enable this code by default.
- */
-Terminal.prototype.fillRectangle = function(params) {
- var ch = params[0]
- , t = params[1]
- , l = params[2]
- , b = params[3]
- , r = params[4];
-
- var line
- , i;
-
- for (; t < b + 1; t++) {
- line = this.lines.get(this.ybase + t);
- for (i = l; i < r; i++) {
- line[i] = [line[i][0], String.fromCharCode(ch)];
- }
- }
-
- // this.maxRange();
- this.updateRange(params[1]);
- this.updateRange(params[3]);
-};
-
-
-/**
- * CSI Ps ; Pu ' z
- * Enable Locator Reporting (DECELR).
- * Valid values for the first parameter:
- * Ps = 0 -> Locator disabled (default).
- * Ps = 1 -> Locator enabled.
- * Ps = 2 -> Locator enabled for one report, then disabled.
- * The second parameter specifies the coordinate unit for locator
- * reports.
- * Valid values for the second parameter:
- * Pu = 0 <- or omitted -> default to character cells.
- * Pu = 1 <- device physical pixels.
- * Pu = 2 <- character cells.
- */
-Terminal.prototype.enableLocatorReporting = function(params) {
- var val = params[0] > 0;
- //this.mouseEvents = val;
- //this.decLocator = val;
-};
-
-
-/**
- * CSI Pt; Pl; Pb; Pr$ z
- * Erase Rectangular Area (DECERA), VT400 and up.
- * Pt; Pl; Pb; Pr denotes the rectangle.
- * NOTE: xterm doesn't enable this code by default.
- */
-Terminal.prototype.eraseRectangle = function(params) {
- var t = params[0]
- , l = params[1]
- , b = params[2]
- , r = params[3];
-
- var line
- , i
- , ch;
-
- ch = [this.eraseAttr(), ' ', 1]; // xterm?
-
- for (; t < b + 1; t++) {
- line = this.lines.get(this.ybase + t);
- for (i = l; i < r; i++) {
- line[i] = ch;
- }
- }
-
- // this.maxRange();
- this.updateRange(params[0]);
- this.updateRange(params[2]);
-};
-
-
-/**
- * CSI P m SP }
- * Insert P s Column(s) (default = 1) (DECIC), VT420 and up.
- * NOTE: xterm doesn't enable this code by default.
- */
-Terminal.prototype.insertColumns = function() {
- var param = params[0]
- , l = this.ybase + this.rows
- , ch = [this.eraseAttr(), ' ', 1] // xterm?
- , i;
-
- while (param--) {
- for (i = this.ybase; i < l; i++) {
- this.lines.get(i).splice(this.x + 1, 0, ch);
- this.lines.get(i).pop();
- }
- }
-
- this.maxRange();
-};
-
-
-/**
- * CSI P m SP ~
- * Delete P s Column(s) (default = 1) (DECDC), VT420 and up
- * NOTE: xterm doesn't enable this code by default.
- */
-Terminal.prototype.deleteColumns = function() {
- var param = params[0]
- , l = this.ybase + this.rows
- , ch = [this.eraseAttr(), ' ', 1] // xterm?
- , i;
-
- while (param--) {
- for (i = this.ybase; i < l; i++) {
- this.lines.get(i).splice(this.x, 1);
- this.lines.get(i).push(ch);
- }
- }
-
- this.maxRange();
-};
-
/**
* Helpers
*/
child.prototype = new f;
}
-// if bold is broken, we can't
-// use it in the terminal.
-function isBoldBroken(document) {
- var body = document.getElementsByTagName('body')[0];
- var el = document.createElement('span');
- el.innerHTML = 'hello world';
- body.appendChild(el);
- var w1 = el.scrollWidth;
- el.style.fontWeight = 'bold';
- var w2 = el.scrollWidth;
- body.removeChild(el);
- return w1 !== w2;
-}
-
function indexOf(obj, el) {
var i = obj.length;
while (i--) {
}
}
+function wasMondifierKeyOnlyEvent(ev) {
+ return ev.keyCode === 16 || // Shift
+ ev.keyCode === 17 || // Ctrl
+ ev.keyCode === 18; // Alt
+}
+
function keys(obj) {
if (Object.keys) return Object.keys(obj);
var key, keys = [];
Terminal.EventEmitter = EventEmitter;
Terminal.inherits = inherits;
+// Expose for Phantom.JS tests
+Terminal.CharMeasure = CharMeasure;
+
/**
* Adds an event listener to the terminal.
*