diff --git a/.eslintrc.json b/.eslintrc.json index 822ee4ba..936fec8c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -26,6 +26,8 @@ "addons/xterm-addon-serialize/benchmark/tsconfig.json", "addons/xterm-addon-unicode11/src/tsconfig.json", "addons/xterm-addon-unicode11/test/tsconfig.json", + "addons/xterm-addon-unicode-graphemes/src/tsconfig.json", + "addons/xterm-addon-unicode-graphemes/test/tsconfig.json", "addons/xterm-addon-web-links/src/tsconfig.json", "addons/xterm-addon-web-links/test/tsconfig.json", "addons/xterm-addon-webgl/src/tsconfig.json", @@ -34,6 +36,9 @@ "sourceType": "module" }, "ignorePatterns": [ + "addons/xterm-addon-unicode-graphemes/src/tiny-inflate.ts", + "addons/xterm-addon-unicode-graphemes/src/unicode-trie.ts", + "addons/xterm-addon-unicode-graphemes/src/UnicodeProperties.ts", "**/typings/*.d.ts", "**/node_modules", "**/*.js" diff --git a/addons/xterm-addon-unicode-graphemes/src/UnicodeGraphemeProvider.ts b/addons/xterm-addon-unicode-graphemes/src/UnicodeGraphemeProvider.ts index 3dd8af9c..87ec8d32 100644 --- a/addons/xterm-addon-unicode-graphemes/src/UnicodeGraphemeProvider.ts +++ b/addons/xterm-addon-unicode-graphemes/src/UnicodeGraphemeProvider.ts @@ -14,39 +14,36 @@ export class UnicodeGraphemeProvider implements IUnicodeVersionProvider { constructor() { } - charProperties(codepoint: number, preceding: UnicodeCharProperties): UnicodeCharProperties { + public charProperties(codepoint: number, preceding: UnicodeCharProperties): UnicodeCharProperties { let charInfo = UC.getInfo(codepoint); let w = UC.infoToWidthInfo(charInfo); let shouldJoin = false; if (w >= 2) { // Treat emoji_presentation_selector as WIDE. - w = w == 3 || this.ambiguousCharsAreWide || codepoint === 0xfe0f ? 2 : 1; - } else + w = w === 3 || this.ambiguousCharsAreWide || codepoint === 0xfe0f ? 2 : 1; + } else { w = 1; + } if (preceding !== 0) { - let oldWidth = UnicodeService.extractWidth(preceding); + const oldWidth = UnicodeService.extractWidth(preceding); charInfo = UC.shouldJoin(UnicodeService.extractCharKind(preceding), charInfo); shouldJoin = charInfo > 0; if (shouldJoin) { - if (oldWidth > w) + if (oldWidth > w) { w = oldWidth; - else if (charInfo === 32) // FIXME UC.GRAPHEME_BREAK_SAW_Regional_Pair) + } else if (charInfo === 32) { // UC.GRAPHEME_BREAK_SAW_Regional_Pair) w = 2; + } } } return UnicodeService.createPropertyValue(charInfo, w, shouldJoin); } public wcwidth(codepoint: number): UnicodeCharWidth { - let charInfo = UC.getInfo(codepoint); - let w = UC.infoToWidthInfo(charInfo); - let kind = (charInfo & UC.GRAPHEME_BREAK_MASK) >> UC.GRAPHEME_BREAK_SHIFT; - if (kind === UC.GRAPHEME_BREAK_Extend - || kind === UC.GRAPHEME_BREAK_Prepend) - return 0; - else if (w >= 2) - return w == 3 || this.ambiguousCharsAreWide? 2 : 1; - else - return 1; + const charInfo = UC.getInfo(codepoint); + const w = UC.infoToWidthInfo(charInfo); + const kind = (charInfo & UC.GRAPHEME_BREAK_MASK) >> UC.GRAPHEME_BREAK_SHIFT; + return (kind === UC.GRAPHEME_BREAK_Extend || kind === UC.GRAPHEME_BREAK_Prepend) ? 0 + : (w >= 2 && (w === 3 || this.ambiguousCharsAreWide)) ? 2 : 1; } } diff --git a/src/common/InputHandler.ts b/src/common/InputHandler.ts index baabd82f..fac20474 100644 --- a/src/common/InputHandler.ts +++ b/src/common/InputHandler.ts @@ -517,6 +517,8 @@ export class InputHandler extends Disposable implements IInputHandler { bufferRow.setCellFromCodePoint(this._activeBuffer.x - 1, 0, 1, curAttr.fg, curAttr.bg, curAttr.extended); } + let precedingInfo = this._parser.precedingCodepoint === 0 ? 0 + : this._parser.precedingJoinState; for (let pos = start; pos < end; ++pos) { code = data[pos]; @@ -530,14 +532,11 @@ export class InputHandler extends Disposable implements IInputHandler { } } - const precedingInfo = this._parser.precedingCodepoint === 0 ? 0 - : this._parser.precedingJoinState; const currentInfo = this._unicodeService.charProperties(code, precedingInfo); chWidth = UnicodeService.extractWidth(currentInfo); const shouldJoin = UnicodeService.extractShouldJoin(currentInfo); const oldWidth = shouldJoin ? UnicodeService.extractWidth(precedingInfo) : 0; - this._parser.precedingCodepoint = code; - this._parser.precedingJoinState = currentInfo; + precedingInfo = currentInfo; if (screenReaderMode) { this._onA11yChar.fire(stringFromCodePoint(code)); @@ -631,6 +630,19 @@ export class InputHandler extends Disposable implements IInputHandler { } } + this._parser.precedingJoinState = precedingInfo; + // store last char in Parser.precedingCodepoint for REP to work correctly + // This needs to check whether: + // - combining: only base char gets carried on (bug in xterm?) + if (end - start > 0) { + bufferRow.loadCell(this._activeBuffer.x - 1, this._workCell); + if (this._workCell.isCombined()) { + this._parser.precedingCodepoint = this._workCell.getChars().charCodeAt(0); + } else { + this._parser.precedingCodepoint = this._workCell.content; + } + } + // handle wide chars: reset cell to the right if it is second cell of a wide char if (this._activeBuffer.x < cols && end - start > 0 && bufferRow.getWidth(this._activeBuffer.x) === 0 && !bufferRow.hasContent(this._activeBuffer.x)) { bufferRow.setCellFromCodePoint(this._activeBuffer.x, 0, 1, curAttr.fg, curAttr.bg, curAttr.extended);