Handle selections in the middle of ligatures too

This commit is contained in:
Daniel Imms
2025-01-06 11:03:10 -08:00
parent 5bfb130f03
commit c7a1e0aea3
2 changed files with 22 additions and 4 deletions
+16 -2
View File
@@ -377,6 +377,8 @@ export class WebglRenderer extends Disposable implements IRenderer {
let line: IBufferLine;
let joinedRanges: [number, number][];
let isJoined: boolean;
let skipJoinedCheckUntilX: number = 0;
let isValidJoinRange: boolean = true;
let lastCharX: number;
let range: [number, number];
let chars: string;
@@ -405,6 +407,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
row = y + terminal.buffer.ydisp;
line = terminal.buffer.lines.get(row)!;
this._model.lineLengths[y] = 0;
skipJoinedCheckUntilX = 0;
joinedRanges = this._characterJoinerService.getJoinedCharacters(row);
for (x = 0; x < terminal.cols; x++) {
lastBg = this._cellColorResolver.result.bg;
@@ -416,17 +419,28 @@ export class WebglRenderer extends Disposable implements IRenderer {
// If true, indicates that the current character(s) to draw were joined.
isJoined = false;
// Indicates whether this cell is part of a joined range that should be ignored as it cannot
// be rendered entirely, like the selection state differs across the range.
isValidJoinRange = (x >= skipJoinedCheckUntilX);
lastCharX = x;
// Process any joined character ranges as needed. Because of how the
// ranges are produced, we know that they are valid for the characters
// and attributes of our input.
if (joinedRanges.length > 0 && x === joinedRanges[0][0]) {
if (joinedRanges.length > 0 && x === joinedRanges[0][0] && isValidJoinRange) {
range = joinedRanges.shift()!;
// If the ligature's selection state is not consistent, don't join it. This helps the
// selection render correctly regardless whether they should be joined.
if (this._model.selection.isCellSelected(this._terminal, range[0], row) === this._model.selection.isCellSelected(this._terminal, range[1], row)) {
const firstSelectionState = this._model.selection.isCellSelected(this._terminal, range[0], row);
for (i = range[0] + 1; i < range[1]; i++) {
isValidJoinRange &&= (firstSelectionState === this._model.selection.isCellSelected(this._terminal, i, row));
}
if (!isValidJoinRange) {
skipJoinedCheckUntilX = range[1];
} else {
isJoined = true;
// We already know the exact start and end column of the joined range,
@@ -84,6 +84,7 @@ export class DomRendererRowFactory {
let charElement: HTMLSpanElement | undefined;
let cellAmount = 0;
let text = '';
let i = 0;
let oldBg = 0;
let oldFg = 0;
let oldExt = 0;
@@ -122,8 +123,11 @@ export class DomRendererRowFactory {
const range = joinedRanges.shift()!;
// If the ligature's selection state is not consistent, don't join it. This helps the
// selection render correctly regardless whether they should be joined.
if (this._isCellInSelection(range[0], row) !== this._isCellInSelection(range[1], row)) {
isValidJoinRange = false;
const firstSelectionState = this._isCellInSelection(range[0], row);
for (i = range[0] + 1; i < range[1]; i++) {
isValidJoinRange &&= (firstSelectionState === this._isCellInSelection(i, row));
}
if (!isValidJoinRange) {
skipJoinedCheckUntilX = range[1];
} else {
isJoined = true;