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
42 changes: 20 additions & 22 deletions src/common/InputHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 Down Expand Up @@ -773,7 +773,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 +837,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 @@ -1201,7 +1201,7 @@ export class InputHandler extends Disposable implements IInputHandler {
respectProtect
);
if (clearWrap) {
line.isWrapped = false;
this._activeBuffer.setWrapped(this._activeBuffer.ybase + y, false);
}
}

Expand All @@ -1215,7 +1215,7 @@ export class InputHandler extends Disposable implements IInputHandler {
if (line) {
line.fill(this._activeBuffer.getNullCell(this._eraseAttrData()), respectProtect);
this._bufferService.buffer.clearMarkers(this._activeBuffer.ybase + y);
line.isWrapped = false;
this._activeBuffer.setWrapped(this._activeBuffer.ybase + y, false);
}
}

Expand Down Expand Up @@ -1263,10 +1263,7 @@ export class InputHandler extends Disposable implements IInputHandler {
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._activeBuffer.setWrapped(j + 1, false);
}
while (j--) {
this._resetBufferLine(j, respectProtect);
Expand Down Expand Up @@ -1528,9 +1525,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 +1559,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 +1583,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 +1607,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 +3495,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
2 changes: 1 addition & 1 deletion src/common/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,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 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);
}
}
34 changes: 17 additions & 17 deletions src/common/buffer/Buffer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,40 +68,40 @@ describe('Buffer', () => {
describe('wrapped', () => {
it('should return a range for the first row', () => {
buffer.fillViewportRows();
buffer.lines.get(1)!.isWrapped = true;
buffer.setWrapped(1, true);
assert.deepEqual(buffer.getWrappedRangeForLine(0), { first: 0, last: 1 });
});
it('should return a range for a middle row wrapping upwards', () => {
buffer.fillViewportRows();
buffer.lines.get(12)!.isWrapped = true;
buffer.setWrapped(12, true);
assert.deepEqual(buffer.getWrappedRangeForLine(12), { first: 11, last: 12 });
});
it('should return a range for a middle row wrapping downwards', () => {
buffer.fillViewportRows();
buffer.lines.get(13)!.isWrapped = true;
buffer.setWrapped(13, true);
assert.deepEqual(buffer.getWrappedRangeForLine(12), { first: 12, last: 13 });
});
it('should return a range for a middle row wrapping both ways', () => {
buffer.fillViewportRows();
buffer.lines.get(11)!.isWrapped = true;
buffer.lines.get(12)!.isWrapped = true;
buffer.lines.get(13)!.isWrapped = true;
buffer.lines.get(14)!.isWrapped = true;
buffer.setWrapped(11, true);
buffer.setWrapped(12, true);
buffer.setWrapped(13, true);
buffer.setWrapped(14, true);
assert.deepEqual(buffer.getWrappedRangeForLine(12), { first: 10, last: 14 });
});
it('should return a range for the last row', () => {
buffer.fillViewportRows();
buffer.lines.get(23)!.isWrapped = true;
buffer.setWrapped(23, true);
assert.deepEqual(buffer.getWrappedRangeForLine(buffer.lines.length - 1), { first: 22, last: 23 });
});
it('should return a range for a row that wraps upward to first row', () => {
buffer.fillViewportRows();
buffer.lines.get(1)!.isWrapped = true;
buffer.setWrapped(1, true);
assert.deepEqual(buffer.getWrappedRangeForLine(1), { first: 0, last: 1 });
});
it('should return a range for a row that wraps downward to last row', () => {
buffer.fillViewportRows();
buffer.lines.get(buffer.lines.length - 1)!.isWrapped = true;
buffer.setWrapped(buffer.lines.length - 1, true);
assert.deepEqual(buffer.getWrappedRangeForLine(buffer.lines.length - 2), { first: 22, last: 23 });
});
});
Expand Down Expand Up @@ -526,7 +526,7 @@ describe('Buffer', () => {
buffer.lines.get(0)!.set(1, [0, 'b', 1, 'b'.charCodeAt(0)]);
buffer.lines.get(1)!.set(0, [0, 'c', 1, 'c'.charCodeAt(0)]);
buffer.lines.get(1)!.set(1, [0, 'd', 1, 'd'.charCodeAt(0)]);
buffer.lines.get(1)!.isWrapped = true;
buffer.setWrapped(1, true);
// Buffer:
// "ab " (wrapped)
// "cd"
Expand Down Expand Up @@ -557,7 +557,7 @@ describe('Buffer', () => {
buffer.lines.get(0)!.set(i, [0, '', 0, 0]);
buffer.lines.get(1)!.set(i, [0, '', 0, 0]);
}
buffer.lines.get(1)!.isWrapped = true;
buffer.setWrapped(1, true);
// Buffer:
// 汉语汉语汉语 (wrapped)
// 汉语汉语汉语
Expand All @@ -584,7 +584,7 @@ describe('Buffer', () => {
buffer.lines.get(0)!.set(1, [0, 'b', 1, 'b'.charCodeAt(0)]);
buffer.lines.get(1)!.set(0, [0, 'c', 1, 'c'.charCodeAt(0)]);
buffer.lines.get(1)!.set(1, [0, 'd', 1, 'd'.charCodeAt(0)]);
buffer.lines.get(1)!.isWrapped = true;
buffer.setWrapped(1, true);
// Buffer:
// "ab " (wrapped)
// "cd"
Expand Down Expand Up @@ -618,7 +618,7 @@ describe('Buffer', () => {
buffer.lines.get(0)!.set(i, [0, '', 0, 0]);
buffer.lines.get(1)!.set(i, [0, '', 0, 0]);
}
buffer.lines.get(1)!.isWrapped = true;
buffer.setWrapped(1, true);
// Buffer:
// 汉语汉语汉语 (wrapped)
// 汉语汉语汉语
Expand Down Expand Up @@ -673,17 +673,17 @@ describe('Buffer', () => {
buffer.lines.get(0)!.set(1, [0, 'b', 1, 'b'.charCodeAt(0)]);
buffer.lines.get(1)!.set(0, [0, 'c', 1, 'c'.charCodeAt(0)]);
buffer.lines.get(1)!.set(1, [0, 'd', 1, 'd'.charCodeAt(0)]);
buffer.lines.get(1)!.isWrapped = true;
buffer.setWrapped(1, true);
buffer.lines.get(2)!.set(0, [0, 'e', 1, 'e'.charCodeAt(0)]);
buffer.lines.get(2)!.set(1, [0, 'f', 1, 'f'.charCodeAt(0)]);
buffer.lines.get(3)!.set(0, [0, 'g', 1, 'g'.charCodeAt(0)]);
buffer.lines.get(3)!.set(1, [0, 'h', 1, 'h'.charCodeAt(0)]);
buffer.lines.get(3)!.isWrapped = true;
buffer.setWrapped(3, true);
buffer.lines.get(4)!.set(0, [0, 'i', 1, 'i'.charCodeAt(0)]);
buffer.lines.get(4)!.set(1, [0, 'j', 1, 'j'.charCodeAt(0)]);
buffer.lines.get(5)!.set(0, [0, 'k', 1, 'k'.charCodeAt(0)]);
buffer.lines.get(5)!.set(1, [0, 'l', 1, 'l'.charCodeAt(0)]);
buffer.lines.get(5)!.isWrapped = true;
buffer.setWrapped(5, true);
});
describe('viewport not yet filled', () => {
it('should move the cursor up and add empty lines', () => {
Expand Down
7 changes: 6 additions & 1 deletion src/common/buffer/Buffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ export class Buffer implements IBuffer {
return correctBufferLength > MAX_BUFFER_SIZE ? MAX_BUFFER_SIZE : correctBufferLength;
}

public setWrapped(absrow: number, value: boolean): void {
const line = this.lines.get(absrow);
line instanceof BufferLine && line.setWrapped(value);
}

/**
* Fills the buffer's viewport with blank lines.
*/
Expand All @@ -135,7 +140,7 @@ export class Buffer implements IBuffer {
}

/**
* Clears the buffer to it's initial state, discarding all previous data.
* Clears the buffer to its initial state, discarding all previous data.
*/
public clear(): void {
this.ydisp = 0;
Expand Down
18 changes: 15 additions & 3 deletions src/common/buffer/BufferLine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,26 @@ export class BufferLine implements IBufferLine {
protected _combined: {[index: number]: string} = {};
protected _extendedAttrs: {[index: number]: IExtendedAttrs | undefined} = {};
public length: number;
private _isWrapped: boolean;

constructor(cols: number, fillCellData?: ICellData, public isWrapped: boolean = false) {
public get isWrapped(): boolean {
return this._isWrapped;
}
/**
* @internal
*/
public setWrapped(isWrapped: boolean): void {
this._isWrapped = isWrapped;
}

constructor(cols: number, fillCellData?: ICellData, isWrapped: boolean = false) {
this._data = new Uint32Array(cols * CELL_SIZE);
const cell = fillCellData ?? CellData.fromCharData([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]);
for (let i = 0; i < cols; ++i) {
this.setCell(i, cell);
}
this.length = cols;
this._isWrapped = isWrapped;
}

/**
Expand Down Expand Up @@ -439,7 +451,7 @@ export class BufferLine implements IBufferLine {
for (const el in line._extendedAttrs) {
this._extendedAttrs[el] = line._extendedAttrs[el];
}
this.isWrapped = line.isWrapped;
this._isWrapped = line._isWrapped;
}

/** create a new clone */
Expand All @@ -453,7 +465,7 @@ export class BufferLine implements IBufferLine {
for (const el in this._extendedAttrs) {
newLine._extendedAttrs[el] = this._extendedAttrs[el];
}
newLine.isWrapped = this.isWrapped;
newLine._isWrapped = this._isWrapped;
return newLine;
}

Expand Down
1 change: 1 addition & 0 deletions src/common/buffer/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export interface IBuffer {
addMarker(y: number): IMarker;
clearMarkers(y: number): void;
clearAllMarkers(): void;
setWrapped(row: number, value: boolean): void;
}

export interface IBufferSet extends IDisposable {
Expand Down
3 changes: 2 additions & 1 deletion src/common/services/BufferService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { Disposable } from 'common/Lifecycle';
import { IAttributeData, IBufferLine } from 'common/Types';
import { BufferSet } from 'common/buffer/BufferSet';
import { BufferLine } from 'common/buffer/BufferLine';
import { IBuffer, IBufferSet } from 'common/buffer/Types';
import { IBufferService, ILogService, IOptionsService, type IBufferResizeEvent } from 'common/services/Services';
import { Emitter } from 'common/Event';
Expand Down Expand Up @@ -73,7 +74,7 @@ export class BufferService extends Disposable implements IBufferService {
newLine = buffer.getBlankLine(eraseAttr, isWrapped);
this._cachedBlankLine = newLine;
}
newLine.isWrapped = isWrapped;
(newLine as BufferLine).setWrapped(isWrapped);

const topRow = buffer.ybase + buffer.scrollTop;
const bottomRow = buffer.ybase + buffer.scrollBottom;
Expand Down
Loading