Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/browser/TestUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,9 @@ export class MockBuffer implements IBuffer {
public clearAllMarkers(): void {
throw new Error('Method not implemented.');
}
public setWrapped(row: number, value: boolean): void {
throw new Error('Method not implemented.');
}
}

export class MockRenderer implements IRenderer {
Expand Down
12 changes: 6 additions & 6 deletions src/browser/services/SelectionService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ describe('SelectionService', () => {
it('should expand upwards or downards for wrapped lines', () => {
buffer.lines.set(0, stringToRow(' foo'));
buffer.lines.set(1, stringToRow('bar '));
buffer.lines.get(1)!.isWrapped = true;
buffer.setWrapped(1, true);
selectionService.selectWordAt([1, 1]);
assert.equal(selectionService.selectionText, 'foobar');
selectionService.model.clearSelection();
Expand All @@ -207,10 +207,10 @@ describe('SelectionService', () => {
buffer.lines.set(2, stringToRow('bbbbbbbbbbbbbbbbbbbb'));
buffer.lines.set(3, stringToRow('cccccccccccccccccccc'));
buffer.lines.set(4, stringToRow('bar '));
buffer.lines.get(1)!.isWrapped = true;
buffer.lines.get(2)!.isWrapped = true;
buffer.lines.get(3)!.isWrapped = true;
buffer.lines.get(4)!.isWrapped = true;
buffer.setWrapped(1, true);
buffer.setWrapped(2, true);
buffer.setWrapped(3, true);
buffer.setWrapped(4, true);
selectionService.selectWordAt([18, 0]);
assert.equal(selectionService.selectionText, expectedText);
selectionService.model.clearSelection();
Expand Down Expand Up @@ -349,8 +349,8 @@ describe('SelectionService', () => {
it('should select the entire wrapped line', () => {
buffer.lines.set(0, stringToRow('foo'));
const line2 = stringToRow('bar');
line2.isWrapped = true;
buffer.lines.set(1, line2);
buffer.setWrapped(1, true);
selectionService.selectLineAt(0);
assert.equal(selectionService.selectionText, 'foobar', 'The selected text is correct');
assert.deepEqual(selectionService.model.selectionStart, [0, 0]);
Expand Down
14 changes: 0 additions & 14 deletions src/common/CircularList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,20 +115,6 @@ export class CircularList<T> extends Disposable implements ICircularList<T> {
}
}

/**
* Advance ringbuffer index and return current element for recycling.
* Note: The buffer must be full for this method to work.
* @throws When the buffer is not full.
*/
public recycle(): T {
if (this._length !== this._maxLength) {
throw new Error('Can only recycle when the buffer is full');
}
this._startIndex = ++this._startIndex % this._maxLength;
this.onTrimEmitter.fire(1);
return this._array[this._getCyclicIndex(this._length - 1)]!;
}

/**
* Ringbuffer is at max length.
*/
Expand Down
9 changes: 6 additions & 3 deletions src/common/InputHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -459,8 +459,10 @@ describe('InputHandler', () => {
await resetToBaseState();
bufferService.buffer.y = 2;
bufferService.buffer.x = 40;
inputHandler.eraseInLine(Params.fromArray([0]));
assert.equal(bufferService.buffer.lines.get(2)!.isWrapped, true);
assert.equal(bufferService.buffer.lines.get(3)!.isWrapped, true);
inputHandler.eraseInLine(Params.fromArray([0]));
assert.equal(bufferService.buffer.lines.get(2)!.isWrapped, true);assert.equal(bufferService.buffer.lines.get(3)!.isWrapped, false);
bufferService.buffer.y = 2;
bufferService.buffer.x = 0;
inputHandler.eraseInLine(Params.fromArray([0]));
Expand All @@ -471,14 +473,15 @@ describe('InputHandler', () => {
bufferService.buffer.y = 2;
bufferService.buffer.x = 40;
inputHandler.eraseInLine(Params.fromArray([1]));
assert.equal(bufferService.buffer.lines.get(2)!.isWrapped, true);
assert.equal(bufferService.buffer.lines.get(2)!.isWrapped, false);
assert.equal(bufferService.buffer.lines.get(3)!.isWrapped, true);

// params[2] - erase complete line
await resetToBaseState();
bufferService.buffer.y = 2;
bufferService.buffer.x = 40;
inputHandler.eraseInLine(Params.fromArray([2]));
assert.equal(bufferService.buffer.lines.get(2)!.isWrapped, false);
assert.equal(bufferService.buffer.lines.get(2)!.isWrapped, false);assert.equal(bufferService.buffer.lines.get(3)!.isWrapped, false);
});
it('ED2 with scrollOnEraseInDisplay turned on', async () => {
const inputHandler = new TestInputHandler(
Expand Down
99 changes: 48 additions & 51 deletions src/common/InputHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -596,8 +596,8 @@ export class InputHandler extends Disposable implements IInputHandler {
// autowrap - DECAWM
// automatically wraps to the beginning of the next line
if (wraparoundMode) {
const oldRow = bufferRow;
let oldCol = this._activeBuffer.x - oldWidth;
const oldRow = bufferRow as BufferLine;
const oldCol = this._activeBuffer.x - oldWidth;
this._activeBuffer.x = oldWidth;
this._activeBuffer.y++;
if (this._activeBuffer.y === this._activeBuffer.scrollBottom + 1) {
Expand All @@ -609,7 +609,7 @@ export class InputHandler extends Disposable implements IInputHandler {
}
// The line already exists (eg. the initial viewport), mark it as a
// wrapped line
this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y)!.isWrapped = true;
this._activeBuffer.setWrapped(this._activeBuffer.ybase + this._activeBuffer.y, true);
}
// row changed, get it again
bufferRow = this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y);
Expand All @@ -623,9 +623,7 @@ export class InputHandler extends Disposable implements IInputHandler {
oldCol, 0, oldWidth, false);
}
// clear left over cells to the right
while (oldCol < cols) {
oldRow.setCellFromCodepoint(oldCol++, 0, 1, curAttr);
}
oldRow.eraseRight(oldCol);
} else {
this._activeBuffer.x = cols - 1;
if (chWidth === 2) {
Expand Down Expand Up @@ -773,7 +771,7 @@ export class InputHandler extends Disposable implements IInputHandler {
// reprint is common, especially on resize. Note that the windowsMode wrapped line heuristics
// can mess with this so windowsMode should be disabled, which is recommended on Windows build
// 21376 and above.
this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y)!.isWrapped = false;
this._activeBuffer.setWrapped(this._activeBuffer.ybase + this._activeBuffer.y, false);
}
// If the end of the line is hit, prevent this action from wrapping around to the next line.
if (this._activeBuffer.x >= this._bufferService.cols) {
Expand Down Expand Up @@ -837,7 +835,7 @@ export class InputHandler extends Disposable implements IInputHandler {
&& this._activeBuffer.y > this._activeBuffer.scrollTop
&& this._activeBuffer.y <= this._activeBuffer.scrollBottom
&& this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y)?.isWrapped) {
this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y)!.isWrapped = false;
this._activeBuffer.setWrapped(this._activeBuffer.ybase + this._activeBuffer.y, false);
this._activeBuffer.y--;
this._activeBuffer.x = this._bufferService.cols - 1;
// find last taken cell - last cell can have 3 different states:
Expand Down Expand Up @@ -1183,25 +1181,34 @@ export class InputHandler extends Disposable implements IInputHandler {
/**
* Helper method to erase cells in a terminal row.
* The cell gets replaced with the eraseChar of the terminal.
* Clear isWrapped if start===0;
* clear isWrapped of next line if end >= cols.
* @param y The row index relative to the viewport.
* @param start The start x index of the range to be erased.
* @param end The end x index of the range to be erased (exclusive).
* @param clearWrap clear the isWrapped flag
* @param respectProtect Whether to respect the protection attribute (DECSCA).
*/
private _eraseInBufferLine(y: number, start: number, end: number, clearWrap: boolean = false, respectProtect: boolean = false): void {
const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y);
if (!line) {
private _eraseInBufferLine(y: number, start: number, end: number, respectProtect: boolean = false): void {
const yAbs = y + this._activeBuffer.ybase;
const line = this._activeBuffer.lines.get(yAbs);
if (! (line instanceof BufferLine)) {
return;
}
line.replaceCells(
start,
end,
this._activeBuffer.getNullCell(this._eraseAttrData()),
respectProtect
);
if (clearWrap) {
line.isWrapped = false;
if (! respectProtect && end >= this._bufferService.cols) {
const next = line.nextBufferLine;
if (next) next.asUnwrapped(line);
line.eraseRight(start);
line.logicalLine.backgroundColor = this._curAttrData.bg & ~0xFC000000;
} else {
line.replaceCells(
start,
end,
this._activeBuffer.getNullCell(this._eraseAttrData()),
respectProtect
);
}
if (start === 0) {
this._activeBuffer.setWrapped(this._activeBuffer.ybase + y, false);
}
}

Expand All @@ -1211,12 +1218,8 @@ export class InputHandler extends Disposable implements IInputHandler {
* @param y row index
*/
private _resetBufferLine(y: number, respectProtect: boolean = false): void {
const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y);
if (line) {
line.fill(this._activeBuffer.getNullCell(this._eraseAttrData()), respectProtect);
this._bufferService.buffer.clearMarkers(this._activeBuffer.ybase + y);
line.isWrapped = false;
}
this._eraseInBufferLine(y, 0, this._bufferService.cols, respectProtect);
this._bufferService.buffer.clearMarkers(this._activeBuffer.ybase + y);
}

/**
Expand Down Expand Up @@ -1250,7 +1253,7 @@ export class InputHandler extends Disposable implements IInputHandler {
case 0:
j = this._activeBuffer.y;
this._dirtyRowTracker.markDirty(j);
this._eraseInBufferLine(j++, this._activeBuffer.x, this._bufferService.cols, this._activeBuffer.x === 0, respectProtect);
this._eraseInBufferLine(j++, this._activeBuffer.x, this._bufferService.cols, respectProtect);
for (; j < this._bufferService.rows; j++) {
this._resetBufferLine(j, respectProtect);
}
Expand All @@ -1260,14 +1263,7 @@ export class InputHandler extends Disposable implements IInputHandler {
j = this._activeBuffer.y;
this._dirtyRowTracker.markDirty(j);
// Deleted front part of line and everything before. This line will no longer be wrapped.
this._eraseInBufferLine(j, 0, this._activeBuffer.x + 1, true, respectProtect);
if (this._activeBuffer.x + 1 >= this._bufferService.cols) {
// Deleted entire previous line. This next line can no longer be wrapped.
const nextLine = this._activeBuffer.lines.get(j + 1);
if (nextLine) {
nextLine.isWrapped = false;
}
}
this._eraseInBufferLine(j, 0, this._activeBuffer.x + 1, respectProtect);
while (j--) {
this._resetBufferLine(j, respectProtect);
}
Expand Down Expand Up @@ -1337,13 +1333,13 @@ export class InputHandler extends Disposable implements IInputHandler {
this._restrictCursor(this._bufferService.cols);
switch (params.params[0]) {
case 0:
this._eraseInBufferLine(this._activeBuffer.y, this._activeBuffer.x, this._bufferService.cols, this._activeBuffer.x === 0, respectProtect);
this._eraseInBufferLine(this._activeBuffer.y, this._activeBuffer.x, this._bufferService.cols, respectProtect);
break;
case 1:
this._eraseInBufferLine(this._activeBuffer.y, 0, this._activeBuffer.x + 1, false, respectProtect);
this._eraseInBufferLine(this._activeBuffer.y, 0, this._activeBuffer.x + 1, respectProtect);
break;
case 2:
this._eraseInBufferLine(this._activeBuffer.y, 0, this._bufferService.cols, true, respectProtect);
this._eraseInBufferLine(this._activeBuffer.y, 0, this._bufferService.cols, respectProtect);
break;
}
this._dirtyRowTracker.markDirty(this._activeBuffer.y);
Expand Down Expand Up @@ -1528,9 +1524,10 @@ export class InputHandler extends Disposable implements IInputHandler {
}
const param = params.params[0] || 1;
for (let y = this._activeBuffer.scrollTop; y <= this._activeBuffer.scrollBottom; ++y) {
const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!;
const row = this._activeBuffer.ybase + y;
const line = this._activeBuffer.lines.get(row)!;
line.deleteCells(0, param, this._activeBuffer.getNullCell(this._eraseAttrData()));
line.isWrapped = false;
this._activeBuffer.setWrapped(row, false);
}
this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom);
return true;
Expand Down Expand Up @@ -1561,9 +1558,10 @@ export class InputHandler extends Disposable implements IInputHandler {
}
const param = params.params[0] || 1;
for (let y = this._activeBuffer.scrollTop; y <= this._activeBuffer.scrollBottom; ++y) {
const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!;
const row = this._activeBuffer.ybase + y;
const line = this._activeBuffer.lines.get(row)!;
this._activeBuffer.setWrapped(row, false);
line.insertCells(0, param, this._activeBuffer.getNullCell(this._eraseAttrData()));
line.isWrapped = false;
}
this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom);
return true;
Expand All @@ -1584,9 +1582,10 @@ export class InputHandler extends Disposable implements IInputHandler {
}
const param = params.params[0] || 1;
for (let y = this._activeBuffer.scrollTop; y <= this._activeBuffer.scrollBottom; ++y) {
const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!;
const row = this._activeBuffer.ybase + y;
this._activeBuffer.setWrapped(row, false);
const line = this._activeBuffer.lines.get(row)!;
line.insertCells(this._activeBuffer.x, param, this._activeBuffer.getNullCell(this._eraseAttrData()));
line.isWrapped = false;
}
this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom);
return true;
Expand All @@ -1607,9 +1606,10 @@ export class InputHandler extends Disposable implements IInputHandler {
}
const param = params.params[0] || 1;
for (let y = this._activeBuffer.scrollTop; y <= this._activeBuffer.scrollBottom; ++y) {
const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!;
const row = this._activeBuffer.ybase + y;
const line = this._activeBuffer.lines.get(row)!;
this._activeBuffer.setWrapped(row, false);
line.deleteCells(this._activeBuffer.x, param, this._activeBuffer.getNullCell(this._eraseAttrData()));
line.isWrapped = false;
}
this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom);
return true;
Expand Down Expand Up @@ -3494,11 +3494,8 @@ export class InputHandler extends Disposable implements IInputHandler {
this._setCursor(0, 0);
for (let yOffset = 0; yOffset < this._bufferService.rows; ++yOffset) {
const row = this._activeBuffer.ybase + this._activeBuffer.y + yOffset;
const line = this._activeBuffer.lines.get(row);
if (line) {
line.fill(cell);
line.isWrapped = false;
}
this._activeBuffer.setWrapped(row, false);
this._activeBuffer.lines.get(row)?.fill(cell);
}
this._dirtyRowTracker.markAllDirty();
this._setCursor(0, 0);
Expand Down
4 changes: 1 addition & 3 deletions src/common/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ export interface ICircularList<T> {
get(index: number): T | undefined;
set(index: number, value: T): void;
push(value: T): void;
recycle(): T;
pop(): T | undefined;
splice(start: number, deleteCount: number, ...items: T[]): void;
trimStart(count: number): void;
Expand Down Expand Up @@ -224,7 +223,7 @@ export interface ICellData extends IAttributeData {
*/
export interface IBufferLine {
length: number;
isWrapped: boolean;
get isWrapped(): boolean;
get(index: number): CharData;
set(index: number, value: CharData): void;
loadCell(index: number, cell: ICellData): ICellData;
Expand All @@ -238,7 +237,6 @@ export interface IBufferLine {
cleanupMemory(): number;
fill(fillCellData: ICellData, respectProtect?: boolean): void;
copyFrom(line: IBufferLine): void;
clone(): IBufferLine;
getTrimmedLength(): number;
getNoBgTrimmedLength(): number;
translateToString(trimRight?: boolean, startCol?: number, endCol?: number, outColumns?: number[]): string;
Expand Down
6 changes: 2 additions & 4 deletions src/common/WindowsMode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ export function updateWindowsModeWrappedState(bufferService: IBufferService): vo
// wrapped.
const line = bufferService.buffer.lines.get(bufferService.buffer.ybase + bufferService.buffer.y - 1);
const lastChar = line?.get(bufferService.cols - 1);

const nextLine = bufferService.buffer.lines.get(bufferService.buffer.ybase + bufferService.buffer.y);
if (nextLine && lastChar) {
nextLine.isWrapped = (lastChar[CHAR_DATA_CODE_INDEX] !== NULL_CELL_CODE && lastChar[CHAR_DATA_CODE_INDEX] !== WHITESPACE_CELL_CODE);
if (lastChar) {
bufferService.buffer.setWrapped(bufferService.buffer.ybase + bufferService.buffer.y, lastChar[CHAR_DATA_CODE_INDEX] !== NULL_CELL_CODE && lastChar[CHAR_DATA_CODE_INDEX] !== WHITESPACE_CELL_CODE);
}
}
Loading
Loading