From 9c483c32ec7162b636afb84a772946e9f1c98dad Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 17 Jan 2019 09:13:57 -0800 Subject: [PATCH 1/4] Support RTL languages in the canvas renderer Part of #701 --- src/Terminal.ts | 3 ++- src/Unicode.ts | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/Unicode.ts diff --git a/src/Terminal.ts b/src/Terminal.ts index 4c0cd0f8a4..c31f320fc3 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -52,6 +52,7 @@ import { IKeyboardEvent } from './common/Types'; import { evaluateKeyboardEvent } from './core/input/Keyboard'; import { KeyboardResultType, ICharset } from './core/Types'; import { clone } from './common/Clone'; +import { registerRtlCharacterJoiners } from './Unicode'; // Let it work inside Node.js for automated testing purposes. const document = (typeof window !== 'undefined') ? window.document : null; @@ -752,7 +753,6 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II // Listen for mouse events and translate // them into terminal mouse protocols. this.bindMouse(); - } private _setupRenderer(): void { @@ -762,6 +762,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II default: throw new Error(`Unrecognized rendererType "${this.options.rendererType}"`); } this.register(this.renderer); + registerRtlCharacterJoiners(this); } /** diff --git a/src/Unicode.ts b/src/Unicode.ts new file mode 100644 index 0000000000..0a42c9f2e2 --- /dev/null +++ b/src/Unicode.ts @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2019 The xterm.js authors. All rights reserved. + */ + +import { Terminal } from 'xterm'; + +export function registerRtlCharacterJoiners(terminal: Terminal): void { + // Hebrew + terminal.registerCharacterJoiner(createUnicodeRangeJoiner(0x0590, 0x05FF)); + // Arabic (Kurdish, Persian, Urdu) + terminal.registerCharacterJoiner(createUnicodeRangeJoiner(0x0600, 0x06FF)); + // Arabic Supplement + terminal.registerCharacterJoiner(createUnicodeRangeJoiner(0x0750, 0x077F)); + // Thanana (Dhivehi, Maldavian) + terminal.registerCharacterJoiner(createUnicodeRangeJoiner(0x0780, 0x07BF)); + // Arabic Extended-A + terminal.registerCharacterJoiner(createUnicodeRangeJoiner(0x08A0, 0x08FF)); + // Arabic Presentation Forms-A + terminal.registerCharacterJoiner(createUnicodeRangeJoiner(0xFB50, 0xFDFF)); + // Arabic Presentation Forms-B + terminal.registerCharacterJoiner(createUnicodeRangeJoiner(0xFE70, 0xFEFF)); + // Rumi Numeral Symbols + terminal.registerCharacterJoiner(createUnicodeRangeJoiner(0x10E60, 0x10E60)); + // Arabic Mathematical Alphabetic Symbols + terminal.registerCharacterJoiner(createUnicodeRangeJoiner(0x1EE00, 0x1EEFF)); +} + +function createUnicodeRangeJoiner(rangeStart: number, rangeEnd: number): (text: string) => [number, number][] { + return (text: string) => { + let start = -1; + let length = 0; + const result: [number, number][] = []; + for (let i = 0; i < text.length; i++) { + const code = text.charCodeAt(i); + if (code >= rangeStart && code <= rangeEnd) { + if (start === -1) { + start = i; + } + length++; + } else if (length > 1) { + result.push([start, start + length + 1]); + start = -1; + length = 0; + } + } + if (length > 0) { + result.push([start, start + length + 1]); + } + return result; + } +} From b5355806e1a75c9420d7fde826287d3dc22a2f05 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 17 Jan 2019 09:29:16 -0800 Subject: [PATCH 2/4] Fix lint --- src/Unicode.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Unicode.ts b/src/Unicode.ts index 0a42c9f2e2..70bf007c8d 100644 --- a/src/Unicode.ts +++ b/src/Unicode.ts @@ -47,5 +47,5 @@ function createUnicodeRangeJoiner(rangeStart: number, rangeEnd: number): (text: result.push([start, start + length + 1]); } return result; - } + }; } From 8a86eceab87466304a9ce87d9955764db934cfc3 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 17 Jan 2019 09:38:04 -0800 Subject: [PATCH 3/4] Add test, fix bugs --- src/Unicode.test.ts | 19 +++++++++++++++++++ src/Unicode.ts | 13 +++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 src/Unicode.test.ts diff --git a/src/Unicode.test.ts b/src/Unicode.test.ts new file mode 100644 index 0000000000..f8356c4592 --- /dev/null +++ b/src/Unicode.test.ts @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { assert } from 'chai'; +import { createUnicodeRangeJoiner } from './Unicode'; + +describe('createUnicodeRangeJoiner', () => { + it('should join charcaters within the range', () => { + // Join a-z + const joiner = createUnicodeRangeJoiner(97, 122); + assert.deepEqual(joiner('ABCabc aBc abC Abc'), [ + [3, 6], // abc + [11, 13], // ab + [16, 18] // bc + ]); + }); +}); diff --git a/src/Unicode.ts b/src/Unicode.ts index 70bf007c8d..1c3e7f9639 100644 --- a/src/Unicode.ts +++ b/src/Unicode.ts @@ -25,7 +25,7 @@ export function registerRtlCharacterJoiners(terminal: Terminal): void { terminal.registerCharacterJoiner(createUnicodeRangeJoiner(0x1EE00, 0x1EEFF)); } -function createUnicodeRangeJoiner(rangeStart: number, rangeEnd: number): (text: string) => [number, number][] { +export function createUnicodeRangeJoiner(rangeStart: number, rangeEnd: number): (text: string) => [number, number][] { return (text: string) => { let start = -1; let length = 0; @@ -33,18 +33,23 @@ function createUnicodeRangeJoiner(rangeStart: number, rangeEnd: number): (text: for (let i = 0; i < text.length; i++) { const code = text.charCodeAt(i); if (code >= rangeStart && code <= rangeEnd) { + // Add to range if (start === -1) { start = i; } length++; - } else if (length > 1) { - result.push([start, start + length + 1]); + } else { + if (length > 1) { + // Finish range + result.push([start, start + length]); + } + // Clear a single match start = -1; length = 0; } } if (length > 0) { - result.push([start, start + length + 1]); + result.push([start, start + length]); } return result; }; From 88890b364d1d8f02ff2decea1fe79b28c5d23392 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 17 Jan 2019 13:21:34 -0800 Subject: [PATCH 4/4] Include space --- src/Unicode.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Unicode.ts b/src/Unicode.ts index 1c3e7f9639..e3638394aa 100644 --- a/src/Unicode.ts +++ b/src/Unicode.ts @@ -32,7 +32,7 @@ export function createUnicodeRangeJoiner(rangeStart: number, rangeEnd: number): const result: [number, number][] = []; for (let i = 0; i < text.length; i++) { const code = text.charCodeAt(i); - if (code >= rangeStart && code <= rangeEnd) { + if (code >= rangeStart && code <= rangeEnd || code === 32) { // Add to range if (start === -1) { start = i;