From 165c8d4522926f2025ecb1a870153dee9cc9b905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Tue, 4 Sep 2018 16:30:17 +0200 Subject: [PATCH] convenient methods fill, makeCopyOf and clone for BufferLine --- src/BufferLine.test.ts | 53 ++++++++++++++++++++++++++++++++ src/BufferLine.ts | 68 ++++++++++++++++++++++++++++++++++++++++-- src/Types.ts | 3 ++ 3 files changed, 122 insertions(+), 2 deletions(-) diff --git a/src/BufferLine.test.ts b/src/BufferLine.test.ts index 9d6ba036..47073a4e 100644 --- a/src/BufferLine.test.ts +++ b/src/BufferLine.test.ts @@ -90,4 +90,57 @@ describe('BufferLine', function(): void { [5, 'e', 0, 'e'.charCodeAt(0)] ]); }); + it('fill', function(): void { + const line = new TestBufferLine(5); + line.set(0, [1, 'a', 0, 'a'.charCodeAt(0)]); + line.set(1, [2, 'b', 0, 'b'.charCodeAt(0)]); + line.set(2, [3, 'c', 0, 'c'.charCodeAt(0)]); + line.set(3, [4, 'd', 0, 'd'.charCodeAt(0)]); + line.set(4, [5, 'e', 0, 'e'.charCodeAt(0)]); + line.fill([123, 'z', 0, 'z'.charCodeAt(0)]); + chai.expect(line.toArray()).eql([ + [123, 'z', 0, 'z'.charCodeAt(0)], + [123, 'z', 0, 'z'.charCodeAt(0)], + [123, 'z', 0, 'z'.charCodeAt(0)], + [123, 'z', 0, 'z'.charCodeAt(0)], + [123, 'z', 0, 'z'.charCodeAt(0)] + ]); + }); + it('clone', function(): void { + const line = new TestBufferLine(5, null, true); + line.set(0, [1, 'a', 0, 'a'.charCodeAt(0)]); + line.set(1, [2, 'b', 0, 'b'.charCodeAt(0)]); + line.set(2, [3, 'c', 0, 'c'.charCodeAt(0)]); + line.set(3, [4, 'd', 0, 'd'.charCodeAt(0)]); + line.set(4, [5, 'e', 0, 'e'.charCodeAt(0)]); + const line2 = line.clone(); + chai.expect(TestBufferLine.prototype.toArray.apply(line2)).eql(line.toArray()); + chai.expect(line2.length).equals(line.length); + chai.expect(line2.isWrapped).equals(line.isWrapped); + }); + it('makeCopyOf', function(): void { + const line = new TestBufferLine(5); + line.set(0, [1, 'a', 0, 'a'.charCodeAt(0)]); + line.set(1, [2, 'b', 0, 'b'.charCodeAt(0)]); + line.set(2, [3, 'c', 0, 'c'.charCodeAt(0)]); + line.set(3, [4, 'd', 0, 'd'.charCodeAt(0)]); + line.set(4, [5, 'e', 0, 'e'.charCodeAt(0)]); + const line2 = new TestBufferLine(5, [1, 'a', 0, 'a'.charCodeAt(0)], true); + line2.makeCopyOf(line); + chai.expect(line2.toArray()).eql(line.toArray()); + chai.expect(line2.length).equals(line.length); + chai.expect(line2.isWrapped).equals(line.isWrapped); + }); + it('should support combining chars', function(): void { + // CHAR_DATA_CODE_INDEX resembles current behavior in InputHandler.print + // --> set code to the last charCodeAt value of the string + // Note: needs to be fixed once the string pointer is in place + const line = new TestBufferLine(2, [1, 'e\u0301', 0, '\u0301'.charCodeAt(0)]); + chai.expect(line.toArray()).eql([[1, 'e\u0301', 0, '\u0301'.charCodeAt(0)], [1, 'e\u0301', 0, '\u0301'.charCodeAt(0)]]); + const line2 = new TestBufferLine(5, [1, 'a', 0, '\u0301'.charCodeAt(0)], true); + line2.makeCopyOf(line); + chai.expect(line2.toArray()).eql(line.toArray()); + const line3 = line.clone(); + chai.expect(TestBufferLine.prototype.toArray.apply(line3)).eql(line.toArray()); + }); }); diff --git a/src/BufferLine.ts b/src/BufferLine.ts index 2ecc9f26..1fa5ca61 100644 --- a/src/BufferLine.ts +++ b/src/BufferLine.ts @@ -91,6 +91,27 @@ export class BufferLineOld implements IBufferLine { } this.length = cols; } + + public fill(fillCharData: CharData): void { + for (let i = 0; i < this.length; ++i) { + this.set(i, fillCharData); + } + } + + public makeCopyOf(line: IBufferLine): void { + this._data = []; + for (let i = 0; i < line.length; ++i) { + this.set(i, line.get(i)); + } + this.length = line.length; + this.isWrapped = line.isWrapped; + } + + public clone(): IBufferLine { + const newLine = new BufferLineOld(0); + newLine.makeCopyOf(this); + return newLine; + } } const enum Cell { @@ -111,7 +132,6 @@ const enum Cell { * line.set(0, ch); // do this to update line data * TODO: * - provide getData/setData to directly access the data - * - clear/reset method */ export class BufferLine implements IBufferLine { static blankLine(cols: number, attr: number, isWrapped?: boolean): IBufferLine { @@ -141,7 +161,9 @@ export class BufferLine implements IBufferLine { ? this._combined[index] : (stringData) ? String.fromCharCode(stringData) : '', this._data[index * Cell.SIZE + Cell.WIDTH], - stringData & ~0x80000000 + (stringData & 0x80000000) + ? this._combined[index].charCodeAt(this._combined[index].length - 1) + : stringData ]; } @@ -218,4 +240,46 @@ export class BufferLine implements IBufferLine { } this.length = cols; } + + /** + * new methods... + */ + + /** fill a line with fillCharData */ + public fill(fillCharData: CharData): void { + this._combined = {}; + for (let i = 0; i < this.length; ++i) { + this.set(i, fillCharData); + } + } + + /** alter to a full copy of line */ + public makeCopyOf(line: BufferLine): void { + if (this.length !== line.length) { + this._data = new Uint32Array(line._data); + } else { + // use high speed copy if lengths are equal + this._data.set(line._data); + } + this.length = line.length; + this._combined = {}; + for (const el in line._combined) { + this._combined[el] = line._combined[el]; + } + this.isWrapped = line.isWrapped; + } + + /** create a new clone */ + public clone(): IBufferLine { + const newLine = new BufferLine(0); + // creation of new typed array from another is actually pretty slow :( + // still faster than copying values one by one + newLine._data = new Uint32Array(this._data); + newLine.length = this.length; + for (const el in this._combined) { + newLine._combined[el] = this._combined[el]; + } + newLine.isWrapped = this.isWrapped; + return newLine; + } } diff --git a/src/Types.ts b/src/Types.ts index 615ae2d2..b852b09f 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -519,4 +519,7 @@ export interface IBufferLine { deleteCells(pos: number, n: number, fill: CharData): void; replaceCells(start: number, end: number, fill: CharData): void; resize(cols: number, fill: CharData, shrink?: boolean): void; + fill(fillCharData: CharData): void; + makeCopyOf(line: IBufferLine): void; + clone(): IBufferLine; }