Merge branch 'master' into faster_wcwidth
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* @license MIT
|
||||
*/
|
||||
import { assert } from 'chai';
|
||||
import { ITerminal } from './Interfaces';
|
||||
import { Buffer } from './Buffer';
|
||||
import { CircularList } from './utils/CircularList';
|
||||
|
||||
describe('Buffer', () => {
|
||||
let terminal: ITerminal;
|
||||
let buffer: Buffer;
|
||||
|
||||
beforeEach(() => {
|
||||
terminal = <any>{
|
||||
cols: 80,
|
||||
rows: 24,
|
||||
scrollback: 1000
|
||||
};
|
||||
buffer = new Buffer(terminal);
|
||||
});
|
||||
|
||||
describe('constructor', () => {
|
||||
it('should create a CircularList with max length equal to scrollback, for its lines', () => {
|
||||
assert.instanceOf(buffer.lines, CircularList);
|
||||
assert.equal(buffer.lines.maxLength, terminal.scrollback);
|
||||
});
|
||||
it('should set the Buffer\'s scrollBottom value equal to the terminal\'s rows -1', () => {
|
||||
assert.equal(buffer.scrollBottom, terminal.rows - 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { ITerminal } from './Interfaces';
|
||||
import { CircularList } from './utils/CircularList';
|
||||
|
||||
/**
|
||||
* This class represents a terminal buffer (an internal state of the terminal), where the
|
||||
* following information is stored (in high-level):
|
||||
* - text content of this particular buffer
|
||||
* - cursor position
|
||||
* - scroll position
|
||||
*/
|
||||
export class Buffer {
|
||||
public lines: CircularList<[number, string, number][]>;
|
||||
|
||||
/**
|
||||
* Create a new Buffer.
|
||||
* @param {Terminal} terminal - The terminal the Buffer will belong to
|
||||
* @param {number} ydisp - The scroll position of the Buffer in the viewport
|
||||
* @param {number} ybase - The scroll position of the y cursor (ybase + y = the y position within the Buffer)
|
||||
* @param {number} y - The cursor's y position after ybase
|
||||
* @param {number} x - The cursor's x position after ybase
|
||||
*/
|
||||
constructor(
|
||||
private terminal: ITerminal,
|
||||
public ydisp: number = 0,
|
||||
public ybase: number = 0,
|
||||
public y: number = 0,
|
||||
public x: number = 0,
|
||||
public scrollBottom: number = 0,
|
||||
public scrollTop: number = 0,
|
||||
public tabs: any = {},
|
||||
) {
|
||||
this.lines = new CircularList<[number, string, number][]>(this.terminal.scrollback);
|
||||
this.scrollBottom = this.terminal.rows - 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @license MIT
|
||||
*/
|
||||
import { assert } from 'chai';
|
||||
import { ITerminal } from './Interfaces';
|
||||
import { BufferSet } from './BufferSet';
|
||||
import { Buffer } from './Buffer';
|
||||
|
||||
describe('BufferSet', () => {
|
||||
let terminal: ITerminal;
|
||||
let bufferSet: BufferSet;
|
||||
|
||||
beforeEach(() => {
|
||||
terminal = <any>{
|
||||
cols: 80,
|
||||
rows: 24,
|
||||
scrollback: 1000
|
||||
};
|
||||
bufferSet = new BufferSet(terminal);
|
||||
});
|
||||
|
||||
describe('constructor', () => {
|
||||
it('should create two different buffers: alt and normal', () => {
|
||||
assert.instanceOf(bufferSet.normal, Buffer);
|
||||
assert.instanceOf(bufferSet.alt, Buffer);
|
||||
assert.notEqual(bufferSet.normal, bufferSet.alt);
|
||||
});
|
||||
});
|
||||
|
||||
describe('activateNormalBuffer', () => {
|
||||
beforeEach(() => {
|
||||
bufferSet.activateNormalBuffer();
|
||||
});
|
||||
|
||||
it('should set the normal buffer as the currently active buffer', () => {
|
||||
assert.equal(bufferSet.active, bufferSet.normal);
|
||||
});
|
||||
});
|
||||
|
||||
describe('activateAltBuffer', () => {
|
||||
beforeEach(() => {
|
||||
bufferSet.activateAltBuffer();
|
||||
});
|
||||
|
||||
it('should set the alt buffer as the currently active buffer', () => {
|
||||
assert.equal(bufferSet.active, bufferSet.alt);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { ITerminal, IBufferSet } from './Interfaces';
|
||||
import { Buffer } from './Buffer';
|
||||
import { EventEmitter } from './EventEmitter';
|
||||
|
||||
/**
|
||||
* The BufferSet represents the set of two buffers used by xterm terminals (normal and alt) and
|
||||
* provides also utilities for working with them.
|
||||
*/
|
||||
export class BufferSet extends EventEmitter implements IBufferSet {
|
||||
private _normal: Buffer;
|
||||
private _alt: Buffer;
|
||||
private _activeBuffer: Buffer;
|
||||
|
||||
/**
|
||||
* Create a new BufferSet for the given terminal.
|
||||
* @param {Terminal} terminal - The terminal the BufferSet will belong to
|
||||
*/
|
||||
constructor(private _terminal: ITerminal) {
|
||||
super();
|
||||
this._normal = new Buffer(this._terminal);
|
||||
this._alt = new Buffer(this._terminal);
|
||||
this._activeBuffer = this._normal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the alt Buffer of the BufferSet
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
public get alt(): Buffer {
|
||||
return this._alt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the normal Buffer of the BufferSet
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
public get active(): Buffer {
|
||||
return this._activeBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently active Buffer of the BufferSet
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
public get normal(): Buffer {
|
||||
return this._normal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the normal Buffer of the BufferSet as its currently active Buffer
|
||||
*/
|
||||
public activateNormalBuffer(): void {
|
||||
this._activeBuffer = this._normal;
|
||||
this.emit('activate', this._normal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the alt Buffer of the BufferSet as its currently active Buffer
|
||||
*/
|
||||
public activateAltBuffer(): void {
|
||||
this._activeBuffer = this._alt;
|
||||
this.emit('activate', this._alt);
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -2,12 +2,14 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IEventEmitter } from './Interfaces';
|
||||
|
||||
interface ListenerType {
|
||||
(): void;
|
||||
listener?: () => void;
|
||||
};
|
||||
|
||||
export class EventEmitter {
|
||||
export class EventEmitter implements IEventEmitter {
|
||||
private _events: {[type: string]: ListenerType[]};
|
||||
|
||||
constructor() {
|
||||
|
||||
+169
-197
@@ -27,49 +27,48 @@ export class InputHandler implements IInputHandler {
|
||||
char = this._terminal.charset[char];
|
||||
}
|
||||
|
||||
let row = this._terminal.y + this._terminal.ybase;
|
||||
let row = this._terminal.buffer.y + this._terminal.buffer.ybase;
|
||||
|
||||
// insert combining char in last cell
|
||||
// FIXME: needs handling after cursor jumps
|
||||
if (!ch_width && this._terminal.x) {
|
||||
if (!ch_width && this._terminal.buffer.x) {
|
||||
// dont overflow left
|
||||
if (this._terminal.lines.get(row)[this._terminal.x - 1]) {
|
||||
if (!this._terminal.lines.get(row)[this._terminal.x - 1][2]) {
|
||||
if (this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1]) {
|
||||
if (!this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][2]) {
|
||||
|
||||
// found empty cell after fullwidth, need to go 2 cells back
|
||||
if (this._terminal.lines.get(row)[this._terminal.x - 2])
|
||||
this._terminal.lines.get(row)[this._terminal.x - 2][1] += char;
|
||||
if (this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2])
|
||||
this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2][1] += char;
|
||||
|
||||
} else {
|
||||
this._terminal.lines.get(row)[this._terminal.x - 1][1] += char;
|
||||
this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][1] += char;
|
||||
}
|
||||
this._terminal.updateRange(this._terminal.y);
|
||||
this._terminal.updateRange(this._terminal.buffer.y);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// goto next line if ch would overflow
|
||||
// TODO: needs a global min terminal width of 2
|
||||
if (this._terminal.x + ch_width - 1 >= this._terminal.cols) {
|
||||
if (this._terminal.buffer.x + ch_width - 1 >= this._terminal.cols) {
|
||||
// autowrap - DECAWM
|
||||
if (this._terminal.wraparoundMode) {
|
||||
this._terminal.x = 0;
|
||||
this._terminal.y++;
|
||||
if (this._terminal.y > this._terminal.scrollBottom) {
|
||||
// Insert a new line, scroll and mark as a wrapped line
|
||||
this._terminal.y--;
|
||||
this._terminal.buffer.x = 0;
|
||||
this._terminal.buffer.y++;
|
||||
if (this._terminal.buffer.y > this._terminal.buffer.scrollBottom) {
|
||||
this._terminal.buffer.y--;
|
||||
this._terminal.scroll(true);
|
||||
} else {
|
||||
// The line already exists (eg. the initial viewport), mark it as a
|
||||
// wrapped line
|
||||
this._terminal.lines.get(this._terminal.y).isWrapped = true;
|
||||
this._terminal.buffer.lines.get(this._terminal.buffer.y).isWrapped = true;
|
||||
}
|
||||
} else {
|
||||
if (ch_width === 2) // FIXME: check for xterm behavior
|
||||
return;
|
||||
}
|
||||
}
|
||||
row = this._terminal.y + this._terminal.ybase;
|
||||
row = this._terminal.buffer.y + this._terminal.buffer.ybase;
|
||||
|
||||
// insert mode: move characters to right
|
||||
if (this._terminal.insertMode) {
|
||||
@@ -77,26 +76,26 @@ export class InputHandler implements IInputHandler {
|
||||
for (let moves = 0; moves < ch_width; ++moves) {
|
||||
// remove last cell, if it's width is 0
|
||||
// we have to adjust the second last cell as well
|
||||
const removed = this._terminal.lines.get(this._terminal.y + this._terminal.ybase).pop();
|
||||
const removed = this._terminal.buffer.lines.get(this._terminal.buffer.y + this._terminal.buffer.ybase).pop();
|
||||
if (removed[2] === 0
|
||||
&& this._terminal.lines.get(row)[this._terminal.cols - 2]
|
||||
&& this._terminal.lines.get(row)[this._terminal.cols - 2][2] === 2) {
|
||||
this._terminal.lines.get(row)[this._terminal.cols - 2] = [this._terminal.curAttr, ' ', 1];
|
||||
&& this._terminal.buffer.lines.get(row)[this._terminal.cols - 2]
|
||||
&& this._terminal.buffer.lines.get(row)[this._terminal.cols - 2][2] === 2) {
|
||||
this._terminal.buffer.lines.get(row)[this._terminal.cols - 2] = [this._terminal.curAttr, ' ', 1];
|
||||
}
|
||||
|
||||
// insert empty cell at cursor
|
||||
this._terminal.lines.get(row).splice(this._terminal.x, 0, [this._terminal.curAttr, ' ', 1]);
|
||||
this._terminal.buffer.lines.get(row).splice(this._terminal.buffer.x, 0, [this._terminal.curAttr, ' ', 1]);
|
||||
}
|
||||
}
|
||||
|
||||
this._terminal.lines.get(row)[this._terminal.x] = [this._terminal.curAttr, char, ch_width];
|
||||
this._terminal.x++;
|
||||
this._terminal.updateRange(this._terminal.y);
|
||||
this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, char, ch_width];
|
||||
this._terminal.buffer.x++;
|
||||
this._terminal.updateRange(this._terminal.buffer.y);
|
||||
|
||||
// fullwidth char - set next cell width to zero and advance cursor
|
||||
if (ch_width === 2) {
|
||||
this._terminal.lines.get(row)[this._terminal.x] = [this._terminal.curAttr, '', 0];
|
||||
this._terminal.x++;
|
||||
this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, '', 0];
|
||||
this._terminal.buffer.x++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,16 +121,16 @@ export class InputHandler implements IInputHandler {
|
||||
*/
|
||||
public lineFeed(): void {
|
||||
if (this._terminal.convertEol) {
|
||||
this._terminal.x = 0;
|
||||
this._terminal.buffer.x = 0;
|
||||
}
|
||||
this._terminal.y++;
|
||||
if (this._terminal.y > this._terminal.scrollBottom) {
|
||||
this._terminal.y--;
|
||||
this._terminal.buffer.y++;
|
||||
if (this._terminal.buffer.y > this._terminal.buffer.scrollBottom) {
|
||||
this._terminal.buffer.y--;
|
||||
this._terminal.scroll();
|
||||
}
|
||||
// If the end of the line is hit, prevent this action from wrapping around to the next line.
|
||||
if (this._terminal.x >= this._terminal.cols) {
|
||||
this._terminal.x--;
|
||||
if (this._terminal.buffer.x >= this._terminal.cols) {
|
||||
this._terminal.buffer.x--;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +139,7 @@ export class InputHandler implements IInputHandler {
|
||||
* Carriage Return (Ctrl-M).
|
||||
*/
|
||||
public carriageReturn(): void {
|
||||
this._terminal.x = 0;
|
||||
this._terminal.buffer.x = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,8 +147,8 @@ export class InputHandler implements IInputHandler {
|
||||
* Backspace (Ctrl-H).
|
||||
*/
|
||||
public backspace(): void {
|
||||
if (this._terminal.x > 0) {
|
||||
this._terminal.x--;
|
||||
if (this._terminal.buffer.x > 0) {
|
||||
this._terminal.buffer.x--;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,7 +157,7 @@ export class InputHandler implements IInputHandler {
|
||||
* Horizontal Tab (HT) (Ctrl-I).
|
||||
*/
|
||||
public tab(): void {
|
||||
this._terminal.x = this._terminal.nextStop();
|
||||
this._terminal.buffer.x = this._terminal.nextStop();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,13 +188,13 @@ export class InputHandler implements IInputHandler {
|
||||
param = params[0];
|
||||
if (param < 1) param = 1;
|
||||
|
||||
row = this._terminal.y + this._terminal.ybase;
|
||||
j = this._terminal.x;
|
||||
row = this._terminal.buffer.y + this._terminal.buffer.ybase;
|
||||
j = this._terminal.buffer.x;
|
||||
ch = [this._terminal.eraseAttr(), ' ', 1]; // xterm
|
||||
|
||||
while (param-- && j < this._terminal.cols) {
|
||||
this._terminal.lines.get(row).splice(j++, 0, ch);
|
||||
this._terminal.lines.get(row).pop();
|
||||
this._terminal.buffer.lines.get(row).splice(j++, 0, ch);
|
||||
this._terminal.buffer.lines.get(row).pop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,9 +207,9 @@ export class InputHandler implements IInputHandler {
|
||||
if (param < 1) {
|
||||
param = 1;
|
||||
}
|
||||
this._terminal.y -= param;
|
||||
if (this._terminal.y < 0) {
|
||||
this._terminal.y = 0;
|
||||
this._terminal.buffer.y -= param;
|
||||
if (this._terminal.buffer.y < 0) {
|
||||
this._terminal.buffer.y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,13 +222,13 @@ export class InputHandler implements IInputHandler {
|
||||
if (param < 1) {
|
||||
param = 1;
|
||||
}
|
||||
this._terminal.y += param;
|
||||
if (this._terminal.y >= this._terminal.rows) {
|
||||
this._terminal.y = this._terminal.rows - 1;
|
||||
this._terminal.buffer.y += param;
|
||||
if (this._terminal.buffer.y >= this._terminal.rows) {
|
||||
this._terminal.buffer.y = this._terminal.rows - 1;
|
||||
}
|
||||
// If the end of the line is hit, prevent this action from wrapping around to the next line.
|
||||
if (this._terminal.x >= this._terminal.cols) {
|
||||
this._terminal.x--;
|
||||
if (this._terminal.buffer.x >= this._terminal.cols) {
|
||||
this._terminal.buffer.x--;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,9 +241,9 @@ export class InputHandler implements IInputHandler {
|
||||
if (param < 1) {
|
||||
param = 1;
|
||||
}
|
||||
this._terminal.x += param;
|
||||
if (this._terminal.x >= this._terminal.cols) {
|
||||
this._terminal.x = this._terminal.cols - 1;
|
||||
this._terminal.buffer.x += param;
|
||||
if (this._terminal.buffer.x >= this._terminal.cols) {
|
||||
this._terminal.buffer.x = this._terminal.cols - 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,12 +257,12 @@ export class InputHandler implements IInputHandler {
|
||||
param = 1;
|
||||
}
|
||||
// If the end of the line is hit, prevent this action from wrapping around to the next line.
|
||||
if (this._terminal.x >= this._terminal.cols) {
|
||||
this._terminal.x--;
|
||||
if (this._terminal.buffer.x >= this._terminal.cols) {
|
||||
this._terminal.buffer.x--;
|
||||
}
|
||||
this._terminal.x -= param;
|
||||
if (this._terminal.x < 0) {
|
||||
this._terminal.x = 0;
|
||||
this._terminal.buffer.x -= param;
|
||||
if (this._terminal.buffer.x < 0) {
|
||||
this._terminal.buffer.x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,11 +276,11 @@ export class InputHandler implements IInputHandler {
|
||||
if (param < 1) {
|
||||
param = 1;
|
||||
}
|
||||
this._terminal.y += param;
|
||||
if (this._terminal.y >= this._terminal.rows) {
|
||||
this._terminal.y = this._terminal.rows - 1;
|
||||
this._terminal.buffer.y += param;
|
||||
if (this._terminal.buffer.y >= this._terminal.rows) {
|
||||
this._terminal.buffer.y = this._terminal.rows - 1;
|
||||
}
|
||||
this._terminal.x = 0;
|
||||
this._terminal.buffer.x = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -295,11 +294,11 @@ export class InputHandler implements IInputHandler {
|
||||
if (param < 1) {
|
||||
param = 1;
|
||||
}
|
||||
this._terminal.y -= param;
|
||||
if (this._terminal.y < 0) {
|
||||
this._terminal.y = 0;
|
||||
this._terminal.buffer.y -= param;
|
||||
if (this._terminal.buffer.y < 0) {
|
||||
this._terminal.buffer.y = 0;
|
||||
}
|
||||
this._terminal.x = 0;
|
||||
this._terminal.buffer.x = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -312,7 +311,7 @@ export class InputHandler implements IInputHandler {
|
||||
if (param < 1) {
|
||||
param = 1;
|
||||
}
|
||||
this._terminal.x = param - 1;
|
||||
this._terminal.buffer.x = param - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -342,8 +341,8 @@ export class InputHandler implements IInputHandler {
|
||||
col = this._terminal.cols - 1;
|
||||
}
|
||||
|
||||
this._terminal.x = col;
|
||||
this._terminal.y = row;
|
||||
this._terminal.buffer.x = col;
|
||||
this._terminal.buffer.y = row;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -353,7 +352,7 @@ export class InputHandler implements IInputHandler {
|
||||
public cursorForwardTab(params: number[]): void {
|
||||
let param = params[0] || 1;
|
||||
while (param--) {
|
||||
this._terminal.x = this._terminal.nextStop();
|
||||
this._terminal.buffer.x = this._terminal.nextStop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,15 +372,15 @@ export class InputHandler implements IInputHandler {
|
||||
let j;
|
||||
switch (params[0]) {
|
||||
case 0:
|
||||
this._terminal.eraseRight(this._terminal.x, this._terminal.y);
|
||||
j = this._terminal.y + 1;
|
||||
this._terminal.eraseRight(this._terminal.buffer.x, this._terminal.buffer.y);
|
||||
j = this._terminal.buffer.y + 1;
|
||||
for (; j < this._terminal.rows; j++) {
|
||||
this._terminal.eraseLine(j);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
this._terminal.eraseLeft(this._terminal.x, this._terminal.y);
|
||||
j = this._terminal.y;
|
||||
this._terminal.eraseLeft(this._terminal.buffer.x, this._terminal.buffer.y);
|
||||
j = this._terminal.buffer.y;
|
||||
while (j--) {
|
||||
this._terminal.eraseLine(j);
|
||||
}
|
||||
@@ -392,11 +391,11 @@ export class InputHandler implements IInputHandler {
|
||||
break;
|
||||
case 3:
|
||||
// Clear scrollback (everything not in viewport)
|
||||
const scrollBackSize = this._terminal.lines.length - this._terminal.rows;
|
||||
const scrollBackSize = this._terminal.buffer.lines.length - this._terminal.rows;
|
||||
if (scrollBackSize > 0) {
|
||||
this._terminal.lines.trimStart(scrollBackSize);
|
||||
this._terminal.ybase = Math.max(this._terminal.ybase - scrollBackSize, 0);
|
||||
this._terminal.ydisp = Math.max(this._terminal.ydisp - scrollBackSize, 0);
|
||||
this._terminal.buffer.lines.trimStart(scrollBackSize);
|
||||
this._terminal.buffer.ybase = Math.max(this._terminal.buffer.ybase - scrollBackSize, 0);
|
||||
this._terminal.buffer.ydisp = Math.max(this._terminal.buffer.ydisp - scrollBackSize, 0);
|
||||
// Force a scroll event to refresh viewport
|
||||
this._terminal.emit('scroll', 0);
|
||||
}
|
||||
@@ -418,13 +417,13 @@ export class InputHandler implements IInputHandler {
|
||||
public eraseInLine(params: number[]): void {
|
||||
switch (params[0]) {
|
||||
case 0:
|
||||
this._terminal.eraseRight(this._terminal.x, this._terminal.y);
|
||||
this._terminal.eraseRight(this._terminal.buffer.x, this._terminal.buffer.y);
|
||||
break;
|
||||
case 1:
|
||||
this._terminal.eraseLeft(this._terminal.x, this._terminal.y);
|
||||
this._terminal.eraseLeft(this._terminal.buffer.x, this._terminal.buffer.y);
|
||||
break;
|
||||
case 2:
|
||||
this._terminal.eraseLine(this._terminal.y);
|
||||
this._terminal.eraseLine(this._terminal.buffer.y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -440,29 +439,29 @@ export class InputHandler implements IInputHandler {
|
||||
if (param < 1) {
|
||||
param = 1;
|
||||
}
|
||||
row = this._terminal.y + this._terminal.ybase;
|
||||
row = this._terminal.buffer.y + this._terminal.buffer.ybase;
|
||||
|
||||
j = this._terminal.rows - 1 - this._terminal.scrollBottom;
|
||||
j = this._terminal.rows - 1 + this._terminal.ybase - j + 1;
|
||||
j = this._terminal.rows - 1 - this._terminal.buffer.scrollBottom;
|
||||
j = this._terminal.rows - 1 + this._terminal.buffer.ybase - j + 1;
|
||||
|
||||
while (param--) {
|
||||
if (this._terminal.lines.length === this._terminal.lines.maxLength) {
|
||||
if (this._terminal.buffer.lines.length === this._terminal.buffer.lines.maxLength) {
|
||||
// Trim the start of lines to make room for the new line
|
||||
this._terminal.lines.trimStart(1);
|
||||
this._terminal.ybase--;
|
||||
this._terminal.ydisp--;
|
||||
this._terminal.buffer.lines.trimStart(1);
|
||||
this._terminal.buffer.ybase--;
|
||||
this._terminal.buffer.ydisp--;
|
||||
row--;
|
||||
j--;
|
||||
}
|
||||
// test: echo -e '\e[44m\e[1L\e[0m'
|
||||
// blankLine(true) - xterm/linux behavior
|
||||
this._terminal.lines.splice(row, 0, this._terminal.blankLine(true));
|
||||
this._terminal.lines.splice(j, 1);
|
||||
this._terminal.buffer.lines.splice(row, 0, this._terminal.blankLine(true));
|
||||
this._terminal.buffer.lines.splice(j, 1);
|
||||
}
|
||||
|
||||
// this.maxRange();
|
||||
this._terminal.updateRange(this._terminal.y);
|
||||
this._terminal.updateRange(this._terminal.scrollBottom);
|
||||
this._terminal.updateRange(this._terminal.buffer.y);
|
||||
this._terminal.updateRange(this._terminal.buffer.scrollBottom);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -476,27 +475,27 @@ export class InputHandler implements IInputHandler {
|
||||
if (param < 1) {
|
||||
param = 1;
|
||||
}
|
||||
row = this._terminal.y + this._terminal.ybase;
|
||||
row = this._terminal.buffer.y + this._terminal.buffer.ybase;
|
||||
|
||||
j = this._terminal.rows - 1 - this._terminal.scrollBottom;
|
||||
j = this._terminal.rows - 1 + this._terminal.ybase - j;
|
||||
j = this._terminal.rows - 1 - this._terminal.buffer.scrollBottom;
|
||||
j = this._terminal.rows - 1 + this._terminal.buffer.ybase - j;
|
||||
|
||||
while (param--) {
|
||||
if (this._terminal.lines.length === this._terminal.lines.maxLength) {
|
||||
if (this._terminal.buffer.lines.length === this._terminal.buffer.lines.maxLength) {
|
||||
// Trim the start of lines to make room for the new line
|
||||
this._terminal.lines.trimStart(1);
|
||||
this._terminal.ybase -= 1;
|
||||
this._terminal.ydisp -= 1;
|
||||
this._terminal.buffer.lines.trimStart(1);
|
||||
this._terminal.buffer.ybase -= 1;
|
||||
this._terminal.buffer.ydisp -= 1;
|
||||
}
|
||||
// test: echo -e '\e[44m\e[1M\e[0m'
|
||||
// blankLine(true) - xterm/linux behavior
|
||||
this._terminal.lines.splice(j + 1, 0, this._terminal.blankLine(true));
|
||||
this._terminal.lines.splice(row, 1);
|
||||
this._terminal.buffer.lines.splice(j + 1, 0, this._terminal.blankLine(true));
|
||||
this._terminal.buffer.lines.splice(row, 1);
|
||||
}
|
||||
|
||||
// this.maxRange();
|
||||
this._terminal.updateRange(this._terminal.y);
|
||||
this._terminal.updateRange(this._terminal.scrollBottom);
|
||||
this._terminal.updateRange(this._terminal.buffer.y);
|
||||
this._terminal.updateRange(this._terminal.buffer.scrollBottom);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -511,12 +510,12 @@ export class InputHandler implements IInputHandler {
|
||||
param = 1;
|
||||
}
|
||||
|
||||
row = this._terminal.y + this._terminal.ybase;
|
||||
row = this._terminal.buffer.y + this._terminal.buffer.ybase;
|
||||
ch = [this._terminal.eraseAttr(), ' ', 1]; // xterm
|
||||
|
||||
while (param--) {
|
||||
this._terminal.lines.get(row).splice(this._terminal.x, 1);
|
||||
this._terminal.lines.get(row).push(ch);
|
||||
this._terminal.buffer.lines.get(row).splice(this._terminal.buffer.x, 1);
|
||||
this._terminal.buffer.lines.get(row).push(ch);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,12 +525,12 @@ export class InputHandler implements IInputHandler {
|
||||
public scrollUp(params: number[]): void {
|
||||
let param = params[0] || 1;
|
||||
while (param--) {
|
||||
this._terminal.lines.splice(this._terminal.ybase + this._terminal.scrollTop, 1);
|
||||
this._terminal.lines.splice(this._terminal.ybase + this._terminal.scrollBottom, 0, this._terminal.blankLine());
|
||||
this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollTop, 1);
|
||||
this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollBottom, 0, this._terminal.blankLine());
|
||||
}
|
||||
// this.maxRange();
|
||||
this._terminal.updateRange(this._terminal.scrollTop);
|
||||
this._terminal.updateRange(this._terminal.scrollBottom);
|
||||
this._terminal.updateRange(this._terminal.buffer.scrollTop);
|
||||
this._terminal.updateRange(this._terminal.buffer.scrollBottom);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -540,12 +539,12 @@ export class InputHandler implements IInputHandler {
|
||||
public scrollDown(params: number[]): void {
|
||||
let param = params[0] || 1;
|
||||
while (param--) {
|
||||
this._terminal.lines.splice(this._terminal.ybase + this._terminal.scrollBottom, 1);
|
||||
this._terminal.lines.splice(this._terminal.ybase + this._terminal.scrollTop, 0, this._terminal.blankLine());
|
||||
this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollBottom, 1);
|
||||
this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollTop, 0, this._terminal.blankLine());
|
||||
}
|
||||
// this.maxRange();
|
||||
this._terminal.updateRange(this._terminal.scrollTop);
|
||||
this._terminal.updateRange(this._terminal.scrollBottom);
|
||||
this._terminal.updateRange(this._terminal.buffer.scrollTop);
|
||||
this._terminal.updateRange(this._terminal.buffer.scrollBottom);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -560,12 +559,12 @@ export class InputHandler implements IInputHandler {
|
||||
param = 1;
|
||||
}
|
||||
|
||||
row = this._terminal.y + this._terminal.ybase;
|
||||
j = this._terminal.x;
|
||||
row = this._terminal.buffer.y + this._terminal.buffer.ybase;
|
||||
j = this._terminal.buffer.x;
|
||||
ch = [this._terminal.eraseAttr(), ' ', 1]; // xterm
|
||||
|
||||
while (param-- && j < this._terminal.cols) {
|
||||
this._terminal.lines.get(row)[j++] = ch;
|
||||
this._terminal.buffer.lines.get(row)[j++] = ch;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -575,7 +574,7 @@ export class InputHandler implements IInputHandler {
|
||||
public cursorBackwardTab(params: number[]): void {
|
||||
let param = params[0] || 1;
|
||||
while (param--) {
|
||||
this._terminal.x = this._terminal.prevStop();
|
||||
this._terminal.buffer.x = this._terminal.prevStop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -588,9 +587,9 @@ export class InputHandler implements IInputHandler {
|
||||
if (param < 1) {
|
||||
param = 1;
|
||||
}
|
||||
this._terminal.x = param - 1;
|
||||
if (this._terminal.x >= this._terminal.cols) {
|
||||
this._terminal.x = this._terminal.cols - 1;
|
||||
this._terminal.buffer.x = param - 1;
|
||||
if (this._terminal.buffer.x >= this._terminal.cols) {
|
||||
this._terminal.buffer.x = this._terminal.cols - 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -604,9 +603,9 @@ export class InputHandler implements IInputHandler {
|
||||
if (param < 1) {
|
||||
param = 1;
|
||||
}
|
||||
this._terminal.x += param;
|
||||
if (this._terminal.x >= this._terminal.cols) {
|
||||
this._terminal.x = this._terminal.cols - 1;
|
||||
this._terminal.buffer.x += param;
|
||||
if (this._terminal.buffer.x >= this._terminal.cols) {
|
||||
this._terminal.buffer.x = this._terminal.cols - 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -615,11 +614,11 @@ export class InputHandler implements IInputHandler {
|
||||
*/
|
||||
public repeatPrecedingCharacter(params: number[]): void {
|
||||
let param = params[0] || 1
|
||||
, line = this._terminal.lines.get(this._terminal.ybase + this._terminal.y)
|
||||
, ch = line[this._terminal.x - 1] || [this._terminal.defAttr, ' ', 1];
|
||||
, line = this._terminal.buffer.lines.get(this._terminal.buffer.ybase + this._terminal.buffer.y)
|
||||
, ch = line[this._terminal.buffer.x - 1] || [this._terminal.defAttr, ' ', 1];
|
||||
|
||||
while (param--) {
|
||||
line[this._terminal.x++] = ch;
|
||||
line[this._terminal.buffer.x++] = ch;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -698,9 +697,9 @@ export class InputHandler implements IInputHandler {
|
||||
if (param < 1) {
|
||||
param = 1;
|
||||
}
|
||||
this._terminal.y = param - 1;
|
||||
if (this._terminal.y >= this._terminal.rows) {
|
||||
this._terminal.y = this._terminal.rows - 1;
|
||||
this._terminal.buffer.y = param - 1;
|
||||
if (this._terminal.buffer.y >= this._terminal.rows) {
|
||||
this._terminal.buffer.y = this._terminal.rows - 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -714,13 +713,13 @@ export class InputHandler implements IInputHandler {
|
||||
if (param < 1) {
|
||||
param = 1;
|
||||
}
|
||||
this._terminal.y += param;
|
||||
if (this._terminal.y >= this._terminal.rows) {
|
||||
this._terminal.y = this._terminal.rows - 1;
|
||||
this._terminal.buffer.y += param;
|
||||
if (this._terminal.buffer.y >= this._terminal.rows) {
|
||||
this._terminal.buffer.y = this._terminal.rows - 1;
|
||||
}
|
||||
// If the end of the line is hit, prevent this action from wrapping around to the next line.
|
||||
if (this._terminal.x >= this._terminal.cols) {
|
||||
this._terminal.x--;
|
||||
if (this._terminal.buffer.x >= this._terminal.cols) {
|
||||
this._terminal.buffer.x--;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -733,14 +732,14 @@ export class InputHandler implements IInputHandler {
|
||||
if (params[0] < 1) params[0] = 1;
|
||||
if (params[1] < 1) params[1] = 1;
|
||||
|
||||
this._terminal.y = params[0] - 1;
|
||||
if (this._terminal.y >= this._terminal.rows) {
|
||||
this._terminal.y = this._terminal.rows - 1;
|
||||
this._terminal.buffer.y = params[0] - 1;
|
||||
if (this._terminal.buffer.y >= this._terminal.rows) {
|
||||
this._terminal.buffer.y = this._terminal.rows - 1;
|
||||
}
|
||||
|
||||
this._terminal.x = params[1] - 1;
|
||||
if (this._terminal.x >= this._terminal.cols) {
|
||||
this._terminal.x = this._terminal.cols - 1;
|
||||
this._terminal.buffer.x = params[1] - 1;
|
||||
if (this._terminal.buffer.x >= this._terminal.cols) {
|
||||
this._terminal.buffer.x = this._terminal.cols - 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -755,9 +754,9 @@ export class InputHandler implements IInputHandler {
|
||||
public tabClear(params: number[]): void {
|
||||
let param = params[0];
|
||||
if (param <= 0) {
|
||||
delete this._terminal.tabs[this._terminal.x];
|
||||
delete this._terminal.buffer.tabs[this._terminal.buffer.x];
|
||||
} else if (param === 3) {
|
||||
this._terminal.tabs = {};
|
||||
this._terminal.buffer.tabs = {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -943,30 +942,14 @@ export class InputHandler implements IInputHandler {
|
||||
this._terminal.cursorHidden = false;
|
||||
break;
|
||||
case 1049: // alt screen buffer cursor
|
||||
// this._terminal.saveCursor();
|
||||
; // FALL-THROUGH
|
||||
this.saveCursor(params);
|
||||
// FALL-THROUGH
|
||||
case 47: // alt screen buffer
|
||||
case 1047: // alt screen buffer
|
||||
if (!this._terminal.normal) {
|
||||
let normal = {
|
||||
lines: this._terminal.lines,
|
||||
ybase: this._terminal.ybase,
|
||||
ydisp: this._terminal.ydisp,
|
||||
x: this._terminal.x,
|
||||
y: this._terminal.y,
|
||||
scrollTop: this._terminal.scrollTop,
|
||||
scrollBottom: this._terminal.scrollBottom,
|
||||
tabs: this._terminal.tabs
|
||||
// XXX save charset(s) here?
|
||||
// charset: this._terminal.charset,
|
||||
// glevel: this._terminal.glevel,
|
||||
// charsets: this._terminal.charsets
|
||||
};
|
||||
this._terminal.reset();
|
||||
this._terminal.viewport.syncScrollArea();
|
||||
this._terminal.normal = normal;
|
||||
this._terminal.showCursor();
|
||||
}
|
||||
this._terminal.buffers.activateAltBuffer();
|
||||
this._terminal.reset();
|
||||
this._terminal.viewport.syncScrollArea();
|
||||
this._terminal.showCursor();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1127,26 +1110,15 @@ export class InputHandler implements IInputHandler {
|
||||
; // FALL-THROUGH
|
||||
case 47: // normal screen buffer
|
||||
case 1047: // normal screen buffer - clearing it first
|
||||
if (this._terminal.normal) {
|
||||
this._terminal.lines = this._terminal.normal.lines;
|
||||
this._terminal.ybase = this._terminal.normal.ybase;
|
||||
this._terminal.ydisp = this._terminal.normal.ydisp;
|
||||
this._terminal.x = this._terminal.normal.x;
|
||||
this._terminal.y = this._terminal.normal.y;
|
||||
this._terminal.scrollTop = this._terminal.normal.scrollTop;
|
||||
this._terminal.scrollBottom = this._terminal.normal.scrollBottom;
|
||||
this._terminal.tabs = this._terminal.normal.tabs;
|
||||
this._terminal.normal = null;
|
||||
// Ensure the selection manager has the correct buffer
|
||||
this._terminal.selectionManager.setBuffer(this._terminal.lines);
|
||||
// if (params === 1049) {
|
||||
// this.x = this.savedX;
|
||||
// this.y = this.savedY;
|
||||
// }
|
||||
this._terminal.refresh(0, this._terminal.rows - 1);
|
||||
this._terminal.viewport.syncScrollArea();
|
||||
this._terminal.showCursor();
|
||||
// Ensure the selection manager has the correct buffer
|
||||
this._terminal.buffers.activateNormalBuffer();
|
||||
if (params[0] === 1049) {
|
||||
this.restoreCursor(params);
|
||||
}
|
||||
this._terminal.selectionManager.setBuffer(this._terminal.buffer.lines);
|
||||
this._terminal.refresh(0, this._terminal.rows - 1);
|
||||
this._terminal.viewport.syncScrollArea();
|
||||
this._terminal.showCursor();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1366,9 +1338,9 @@ export class InputHandler implements IInputHandler {
|
||||
case 6:
|
||||
// cursor position
|
||||
this._terminal.send(C0.ESC + '['
|
||||
+ (this._terminal.y + 1)
|
||||
+ (this._terminal.buffer.y + 1)
|
||||
+ ';'
|
||||
+ (this._terminal.x + 1)
|
||||
+ (this._terminal.buffer.x + 1)
|
||||
+ 'R');
|
||||
break;
|
||||
}
|
||||
@@ -1379,9 +1351,9 @@ export class InputHandler implements IInputHandler {
|
||||
case 6:
|
||||
// cursor position
|
||||
this._terminal.send(C0.ESC + '[?'
|
||||
+ (this._terminal.y + 1)
|
||||
+ (this._terminal.buffer.y + 1)
|
||||
+ ';'
|
||||
+ (this._terminal.x + 1)
|
||||
+ (this._terminal.buffer.x + 1)
|
||||
+ 'R');
|
||||
break;
|
||||
case 15:
|
||||
@@ -1416,10 +1388,10 @@ export class InputHandler implements IInputHandler {
|
||||
this._terminal.applicationKeypad = false; // ?
|
||||
this._terminal.viewport.syncScrollArea();
|
||||
this._terminal.applicationCursor = false;
|
||||
this._terminal.scrollTop = 0;
|
||||
this._terminal.scrollBottom = this._terminal.rows - 1;
|
||||
this._terminal.buffer.scrollTop = 0;
|
||||
this._terminal.buffer.scrollBottom = this._terminal.rows - 1;
|
||||
this._terminal.curAttr = this._terminal.defAttr;
|
||||
this._terminal.x = this._terminal.y = 0; // ?
|
||||
this._terminal.buffer.x = this._terminal.buffer.y = 0; // ?
|
||||
this._terminal.charset = null;
|
||||
this._terminal.glevel = 0; // ??
|
||||
this._terminal.charsets = [null]; // ??
|
||||
@@ -1463,10 +1435,10 @@ export class InputHandler implements IInputHandler {
|
||||
*/
|
||||
public setScrollRegion(params: number[]): void {
|
||||
if (this._terminal.prefix) return;
|
||||
this._terminal.scrollTop = (params[0] || 1) - 1;
|
||||
this._terminal.scrollBottom = (params[1] && params[1] <= this._terminal.rows ? params[1] : this._terminal.rows) - 1;
|
||||
this._terminal.x = 0;
|
||||
this._terminal.y = 0;
|
||||
this._terminal.buffer.scrollTop = (params[0] || 1) - 1;
|
||||
this._terminal.buffer.scrollBottom = (params[1] && params[1] <= this._terminal.rows ? params[1] : this._terminal.rows) - 1;
|
||||
this._terminal.buffer.x = 0;
|
||||
this._terminal.buffer.y = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1475,8 +1447,8 @@ export class InputHandler implements IInputHandler {
|
||||
* Save cursor (ANSI.SYS).
|
||||
*/
|
||||
public saveCursor(params: number[]): void {
|
||||
this._terminal.savedX = this._terminal.x;
|
||||
this._terminal.savedY = this._terminal.y;
|
||||
this._terminal.buffers.active.x = this._terminal.buffer.x;
|
||||
this._terminal.buffers.active.y = this._terminal.buffer.y;
|
||||
}
|
||||
|
||||
|
||||
@@ -1485,8 +1457,8 @@ export class InputHandler implements IInputHandler {
|
||||
* Restore cursor (ANSI.SYS).
|
||||
*/
|
||||
public restoreCursor(params: number[]): void {
|
||||
this._terminal.x = this._terminal.savedX || 0;
|
||||
this._terminal.y = this._terminal.savedY || 0;
|
||||
this._terminal.buffer.x = this._terminal.buffers.active.x || 0;
|
||||
this._terminal.buffer.y = this._terminal.buffers.active.y || 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+29
-6
@@ -24,9 +24,6 @@ export interface ITerminal {
|
||||
selectionManager: ISelectionManager;
|
||||
charMeasure: ICharMeasure;
|
||||
textarea: HTMLTextAreaElement;
|
||||
ybase: number;
|
||||
ydisp: number;
|
||||
lines: ICircularList<string>;
|
||||
rows: number;
|
||||
cols: number;
|
||||
browser: IBrowser;
|
||||
@@ -34,9 +31,10 @@ export interface ITerminal {
|
||||
children: HTMLElement[];
|
||||
cursorHidden: boolean;
|
||||
cursorState: number;
|
||||
x: number;
|
||||
y: number;
|
||||
defAttr: number;
|
||||
scrollback: number;
|
||||
buffers: IBufferSet;
|
||||
buffer: IBuffer;
|
||||
|
||||
/**
|
||||
* Emit the 'data' event and populate the given data.
|
||||
@@ -48,6 +46,26 @@ export interface ITerminal {
|
||||
cancel(ev: Event, force?: boolean);
|
||||
log(text: string): void;
|
||||
emit(event: string, data: any);
|
||||
reset(): void;
|
||||
showCursor(): void;
|
||||
}
|
||||
|
||||
export interface IBuffer {
|
||||
lines: ICircularList<[number, string, number][]>;
|
||||
ydisp: number;
|
||||
ybase: number;
|
||||
y: number;
|
||||
x: number;
|
||||
tabs: any;
|
||||
}
|
||||
|
||||
export interface IBufferSet {
|
||||
alt: IBuffer;
|
||||
normal: IBuffer;
|
||||
active: IBuffer;
|
||||
|
||||
activateNormalBuffer(): void;
|
||||
activateAltBuffer(): void;
|
||||
}
|
||||
|
||||
export interface ISelectionManager {
|
||||
@@ -71,7 +89,7 @@ export interface ILinkifier {
|
||||
deregisterLinkMatcher(matcherId: number): boolean;
|
||||
}
|
||||
|
||||
interface ICircularList<T> {
|
||||
export interface ICircularList<T> extends IEventEmitter {
|
||||
length: number;
|
||||
maxLength: number;
|
||||
|
||||
@@ -85,6 +103,11 @@ interface ICircularList<T> {
|
||||
shiftElements(start: number, count: number, offset: number): void;
|
||||
}
|
||||
|
||||
export interface IEventEmitter {
|
||||
on(type, listener): void;
|
||||
off(type, listener): void;
|
||||
}
|
||||
|
||||
export interface LinkMatcherOptions {
|
||||
/**
|
||||
* The index of the link from the regex.match(text) call. This defaults to 0
|
||||
|
||||
+3
-3
@@ -52,7 +52,7 @@ escapedStateHandler['c'] = (parser, terminal) => {
|
||||
};
|
||||
escapedStateHandler['E'] = (parser, terminal) => {
|
||||
// ESC E Next Line ( NEL is 0x85).
|
||||
terminal.x = 0;
|
||||
terminal.buffer.x = 0;
|
||||
terminal.index();
|
||||
parser.setState(ParserState.NORMAL);
|
||||
};
|
||||
@@ -499,9 +499,9 @@ export class Parser {
|
||||
// DECSTBM
|
||||
case 'r':
|
||||
pt = ''
|
||||
+ (this._terminal.scrollTop + 1)
|
||||
+ (this._terminal.buffer.scrollTop + 1)
|
||||
+ ';'
|
||||
+ (this._terminal.scrollBottom + 1)
|
||||
+ (this._terminal.buffer.scrollBottom + 1)
|
||||
+ 'r';
|
||||
break;
|
||||
|
||||
|
||||
+6
-6
@@ -139,15 +139,15 @@ export class Renderer {
|
||||
}
|
||||
|
||||
for (; y <= end; y++) {
|
||||
let row = y + this._terminal.ydisp;
|
||||
let row = y + this._terminal.buffer.ydisp;
|
||||
|
||||
let line = this._terminal.lines.get(row);
|
||||
let line = this._terminal.buffer.lines.get(row);
|
||||
|
||||
let x;
|
||||
if (this._terminal.y === y - (this._terminal.ybase - this._terminal.ydisp) &&
|
||||
if (this._terminal.buffer.y === y - (this._terminal.buffer.ybase - this._terminal.buffer.ydisp) &&
|
||||
this._terminal.cursorState &&
|
||||
!this._terminal.cursorHidden) {
|
||||
x = this._terminal.x;
|
||||
x = this._terminal.buffer.x;
|
||||
} else {
|
||||
x = -1;
|
||||
}
|
||||
@@ -337,8 +337,8 @@ export class Renderer {
|
||||
}
|
||||
|
||||
// Translate from buffer position to viewport position
|
||||
const viewportStartRow = start[1] - this._terminal.ydisp;
|
||||
const viewportEndRow = end[1] - this._terminal.ydisp;
|
||||
const viewportStartRow = start[1] - this._terminal.buffer.ydisp;
|
||||
const viewportEndRow = end[1] - this._terminal.buffer.ydisp;
|
||||
const viewportCappedStartRow = Math.max(viewportStartRow, 0);
|
||||
const viewportCappedEndRow = Math.min(viewportEndRow, this._terminal.rows - 1);
|
||||
|
||||
|
||||
@@ -3,16 +3,17 @@
|
||||
*/
|
||||
import jsdom = require('jsdom');
|
||||
import { assert } from 'chai';
|
||||
import { ITerminal } from './Interfaces';
|
||||
import { ITerminal, ICircularList } from './Interfaces';
|
||||
import { CharMeasure } from './utils/CharMeasure';
|
||||
import { CircularList } from './utils/CircularList';
|
||||
import { SelectionManager } from './SelectionManager';
|
||||
import { SelectionModel } from './SelectionModel';
|
||||
import { BufferSet } from './BufferSet';
|
||||
|
||||
class TestSelectionManager extends SelectionManager {
|
||||
constructor(
|
||||
terminal: ITerminal,
|
||||
buffer: CircularList<any>,
|
||||
buffer: ICircularList<[number, string, number][]>,
|
||||
rowContainer: HTMLElement,
|
||||
charMeasure: CharMeasure
|
||||
) {
|
||||
@@ -36,7 +37,7 @@ describe('SelectionManager', () => {
|
||||
let document: Document;
|
||||
|
||||
let terminal: ITerminal;
|
||||
let buffer: CircularList<any>;
|
||||
let bufferLines: ICircularList<[number, string, number][]>;
|
||||
let rowContainer: HTMLElement;
|
||||
let selectionManager: TestSelectionManager;
|
||||
|
||||
@@ -44,9 +45,12 @@ describe('SelectionManager', () => {
|
||||
dom = new jsdom.JSDOM('');
|
||||
window = dom.window;
|
||||
document = window.document;
|
||||
buffer = new CircularList<any>(100);
|
||||
terminal = <any>{ cols: 80, rows: 2 };
|
||||
selectionManager = new TestSelectionManager(terminal, buffer, rowContainer, null);
|
||||
terminal.scrollback = 100;
|
||||
terminal.buffers = new BufferSet(terminal);
|
||||
terminal.buffer = terminal.buffers.active;
|
||||
bufferLines = terminal.buffer.lines;
|
||||
selectionManager = new TestSelectionManager(terminal, bufferLines, rowContainer, null);
|
||||
});
|
||||
|
||||
function stringToRow(text: string): [number, string, number][] {
|
||||
@@ -59,7 +63,7 @@ describe('SelectionManager', () => {
|
||||
|
||||
describe('_selectWordAt', () => {
|
||||
it('should expand selection for normal width chars', () => {
|
||||
buffer.push(stringToRow('foo bar'));
|
||||
bufferLines.push(stringToRow('foo bar'));
|
||||
selectionManager.selectWordAt([0, 0]);
|
||||
assert.equal(selectionManager.selectionText, 'foo');
|
||||
selectionManager.selectWordAt([1, 0]);
|
||||
@@ -76,7 +80,7 @@ describe('SelectionManager', () => {
|
||||
assert.equal(selectionManager.selectionText, 'bar');
|
||||
});
|
||||
it('should expand selection for whitespace', () => {
|
||||
buffer.push(stringToRow('a b'));
|
||||
bufferLines.push(stringToRow('a b'));
|
||||
selectionManager.selectWordAt([0, 0]);
|
||||
assert.equal(selectionManager.selectionText, 'a');
|
||||
selectionManager.selectWordAt([1, 0]);
|
||||
@@ -90,7 +94,7 @@ describe('SelectionManager', () => {
|
||||
});
|
||||
it('should expand selection for wide characters', () => {
|
||||
// Wide characters use a special format
|
||||
buffer.push([
|
||||
bufferLines.push([
|
||||
[null, '中', 2],
|
||||
[null, '', 0],
|
||||
[null, '文', 2],
|
||||
@@ -142,7 +146,7 @@ describe('SelectionManager', () => {
|
||||
assert.equal(selectionManager.selectionText, 'foo');
|
||||
});
|
||||
it('should select up to non-path characters that are commonly adjacent to paths', () => {
|
||||
buffer.push(stringToRow('(cd)[ef]{gh}\'ij"'));
|
||||
bufferLines.push(stringToRow('(cd)[ef]{gh}\'ij"'));
|
||||
selectionManager.selectWordAt([0, 0]);
|
||||
assert.equal(selectionManager.selectionText, '(cd');
|
||||
selectionManager.selectWordAt([1, 0]);
|
||||
@@ -180,7 +184,7 @@ describe('SelectionManager', () => {
|
||||
|
||||
describe('_selectLineAt', () => {
|
||||
it('should select the entire line', () => {
|
||||
buffer.push(stringToRow('foo bar'));
|
||||
bufferLines.push(stringToRow('foo bar'));
|
||||
selectionManager.selectLineAt(0);
|
||||
assert.equal(selectionManager.selectionText, 'foo bar', 'The selected text is correct');
|
||||
assert.deepEqual(selectionManager.model.finalSelectionStart, [0, 0]);
|
||||
@@ -190,13 +194,13 @@ describe('SelectionManager', () => {
|
||||
|
||||
describe('selectAll', () => {
|
||||
it('should select the entire buffer, beyond the viewport', () => {
|
||||
buffer.push(stringToRow('1'));
|
||||
buffer.push(stringToRow('2'));
|
||||
buffer.push(stringToRow('3'));
|
||||
buffer.push(stringToRow('4'));
|
||||
buffer.push(stringToRow('5'));
|
||||
bufferLines.push(stringToRow('1'));
|
||||
bufferLines.push(stringToRow('2'));
|
||||
bufferLines.push(stringToRow('3'));
|
||||
bufferLines.push(stringToRow('4'));
|
||||
bufferLines.push(stringToRow('5'));
|
||||
selectionManager.selectAll();
|
||||
terminal.ybase = buffer.length - terminal.rows;
|
||||
terminal.buffer.ybase = bufferLines.length - terminal.rows;
|
||||
assert.equal(selectionManager.selectionText, '1\n2\n3\n4\n5');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,7 +7,7 @@ import * as Browser from './utils/Browser';
|
||||
import { CharMeasure } from './utils/CharMeasure';
|
||||
import { CircularList } from './utils/CircularList';
|
||||
import { EventEmitter } from './EventEmitter';
|
||||
import { ITerminal } from './Interfaces';
|
||||
import { ITerminal, ICircularList } from './Interfaces';
|
||||
import { SelectionModel } from './SelectionModel';
|
||||
import { translateBufferLineToString } from './utils/BufferLine';
|
||||
|
||||
@@ -98,7 +98,7 @@ export class SelectionManager extends EventEmitter {
|
||||
|
||||
constructor(
|
||||
private _terminal: ITerminal,
|
||||
private _buffer: CircularList<any>,
|
||||
private _buffer: ICircularList<[number, string, number][]>,
|
||||
private _rowContainer: HTMLElement,
|
||||
private _charMeasure: CharMeasure
|
||||
) {
|
||||
@@ -147,7 +147,7 @@ export class SelectionManager extends EventEmitter {
|
||||
* switched in or out.
|
||||
* @param buffer The active buffer.
|
||||
*/
|
||||
public setBuffer(buffer: CircularList<any>): void {
|
||||
public setBuffer(buffer: ICircularList<[number, string, number][]>): void {
|
||||
this._buffer = buffer;
|
||||
this.clearSelection();
|
||||
}
|
||||
@@ -186,7 +186,7 @@ export class SelectionManager extends EventEmitter {
|
||||
for (let i = start[1] + 1; i <= end[1] - 1; i++) {
|
||||
const bufferLine = this._buffer.get(i);
|
||||
const lineText = translateBufferLineToString(bufferLine, true);
|
||||
if (bufferLine.isWrapped) {
|
||||
if ((<any>bufferLine).isWrapped) {
|
||||
result[result.length - 1] += lineText;
|
||||
} else {
|
||||
result.push(lineText);
|
||||
@@ -197,7 +197,7 @@ export class SelectionManager extends EventEmitter {
|
||||
if (start[1] !== end[1]) {
|
||||
const bufferLine = this._buffer.get(end[1]);
|
||||
const lineText = translateBufferLineToString(bufferLine, true, 0, end[0]);
|
||||
if (bufferLine.isWrapped) {
|
||||
if ((<any>bufferLine).isWrapped) {
|
||||
result[result.length - 1] += lineText;
|
||||
} else {
|
||||
result.push(lineText);
|
||||
@@ -281,7 +281,7 @@ export class SelectionManager extends EventEmitter {
|
||||
coords[0]--;
|
||||
coords[1]--;
|
||||
// Convert viewport coords to buffer coords
|
||||
coords[1] += this._terminal.ydisp;
|
||||
coords[1] += this._terminal.buffer.ydisp;
|
||||
return coords;
|
||||
}
|
||||
|
||||
@@ -476,9 +476,9 @@ export class SelectionManager extends EventEmitter {
|
||||
this._terminal.scrollDisp(this._dragScrollAmount, false);
|
||||
// Re-evaluate selection
|
||||
if (this._dragScrollAmount > 0) {
|
||||
this._model.selectionEnd = [this._terminal.cols - 1, this._terminal.ydisp + this._terminal.rows];
|
||||
this._model.selectionEnd = [this._terminal.cols - 1, this._terminal.buffer.ydisp + this._terminal.rows];
|
||||
} else {
|
||||
this._model.selectionEnd = [0, this._terminal.ydisp];
|
||||
this._model.selectionEnd = [0, this._terminal.buffer.ydisp];
|
||||
}
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import { assert } from 'chai';
|
||||
import { ITerminal } from './Interfaces';
|
||||
import { SelectionModel } from './SelectionModel';
|
||||
import {BufferSet} from './BufferSet';
|
||||
|
||||
class TestSelectionModel extends SelectionModel {
|
||||
constructor(
|
||||
@@ -22,6 +23,10 @@ describe('SelectionManager', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
terminal = <any>{ cols: 80, rows: 2, ybase: 0 };
|
||||
terminal.scrollback = 10;
|
||||
terminal.buffers = new BufferSet(terminal);
|
||||
terminal.buffer = terminal.buffers.active;
|
||||
|
||||
model = new TestSelectionModel(terminal);
|
||||
});
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ export class SelectionModel {
|
||||
*/
|
||||
public get finalSelectionEnd(): [number, number] {
|
||||
if (this.isSelectAllActive) {
|
||||
return [this._terminal.cols, this._terminal.ybase + this._terminal.rows - 1];
|
||||
return [this._terminal.cols, this._terminal.buffer.ybase + this._terminal.rows - 1];
|
||||
}
|
||||
|
||||
if (!this.selectionStart) {
|
||||
|
||||
+11
-9
@@ -1,10 +1,10 @@
|
||||
import { assert } from 'chai';
|
||||
import { Viewport } from './Viewport';
|
||||
import {BufferSet} from './BufferSet';
|
||||
|
||||
describe('Viewport', () => {
|
||||
let terminal;
|
||||
let viewportElement;
|
||||
let selectionContainer;
|
||||
let charMeasure;
|
||||
let viewport;
|
||||
let scrollAreaElement;
|
||||
@@ -13,7 +13,6 @@ describe('Viewport', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
terminal = {
|
||||
lines: [],
|
||||
rows: 0,
|
||||
ydisp: 0,
|
||||
on: () => {},
|
||||
@@ -26,8 +25,11 @@ describe('Viewport', () => {
|
||||
style: {
|
||||
height: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
scrollback: 10
|
||||
};
|
||||
terminal.buffers = new BufferSet(terminal);
|
||||
terminal.buffer = terminal.buffers.active;
|
||||
viewportElement = {
|
||||
addEventListener: () => {},
|
||||
style: {
|
||||
@@ -60,14 +62,14 @@ describe('Viewport', () => {
|
||||
}, 0);
|
||||
});
|
||||
it('should set the height of the viewport when the line-height changed', () => {
|
||||
terminal.lines.push('');
|
||||
terminal.lines.push('');
|
||||
terminal.buffer.lines.push('');
|
||||
terminal.buffer.lines.push('');
|
||||
terminal.rows = 1;
|
||||
viewport.refresh();
|
||||
assert.equal(viewportElement.style.height, 1 * CHARACTER_HEIGHT + 'px');
|
||||
charMeasure.height = 20;
|
||||
charMeasure.height = 2 * CHARACTER_HEIGHT;
|
||||
viewport.refresh();
|
||||
assert.equal(viewportElement.style.height, 20 + 'px');
|
||||
assert.equal(viewportElement.style.height, 2 * CHARACTER_HEIGHT + 'px');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -75,13 +77,13 @@ describe('Viewport', () => {
|
||||
it('should sync the scroll area', done => {
|
||||
// Allow CharMeasure to be initialized
|
||||
setTimeout(() => {
|
||||
terminal.lines.push('');
|
||||
terminal.buffer.lines.push('');
|
||||
terminal.rows = 1;
|
||||
assert.equal(scrollAreaElement.style.height, 0 * CHARACTER_HEIGHT + 'px');
|
||||
viewport.syncScrollArea();
|
||||
assert.equal(viewportElement.style.height, 1 * CHARACTER_HEIGHT + 'px');
|
||||
assert.equal(scrollAreaElement.style.height, 1 * CHARACTER_HEIGHT + 'px');
|
||||
terminal.lines.push('');
|
||||
terminal.buffer.lines.push('');
|
||||
viewport.syncScrollArea();
|
||||
assert.equal(viewportElement.style.height, 1 * CHARACTER_HEIGHT + 'px');
|
||||
assert.equal(scrollAreaElement.style.height, 2 * CHARACTER_HEIGHT + 'px');
|
||||
|
||||
+5
-7
@@ -20,7 +20,7 @@ export class Viewport {
|
||||
* @param terminal The terminal this viewport belongs to.
|
||||
* @param viewportElement The DOM element acting as the viewport.
|
||||
* @param scrollArea The DOM element acting as the scroll area.
|
||||
* @param charMeasureElement A DOM element used to measure the character size of. the terminal.
|
||||
* @param charMeasure A DOM element used to measure the character size of. the terminal.
|
||||
*/
|
||||
constructor(
|
||||
private terminal: ITerminal,
|
||||
@@ -43,8 +43,6 @@ export class Viewport {
|
||||
/**
|
||||
* Refreshes row height, setting line-height, viewport height and scroll area height if
|
||||
* necessary.
|
||||
* @param charSize A character size measurement bounding rect object, if it doesn't exist it will
|
||||
* be created.
|
||||
*/
|
||||
private refresh(): void {
|
||||
if (this.charMeasure.height > 0) {
|
||||
@@ -68,9 +66,9 @@ export class Viewport {
|
||||
* Updates dimensions and synchronizes the scroll area if necessary.
|
||||
*/
|
||||
public syncScrollArea(): void {
|
||||
if (this.lastRecordedBufferLength !== this.terminal.lines.length) {
|
||||
if (this.lastRecordedBufferLength !== this.terminal.buffer.lines.length) {
|
||||
// If buffer height changed
|
||||
this.lastRecordedBufferLength = this.terminal.lines.length;
|
||||
this.lastRecordedBufferLength = this.terminal.buffer.lines.length;
|
||||
this.refresh();
|
||||
} else if (this.lastRecordedViewportHeight !== this.terminal.rows) {
|
||||
// If viewport height changed
|
||||
@@ -83,7 +81,7 @@ export class Viewport {
|
||||
}
|
||||
|
||||
// Sync scrollTop
|
||||
const scrollTop = this.terminal.ydisp * this.currentRowHeight;
|
||||
const scrollTop = this.terminal.buffer.ydisp * this.currentRowHeight;
|
||||
if (this.viewportElement.scrollTop !== scrollTop) {
|
||||
this.viewportElement.scrollTop = scrollTop;
|
||||
}
|
||||
@@ -96,7 +94,7 @@ export class Viewport {
|
||||
*/
|
||||
private onScroll(ev: Event) {
|
||||
const newRow = Math.round(this.viewportElement.scrollTop / this.currentRowHeight);
|
||||
const diff = newRow - this.terminal.ydisp;
|
||||
const diff = newRow - this.terminal.buffer.ydisp;
|
||||
this.terminal.scrollDisp(diff, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -62,10 +62,10 @@ function formatError(in_, out_, expected) {
|
||||
function terminalToString(term) {
|
||||
var result = '';
|
||||
var line_s = '';
|
||||
for (var line = term.ybase; line < term.ybase + term.rows; line++) {
|
||||
for (var line = term.buffer.ybase; line < term.buffer.ybase + term.rows; line++) {
|
||||
line_s = '';
|
||||
for (var cell=0; cell<term.cols; ++cell) {
|
||||
line_s += term.lines.get(line)[cell][1];
|
||||
line_s += term.buffer.lines.get(line)[cell][1];
|
||||
}
|
||||
// rtrim empty cells as xterm does
|
||||
line_s = line_s.replace(/\s+$/, '');
|
||||
|
||||
+128
-128
@@ -64,15 +64,15 @@ describe('xterm.js', function() {
|
||||
|
||||
describe('clear', function() {
|
||||
it('should clear a buffer equal to rows', function() {
|
||||
var promptLine = xterm.lines.get(xterm.ybase + xterm.y);
|
||||
var promptLine = xterm.buffer.lines.get(xterm.buffer.ybase + xterm.buffer.y);
|
||||
xterm.clear();
|
||||
assert.equal(xterm.y, 0);
|
||||
assert.equal(xterm.ybase, 0);
|
||||
assert.equal(xterm.ydisp, 0);
|
||||
assert.equal(xterm.lines.length, xterm.rows);
|
||||
assert.deepEqual(xterm.lines.get(0), promptLine);
|
||||
assert.equal(xterm.buffer.y, 0);
|
||||
assert.equal(xterm.buffer.ybase, 0);
|
||||
assert.equal(xterm.buffer.ydisp, 0);
|
||||
assert.equal(xterm.buffer.lines.length, xterm.rows);
|
||||
assert.deepEqual(xterm.buffer.lines.get(0), promptLine);
|
||||
for (var i = 1; i < xterm.rows; i++) {
|
||||
assert.deepEqual(xterm.lines.get(i), xterm.blankLine());
|
||||
assert.deepEqual(xterm.buffer.lines.get(i), xterm.blankLine());
|
||||
}
|
||||
});
|
||||
it('should clear a buffer larger than rows', function() {
|
||||
@@ -81,28 +81,28 @@ describe('xterm.js', function() {
|
||||
xterm.write('test\n');
|
||||
}
|
||||
|
||||
var promptLine = xterm.lines.get(xterm.ybase + xterm.y);
|
||||
var promptLine = xterm.buffer.lines.get(xterm.buffer.ybase + xterm.buffer.y);
|
||||
xterm.clear();
|
||||
assert.equal(xterm.y, 0);
|
||||
assert.equal(xterm.ybase, 0);
|
||||
assert.equal(xterm.ydisp, 0);
|
||||
assert.equal(xterm.lines.length, xterm.rows);
|
||||
assert.deepEqual(xterm.lines.get(0), promptLine);
|
||||
assert.equal(xterm.buffer.y, 0);
|
||||
assert.equal(xterm.buffer.ybase, 0);
|
||||
assert.equal(xterm.buffer.ydisp, 0);
|
||||
assert.equal(xterm.buffer.lines.length, xterm.rows);
|
||||
assert.deepEqual(xterm.buffer.lines.get(0), promptLine);
|
||||
for (var i = 1; i < xterm.rows; i++) {
|
||||
assert.deepEqual(xterm.lines.get(i), xterm.blankLine());
|
||||
assert.deepEqual(xterm.buffer.lines.get(i), xterm.blankLine());
|
||||
}
|
||||
});
|
||||
it('should not break the prompt when cleared twice', function() {
|
||||
var promptLine = xterm.lines.get(xterm.ybase + xterm.y);
|
||||
var promptLine = xterm.buffer.lines.get(xterm.buffer.ybase + xterm.buffer.y);
|
||||
xterm.clear();
|
||||
xterm.clear();
|
||||
assert.equal(xterm.y, 0);
|
||||
assert.equal(xterm.ybase, 0);
|
||||
assert.equal(xterm.ydisp, 0);
|
||||
assert.equal(xterm.lines.length, xterm.rows);
|
||||
assert.deepEqual(xterm.lines.get(0), promptLine);
|
||||
assert.equal(xterm.buffer.y, 0);
|
||||
assert.equal(xterm.buffer.ybase, 0);
|
||||
assert.equal(xterm.buffer.ydisp, 0);
|
||||
assert.equal(xterm.buffer.lines.length, xterm.rows);
|
||||
assert.deepEqual(xterm.buffer.lines.get(0), promptLine);
|
||||
for (var i = 1; i < xterm.rows; i++) {
|
||||
assert.deepEqual(xterm.lines.get(i), xterm.blankLine());
|
||||
assert.deepEqual(xterm.buffer.lines.get(i), xterm.blankLine());
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -117,29 +117,29 @@ describe('xterm.js', function() {
|
||||
startYDisp = xterm.rows + 1;
|
||||
});
|
||||
it('should scroll a single line', function() {
|
||||
assert.equal(xterm.ydisp, startYDisp);
|
||||
assert.equal(xterm.buffer.ydisp, startYDisp);
|
||||
xterm.scrollDisp(-1);
|
||||
assert.equal(xterm.ydisp, startYDisp - 1);
|
||||
assert.equal(xterm.buffer.ydisp, startYDisp - 1);
|
||||
xterm.scrollDisp(1);
|
||||
assert.equal(xterm.ydisp, startYDisp);
|
||||
assert.equal(xterm.buffer.ydisp, startYDisp);
|
||||
});
|
||||
it('should scroll multiple lines', function() {
|
||||
assert.equal(xterm.ydisp, startYDisp);
|
||||
assert.equal(xterm.buffer.ydisp, startYDisp);
|
||||
xterm.scrollDisp(-5);
|
||||
assert.equal(xterm.ydisp, startYDisp - 5);
|
||||
assert.equal(xterm.buffer.ydisp, startYDisp - 5);
|
||||
xterm.scrollDisp(5);
|
||||
assert.equal(xterm.ydisp, startYDisp);
|
||||
assert.equal(xterm.buffer.ydisp, startYDisp);
|
||||
});
|
||||
it('should not scroll beyond the bounds of the buffer', function() {
|
||||
assert.equal(xterm.ydisp, startYDisp);
|
||||
assert.equal(xterm.buffer.ydisp, startYDisp);
|
||||
xterm.scrollDisp(1);
|
||||
assert.equal(xterm.ydisp, startYDisp);
|
||||
assert.equal(xterm.buffer.ydisp, startYDisp);
|
||||
for (var i = 0; i < startYDisp; i++) {
|
||||
xterm.scrollDisp(-1);
|
||||
}
|
||||
assert.equal(xterm.ydisp, 0);
|
||||
assert.equal(xterm.buffer.ydisp, 0);
|
||||
xterm.scrollDisp(-1);
|
||||
assert.equal(xterm.ydisp, 0);
|
||||
assert.equal(xterm.buffer.ydisp, 0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -152,18 +152,18 @@ describe('xterm.js', function() {
|
||||
startYDisp = (xterm.rows * 2) + 1;
|
||||
});
|
||||
it('should scroll a single page', function() {
|
||||
assert.equal(xterm.ydisp, startYDisp);
|
||||
assert.equal(xterm.buffer.ydisp, startYDisp);
|
||||
xterm.scrollPages(-1);
|
||||
assert.equal(xterm.ydisp, startYDisp - (xterm.rows - 1));
|
||||
assert.equal(xterm.buffer.ydisp, startYDisp - (xterm.rows - 1));
|
||||
xterm.scrollPages(1);
|
||||
assert.equal(xterm.ydisp, startYDisp);
|
||||
assert.equal(xterm.buffer.ydisp, startYDisp);
|
||||
});
|
||||
it('should scroll a multiple pages', function() {
|
||||
assert.equal(xterm.ydisp, startYDisp);
|
||||
assert.equal(xterm.buffer.ydisp, startYDisp);
|
||||
xterm.scrollPages(-2);
|
||||
assert.equal(xterm.ydisp, startYDisp - (xterm.rows - 1) * 2);
|
||||
assert.equal(xterm.buffer.ydisp, startYDisp - (xterm.rows - 1) * 2);
|
||||
xterm.scrollPages(2);
|
||||
assert.equal(xterm.ydisp, startYDisp);
|
||||
assert.equal(xterm.buffer.ydisp, startYDisp);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -174,9 +174,9 @@ describe('xterm.js', function() {
|
||||
}
|
||||
});
|
||||
it('should scroll to the top', function() {
|
||||
assert.notEqual(xterm.ydisp, 0);
|
||||
assert.notEqual(xterm.buffer.ydisp, 0);
|
||||
xterm.scrollToTop();
|
||||
assert.equal(xterm.ydisp, 0);
|
||||
assert.equal(xterm.buffer.ydisp, 0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -191,13 +191,13 @@ describe('xterm.js', function() {
|
||||
it('should scroll to the bottom', function() {
|
||||
xterm.scrollDisp(-1);
|
||||
xterm.scrollToBottom();
|
||||
assert.equal(xterm.ydisp, startYDisp);
|
||||
assert.equal(xterm.buffer.ydisp, startYDisp);
|
||||
xterm.scrollPages(-1);
|
||||
xterm.scrollToBottom();
|
||||
assert.equal(xterm.ydisp, startYDisp);
|
||||
assert.equal(xterm.buffer.ydisp, startYDisp);
|
||||
xterm.scrollToTop();
|
||||
xterm.scrollToBottom();
|
||||
assert.equal(xterm.ydisp, startYDisp);
|
||||
assert.equal(xterm.buffer.ydisp, startYDisp);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -214,13 +214,13 @@ describe('xterm.js', function() {
|
||||
stopPropagation: function(){}
|
||||
};
|
||||
|
||||
xterm.ydisp = 0;
|
||||
xterm.ybase = 40;
|
||||
assert.notEqual(xterm.ydisp, xterm.ybase);
|
||||
xterm.buffer.ydisp = 0;
|
||||
xterm.buffer.ybase = 40;
|
||||
assert.notEqual(xterm.buffer.ydisp, xterm.buffer.ybase);
|
||||
xterm.keyDown(event);
|
||||
|
||||
// Ensure that now the terminal is scrolled to bottom
|
||||
assert.equal(xterm.ydisp, xterm.ybase);
|
||||
assert.equal(xterm.buffer.ydisp, xterm.buffer.ybase);
|
||||
});
|
||||
|
||||
it('should not scroll down, when a custom keydown handler prevents the event', function () {
|
||||
@@ -233,11 +233,11 @@ describe('xterm.js', function() {
|
||||
return false;
|
||||
});
|
||||
|
||||
assert.equal(xterm.ydisp, startYDisp);
|
||||
assert.equal(xterm.buffer.ydisp, startYDisp);
|
||||
xterm.scrollDisp(-1);
|
||||
assert.equal(xterm.ydisp, startYDisp - 1);
|
||||
assert.equal(xterm.buffer.ydisp, startYDisp - 1);
|
||||
xterm.keyDown({ keyCode: 0 });
|
||||
assert.equal(xterm.ydisp, startYDisp - 1);
|
||||
assert.equal(xterm.buffer.ydisp, startYDisp - 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -575,48 +575,48 @@ describe('xterm.js', function() {
|
||||
var high = String.fromCharCode(0xD800);
|
||||
for (var i=0xDC00; i<=0xDCFF; ++i) {
|
||||
xterm.write(high + String.fromCharCode(i));
|
||||
var tchar = xterm.lines.get(0)[0];
|
||||
var tchar = xterm.buffer.lines.get(0)[0];
|
||||
expect(tchar[1]).eql(high + String.fromCharCode(i));
|
||||
expect(tchar[1].length).eql(2);
|
||||
expect(tchar[2]).eql(1);
|
||||
expect(xterm.lines.get(0)[1][1]).eql(' ');
|
||||
expect(xterm.buffer.lines.get(0)[1][1]).eql(' ');
|
||||
xterm.reset();
|
||||
}
|
||||
});
|
||||
it('2 characters at last cell', function() {
|
||||
var high = String.fromCharCode(0xD800);
|
||||
for (var i=0xDC00; i<=0xDCFF; ++i) {
|
||||
xterm.x = xterm.cols - 1;
|
||||
xterm.buffer.x = xterm.cols - 1;
|
||||
xterm.write(high + String.fromCharCode(i));
|
||||
expect(xterm.lines.get(0)[xterm.x-1][1]).eql(high + String.fromCharCode(i));
|
||||
expect(xterm.lines.get(0)[xterm.x-1][1].length).eql(2);
|
||||
expect(xterm.lines.get(1)[0][1]).eql(' ');
|
||||
expect(xterm.buffer.lines.get(0)[xterm.buffer.x-1][1]).eql(high + String.fromCharCode(i));
|
||||
expect(xterm.buffer.lines.get(0)[xterm.buffer.x-1][1].length).eql(2);
|
||||
expect(xterm.buffer.lines.get(1)[0][1]).eql(' ');
|
||||
xterm.reset();
|
||||
}
|
||||
});
|
||||
it('2 characters per cell over line end with autowrap', function() {
|
||||
var high = String.fromCharCode(0xD800);
|
||||
for (var i=0xDC00; i<=0xDCFF; ++i) {
|
||||
xterm.x = xterm.cols - 1;
|
||||
xterm.buffer.x = xterm.cols - 1;
|
||||
xterm.wraparoundMode = true;
|
||||
xterm.write('a' + high + String.fromCharCode(i));
|
||||
expect(xterm.lines.get(0)[xterm.cols-1][1]).eql('a');
|
||||
expect(xterm.lines.get(1)[0][1]).eql(high + String.fromCharCode(i));
|
||||
expect(xterm.lines.get(1)[0][1].length).eql(2);
|
||||
expect(xterm.lines.get(1)[1][1]).eql(' ');
|
||||
expect(xterm.buffer.lines.get(0)[xterm.cols-1][1]).eql('a');
|
||||
expect(xterm.buffer.lines.get(1)[0][1]).eql(high + String.fromCharCode(i));
|
||||
expect(xterm.buffer.lines.get(1)[0][1].length).eql(2);
|
||||
expect(xterm.buffer.lines.get(1)[1][1]).eql(' ');
|
||||
xterm.reset();
|
||||
}
|
||||
});
|
||||
it('2 characters per cell over line end without autowrap', function() {
|
||||
var high = String.fromCharCode(0xD800);
|
||||
for (var i=0xDC00; i<=0xDCFF; ++i) {
|
||||
xterm.x = xterm.cols - 1;
|
||||
xterm.buffer.x = xterm.cols - 1;
|
||||
xterm.wraparoundMode = false;
|
||||
xterm.write('a' + high + String.fromCharCode(i));
|
||||
// auto wraparound mode should cut off the rest of the line
|
||||
expect(xterm.lines.get(0)[xterm.cols-1][1]).eql('a');
|
||||
expect(xterm.lines.get(0)[xterm.cols-1][1].length).eql(1);
|
||||
expect(xterm.lines.get(1)[1][1]).eql(' ');
|
||||
expect(xterm.buffer.lines.get(0)[xterm.cols-1][1]).eql('a');
|
||||
expect(xterm.buffer.lines.get(0)[xterm.cols-1][1].length).eql(1);
|
||||
expect(xterm.buffer.lines.get(1)[1][1]).eql(' ');
|
||||
xterm.reset();
|
||||
}
|
||||
});
|
||||
@@ -625,11 +625,11 @@ describe('xterm.js', function() {
|
||||
for (var i=0xDC00; i<=0xDCFF; ++i) {
|
||||
xterm.write(high);
|
||||
xterm.write(String.fromCharCode(i));
|
||||
var tchar = xterm.lines.get(0)[0];
|
||||
var tchar = xterm.buffer.lines.get(0)[0];
|
||||
expect(tchar[1]).eql(high + String.fromCharCode(i));
|
||||
expect(tchar[1].length).eql(2);
|
||||
expect(tchar[2]).eql(1);
|
||||
expect(xterm.lines.get(0)[1][1]).eql(' ');
|
||||
expect(xterm.buffer.lines.get(0)[1][1]).eql(' ');
|
||||
xterm.reset();
|
||||
}
|
||||
});
|
||||
@@ -638,30 +638,30 @@ describe('xterm.js', function() {
|
||||
describe('unicode - combining characters', function() {
|
||||
it('café', function () {
|
||||
xterm.write('cafe\u0301');
|
||||
expect(xterm.lines.get(0)[3][1]).eql('e\u0301');
|
||||
expect(xterm.lines.get(0)[3][1].length).eql(2);
|
||||
expect(xterm.lines.get(0)[3][2]).eql(1);
|
||||
expect(xterm.buffer.lines.get(0)[3][1]).eql('e\u0301');
|
||||
expect(xterm.buffer.lines.get(0)[3][1].length).eql(2);
|
||||
expect(xterm.buffer.lines.get(0)[3][2]).eql(1);
|
||||
});
|
||||
it('café - end of line', function() {
|
||||
xterm.x = xterm.cols - 1 - 3;
|
||||
xterm.buffer.x = xterm.cols - 1 - 3;
|
||||
xterm.write('cafe\u0301');
|
||||
expect(xterm.lines.get(0)[xterm.cols-1][1]).eql('e\u0301');
|
||||
expect(xterm.lines.get(0)[xterm.cols-1][1].length).eql(2);
|
||||
expect(xterm.lines.get(0)[xterm.cols-1][2]).eql(1);
|
||||
expect(xterm.lines.get(0)[1][1]).eql(' ');
|
||||
expect(xterm.lines.get(0)[1][1].length).eql(1);
|
||||
expect(xterm.lines.get(0)[1][2]).eql(1);
|
||||
expect(xterm.buffer.lines.get(0)[xterm.cols-1][1]).eql('e\u0301');
|
||||
expect(xterm.buffer.lines.get(0)[xterm.cols-1][1].length).eql(2);
|
||||
expect(xterm.buffer.lines.get(0)[xterm.cols-1][2]).eql(1);
|
||||
expect(xterm.buffer.lines.get(0)[1][1]).eql(' ');
|
||||
expect(xterm.buffer.lines.get(0)[1][1].length).eql(1);
|
||||
expect(xterm.buffer.lines.get(0)[1][2]).eql(1);
|
||||
});
|
||||
it('multiple combined é', function() {
|
||||
xterm.wraparoundMode = true;
|
||||
xterm.write(Array(100).join('e\u0301'));
|
||||
for (var i=0; i<xterm.cols; ++i) {
|
||||
var tchar = xterm.lines.get(0)[i];
|
||||
var tchar = xterm.buffer.lines.get(0)[i];
|
||||
expect(tchar[1]).eql('e\u0301');
|
||||
expect(tchar[1].length).eql(2);
|
||||
expect(tchar[2]).eql(1);
|
||||
}
|
||||
tchar = xterm.lines.get(1)[0];
|
||||
tchar = xterm.buffer.lines.get(1)[0];
|
||||
expect(tchar[1]).eql('e\u0301');
|
||||
expect(tchar[1].length).eql(2);
|
||||
expect(tchar[2]).eql(1);
|
||||
@@ -670,12 +670,12 @@ describe('xterm.js', function() {
|
||||
xterm.wraparoundMode = true;
|
||||
xterm.write(Array(100).join('\uD800\uDC00\u0301'));
|
||||
for (var i=0; i<xterm.cols; ++i) {
|
||||
var tchar = xterm.lines.get(0)[i];
|
||||
var tchar = xterm.buffer.lines.get(0)[i];
|
||||
expect(tchar[1]).eql('\uD800\uDC00\u0301');
|
||||
expect(tchar[1].length).eql(3);
|
||||
expect(tchar[2]).eql(1);
|
||||
}
|
||||
tchar = xterm.lines.get(1)[0];
|
||||
tchar = xterm.buffer.lines.get(1)[0];
|
||||
expect(tchar[1]).eql('\uD800\uDC00\u0301');
|
||||
expect(tchar[1].length).eql(3);
|
||||
expect(tchar[2]).eql(1);
|
||||
@@ -684,21 +684,21 @@ describe('xterm.js', function() {
|
||||
|
||||
describe('unicode - fullwidth characters', function() {
|
||||
it('cursor movement even', function() {
|
||||
expect(xterm.x).eql(0);
|
||||
expect(xterm.buffer.x).eql(0);
|
||||
xterm.write('¥');
|
||||
expect(xterm.x).eql(2);
|
||||
expect(xterm.buffer.x).eql(2);
|
||||
});
|
||||
it('cursor movement odd', function() {
|
||||
xterm.x = 1;
|
||||
expect(xterm.x).eql(1);
|
||||
xterm.buffer.x = 1;
|
||||
expect(xterm.buffer.x).eql(1);
|
||||
xterm.write('¥');
|
||||
expect(xterm.x).eql(3);
|
||||
expect(xterm.buffer.x).eql(3);
|
||||
});
|
||||
it('line of ¥ even', function() {
|
||||
xterm.wraparoundMode = true;
|
||||
xterm.write(Array(50).join('¥'));
|
||||
for (var i=0; i<xterm.cols; ++i) {
|
||||
var tchar = xterm.lines.get(0)[i];
|
||||
var tchar = xterm.buffer.lines.get(0)[i];
|
||||
if (i % 2) {
|
||||
expect(tchar[1]).eql('');
|
||||
expect(tchar[1].length).eql(0);
|
||||
@@ -709,17 +709,17 @@ describe('xterm.js', function() {
|
||||
expect(tchar[2]).eql(2);
|
||||
}
|
||||
}
|
||||
tchar = xterm.lines.get(1)[0];
|
||||
tchar = xterm.buffer.lines.get(1)[0];
|
||||
expect(tchar[1]).eql('¥');
|
||||
expect(tchar[1].length).eql(1);
|
||||
expect(tchar[2]).eql(2);
|
||||
});
|
||||
it('line of ¥ odd', function() {
|
||||
xterm.wraparoundMode = true;
|
||||
xterm.x = 1;
|
||||
xterm.buffer.x = 1;
|
||||
xterm.write(Array(50).join('¥'));
|
||||
for (var i=1; i<xterm.cols-1; ++i) {
|
||||
var tchar = xterm.lines.get(0)[i];
|
||||
var tchar = xterm.buffer.lines.get(0)[i];
|
||||
if (!(i % 2)) {
|
||||
expect(tchar[1]).eql('');
|
||||
expect(tchar[1].length).eql(0);
|
||||
@@ -730,21 +730,21 @@ describe('xterm.js', function() {
|
||||
expect(tchar[2]).eql(2);
|
||||
}
|
||||
}
|
||||
tchar = xterm.lines.get(0)[xterm.cols-1];
|
||||
tchar = xterm.buffer.lines.get(0)[xterm.cols-1];
|
||||
expect(tchar[1]).eql(' ');
|
||||
expect(tchar[1].length).eql(1);
|
||||
expect(tchar[2]).eql(1);
|
||||
tchar = xterm.lines.get(1)[0];
|
||||
tchar = xterm.buffer.lines.get(1)[0];
|
||||
expect(tchar[1]).eql('¥');
|
||||
expect(tchar[1].length).eql(1);
|
||||
expect(tchar[2]).eql(2);
|
||||
});
|
||||
it('line of ¥ with combining odd', function() {
|
||||
xterm.wraparoundMode = true;
|
||||
xterm.x = 1;
|
||||
xterm.buffer.x = 1;
|
||||
xterm.write(Array(50).join('¥\u0301'));
|
||||
for (var i=1; i<xterm.cols-1; ++i) {
|
||||
var tchar = xterm.lines.get(0)[i];
|
||||
var tchar = xterm.buffer.lines.get(0)[i];
|
||||
if (!(i % 2)) {
|
||||
expect(tchar[1]).eql('');
|
||||
expect(tchar[1].length).eql(0);
|
||||
@@ -755,11 +755,11 @@ describe('xterm.js', function() {
|
||||
expect(tchar[2]).eql(2);
|
||||
}
|
||||
}
|
||||
tchar = xterm.lines.get(0)[xterm.cols-1];
|
||||
tchar = xterm.buffer.lines.get(0)[xterm.cols-1];
|
||||
expect(tchar[1]).eql(' ');
|
||||
expect(tchar[1].length).eql(1);
|
||||
expect(tchar[2]).eql(1);
|
||||
tchar = xterm.lines.get(1)[0];
|
||||
tchar = xterm.buffer.lines.get(1)[0];
|
||||
expect(tchar[1]).eql('¥\u0301');
|
||||
expect(tchar[1].length).eql(2);
|
||||
expect(tchar[2]).eql(2);
|
||||
@@ -768,7 +768,7 @@ describe('xterm.js', function() {
|
||||
xterm.wraparoundMode = true;
|
||||
xterm.write(Array(50).join('¥\u0301'));
|
||||
for (var i=0; i<xterm.cols; ++i) {
|
||||
var tchar = xterm.lines.get(0)[i];
|
||||
var tchar = xterm.buffer.lines.get(0)[i];
|
||||
if (i % 2) {
|
||||
expect(tchar[1]).eql('');
|
||||
expect(tchar[1].length).eql(0);
|
||||
@@ -779,17 +779,17 @@ describe('xterm.js', function() {
|
||||
expect(tchar[2]).eql(2);
|
||||
}
|
||||
}
|
||||
tchar = xterm.lines.get(1)[0];
|
||||
tchar = xterm.buffer.lines.get(1)[0];
|
||||
expect(tchar[1]).eql('¥\u0301');
|
||||
expect(tchar[1].length).eql(2);
|
||||
expect(tchar[2]).eql(2);
|
||||
});
|
||||
it('line of surrogate fullwidth with combining odd', function() {
|
||||
xterm.wraparoundMode = true;
|
||||
xterm.x = 1;
|
||||
xterm.buffer.x = 1;
|
||||
xterm.write(Array(50).join('\ud843\ude6d\u0301'));
|
||||
for (var i=1; i<xterm.cols-1; ++i) {
|
||||
var tchar = xterm.lines.get(0)[i];
|
||||
var tchar = xterm.buffer.lines.get(0)[i];
|
||||
if (!(i % 2)) {
|
||||
expect(tchar[1]).eql('');
|
||||
expect(tchar[1].length).eql(0);
|
||||
@@ -800,11 +800,11 @@ describe('xterm.js', function() {
|
||||
expect(tchar[2]).eql(2);
|
||||
}
|
||||
}
|
||||
tchar = xterm.lines.get(0)[xterm.cols-1];
|
||||
tchar = xterm.buffer.lines.get(0)[xterm.cols-1];
|
||||
expect(tchar[1]).eql(' ');
|
||||
expect(tchar[1].length).eql(1);
|
||||
expect(tchar[2]).eql(1);
|
||||
tchar = xterm.lines.get(1)[0];
|
||||
tchar = xterm.buffer.lines.get(1)[0];
|
||||
expect(tchar[1]).eql('\ud843\ude6d\u0301');
|
||||
expect(tchar[1].length).eql(3);
|
||||
expect(tchar[2]).eql(2);
|
||||
@@ -813,7 +813,7 @@ describe('xterm.js', function() {
|
||||
xterm.wraparoundMode = true;
|
||||
xterm.write(Array(50).join('\ud843\ude6d\u0301'));
|
||||
for (var i=0; i<xterm.cols; ++i) {
|
||||
var tchar = xterm.lines.get(0)[i];
|
||||
var tchar = xterm.buffer.lines.get(0)[i];
|
||||
if (i % 2) {
|
||||
expect(tchar[1]).eql('');
|
||||
expect(tchar[1].length).eql(0);
|
||||
@@ -824,7 +824,7 @@ describe('xterm.js', function() {
|
||||
expect(tchar[2]).eql(2);
|
||||
}
|
||||
}
|
||||
tchar = xterm.lines.get(1)[0];
|
||||
tchar = xterm.buffer.lines.get(1)[0];
|
||||
expect(tchar[1]).eql('\ud843\ude6d\u0301');
|
||||
expect(tchar[1].length).eql(3);
|
||||
expect(tchar[2]).eql(2);
|
||||
@@ -834,44 +834,44 @@ describe('xterm.js', function() {
|
||||
describe('insert mode', function() {
|
||||
it('halfwidth - all', function () {
|
||||
xterm.write(Array(9).join('0123456789').slice(-80));
|
||||
xterm.x = 10;
|
||||
xterm.y = 0;
|
||||
xterm.buffer.x = 10;
|
||||
xterm.buffer.y = 0;
|
||||
xterm.insertMode = true;
|
||||
xterm.write('abcde');
|
||||
expect(xterm.lines.get(0).length).eql(xterm.cols);
|
||||
expect(xterm.lines.get(0)[10][1]).eql('a');
|
||||
expect(xterm.lines.get(0)[14][1]).eql('e');
|
||||
expect(xterm.lines.get(0)[15][1]).eql('0');
|
||||
expect(xterm.lines.get(0)[79][1]).eql('4');
|
||||
expect(xterm.buffer.lines.get(0).length).eql(xterm.cols);
|
||||
expect(xterm.buffer.lines.get(0)[10][1]).eql('a');
|
||||
expect(xterm.buffer.lines.get(0)[14][1]).eql('e');
|
||||
expect(xterm.buffer.lines.get(0)[15][1]).eql('0');
|
||||
expect(xterm.buffer.lines.get(0)[79][1]).eql('4');
|
||||
});
|
||||
it('fullwidth - insert', function() {
|
||||
xterm.write(Array(9).join('0123456789').slice(-80));
|
||||
xterm.x = 10;
|
||||
xterm.y = 0;
|
||||
xterm.buffer.x = 10;
|
||||
xterm.buffer.y = 0;
|
||||
xterm.insertMode = true;
|
||||
xterm.write('¥¥¥');
|
||||
expect(xterm.lines.get(0).length).eql(xterm.cols);
|
||||
expect(xterm.lines.get(0)[10][1]).eql('¥');
|
||||
expect(xterm.lines.get(0)[11][1]).eql('');
|
||||
expect(xterm.lines.get(0)[14][1]).eql('¥');
|
||||
expect(xterm.lines.get(0)[15][1]).eql('');
|
||||
expect(xterm.lines.get(0)[79][1]).eql('3');
|
||||
expect(xterm.buffer.lines.get(0).length).eql(xterm.cols);
|
||||
expect(xterm.buffer.lines.get(0)[10][1]).eql('¥');
|
||||
expect(xterm.buffer.lines.get(0)[11][1]).eql('');
|
||||
expect(xterm.buffer.lines.get(0)[14][1]).eql('¥');
|
||||
expect(xterm.buffer.lines.get(0)[15][1]).eql('');
|
||||
expect(xterm.buffer.lines.get(0)[79][1]).eql('3');
|
||||
});
|
||||
it('fullwidth - right border', function() {
|
||||
xterm.write(Array(41).join('¥'));
|
||||
xterm.x = 10;
|
||||
xterm.y = 0;
|
||||
xterm.buffer.x = 10;
|
||||
xterm.buffer.y = 0;
|
||||
xterm.insertMode = true;
|
||||
xterm.write('a');
|
||||
expect(xterm.lines.get(0).length).eql(xterm.cols);
|
||||
expect(xterm.lines.get(0)[10][1]).eql('a');
|
||||
expect(xterm.lines.get(0)[11][1]).eql('¥');
|
||||
expect(xterm.lines.get(0)[79][1]).eql(' '); // fullwidth char got replaced
|
||||
expect(xterm.buffer.lines.get(0).length).eql(xterm.cols);
|
||||
expect(xterm.buffer.lines.get(0)[10][1]).eql('a');
|
||||
expect(xterm.buffer.lines.get(0)[11][1]).eql('¥');
|
||||
expect(xterm.buffer.lines.get(0)[79][1]).eql(' '); // fullwidth char got replaced
|
||||
xterm.write('b');
|
||||
expect(xterm.lines.get(0).length).eql(xterm.cols);
|
||||
expect(xterm.lines.get(0)[11][1]).eql('b');
|
||||
expect(xterm.lines.get(0)[12][1]).eql('¥');
|
||||
expect(xterm.lines.get(0)[79][1]).eql(''); // empty cell after fullwidth
|
||||
expect(xterm.buffer.lines.get(0).length).eql(xterm.cols);
|
||||
expect(xterm.buffer.lines.get(0)[11][1]).eql('b');
|
||||
expect(xterm.buffer.lines.get(0)[12][1]).eql('¥');
|
||||
expect(xterm.buffer.lines.get(0)[79][1]).eql(''); // empty cell after fullwidth
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+111
-128
@@ -10,6 +10,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { BufferSet } from './BufferSet';
|
||||
import { CompositionHelper } from './CompositionHelper';
|
||||
import { EventEmitter } from './EventEmitter';
|
||||
import { Viewport } from './Viewport';
|
||||
@@ -141,33 +142,10 @@ function Terminal(options) {
|
||||
this.on('data', options.handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* The scroll position of the y cursor, ie. ybase + y = the y position within the entire
|
||||
* buffer
|
||||
*/
|
||||
this.ybase = 0;
|
||||
|
||||
/**
|
||||
* The scroll position of the viewport
|
||||
*/
|
||||
this.ydisp = 0;
|
||||
|
||||
/**
|
||||
* The cursor's x position after ybase
|
||||
*/
|
||||
this.x = 0;
|
||||
|
||||
/**
|
||||
* The cursor's y position after ybase
|
||||
*/
|
||||
this.y = 0;
|
||||
|
||||
this.cursorState = 0;
|
||||
this.cursorHidden = false;
|
||||
this.convertEol;
|
||||
this.queue = '';
|
||||
this.scrollTop = 0;
|
||||
this.scrollBottom = this.rows - 1;
|
||||
this.customKeyEventHandler = null;
|
||||
this.cursorBlinkInterval = null;
|
||||
|
||||
@@ -177,7 +155,6 @@ function Terminal(options) {
|
||||
this.originMode = false;
|
||||
this.insertMode = false;
|
||||
this.wraparoundMode = true; // defaults: xterm - true, vt100 - false
|
||||
this.normal = null;
|
||||
|
||||
// charset
|
||||
this.charset = null;
|
||||
@@ -243,21 +220,23 @@ function Terminal(options) {
|
||||
// leftover surrogate high from previous write invocation
|
||||
this.surrogate_high = '';
|
||||
|
||||
/**
|
||||
* An array of all lines in the entire buffer, including the prompt. The lines are array of
|
||||
* characters which are 2-length arrays where [0] is an attribute and [1] is the character.
|
||||
*/
|
||||
this.lines = new CircularList(this.scrollback);
|
||||
// Create the terminal's buffers and set the current buffer
|
||||
this.buffers = new BufferSet(this);
|
||||
this.buffer = this.buffers.active; // Convenience shortcut;
|
||||
this.buffers.on('activate', function (buffer) {
|
||||
this._terminal.buffer = buffer;
|
||||
});
|
||||
|
||||
var i = this.rows;
|
||||
|
||||
while (i--) {
|
||||
this.lines.push(this.blankLine());
|
||||
this.buffer.lines.push(this.blankLine());
|
||||
}
|
||||
// Ensure the selection manager has the correct buffer
|
||||
if (this.selectionManager) {
|
||||
this.selectionManager.setBuffer(this.lines);
|
||||
this.selectionManager.setBuffer(this.buffer.lines);
|
||||
}
|
||||
|
||||
this.tabs;
|
||||
this.setupStops();
|
||||
|
||||
// Store if user went browsing history in scrollback
|
||||
@@ -430,17 +409,17 @@ Terminal.prototype.setOption = function(key, value) {
|
||||
}
|
||||
|
||||
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 (this.buffer.lines.length > value) {
|
||||
const amountToTrim = this.buffer.lines.length - value;
|
||||
const needsRefresh = (this.buffer.ydisp - amountToTrim < 0);
|
||||
this.buffer.lines.trimStart(amountToTrim);
|
||||
this.buffer.ybase = Math.max(this.buffer.ybase - amountToTrim, 0);
|
||||
this.buffer.ydisp = Math.max(this.buffer.ydisp - amountToTrim, 0);
|
||||
if (needsRefresh) {
|
||||
this.refresh(0, this.rows - 1);
|
||||
}
|
||||
}
|
||||
this.lines.maxLength = value;
|
||||
this.buffer.lines.maxLength = value;
|
||||
this.viewport.syncScrollArea();
|
||||
}
|
||||
break;
|
||||
@@ -513,7 +492,7 @@ Terminal.prototype.blur = function() {
|
||||
*/
|
||||
Terminal.bindBlur = function (term) {
|
||||
on(term.textarea, 'blur', function (ev) {
|
||||
term.refresh(term.y, term.y);
|
||||
term.refresh(term.buffer.y, term.buffer.y);
|
||||
if (term.sendFocus) {
|
||||
term.send(C0.ESC + '[O');
|
||||
}
|
||||
@@ -725,7 +704,9 @@ Terminal.prototype.open = function(parent, focus) {
|
||||
|
||||
this.viewport = new Viewport(this, this.viewportElement, this.viewportScrollArea, this.charMeasure);
|
||||
this.renderer = new Renderer(this);
|
||||
this.selectionManager = new SelectionManager(this, this.lines, this.rowContainer, this.charMeasure);
|
||||
this.selectionManager = new SelectionManager(
|
||||
this, this.buffer.lines, this.rowContainer, this.charMeasure
|
||||
);
|
||||
this.selectionManager.on('refresh', data => {
|
||||
this.renderer.refreshSelection(data.start, data.end);
|
||||
});
|
||||
@@ -1156,7 +1137,7 @@ Terminal.prototype.queueLinkification = function(start, end) {
|
||||
Terminal.prototype.showCursor = function() {
|
||||
if (!this.cursorState) {
|
||||
this.cursorState = 1;
|
||||
this.refresh(this.y, this.y);
|
||||
this.refresh(this.buffer.y, this.buffer.y);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1169,48 +1150,48 @@ Terminal.prototype.scroll = function(isWrapped) {
|
||||
var row;
|
||||
|
||||
// Make room for the new row in lines
|
||||
if (this.lines.length === this.lines.maxLength) {
|
||||
this.lines.trimStart(1);
|
||||
this.ybase--;
|
||||
if (this.ydisp !== 0) {
|
||||
this.ydisp--;
|
||||
if (this.buffer.lines.length === this.buffer.lines.maxLength) {
|
||||
this.buffer.lines.trimStart(1);
|
||||
this.buffer.ybase--;
|
||||
if (this.buffer.ydisp !== 0) {
|
||||
this.buffer.ydisp--;
|
||||
}
|
||||
}
|
||||
|
||||
this.ybase++;
|
||||
this.buffer.ybase++;
|
||||
|
||||
// TODO: Why is this done twice?
|
||||
if (!this.userScrolling) {
|
||||
this.ydisp = this.ybase;
|
||||
this.buffer.ydisp = this.buffer.ybase;
|
||||
}
|
||||
|
||||
// last line
|
||||
row = this.ybase + this.rows - 1;
|
||||
row = this.buffer.ybase + this.rows - 1;
|
||||
|
||||
// subtract the bottom scroll region
|
||||
row -= this.rows - 1 - this.scrollBottom;
|
||||
row -= this.rows - 1 - this.buffer.scrollBottom;
|
||||
|
||||
if (row === this.lines.length) {
|
||||
if (row === this.buffer.lines.length) {
|
||||
// Optimization: pushing is faster than splicing when they amount to the same behavior
|
||||
this.lines.push(this.blankLine(undefined, isWrapped));
|
||||
this.buffer.lines.push(this.blankLine(undefined, isWrapped));
|
||||
} else {
|
||||
// add our new line
|
||||
this.lines.splice(row, 0, this.blankLine(undefined, isWrapped));
|
||||
this.buffer.lines.splice(row, 0, this.blankLine(undefined, isWrapped));
|
||||
}
|
||||
|
||||
if (this.scrollTop !== 0) {
|
||||
if (this.ybase !== 0) {
|
||||
this.ybase--;
|
||||
if (this.buffer.scrollTop !== 0) {
|
||||
if (this.buffer.ybase !== 0) {
|
||||
this.buffer.ybase--;
|
||||
if (!this.userScrolling) {
|
||||
this.ydisp = this.ybase;
|
||||
this.buffer.ydisp = this.buffer.ybase;
|
||||
}
|
||||
}
|
||||
this.lines.splice(this.ybase + this.scrollTop, 1);
|
||||
this.buffer.lines.splice(this.buffer.ybase + this.buffer.scrollTop, 1);
|
||||
}
|
||||
|
||||
// this.maxRange();
|
||||
this.updateRange(this.scrollTop);
|
||||
this.updateRange(this.scrollBottom);
|
||||
this.updateRange(this.buffer.scrollTop);
|
||||
this.updateRange(this.buffer.scrollBottom);
|
||||
|
||||
/**
|
||||
* This event is emitted whenever the terminal is scrolled.
|
||||
@@ -1218,7 +1199,7 @@ Terminal.prototype.scroll = function(isWrapped) {
|
||||
*
|
||||
* @event scroll
|
||||
*/
|
||||
this.emit('scroll', this.ydisp);
|
||||
this.emit('scroll', this.buffer.ydisp);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1230,24 +1211,24 @@ Terminal.prototype.scroll = function(isWrapped) {
|
||||
*/
|
||||
Terminal.prototype.scrollDisp = function(disp, suppressScrollEvent) {
|
||||
if (disp < 0) {
|
||||
if (this.ydisp === 0) {
|
||||
if (this.buffer.ydisp === 0) {
|
||||
return;
|
||||
}
|
||||
this.userScrolling = true;
|
||||
} else if (disp + this.ydisp >= this.ybase) {
|
||||
} else if (disp + this.buffer.ydisp >= this.buffer.ybase) {
|
||||
this.userScrolling = false;
|
||||
}
|
||||
|
||||
const oldYdisp = this.ydisp;
|
||||
this.ydisp = Math.max(Math.min(this.ydisp + disp, this.ybase), 0);
|
||||
const oldYdisp = this.buffer.ydisp;
|
||||
this.buffer.ydisp = Math.max(Math.min(this.buffer.ydisp + disp, this.buffer.ybase), 0);
|
||||
|
||||
// No change occurred, don't trigger scroll/refresh
|
||||
if (oldYdisp === this.ydisp) {
|
||||
if (oldYdisp === this.buffer.ydisp) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!suppressScrollEvent) {
|
||||
this.emit('scroll', this.ydisp);
|
||||
this.emit('scroll', this.buffer.ydisp);
|
||||
}
|
||||
|
||||
this.refresh(0, this.rows - 1);
|
||||
@@ -1265,14 +1246,14 @@ Terminal.prototype.scrollPages = function(pageCount) {
|
||||
* Scrolls the display of the terminal to the top.
|
||||
*/
|
||||
Terminal.prototype.scrollToTop = function() {
|
||||
this.scrollDisp(-this.ydisp);
|
||||
this.scrollDisp(-this.buffer.ydisp);
|
||||
};
|
||||
|
||||
/**
|
||||
* Scrolls the display of the terminal to the bottom.
|
||||
*/
|
||||
Terminal.prototype.scrollToBottom = function() {
|
||||
this.scrollDisp(this.ybase - this.ydisp);
|
||||
this.scrollDisp(this.buffer.ybase - this.buffer.ydisp);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1316,8 +1297,8 @@ Terminal.prototype.innerWrite = function() {
|
||||
this.xoffSentToCatchUp = false;
|
||||
}
|
||||
|
||||
this.refreshStart = this.y;
|
||||
this.refreshEnd = this.y;
|
||||
this.refreshStart = this.buffer.y;
|
||||
this.refreshEnd = this.buffer.y;
|
||||
|
||||
// HACK: Set the parser state based on it's state at the time of return.
|
||||
// This works around the bug #662 which saw the parser state reset in the
|
||||
@@ -1327,7 +1308,7 @@ Terminal.prototype.innerWrite = function() {
|
||||
var state = this.parser.parse(data);
|
||||
this.parser.setState(state);
|
||||
|
||||
this.updateRange(this.y);
|
||||
this.updateRange(this.buffer.y);
|
||||
this.refresh(this.refreshStart, this.refreshEnd);
|
||||
}
|
||||
if (this.writeBuffer.length > 0) {
|
||||
@@ -1480,7 +1461,7 @@ Terminal.prototype.keyDown = function(ev) {
|
||||
this.restartCursorBlinking();
|
||||
|
||||
if (!this.compositionHelper.keydown.bind(this.compositionHelper)(ev)) {
|
||||
if (this.ybase !== this.ydisp) {
|
||||
if (this.buffer.ybase !== this.buffer.ydisp) {
|
||||
this.scrollToBottom();
|
||||
}
|
||||
return false;
|
||||
@@ -1958,10 +1939,10 @@ Terminal.prototype.resize = function(x, y) {
|
||||
j = this.cols;
|
||||
if (j < x) {
|
||||
ch = [this.defAttr, ' ', 1]; // does xterm use the default attr?
|
||||
i = this.lines.length;
|
||||
i = this.buffer.lines.length;
|
||||
while (i--) {
|
||||
while (this.lines.get(i).length < x) {
|
||||
this.lines.get(i).push(ch);
|
||||
while (this.buffer.lines.get(i).length < x) {
|
||||
this.buffer.lines.get(i).push(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1975,21 +1956,21 @@ Terminal.prototype.resize = function(x, y) {
|
||||
if (j < y) {
|
||||
el = this.element;
|
||||
while (j++ < y) {
|
||||
// y is rows, not this.y
|
||||
if (this.lines.length < y + this.ybase) {
|
||||
if (this.ybase > 0 && this.lines.length <= this.ybase + this.y + addToY + 1) {
|
||||
// y is rows, not this.buffer.y
|
||||
if (this.buffer.lines.length < y + this.buffer.ybase) {
|
||||
if (this.buffer.ybase > 0 && this.buffer.lines.length <= this.buffer.ybase + this.buffer.y + addToY + 1) {
|
||||
// There is room above the buffer and there are no empty elements below the line,
|
||||
// scroll up
|
||||
this.ybase--;
|
||||
this.buffer.ybase--;
|
||||
addToY++;
|
||||
if (this.ydisp > 0) {
|
||||
if (this.buffer.ydisp > 0) {
|
||||
// Viewport is at the top of the buffer, must increase downwards
|
||||
this.ydisp--;
|
||||
this.buffer.ydisp--;
|
||||
}
|
||||
} else {
|
||||
// Add a blank line if there is no buffer left at the top to scroll to, or if there
|
||||
// are blank lines after the cursor
|
||||
this.lines.push(this.blankLine());
|
||||
this.buffer.lines.push(this.blankLine());
|
||||
}
|
||||
}
|
||||
if (this.children.length < y) {
|
||||
@@ -1998,14 +1979,14 @@ Terminal.prototype.resize = function(x, y) {
|
||||
}
|
||||
} else { // (j > y)
|
||||
while (j-- > y) {
|
||||
if (this.lines.length > y + this.ybase) {
|
||||
if (this.lines.length > this.ybase + this.y + 1) {
|
||||
if (this.buffer.lines.length > y + this.buffer.ybase) {
|
||||
if (this.buffer.lines.length > this.buffer.ybase + this.buffer.y + 1) {
|
||||
// The line is a blank line below the cursor, remove it
|
||||
this.lines.pop();
|
||||
this.buffer.lines.pop();
|
||||
} else {
|
||||
// The line is the cursor, scroll down
|
||||
this.ybase++;
|
||||
this.ydisp++;
|
||||
this.buffer.ybase++;
|
||||
this.buffer.ydisp++;
|
||||
}
|
||||
}
|
||||
if (this.children.length > y) {
|
||||
@@ -2018,26 +1999,24 @@ Terminal.prototype.resize = function(x, y) {
|
||||
this.rows = y;
|
||||
|
||||
// Make sure that the cursor stays on screen
|
||||
if (this.y >= y) {
|
||||
this.y = y - 1;
|
||||
if (this.buffer.y >= y) {
|
||||
this.buffer.y = y - 1;
|
||||
}
|
||||
if (addToY) {
|
||||
this.y += addToY;
|
||||
this.buffer.y += addToY;
|
||||
}
|
||||
|
||||
if (this.x >= x) {
|
||||
this.x = x - 1;
|
||||
if (this.buffer.x >= x) {
|
||||
this.buffer.x = x - 1;
|
||||
}
|
||||
|
||||
this.scrollTop = 0;
|
||||
this.scrollBottom = y - 1;
|
||||
this.buffer.scrollTop = 0;
|
||||
this.buffer.scrollBottom = y - 1;
|
||||
|
||||
this.charMeasure.measure();
|
||||
|
||||
this.refresh(0, this.rows - 1);
|
||||
|
||||
this.normal = null;
|
||||
|
||||
this.geometry = [this.cols, this.rows];
|
||||
this.emit('resize', {terminal: this, cols: x, rows: y});
|
||||
};
|
||||
@@ -2073,16 +2052,16 @@ Terminal.prototype.maxRange = function() {
|
||||
*/
|
||||
Terminal.prototype.setupStops = function(i) {
|
||||
if (i != null) {
|
||||
if (!this.tabs[i]) {
|
||||
if (!this.buffer.tabs[i]) {
|
||||
i = this.prevStop(i);
|
||||
}
|
||||
} else {
|
||||
this.tabs = {};
|
||||
this.buffer.tabs = {};
|
||||
i = 0;
|
||||
}
|
||||
|
||||
for (; i < this.cols; i += this.getOption('tabStopWidth')) {
|
||||
this.tabs[i] = true;
|
||||
this.buffer.tabs[i] = true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2092,8 +2071,8 @@ Terminal.prototype.setupStops = function(i) {
|
||||
* @param {number} x The position to move the cursor to the previous tab stop.
|
||||
*/
|
||||
Terminal.prototype.prevStop = function(x) {
|
||||
if (x == null) x = this.x;
|
||||
while (!this.tabs[--x] && x > 0);
|
||||
if (x == null) x = this.buffer.x;
|
||||
while (!this.buffer.tabs[--x] && x > 0);
|
||||
return x >= this.cols
|
||||
? this.cols - 1
|
||||
: x < 0 ? 0 : x;
|
||||
@@ -2105,8 +2084,8 @@ Terminal.prototype.prevStop = function(x) {
|
||||
* @param {number} x The position to move the cursor one tab stop forward.
|
||||
*/
|
||||
Terminal.prototype.nextStop = function(x) {
|
||||
if (x == null) x = this.x;
|
||||
while (!this.tabs[++x] && x < this.cols);
|
||||
if (x == null) x = this.buffer.x;
|
||||
while (!this.buffer.tabs[++x] && x < this.cols);
|
||||
return x >= this.cols
|
||||
? this.cols - 1
|
||||
: x < 0 ? 0 : x;
|
||||
@@ -2119,7 +2098,7 @@ Terminal.prototype.nextStop = function(x) {
|
||||
* @param {number} y The line in which to operate.
|
||||
*/
|
||||
Terminal.prototype.eraseRight = function(x, y) {
|
||||
var line = this.lines.get(this.ybase + y);
|
||||
var line = this.buffer.lines.get(this.buffer.ybase + y);
|
||||
if (!line) {
|
||||
return;
|
||||
}
|
||||
@@ -2138,7 +2117,7 @@ Terminal.prototype.eraseRight = function(x, y) {
|
||||
* @param {number} y The line in which to operate.
|
||||
*/
|
||||
Terminal.prototype.eraseLeft = function(x, y) {
|
||||
var line = this.lines.get(this.ybase + y);
|
||||
var line = this.buffer.lines.get(this.buffer.ybase + y);
|
||||
if (!line) {
|
||||
return;
|
||||
}
|
||||
@@ -2154,20 +2133,20 @@ Terminal.prototype.eraseLeft = function(x, y) {
|
||||
* Clears the entire buffer, making the prompt line the new first line.
|
||||
*/
|
||||
Terminal.prototype.clear = function() {
|
||||
if (this.ybase === 0 && this.y === 0) {
|
||||
if (this.buffer.ybase === 0 && this.buffer.y === 0) {
|
||||
// Don't clear if it's already clear
|
||||
return;
|
||||
}
|
||||
this.lines.set(0, this.lines.get(this.ybase + this.y));
|
||||
this.lines.length = 1;
|
||||
this.ydisp = 0;
|
||||
this.ybase = 0;
|
||||
this.y = 0;
|
||||
this.buffer.lines.set(0, this.buffer.lines.get(this.buffer.ybase + this.buffer.y));
|
||||
this.buffer.lines.length = 1;
|
||||
this.buffer.ydisp = 0;
|
||||
this.buffer.ybase = 0;
|
||||
this.buffer.y = 0;
|
||||
for (var i = 1; i < this.rows; i++) {
|
||||
this.lines.push(this.blankLine());
|
||||
this.buffer.lines.push(this.blankLine());
|
||||
}
|
||||
this.refresh(0, this.rows - 1);
|
||||
this.emit('scroll', this.ydisp);
|
||||
this.emit('scroll', this.buffer.ydisp);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2244,7 +2223,7 @@ Terminal.prototype.handler = function(data) {
|
||||
}
|
||||
|
||||
// Input is being sent to the terminal, the terminal should focus the prompt.
|
||||
if (this.ybase !== this.ydisp) {
|
||||
if (this.buffer.ybase !== this.buffer.ydisp) {
|
||||
this.scrollToBottom();
|
||||
}
|
||||
this.emit('data', data);
|
||||
@@ -2274,14 +2253,14 @@ Terminal.prototype.handleTitle = function(title) {
|
||||
* ESC D Index (IND is 0x84).
|
||||
*/
|
||||
Terminal.prototype.index = function() {
|
||||
this.y++;
|
||||
if (this.y > this.scrollBottom) {
|
||||
this.y--;
|
||||
this.buffer.y++;
|
||||
if (this.buffer.y > this.buffer.scrollBottom) {
|
||||
this.buffer.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--;
|
||||
if (this.buffer.x >= this.cols) {
|
||||
this.buffer.x--;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2293,16 +2272,16 @@ Terminal.prototype.index = function() {
|
||||
*/
|
||||
Terminal.prototype.reverseIndex = function() {
|
||||
var j;
|
||||
if (this.y === this.scrollTop) {
|
||||
if (this.buffer.y === this.buffer.scrollTop) {
|
||||
// possibly move the code below to term.reverseScroll();
|
||||
// test: echo -ne '\e[1;1H\e[44m\eM\e[0m'
|
||||
// blankLine(true) is xterm/linux behavior
|
||||
this.lines.shiftElements(this.y + this.ybase, this.rows - 1, 1);
|
||||
this.lines.set(this.y + this.ybase, this.blankLine(true));
|
||||
this.updateRange(this.scrollTop);
|
||||
this.updateRange(this.scrollBottom);
|
||||
this.buffer.lines.shiftElements(this.buffer.y + this.buffer.ybase, this.rows - 1, 1);
|
||||
this.buffer.lines.set(this.buffer.y + this.buffer.ybase, this.blankLine(true));
|
||||
this.updateRange(this.buffer.scrollTop);
|
||||
this.updateRange(this.buffer.scrollBottom);
|
||||
} else {
|
||||
this.y--;
|
||||
this.buffer.y--;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2315,9 +2294,13 @@ Terminal.prototype.reset = function() {
|
||||
this.options.cols = this.cols;
|
||||
var customKeyEventHandler = this.customKeyEventHandler;
|
||||
var cursorBlinkInterval = this.cursorBlinkInterval;
|
||||
var inputHandler = this.inputHandler;
|
||||
var buffers = this.buffers;
|
||||
Terminal.call(this, this.options);
|
||||
this.customKeyEventHandler = customKeyEventHandler;
|
||||
this.cursorBlinkInterval = cursorBlinkInterval;
|
||||
this.inputHandler = inputHandler;
|
||||
this.buffers = buffers;
|
||||
this.refresh(0, this.rows - 1);
|
||||
this.viewport.syncScrollArea();
|
||||
};
|
||||
@@ -2327,7 +2310,7 @@ Terminal.prototype.reset = function() {
|
||||
* ESC H Tab Set (HTS is 0x88).
|
||||
*/
|
||||
Terminal.prototype.tabSet = function() {
|
||||
this.tabs[this.x] = true;
|
||||
this.buffer.tabs[this.buffer.x] = true;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user