in src/renderer/CharacterJoinerRegistry.ts [34:108]
public getJoinedCharacters(row: number): [number, number][] {
if (this._characterJoiners.length === 0) {
return [];
}
const line = this._terminal.buffer.lines.get(row);
if (line.length === 0) {
return [];
}
const ranges: [number, number][] = [];
const lineStr = this._terminal.buffer.translateBufferLineToString(row, true);
// Because some cells can be represented by multiple javascript characters,
// we track the cell and the string indexes separately. This allows us to
// translate the string ranges we get from the joiners back into cell ranges
// for use when rendering
let rangeStartColumn = 0;
let currentStringIndex = 0;
let rangeStartStringIndex = 0;
let rangeAttr = line.get(0)[CHAR_DATA_ATTR_INDEX] >> 9;
for (let x = 0; x < this._terminal.cols; x++) {
const charData = line.get(x);
const chars = charData[CHAR_DATA_CHAR_INDEX];
const width = charData[CHAR_DATA_WIDTH_INDEX];
const attr = charData[CHAR_DATA_ATTR_INDEX] >> 9;
if (width === 0) {
// If this character is of width 0, skip it.
continue;
}
// End of range
if (attr !== rangeAttr) {
// If we ended up with a sequence of more than one character,
// look for ranges to join.
if (x - rangeStartColumn > 1) {
const joinedRanges = this._getJoinedRanges(
lineStr,
rangeStartStringIndex,
currentStringIndex,
line,
rangeStartColumn
);
for (let i = 0; i < joinedRanges.length; i++) {
ranges.push(joinedRanges[i]);
}
}
// Reset our markers for a new range.
rangeStartColumn = x;
rangeStartStringIndex = currentStringIndex;
rangeAttr = attr;
}
currentStringIndex += chars.length;
}
// Process any trailing ranges.
if (this._terminal.cols - rangeStartColumn > 1) {
const joinedRanges = this._getJoinedRanges(
lineStr,
rangeStartStringIndex,
currentStringIndex,
line,
rangeStartColumn
);
for (let i = 0; i < joinedRanges.length; i++) {
ranges.push(joinedRanges[i]);
}
}
return ranges;
}