mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Resize both buffers on resize
This brings in proper support to resize both buffers (#510) and fixes an exception that was caused by wrongfully not clearing the normal buffer when resizing while the alt buffer is active. There was an obscure bug in this that could have caused some great confusion later on; When switching to the alt buffer, a hard terminal reset was performed which tried to retain the buffers. However, because buffers was initialized in the Terminal constructor to a new BufferSet, the Terminal.buffer convenience pointer was pointing at a stale alt buffer which was the one actually being used, not Terminal.buffers.alt. Fixes #842 Fixes #510
This commit is contained in:
+76
-5
@@ -13,21 +13,21 @@ import { CircularList } from './utils/CircularList';
|
||||
* - scroll position
|
||||
*/
|
||||
export class Buffer {
|
||||
public lines: CircularList<[number, string, number][]>;
|
||||
public readonly lines: CircularList<[number, string, number][]>;
|
||||
|
||||
public savedY: number;
|
||||
public savedX: number;
|
||||
|
||||
/**
|
||||
* Create a new Buffer.
|
||||
* @param {Terminal} terminal - The terminal the Buffer will belong to
|
||||
* @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,
|
||||
private _terminal: ITerminal,
|
||||
public ydisp: number = 0,
|
||||
public ybase: number = 0,
|
||||
public y: number = 0,
|
||||
@@ -36,7 +36,78 @@ export class Buffer {
|
||||
public scrollTop: number = 0,
|
||||
public tabs: any = {},
|
||||
) {
|
||||
this.lines = new CircularList<[number, string, number][]>(this.terminal.scrollback);
|
||||
this.scrollBottom = this.terminal.rows - 1;
|
||||
this.lines = new CircularList<[number, string, number][]>(this._terminal.scrollback);
|
||||
this.scrollBottom = this._terminal.rows - 1;
|
||||
}
|
||||
|
||||
public resize(newCols: number, newRows: number): void {
|
||||
// Don't resize the buffer if it's empty and hasn't been used yet.
|
||||
if (this.lines.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Deal with columns increasing (we don't do anything when columns reduce)
|
||||
if (this._terminal.cols < newCols) {
|
||||
const ch: [number, string, number] = [this._terminal.defAttr, ' ', 1]; // does xterm use the default attr?
|
||||
for (let i = 0; i < this.lines.length; i++) {
|
||||
if (this.lines.get(i) === undefined) {
|
||||
this.lines.set(i, this._terminal.blankLine());
|
||||
}
|
||||
while (this.lines.get(i).length < newCols) {
|
||||
this.lines.get(i).push(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Resize rows in both directions as needed
|
||||
let addToY = 0;
|
||||
if (this._terminal.rows < newRows) {
|
||||
for (let y = this._terminal.rows; y < newRows; y++) {
|
||||
if (this.lines.length < newRows + this.ybase) {
|
||||
if (this.ybase > 0 && this.lines.length <= this.ybase + this.y + addToY + 1) {
|
||||
// There is room above the buffer and there are no empty elements below the line,
|
||||
// scroll up
|
||||
this.ybase--;
|
||||
addToY++;
|
||||
if (this.ydisp > 0) {
|
||||
// Viewport is at the top of the buffer, must increase downwards
|
||||
this.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._terminal.blankLine());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // (this._terminal.rows >= newRows)
|
||||
for (let y = this._terminal.rows; y > newRows; y--) {
|
||||
if (this.lines.length > newRows + this.ybase) {
|
||||
if (this.lines.length > this.ybase + this.y + 1) {
|
||||
// The line is a blank line below the cursor, remove it
|
||||
this.lines.pop();
|
||||
} else {
|
||||
// The line is the cursor, scroll down
|
||||
this.ybase++;
|
||||
this.ydisp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure that the cursor stays on screen
|
||||
if (this.y >= newRows) {
|
||||
this.y = newRows - 1;
|
||||
}
|
||||
if (addToY) {
|
||||
this.y += addToY;
|
||||
}
|
||||
|
||||
if (this.x >= newCols) {
|
||||
this.x = newCols - 1;
|
||||
}
|
||||
|
||||
this.scrollTop = 0;
|
||||
this.scrollBottom = newRows - 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,4 +65,9 @@ export class BufferSet extends EventEmitter implements IBufferSet {
|
||||
this._activeBuffer = this._alt;
|
||||
this.emit('activate', this._alt);
|
||||
}
|
||||
|
||||
public resize(newCols: number, newRows: number): void {
|
||||
this._normal.resize(newCols, newRows);
|
||||
this._alt.resize(newCols, newRows);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ export interface ITerminal {
|
||||
emit(event: string, data: any);
|
||||
reset(): void;
|
||||
showCursor(): void;
|
||||
blankLine(cur?: boolean, isWrapped?: boolean);
|
||||
}
|
||||
|
||||
export interface IBuffer {
|
||||
|
||||
+12
-77
@@ -221,7 +221,7 @@ function Terminal(options) {
|
||||
this.surrogate_high = '';
|
||||
|
||||
// Create the terminal's buffers and set the current buffer
|
||||
this.buffers = new BufferSet(this);
|
||||
this.buffers = this.buffers || new BufferSet(this);
|
||||
this.buffer = this.buffers.active; // Convenience shortcut;
|
||||
this.buffers.on('activate', function (buffer) {
|
||||
this._terminal.buffer = buffer;
|
||||
@@ -1930,86 +1930,21 @@ Terminal.prototype.resize = function(x, y) {
|
||||
if (x < 1) x = 1;
|
||||
if (y < 1) y = 1;
|
||||
|
||||
// resize cols
|
||||
j = this.cols;
|
||||
if (j < x) {
|
||||
ch = [this.defAttr, ' ', 1]; // does xterm use the default attr?
|
||||
i = this.buffer.lines.length;
|
||||
while (i--) {
|
||||
if (this.buffer.lines.get(i) === undefined) {
|
||||
this.buffer.lines.set(i, this.blankLine());
|
||||
}
|
||||
while (this.buffer.lines.get(i).length < x) {
|
||||
this.buffer.lines.get(i).push(ch);
|
||||
}
|
||||
}
|
||||
this.buffers.resize(x, y);
|
||||
|
||||
// Adjust rows in the DOM to accurately reflect the new dimensions
|
||||
while (this.children.length < y) {
|
||||
this.insertRow();
|
||||
}
|
||||
while (this.children.length > y) {
|
||||
el = this.children.shift();
|
||||
if (!el) continue;
|
||||
el.parentNode.removeChild(el);
|
||||
}
|
||||
|
||||
this.cols = x;
|
||||
this.setupStops(this.cols);
|
||||
|
||||
// resize rows
|
||||
j = this.rows;
|
||||
addToY = 0;
|
||||
if (j < y) {
|
||||
el = this.element;
|
||||
while (j++ < y) {
|
||||
// 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.buffer.ybase--;
|
||||
addToY++;
|
||||
if (this.buffer.ydisp > 0) {
|
||||
// Viewport is at the top of the buffer, must increase downwards
|
||||
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.buffer.lines.push(this.blankLine());
|
||||
}
|
||||
}
|
||||
if (this.children.length < y) {
|
||||
this.insertRow();
|
||||
}
|
||||
}
|
||||
} else { // (j > y)
|
||||
while (j-- > y) {
|
||||
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.buffer.lines.pop();
|
||||
} else {
|
||||
// The line is the cursor, scroll down
|
||||
this.buffer.ybase++;
|
||||
this.buffer.ydisp++;
|
||||
}
|
||||
}
|
||||
if (this.children.length > y) {
|
||||
el = this.children.shift();
|
||||
if (!el) continue;
|
||||
el.parentNode.removeChild(el);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.rows = y;
|
||||
|
||||
// Make sure that the cursor stays on screen
|
||||
if (this.buffer.y >= y) {
|
||||
this.buffer.y = y - 1;
|
||||
}
|
||||
if (addToY) {
|
||||
this.buffer.y += addToY;
|
||||
}
|
||||
|
||||
if (this.buffer.x >= x) {
|
||||
this.buffer.x = x - 1;
|
||||
}
|
||||
|
||||
this.buffer.scrollTop = 0;
|
||||
this.buffer.scrollBottom = y - 1;
|
||||
this.setupStops(this.cols);
|
||||
|
||||
this.charMeasure.measure();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user