Skip to content

Commit c7a1e0a

Browse files
committed
Handle selections in the middle of ligatures too
1 parent 5bfb130 commit c7a1e0a

2 files changed

Lines changed: 22 additions & 4 deletions

File tree

addons/addon-webgl/src/WebglRenderer.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,8 @@ export class WebglRenderer extends Disposable implements IRenderer {
377377
let line: IBufferLine;
378378
let joinedRanges: [number, number][];
379379
let isJoined: boolean;
380+
let skipJoinedCheckUntilX: number = 0;
381+
let isValidJoinRange: boolean = true;
380382
let lastCharX: number;
381383
let range: [number, number];
382384
let chars: string;
@@ -405,6 +407,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
405407
row = y + terminal.buffer.ydisp;
406408
line = terminal.buffer.lines.get(row)!;
407409
this._model.lineLengths[y] = 0;
410+
skipJoinedCheckUntilX = 0;
408411
joinedRanges = this._characterJoinerService.getJoinedCharacters(row);
409412
for (x = 0; x < terminal.cols; x++) {
410413
lastBg = this._cellColorResolver.result.bg;
@@ -416,17 +419,28 @@ export class WebglRenderer extends Disposable implements IRenderer {
416419

417420
// If true, indicates that the current character(s) to draw were joined.
418421
isJoined = false;
422+
423+
// Indicates whether this cell is part of a joined range that should be ignored as it cannot
424+
// be rendered entirely, like the selection state differs across the range.
425+
isValidJoinRange = (x >= skipJoinedCheckUntilX);
426+
419427
lastCharX = x;
420428

421429
// Process any joined character ranges as needed. Because of how the
422430
// ranges are produced, we know that they are valid for the characters
423431
// and attributes of our input.
424-
if (joinedRanges.length > 0 && x === joinedRanges[0][0]) {
432+
if (joinedRanges.length > 0 && x === joinedRanges[0][0] && isValidJoinRange) {
425433
range = joinedRanges.shift()!;
426434

427435
// If the ligature's selection state is not consistent, don't join it. This helps the
428436
// selection render correctly regardless whether they should be joined.
429-
if (this._model.selection.isCellSelected(this._terminal, range[0], row) === this._model.selection.isCellSelected(this._terminal, range[1], row)) {
437+
const firstSelectionState = this._model.selection.isCellSelected(this._terminal, range[0], row);
438+
for (i = range[0] + 1; i < range[1]; i++) {
439+
isValidJoinRange &&= (firstSelectionState === this._model.selection.isCellSelected(this._terminal, i, row));
440+
}
441+
if (!isValidJoinRange) {
442+
skipJoinedCheckUntilX = range[1];
443+
} else {
430444
isJoined = true;
431445

432446
// We already know the exact start and end column of the joined range,

src/browser/renderer/dom/DomRendererRowFactory.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export class DomRendererRowFactory {
8484
let charElement: HTMLSpanElement | undefined;
8585
let cellAmount = 0;
8686
let text = '';
87+
let i = 0;
8788
let oldBg = 0;
8889
let oldFg = 0;
8990
let oldExt = 0;
@@ -122,8 +123,11 @@ export class DomRendererRowFactory {
122123
const range = joinedRanges.shift()!;
123124
// If the ligature's selection state is not consistent, don't join it. This helps the
124125
// selection render correctly regardless whether they should be joined.
125-
if (this._isCellInSelection(range[0], row) !== this._isCellInSelection(range[1], row)) {
126-
isValidJoinRange = false;
126+
const firstSelectionState = this._isCellInSelection(range[0], row);
127+
for (i = range[0] + 1; i < range[1]; i++) {
128+
isValidJoinRange &&= (firstSelectionState === this._isCellInSelection(i, row));
129+
}
130+
if (!isValidJoinRange) {
127131
skipJoinedCheckUntilX = range[1];
128132
} else {
129133
isJoined = true;

0 commit comments

Comments
 (0)