Merge remote-tracking branch 'upstream/master' into 441_windows_support
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* C0 control codes
|
||||
* See = https://en.wikipedia.org/wiki/C0_and_C1_control_codes
|
||||
*/
|
||||
export namespace C0 {
|
||||
/** Null (Caret = ^@, C = \0) */
|
||||
export const NUL = '\x00';
|
||||
/** Start of Heading (Caret = ^A) */
|
||||
export const SOH = '\x01';
|
||||
/** Start of Text (Caret = ^B) */
|
||||
export const STX = '\x02';
|
||||
/** End of Text (Caret = ^C) */
|
||||
export const ETX = '\x03';
|
||||
/** End of Transmission (Caret = ^D) */
|
||||
export const EOT = '\x04';
|
||||
/** Enquiry (Caret = ^E) */
|
||||
export const ENQ = '\x05';
|
||||
/** Acknowledge (Caret = ^F) */
|
||||
export const ACK = '\x06';
|
||||
/** Bell (Caret = ^G, C = \a) */
|
||||
export const BEL = '\x07';
|
||||
/** Backspace (Caret = ^H, C = \b) */
|
||||
export const BS = '\x08';
|
||||
/** Character Tabulation, Horizontal Tabulation (Caret = ^I, C = \t) */
|
||||
export const HT = '\x09';
|
||||
/** Line Feed (Caret = ^J, C = \n) */
|
||||
export const LF = '\x0a';
|
||||
/** Line Tabulation, Vertical Tabulation (Caret = ^K, C = \v) */
|
||||
export const VT = '\x0b';
|
||||
/** Form Feed (Caret = ^L, C = \f) */
|
||||
export const FF = '\x0c';
|
||||
/** Carriage Return (Caret = ^M, C = \r) */
|
||||
export const CR = '\x0d';
|
||||
/** Shift Out (Caret = ^N) */
|
||||
export const SO = '\x0e';
|
||||
/** Shift In (Caret = ^O) */
|
||||
export const SI = '\x0f';
|
||||
/** Data Link Escape (Caret = ^P) */
|
||||
export const DLE = '\x10';
|
||||
/** Device Control One (XON) (Caret = ^Q) */
|
||||
export const DC1 = '\x11';
|
||||
/** Device Control Two (Caret = ^R) */
|
||||
export const DC2 = '\x12';
|
||||
/** Device Control Three (XOFF) (Caret = ^S) */
|
||||
export const DC3 = '\x13';
|
||||
/** Device Control Four (Caret = ^T) */
|
||||
export const DC4 = '\x14';
|
||||
/** Negative Acknowledge (Caret = ^U) */
|
||||
export const NAK = '\x15';
|
||||
/** Synchronous Idle (Caret = ^V) */
|
||||
export const SYN = '\x16';
|
||||
/** End of Transmission Block (Caret = ^W) */
|
||||
export const ETB = '\x17';
|
||||
/** Cancel (Caret = ^X) */
|
||||
export const CAN = '\x18';
|
||||
/** End of Medium (Caret = ^Y) */
|
||||
export const EM = '\x19';
|
||||
/** Substitute (Caret = ^Z) */
|
||||
export const SUB = '\x1a';
|
||||
/** Escape (Caret = ^[, C = \e) */
|
||||
export const ESC = '\x1b';
|
||||
/** File Separator (Caret = ^\) */
|
||||
export const FS = '\x1c';
|
||||
/** Group Separator (Caret = ^]) */
|
||||
export const GS = '\x1d';
|
||||
/** Record Separator (Caret = ^^) */
|
||||
export const RS = '\x1e';
|
||||
/** Unit Separator (Caret = ^_) */
|
||||
export const US = '\x1f';
|
||||
/** Space */
|
||||
export const SP = '\x20';
|
||||
/** Delete (Caret = ^?) */
|
||||
export const DEL = '\x7f';
|
||||
};
|
||||
+3
-1
@@ -11,7 +11,9 @@ export class EventEmitter {
|
||||
private _events: {[type: string]: ListenerType[]};
|
||||
|
||||
constructor() {
|
||||
this._events = {};
|
||||
// Restore the previous events if available, this will happen if the
|
||||
// constructor is called multiple times on the same object (terminal reset).
|
||||
this._events = this._events || {};
|
||||
}
|
||||
|
||||
public on(type, listener): void {
|
||||
|
||||
+10
-16
@@ -2,11 +2,11 @@ import { assert } from 'chai';
|
||||
import { Viewport } from './Viewport';
|
||||
|
||||
describe('Viewport', () => {
|
||||
var terminal;
|
||||
var viewportElement;
|
||||
var charMeasureElement;
|
||||
var viewport;
|
||||
var scrollAreaElement;
|
||||
let terminal;
|
||||
let viewportElement;
|
||||
let charMeasure;
|
||||
let viewport;
|
||||
let scrollAreaElement;
|
||||
|
||||
const CHARACTER_HEIGHT = 10;
|
||||
|
||||
@@ -34,21 +34,17 @@ describe('Viewport', () => {
|
||||
height: 0
|
||||
}
|
||||
};
|
||||
charMeasureElement = {
|
||||
getBoundingClientRect: () => {
|
||||
return { width: null, height: CHARACTER_HEIGHT };
|
||||
}
|
||||
charMeasure = {
|
||||
height: CHARACTER_HEIGHT
|
||||
};
|
||||
viewport = new Viewport(terminal, viewportElement, scrollAreaElement, charMeasureElement);
|
||||
viewport = new Viewport(terminal, viewportElement, scrollAreaElement, charMeasure);
|
||||
});
|
||||
|
||||
describe('refresh', () => {
|
||||
it('should set the line-height of the terminal', () => {
|
||||
assert.equal(viewportElement.style.lineHeight, CHARACTER_HEIGHT + 'px');
|
||||
assert.equal(terminal.rowContainer.style.lineHeight, CHARACTER_HEIGHT + 'px');
|
||||
charMeasureElement.getBoundingClientRect = () => {
|
||||
return { width: null, height: 1 };
|
||||
};
|
||||
charMeasure.height = 1;
|
||||
viewport.refresh();
|
||||
assert.equal(viewportElement.style.lineHeight, '1px');
|
||||
assert.equal(terminal.rowContainer.style.lineHeight, '1px');
|
||||
@@ -59,9 +55,7 @@ describe('Viewport', () => {
|
||||
terminal.rows = 1;
|
||||
viewport.refresh();
|
||||
assert.equal(viewportElement.style.height, 1 * CHARACTER_HEIGHT + 'px');
|
||||
charMeasureElement.getBoundingClientRect = () => {
|
||||
return { width: null, height: 20 };
|
||||
};
|
||||
charMeasure.height = 20;
|
||||
viewport.refresh();
|
||||
assert.equal(viewportElement.style.height, 20 + 'px');
|
||||
});
|
||||
|
||||
+17
-18
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
import { ITerminal } from './Interfaces';
|
||||
import { CharMeasure } from './utils/CharMeasure';
|
||||
|
||||
/**
|
||||
* Represents the viewport of a terminal, the visible area within the larger buffer of output.
|
||||
@@ -24,7 +25,7 @@ export class Viewport {
|
||||
private terminal: ITerminal,
|
||||
private viewportElement: HTMLElement,
|
||||
private scrollArea: HTMLElement,
|
||||
private charMeasureElement: HTMLElement
|
||||
private charMeasure: CharMeasure
|
||||
) {
|
||||
this.currentRowHeight = 0;
|
||||
this.lastRecordedBufferLength = 0;
|
||||
@@ -43,21 +44,20 @@ export class Viewport {
|
||||
* @param charSize A character size measurement bounding rect object, if it doesn't exist it will
|
||||
* be created.
|
||||
*/
|
||||
private refresh(charSize?: ClientRect): void {
|
||||
var size = charSize || this.charMeasureElement.getBoundingClientRect();
|
||||
if (size.height > 0) {
|
||||
var rowHeightChanged = size.height !== this.currentRowHeight;
|
||||
private refresh(): void {
|
||||
if (this.charMeasure.height > 0) {
|
||||
const rowHeightChanged = this.charMeasure.height !== this.currentRowHeight;
|
||||
if (rowHeightChanged) {
|
||||
this.currentRowHeight = size.height;
|
||||
this.viewportElement.style.lineHeight = size.height + 'px';
|
||||
this.terminal.rowContainer.style.lineHeight = size.height + 'px';
|
||||
this.currentRowHeight = this.charMeasure.height;
|
||||
this.viewportElement.style.lineHeight = this.charMeasure.height + 'px';
|
||||
this.terminal.rowContainer.style.lineHeight = this.charMeasure.height + 'px';
|
||||
}
|
||||
var viewportHeightChanged = this.lastRecordedViewportHeight !== this.terminal.rows;
|
||||
const viewportHeightChanged = this.lastRecordedViewportHeight !== this.terminal.rows;
|
||||
if (rowHeightChanged || viewportHeightChanged) {
|
||||
this.lastRecordedViewportHeight = this.terminal.rows;
|
||||
this.viewportElement.style.height = size.height * this.terminal.rows + 'px';
|
||||
this.viewportElement.style.height = this.charMeasure.height * this.terminal.rows + 'px';
|
||||
}
|
||||
this.scrollArea.style.height = (size.height * this.lastRecordedBufferLength) + 'px';
|
||||
this.scrollArea.style.height = (this.charMeasure.height * this.lastRecordedBufferLength) + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,14 +74,13 @@ export class Viewport {
|
||||
this.refresh();
|
||||
} else {
|
||||
// If size has changed, refresh viewport
|
||||
var size = this.charMeasureElement.getBoundingClientRect();
|
||||
if (size.height !== this.currentRowHeight) {
|
||||
this.refresh(size);
|
||||
if (this.charMeasure.height !== this.currentRowHeight) {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
// Sync scrollTop
|
||||
var scrollTop = this.terminal.ydisp * this.currentRowHeight;
|
||||
const scrollTop = this.terminal.ydisp * this.currentRowHeight;
|
||||
if (this.viewportElement.scrollTop !== scrollTop) {
|
||||
this.viewportElement.scrollTop = scrollTop;
|
||||
}
|
||||
@@ -93,8 +92,8 @@ export class Viewport {
|
||||
* @param ev The scroll event.
|
||||
*/
|
||||
private onScroll(ev: Event) {
|
||||
var newRow = Math.round(this.viewportElement.scrollTop / this.currentRowHeight);
|
||||
var diff = newRow - this.terminal.ydisp;
|
||||
const newRow = Math.round(this.viewportElement.scrollTop / this.currentRowHeight);
|
||||
const diff = newRow - this.terminal.ydisp;
|
||||
this.terminal.scrollDisp(diff, true);
|
||||
}
|
||||
|
||||
@@ -110,7 +109,7 @@ export class Viewport {
|
||||
return;
|
||||
}
|
||||
// Fallback to WheelEvent.DOM_DELTA_PIXEL
|
||||
var multiplier = 1;
|
||||
let multiplier = 1;
|
||||
if (ev.deltaMode === WheelEvent.DOM_DELTA_LINE) {
|
||||
multiplier = this.currentRowHeight;
|
||||
} else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) {
|
||||
|
||||
@@ -92,7 +92,11 @@ describe('xterm output comparison', function() {
|
||||
var from_pty = pty_write_read(in_file);
|
||||
// uncomment this to get log from terminal
|
||||
//console.log = function(){};
|
||||
xterm.write(from_pty);
|
||||
|
||||
// Perform a synchronous .write(data)
|
||||
xterm.writeBuffer.push(from_pty);
|
||||
xterm.innerWrite();
|
||||
|
||||
var from_emulator = terminalToString(xterm);
|
||||
console.log = CONSOLE_LOG;
|
||||
var expected = fs.readFileSync(filename.split('.')[0] + '.text', 'utf8');
|
||||
|
||||
@@ -14,6 +14,15 @@ describe('xterm.js', function() {
|
||||
xterm.compositionHelper = {
|
||||
keydown: function(){ return true; }
|
||||
};
|
||||
// Force synchronous refreshes
|
||||
xterm.queueRefresh = function(start, end) {
|
||||
xterm.refresh(start, end);
|
||||
};
|
||||
// Force synchronous writes
|
||||
xterm.write = function(data) {
|
||||
xterm.writeBuffer.push(data);
|
||||
xterm.innerWrite();
|
||||
};
|
||||
});
|
||||
|
||||
describe('getOption', function() {
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
/**
|
||||
* Attributes and methods to help with identifying the current browser and platform.
|
||||
* @module xterm/utils/Browser
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { contains } from './Generic.js';
|
||||
|
||||
let isNode = (typeof navigator == 'undefined') ? true : false;
|
||||
let userAgent = (isNode) ? 'node' : navigator.userAgent;
|
||||
let platform = (isNode) ? 'node' : navigator.platform;
|
||||
|
||||
export let isFirefox = !!~userAgent.indexOf('Firefox');
|
||||
export let isMSIE = !!~userAgent.indexOf('MSIE') || !!~userAgent.indexOf('Trident');
|
||||
|
||||
// Find the users platform. We use this to interpret the meta key
|
||||
// and ISO third level shifts.
|
||||
// http://stackoverflow.com/q/19877924/577598
|
||||
export let isMac = contains(['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'], platform);
|
||||
export let isIpad = platform === 'iPad';
|
||||
export let isIphone = platform === 'iPhone';
|
||||
export let isMSWindows = contains(['Windows', 'Win16', 'Win32', 'WinCE'], platform);
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Attributes and methods to help with identifying the current browser and platform.
|
||||
* @module xterm/utils/Browser
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { contains } from './Generic';
|
||||
|
||||
const isNode = (typeof navigator === 'undefined') ? true : false;
|
||||
const userAgent = (isNode) ? 'node' : navigator.userAgent;
|
||||
const platform = (isNode) ? 'node' : navigator.platform;
|
||||
|
||||
export const isFirefox = !!~userAgent.indexOf('Firefox');
|
||||
export const isMSIE = !!~userAgent.indexOf('MSIE') || !!~userAgent.indexOf('Trident');
|
||||
|
||||
// Find the users platform. We use this to interpret the meta key
|
||||
// and ISO third level shifts.
|
||||
// http://stackoverflow.com/q/19877924/577598
|
||||
export const isMac = contains(['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'], platform);
|
||||
export const isIpad = platform === 'iPad';
|
||||
export const isIphone = platform === 'iPhone';
|
||||
export const isMSWindows = contains(['Windows', 'Win16', 'Win32', 'WinCE'], platform);
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @module xterm/utils/CharMeasure
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { EventEmitter } from '../EventEmitter.js';
|
||||
|
||||
/**
|
||||
* Utility class that measures the size of a character.
|
||||
*/
|
||||
export class CharMeasure extends EventEmitter {
|
||||
private _parentElement: HTMLElement;
|
||||
private _measureElement: HTMLElement;
|
||||
private _width: number;
|
||||
private _height: number;
|
||||
|
||||
constructor(parentElement: HTMLElement) {
|
||||
super();
|
||||
this._parentElement = parentElement;
|
||||
}
|
||||
|
||||
public get width(): number {
|
||||
return this._width;
|
||||
}
|
||||
|
||||
public get height(): number {
|
||||
return this._height;
|
||||
}
|
||||
|
||||
public measure(): void {
|
||||
if (!this._measureElement) {
|
||||
this._measureElement = document.createElement('span');
|
||||
this._measureElement.style.position = 'absolute';
|
||||
this._measureElement.style.top = '0';
|
||||
this._measureElement.style.left = '-9999em';
|
||||
this._measureElement.textContent = 'W';
|
||||
this._parentElement.appendChild(this._measureElement);
|
||||
// Perform _doMeasure async if the element was just attached as sometimes
|
||||
// getBoundingClientRect does not return accurate values without this.
|
||||
setTimeout(() => this._doMeasure(), 0);
|
||||
} else {
|
||||
this._doMeasure();
|
||||
}
|
||||
}
|
||||
|
||||
private _doMeasure(): void {
|
||||
const oldWidth = this._width;
|
||||
const oldHeight = this._height;
|
||||
const geometry = this._measureElement.getBoundingClientRect();
|
||||
|
||||
if (this._width !== geometry.width || this._height !== geometry.height) {
|
||||
this._width = geometry.width;
|
||||
this._height = geometry.height;
|
||||
this.emit('charsizechanged');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,6 @@
|
||||
* @param {Array} array The array to search for the given element.
|
||||
* @param {Object} el The element to look for into the array
|
||||
*/
|
||||
export let contains = function(arr, el) {
|
||||
export function contains(arr: any[], el: any) {
|
||||
return arr.indexOf(el) >= 0;
|
||||
};
|
||||
@@ -116,6 +116,10 @@
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.terminal .xterm-wide-char {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.terminal .xterm-rows {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
|
||||
+1218
-1066
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user