Skip to content
Open
Show file tree
Hide file tree
Changes from all 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