add protection flag to DECSED/DECSEL, add DECSCA

This commit is contained in:
Jörg Breitbart
2022-09-03 23:52:30 +02:00
parent 93bc9bf152
commit fc46d69a57
4 changed files with 72 additions and 26 deletions
+34 -20
View File
@@ -334,10 +334,10 @@ export class InputHandler extends Disposable implements IInputHandler {
this._parser.registerCsiHandler({ final: 'G' }, params => this.cursorCharAbsolute(params));
this._parser.registerCsiHandler({ final: 'H' }, params => this.cursorPosition(params));
this._parser.registerCsiHandler({ final: 'I' }, params => this.cursorForwardTab(params));
this._parser.registerCsiHandler({ final: 'J' }, params => this.eraseInDisplay(params));
this._parser.registerCsiHandler({ prefix: '?', final: 'J' }, params => this.eraseInDisplay(params));
this._parser.registerCsiHandler({ final: 'K' }, params => this.eraseInLine(params));
this._parser.registerCsiHandler({ prefix: '?', final: 'K' }, params => this.eraseInLine(params));
this._parser.registerCsiHandler({ final: 'J' }, params => this.eraseInDisplay(params, false));
this._parser.registerCsiHandler({ prefix: '?', final: 'J' }, params => this.eraseInDisplay(params, true));
this._parser.registerCsiHandler({ final: 'K' }, params => this.eraseInLine(params, false));
this._parser.registerCsiHandler({ prefix: '?', final: 'K' }, params => this.eraseInLine(params, true));
this._parser.registerCsiHandler({ final: 'L' }, params => this.insertLines(params));
this._parser.registerCsiHandler({ final: 'M' }, params => this.deleteLines(params));
this._parser.registerCsiHandler({ final: 'P' }, params => this.deleteChars(params));
@@ -369,6 +369,7 @@ export class InputHandler extends Disposable implements IInputHandler {
this._parser.registerCsiHandler({ final: 'u' }, params => this.restoreCursor(params));
this._parser.registerCsiHandler({ intermediates: '\'', final: '}' }, params => this.insertColumns(params));
this._parser.registerCsiHandler({ intermediates: '\'', final: '~' }, params => this.deleteColumns(params));
this._parser.registerCsiHandler({ intermediates: '"', final: 'q' }, params => this.selectProtected(params));
/**
* execute handler
@@ -1206,6 +1207,18 @@ export class InputHandler extends Disposable implements IInputHandler {
return true;
}
/**
* CSI Ps " q Select Character Protection Attribute (DECSCA).
*
* @vt: #Y CSI DECSCA "Select Character Protection Attribute" "CSI Ps " q" "Whether DECSED and DECSEL can erase (0=default, 2) or not (1)."
*/
public selectProtected(params: IParams): boolean {
const p = params.params[0];
if (p === 1) this._curAttrData.bg |= BgFlags.PROTECTED;
if (p === 2 || p === 0) this._curAttrData.bg &= ~BgFlags.PROTECTED;
return true;
}
/**
* Helper method to erase cells in a terminal row.
@@ -1215,13 +1228,14 @@ export class InputHandler extends Disposable implements IInputHandler {
* @param end end - 1 is last erased cell
* @param cleanWrap clear the isWrapped flag
*/
private _eraseInBufferLine(y: number, start: number, end: number, clearWrap: boolean = false): void {
private _eraseInBufferLine(y: number, start: number, end: number, clearWrap: boolean = false, protect: boolean = false): void {
const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!;
line.replaceCells(
start,
end,
this._activeBuffer.getNullCell(this._eraseAttrData()),
this._eraseAttrData()
this._eraseAttrData(),
protect
);
if (clearWrap) {
line.isWrapped = false;
@@ -1233,9 +1247,9 @@ export class InputHandler extends Disposable implements IInputHandler {
* The cell gets replaced with the eraseChar of the terminal and the isWrapped property is set to false.
* @param y row index
*/
private _resetBufferLine(y: number): void {
private _resetBufferLine(y: number, protect: boolean = false): void {
const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!;
line.fill(this._activeBuffer.getNullCell(this._eraseAttrData()));
line.fill(this._activeBuffer.getNullCell(this._eraseAttrData()), protect);
this._bufferService.buffer.clearMarkers(this._activeBuffer.ybase + y);
line.isWrapped = false;
}
@@ -1262,18 +1276,18 @@ export class InputHandler extends Disposable implements IInputHandler {
* | 2 | Erase complete viewport. |
* | 3 | Erase scrollback. |
*
* @vt: #P[Protection attributes are not supported.] CSI DECSED "Selective Erase In Display" "CSI ? Ps J" "Currently the same as ED."
* @vt: #Y CSI DECSED "Selective Erase In Display" "CSI ? Ps J" "Same as ED with respecting protection flag."
*/
public eraseInDisplay(params: IParams): boolean {
public eraseInDisplay(params: IParams, protect: boolean = false): boolean {
this._restrictCursor(this._bufferService.cols);
let j;
switch (params.params[0]) {
case 0:
j = this._activeBuffer.y;
this._dirtyRowService.markDirty(j);
this._eraseInBufferLine(j++, this._activeBuffer.x, this._bufferService.cols, this._activeBuffer.x === 0);
this._eraseInBufferLine(j++, this._activeBuffer.x, this._bufferService.cols, this._activeBuffer.x === 0, protect);
for (; j < this._bufferService.rows; j++) {
this._resetBufferLine(j);
this._resetBufferLine(j, protect);
}
this._dirtyRowService.markDirty(j);
break;
@@ -1281,13 +1295,13 @@ export class InputHandler extends Disposable implements IInputHandler {
j = this._activeBuffer.y;
this._dirtyRowService.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);
this._eraseInBufferLine(j, 0, this._activeBuffer.x + 1, true, protect);
if (this._activeBuffer.x + 1 >= this._bufferService.cols) {
// Deleted entire previous line. This next line can no longer be wrapped.
this._activeBuffer.lines.get(j + 1)!.isWrapped = false;
}
while (j--) {
this._resetBufferLine(j);
this._resetBufferLine(j, protect);
}
this._dirtyRowService.markDirty(0);
break;
@@ -1295,7 +1309,7 @@ export class InputHandler extends Disposable implements IInputHandler {
j = this._bufferService.rows;
this._dirtyRowService.markDirty(j - 1);
while (j--) {
this._resetBufferLine(j);
this._resetBufferLine(j, protect);
}
this._dirtyRowService.markDirty(0);
break;
@@ -1334,19 +1348,19 @@ export class InputHandler extends Disposable implements IInputHandler {
* | 1 | Erase from the beginning of the line through the cursor. |
* | 2 | Erase complete line. |
*
* @vt: #P[Protection attributes are not supported.] CSI DECSEL "Selective Erase In Line" "CSI ? Ps K" "Currently the same as EL."
* @vt: #Y CSI DECSEL "Selective Erase In Line" "CSI ? Ps K" "Same as EL with respecting protecting flag."
*/
public eraseInLine(params: IParams): boolean {
public eraseInLine(params: IParams, protect: boolean = false): boolean {
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);
this._eraseInBufferLine(this._activeBuffer.y, this._activeBuffer.x, this._bufferService.cols, this._activeBuffer.x === 0, protect);
break;
case 1:
this._eraseInBufferLine(this._activeBuffer.y, 0, this._activeBuffer.x + 1, false);
this._eraseInBufferLine(this._activeBuffer.y, 0, this._activeBuffer.x + 1, false, protect);
break;
case 2:
this._eraseInBufferLine(this._activeBuffer.y, 0, this._bufferService.cols, true);
this._eraseInBufferLine(this._activeBuffer.y, 0, this._bufferService.cols, true, protect);
break;
}
this._dirtyRowService.markDirty(this._activeBuffer.y);
+2 -2
View File
@@ -203,9 +203,9 @@ export interface IBufferLine {
addCodepointToCell(index: number, codePoint: number): void;
insertCells(pos: number, n: number, ch: ICellData, eraseAttr?: IAttributeData): void;
deleteCells(pos: number, n: number, fill: ICellData, eraseAttr?: IAttributeData): void;
replaceCells(start: number, end: number, fill: ICellData, eraseAttr?: IAttributeData): void;
replaceCells(start: number, end: number, fill: ICellData, eraseAttr?: IAttributeData, protect?: boolean): void;
resize(cols: number, fill: ICellData): void;
fill(fillCellData: ICellData): void;
fill(fillCellData: ICellData, protect?: boolean): void;
copyFrom(line: IBufferLine): void;
clone(): IBufferLine;
getTrimmedLength(): number;
+33 -2
View File
@@ -168,6 +168,11 @@ export class BufferLine implements IBufferLine {
return '';
}
/** Get state of protected flag. */
public isProtected(index: number): number {
return this._data[index * CELL_SIZE + Cell.BG] & BgFlags.PROTECTED;
}
/**
* Load data at `index` into `cell`. This is used to access cells in a way that's more friendly
* to GC as it significantly reduced the amount of new objects/references needed.
@@ -298,7 +303,24 @@ export class BufferLine implements IBufferLine {
}
}
public replaceCells(start: number, end: number, fillCellData: ICellData, eraseAttr?: IAttributeData): void {
public replaceCells(start: number, end: number, fillCellData: ICellData, eraseAttr?: IAttributeData, protect: boolean = false): void {
// full branching on protect==true, hopefully getting fast JIT for standard case
if (protect) {
if (start && this.getWidth(start - 1) === 2 && !this.isProtected(start - 1)) {
this.setCellFromCodePoint(start - 1, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs());
}
if (end < this.length && this.getWidth(end - 1) === 2 && !this.isProtected(end)) {
this.setCellFromCodePoint(end, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs());
}
while (start < end && start < this.length) {
if (!this.isProtected(start)) {
this.setCell(start, fillCellData);
}
start++;
}
return;
}
// handle fullwidth at start: reset cell one to the left if start is second cell of a wide char
if (start && this.getWidth(start - 1) === 2) {
this.setCellFromCodePoint(start - 1, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs());
@@ -352,7 +374,16 @@ export class BufferLine implements IBufferLine {
}
/** fill a line with fillCharData */
public fill(fillCellData: ICellData): void {
public fill(fillCellData: ICellData, protect: boolean = false): void {
// full branching on protect==true, hopefully getting fast JIT for standard case
if (protect) {
for (let i = 0; i < this.length; ++i) {
if (!this.isProtected(i)) {
this.setCell(i, fillCellData);
}
}
return;
}
this._combined = {};
this._extendedAttrs = {};
for (let i = 0; i < this.length; ++i) {
+3 -2
View File
@@ -123,11 +123,12 @@ export const enum FgFlags {
export const enum BgFlags {
/**
* bit 27..32 (upper 3 unused)
* bit 27..32 (upper 2 unused)
*/
ITALIC = 0x4000000,
DIM = 0x8000000,
HAS_EXTENDED = 0x10000000
HAS_EXTENDED = 0x10000000,
PROTECTED = 0x20000000
}
export const enum ExtFlags {