This commit is contained in:
Jörg Breitbart
2023-07-24 16:06:19 +02:00
parent 90f1318596
commit 37153018b9
7 changed files with 76 additions and 60 deletions
+17 -1
View File
@@ -228,6 +228,7 @@ if (document.location.pathname === '/test') {
document.getElementById('add-decoration').addEventListener('click', addDecoration);
document.getElementById('add-overview-ruler').addEventListener('click', addOverviewRuler);
document.getElementById('weblinks-test').addEventListener('click', testWeblinks);
document.getElementById('bce').addEventListener('click', coloredErase);
addVtButtons();
}
@@ -1186,6 +1187,21 @@ ipv6 https://[::1]/with/some?vars=and&a#hash aaa
stop at final '.': This is a sentence with an url to http://example.com.
stop at final '?': Is this the right url http://example.com/?
stop at final '?': Maybe this one http://example.com/with?arguments=false?
`;
`;
term.write(linkExamples.split('\n').join('\r\n'));
}
function coloredErase(): void {
const data = `
Test BG-colored Erase (BCE):
The color block in the following lines should look identical.
For newly created rows at the bottom the last color should be applied
for all cells to the right.
def 41 42 43 44 45 46 47\x1b[47m
\x1b[m \x1b[41m \x1b[42m \x1b[43m \x1b[44m \x1b[45m \x1b[46m \x1b[47m
\x1b[m\x1b[5X\x1b[41m\x1b[5C\x1b[5X\x1b[42m\x1b[5C\x1b[5X\x1b[43m\x1b[5C\x1b[5X\x1b[44m\x1b[5C\x1b[5X\x1b[45m\x1b[5C\x1b[5X\x1b[46m\x1b[5C\x1b[5X\x1b[47m\x1b[5C\x1b[5X\x1b[m
`;
term.write(data.split('\n').join('\r\n'));
}
+1
View File
@@ -83,6 +83,7 @@
<dd><button id="sgr-test" title="Write text with SGR attribute">SGR test</button></dd>
<dd><button id="ansi-colors" title="Write a wide range of ansi colors">Ansi colors test</button></dd>
<dd><button id="osc-hyperlinks" title="Write some OSC 8 hyperlinks">Ansi hyperlinks test</button></dd>
<dd><button id="bce" title="Test colored erase">Colored Erase (BCE)</button></dd>
<dt>Decorations</dt>
<dd><button id="add-decoration" title="Add a decoration to the terminal">Decoration</button></dd>
+1 -2
View File
@@ -444,7 +444,6 @@ export class DomRenderer extends Disposable implements IRenderer {
cursorX,
cursorBlink,
this.dimensions.css.cell.width,
this._bufferService.cols,
this._fontMetrics,
this._linkState
)
@@ -476,6 +475,7 @@ export class DomRenderer extends Disposable implements IRenderer {
const cursorX = Math.min(this._bufferService.buffer.x, this._bufferService.cols - 1);
const cursorBlink = this._optionsService.rawOptions.cursorBlink;
const cursorStyle = this._optionsService.rawOptions.cursorStyle;
cols = Math.min(cols, this._bufferService.cols);
// refresh rows within link range
this._linkState[0] = +enabled;
@@ -499,7 +499,6 @@ export class DomRenderer extends Disposable implements IRenderer {
cursorX,
cursorBlink,
this.dimensions.css.cell.width,
this._bufferService.cols,
this._fontMetrics,
this._linkState
)
@@ -39,7 +39,7 @@ describe('DomRendererRowFactory', () => {
describe('createRow', () => {
it('should not create anything for an empty row', () => {
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
''
);
@@ -49,7 +49,7 @@ describe('DomRendererRowFactory', () => {
lineData.setCell(0, CellData.fromCharData([DEFAULT_ATTR, '語', 2, '語'.charCodeAt(0)]));
// There should be no element for the following "empty" cell
lineData.setCell(1, CellData.fromCharData([DEFAULT_ATTR, '', 0, 0]));
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
'<span style="width: 10px;">語</span>'
);
@@ -57,7 +57,7 @@ describe('DomRendererRowFactory', () => {
it('should add class for cursor and cursor style', () => {
for (const style of ['block', 'bar', 'underline']) {
const fragment = rowFactory.createRow(lineData, 0, true, style, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, true, style, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
`<span class="xterm-cursor xterm-cursor-${style}"> </span>`
);
@@ -65,27 +65,18 @@ describe('DomRendererRowFactory', () => {
});
it('should add class for cursor blink', () => {
const fragment = rowFactory.createRow(lineData, 0, true, 'block', 0, true, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, true, 'block', 0, true, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
`<span class="xterm-cursor xterm-cursor-blink xterm-cursor-block"> </span>`
);
});
it('should not render cells that go beyond the terminal\'s columns', () => {
lineData.setCell(0, CellData.fromCharData([DEFAULT_ATTR, 'a', 1, 'a'.charCodeAt(0)]));
lineData.setCell(1, CellData.fromCharData([DEFAULT_ATTR, 'b', 1, 'b'.charCodeAt(0)]));
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 1, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
'<span>a</span>'
);
});
describe('attributes', () => {
it('should add class for bold', () => {
const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]);
cell.fg = DEFAULT_ATTR_DATA.fg | FgFlags.BOLD;
lineData.setCell(0, cell);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
'<span class="xterm-bold">a</span>'
);
@@ -95,7 +86,7 @@ describe('DomRendererRowFactory', () => {
const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]);
cell.bg = DEFAULT_ATTR_DATA.bg | BgFlags.ITALIC;
lineData.setCell(0, cell);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
'<span class="xterm-italic">a</span>'
);
@@ -105,7 +96,7 @@ describe('DomRendererRowFactory', () => {
const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]);
cell.bg = DEFAULT_ATTR_DATA.bg | BgFlags.DIM;
lineData.setCell(0, cell);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
'<span class="xterm-dim">a</span>'
);
@@ -118,7 +109,7 @@ describe('DomRendererRowFactory', () => {
cell.bg = DEFAULT_ATTR_DATA.bg | BgFlags.HAS_EXTENDED;
cell.extended.underlineStyle = UnderlineStyle.SINGLE;
lineData.setCell(0, cell);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
'<span class="xterm-underline-1">a</span>'
);
@@ -129,7 +120,7 @@ describe('DomRendererRowFactory', () => {
cell.bg = DEFAULT_ATTR_DATA.bg | BgFlags.HAS_EXTENDED;
cell.extended.underlineStyle = UnderlineStyle.DOUBLE;
lineData.setCell(0, cell);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
'<span class="xterm-underline-2">a</span>'
);
@@ -140,7 +131,7 @@ describe('DomRendererRowFactory', () => {
cell.bg = DEFAULT_ATTR_DATA.bg | BgFlags.HAS_EXTENDED;
cell.extended.underlineStyle = UnderlineStyle.CURLY;
lineData.setCell(0, cell);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
'<span class="xterm-underline-3">a</span>'
);
@@ -151,7 +142,7 @@ describe('DomRendererRowFactory', () => {
cell.bg = DEFAULT_ATTR_DATA.bg | BgFlags.HAS_EXTENDED;
cell.extended.underlineStyle = UnderlineStyle.DOTTED;
lineData.setCell(0, cell);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
'<span class="xterm-underline-4">a</span>'
);
@@ -162,7 +153,7 @@ describe('DomRendererRowFactory', () => {
cell.bg = DEFAULT_ATTR_DATA.bg | BgFlags.HAS_EXTENDED;
cell.extended.underlineStyle = UnderlineStyle.DASHED;
lineData.setCell(0, cell);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
'<span class="xterm-underline-5">a</span>'
);
@@ -173,7 +164,7 @@ describe('DomRendererRowFactory', () => {
const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]);
cell.bg = DEFAULT_ATTR_DATA.bg | BgFlags.OVERLINE;
lineData.setCell(0, cell);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
'<span class="xterm-overline">a</span>'
);
@@ -183,7 +174,7 @@ describe('DomRendererRowFactory', () => {
const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]);
cell.fg = DEFAULT_ATTR_DATA.fg | FgFlags.STRIKETHROUGH;
lineData.setCell(0, cell);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
'<span class="xterm-strikethrough">a</span>'
);
@@ -196,7 +187,7 @@ describe('DomRendererRowFactory', () => {
cell.fg &= ~Attributes.PCOLOR_MASK;
cell.fg |= i;
lineData.setCell(0, cell);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
`<span class="xterm-fg-${i}">a</span>`
);
@@ -210,7 +201,7 @@ describe('DomRendererRowFactory', () => {
cell.bg &= ~Attributes.PCOLOR_MASK;
cell.bg |= i;
lineData.setCell(0, cell);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
`<span class="xterm-bg-${i}">a</span>`
);
@@ -222,7 +213,7 @@ describe('DomRendererRowFactory', () => {
cell.fg |= Attributes.CM_P16 | 2 | FgFlags.INVERSE;
cell.bg |= Attributes.CM_P16 | 1;
lineData.setCell(0, cell);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
'<span class="xterm-bg-2 xterm-fg-1">a</span>'
);
@@ -233,7 +224,7 @@ describe('DomRendererRowFactory', () => {
cell.fg |= FgFlags.INVERSE;
cell.bg |= Attributes.CM_P16 | 1;
lineData.setCell(0, cell);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
'<span class="xterm-bg-257 xterm-fg-1">a</span>'
);
@@ -243,7 +234,7 @@ describe('DomRendererRowFactory', () => {
const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]);
cell.fg |= Attributes.CM_P16 | 1 | FgFlags.INVERSE;
lineData.setCell(0, cell);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
'<span class="xterm-bg-1 xterm-fg-257">a</span>'
);
@@ -256,7 +247,7 @@ describe('DomRendererRowFactory', () => {
cell.fg &= ~Attributes.PCOLOR_MASK;
cell.fg |= i;
lineData.setCell(0, cell);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
`<span class="xterm-bold xterm-fg-${i + 8}">a</span>`
);
@@ -268,7 +259,7 @@ describe('DomRendererRowFactory', () => {
cell.fg |= Attributes.CM_RGB | 1 << 16 | 2 << 8 | 3;
cell.bg |= Attributes.CM_RGB | 4 << 16 | 5 << 8 | 6;
lineData.setCell(0, cell);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
'<span style="background-color:#040506;color:#010203;">a</span>'
);
@@ -279,7 +270,7 @@ describe('DomRendererRowFactory', () => {
cell.fg |= Attributes.CM_RGB | 1 << 16 | 2 << 8 | 3 | FgFlags.INVERSE;
cell.bg |= Attributes.CM_RGB | 4 << 16 | 5 << 8 | 6;
lineData.setCell(0, cell);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
'<span style="background-color:#010203;color:#040506;">a</span>'
);
@@ -291,7 +282,7 @@ describe('DomRendererRowFactory', () => {
lineData.setCell(0, CellData.fromCharData([DEFAULT_ATTR, 'a', 1, 'a'.charCodeAt(0)]));
lineData.setCell(1, CellData.fromCharData([DEFAULT_ATTR, 'b', 1, 'b'.charCodeAt(0)]));
rowFactory.handleSelectionChanged([1, 0], [2, 0], false);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
'<span>a</span><span class="xterm-decoration-top">b</span>'
);
@@ -299,7 +290,7 @@ describe('DomRendererRowFactory', () => {
it('should force whitespace cells to be rendered above the background', () => {
lineData.setCell(1, CellData.fromCharData([DEFAULT_ATTR, 'a', 1, 'a'.charCodeAt(0)]));
rowFactory.handleSelectionChanged([0, 0], [2, 0], false);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, 20, EMPTY_METRICS, EMPTY_LINKSTATE);
const fragment = rowFactory.createRow(lineData, 0, false, undefined, 0, false, 5, EMPTY_METRICS, EMPTY_LINKSTATE);
assert.equal(getFragmentHtml(fragment),
'<span class="xterm-decoration-top"> </span><span class="xterm-decoration-top">a</span>'
);
@@ -5,7 +5,7 @@
import { IBufferLine, ICellData, IColor } from 'common/Types';
import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/shared/Constants';
import { NULL_CELL_CODE, WHITESPACE_CELL_CHAR, Attributes } from 'common/buffer/Constants';
import { NULL_CELL_CODE, WHITESPACE_CELL_CHAR, Attributes, NULL_CELL_WIDTH } from 'common/buffer/Constants';
import { CellData } from 'common/buffer/CellData';
import { ICoreService, IDecorationService, IOptionsService } from 'common/services/Services';
import { color, rgba } from 'common/Color';
@@ -57,28 +57,19 @@ export class DomRendererRowFactory {
cursorX: number,
cursorBlink: boolean,
cellWidth: number,
cols: number,
metrics: Uint8Array,
linkState: Uint8Array
): DocumentFragment {
const fragment = this._document.createDocumentFragment();
const joinedRanges = this._characterJoinerService.getJoinedCharacters(row);
// Find the line length first, this prevents the need to output a bunch of
// empty cells at the end. This cannot easily be integrated into the main
// loop below because of the colCount feature (which can be removed after we
// properly support reflow and disallow data to go beyond the right-side of
// the viewport).
let lineLength = 0;
for (let x = Math.min(lineData.length, cols) - 1; x >= 0; x--) {
if (lineData.loadCell(x, this._workCell).getCode() !== NULL_CELL_CODE || (isCursorRow && x === cursorX)) {
lineLength = x + 1;
break;
}
}
const colors = this._themeService.colors;
let lineLength = lineData.getNoBgTrimmedLength();
if (isCursorRow && lineLength < cursorX + 1) {
lineLength = cursorX + 1;
}
let charElement: HTMLSpanElement | undefined;
let cellAmount = 0;
let text = '';
@@ -89,8 +80,7 @@ export class DomRendererRowFactory {
const isHover = linkState[0];
let x = 0;
for (; x < lineLength; x++) {
for (let x = 0; x < lineLength; x++) {
lineData.loadCell(x, this._workCell);
let width = this._workCell.getWidth();
@@ -129,6 +119,7 @@ export class DomRendererRowFactory {
const isInSelection = this._isCellInSelection(x, row);
const isCursorCell = isCursorRow && x === cursorX;
const cc = cell.getCode();
const isNull = cc === NULL_CELL_CODE && width === NULL_CELL_WIDTH;
const isCombined = cell.isCombined();
const isLinkHover = isHover && x >= linkState[1] && x <= linkState[2];
@@ -145,9 +136,9 @@ export class DomRendererRowFactory {
* - underline from hover state did not change
*/
if (
cellAmount && width === 1 && !isCombined
cellAmount
&& (isNull || (width === 1 && !isCombined && cc < 1424 && !metrics[cc]))
&& cell.bg === oldBg && cell.fg === oldFg && cell.extended.ext === oldExt
&& cc < 1424 && !metrics[cc]
&& !isInSelection
&& !isCursorCell
&& isLinkHover === oldLinkHover
@@ -166,7 +157,9 @@ export class DomRendererRowFactory {
} else {
if (cellAmount) {
charElement.textContent = text;
charElement.style.width = `${cellWidth * cellAmount}px`;
if (cellAmount > 1) {
charElement.style.width = `${cellWidth * cellAmount}px`;
}
}
charElement = this._document.createElement('span');
cellAmount = 0;
@@ -385,7 +378,7 @@ export class DomRendererRowFactory {
// account first char for later merge if it meets the start conditions
if (width === 1 && !isCombined && cc < 1424 && !metrics[cc] && !isInSelection && !isCursorCell) {
if ((isNull || (width === 1 && !isCombined && cc < 1424 && !metrics[cc])) && !isInSelection && !isCursorCell) {
cellAmount++;
} else {
// every non-mergeable char gets directly written to its own span
@@ -399,7 +392,13 @@ export class DomRendererRowFactory {
// postfix width and text of last merged span
if (charElement && cellAmount) {
charElement.textContent = text;
charElement.style.width = `${cellWidth * cellAmount}px`;
/*
* optimization: if the last merged span has no BG color set, use faster "width: auto",
* else use correct px value for aligned BG coloring and BCE
*/
if (cellAmount > 1) {
charElement.style.width = (oldBg & Attributes.CM_MASK) ? `${cellWidth * cellAmount}px`: 'auto';
}
}
return fragment;
+1
View File
@@ -242,6 +242,7 @@ export interface IBufferLine {
copyFrom(line: IBufferLine): void;
clone(): IBufferLine;
getTrimmedLength(): number;
getNoBgTrimmedLength(): number;
translateToString(trimRight?: boolean, startCol?: number, endCol?: number): string;
/* direct access to cell attrs */
+10 -1
View File
@@ -5,7 +5,7 @@
import { CharData, IBufferLine, ICellData, IAttributeData, IExtendedAttrs } from 'common/Types';
import { stringFromCodePoint } from 'common/input/TextDecoder';
import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_ATTR_INDEX, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, WHITESPACE_CELL_CHAR, Content, BgFlags, FgFlags } from 'common/buffer/Constants';
import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_ATTR_INDEX, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, WHITESPACE_CELL_CHAR, Content, BgFlags, FgFlags, Attributes } from 'common/buffer/Constants';
import { CellData } from 'common/buffer/CellData';
import { AttributeData, ExtendedAttrs } from 'common/buffer/AttributeData';
@@ -463,6 +463,15 @@ export class BufferLine implements IBufferLine {
return 0;
}
public getNoBgTrimmedLength(): number {
for (let i = this.length - 1; i >= 0; --i) {
if ((this._data[i * CELL_SIZE + Cell.CONTENT] & Content.HAS_CONTENT_MASK) || (this._data[i * CELL_SIZE + Cell.BG] & Attributes.CM_MASK)) {
return i + (this._data[i * CELL_SIZE + Cell.CONTENT] >> Content.WIDTH_SHIFT);
}
}
return 0;
}
public copyCellsFrom(src: BufferLine, srcCol: number, destCol: number, length: number, applyInReverse: boolean): void {
const srcData = src._data;
if (applyInReverse) {