Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'tty-6.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty/serial updates from Greg KH:
"Here is the big set of tty and serial driver changes for 6.16-rc1.

A little more churn than normal in this portion of the kernel for this
development cycle, Jiri and Nicholas were busy with cleanups and
reviews and fixes for the vt unicode handling logic which composed
most of the overall work in here.

Major changes are:

- vt unicode changes/reverts/changes from Nicholas. This should help
out a lot with screen readers and others that rely on vt console
support

- lock guard additions to the core tty/serial code to clean up lots
of error handling logic

- 8250 driver updates and fixes

- device tree conversions to yaml

- sh-sci driver updates

- other small cleanups and updates for serial drivers and tty core
portions

All of these have been in linux-next for 2 weeks with no reported issues"

* tag 'tty-6.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (105 commits)
tty: serial: 8250_omap: fix TX with DMA for am33xx
vt: add VT_GETCONSIZECSRPOS to retrieve console size and cursor position
vt: bracketed paste support
vt: remove VT_RESIZE and VT_RESIZEX from vt_compat_ioctl()
vt: process the full-width ASCII fallback range programmatically
vt: make use of ucs_get_fallback() when glyph is unavailable
vt: add ucs_get_fallback()
vt: create ucs_fallback_table.h_shipped with gen_ucs_fallback_table.py
vt: introduce gen_ucs_fallback_table.py to create ucs_fallback_table.h
vt: move glyph determination to a separate function
vt: make sure displayed double-width characters are remembered as such
vt: ucs.c: fix misappropriate in_range() usage
serial: max3100: Replace open-coded parity calculation with parity8()
dt-bindings: serial: 8250_omap: Drop redundant properties
dt-bindings: serial: Convert socionext,milbeaut-usio-uart to DT schema
dt-bindings: serial: Convert microchip,pic32mzda-uart to DT schema
dt-bindings: serial: Convert arm,sbsa-uart to DT schema
dt-bindings: serial: Convert snps,arc-uart to DT schema
dt-bindings: serial: Convert marvell,armada-3700-uart to DT schema
dt-bindings: serial: Convert lantiq,asc to DT schema
...

+6909 -955
+29 -1
Documentation/devicetree/bindings/serial/8250.yaml
··· 135 135 clock-frequency: true 136 136 137 137 clocks: 138 - maxItems: 1 138 + minItems: 1 139 + items: 140 + - description: The core function clock 141 + - description: An optional bus clock 142 + 143 + clock-names: 144 + minItems: 1 145 + items: 146 + - const: core 147 + - const: bus 139 148 140 149 resets: 141 150 maxItems: 1 ··· 232 223 required: 233 224 - reg 234 225 - interrupts 226 + 227 + if: 228 + properties: 229 + compatible: 230 + contains: 231 + const: spacemit,k1-uart 232 + then: 233 + required: [clock-names] 234 + properties: 235 + clocks: 236 + minItems: 2 237 + clock-names: 238 + minItems: 2 239 + else: 240 + properties: 241 + clocks: 242 + maxItems: 1 243 + clock-names: 244 + maxItems: 1 235 245 236 246 unevaluatedProperties: false 237 247
-7
Documentation/devicetree/bindings/serial/8250_omap.yaml
··· 64 64 clock-names: 65 65 const: fclk 66 66 67 - rts-gpios: true 68 - cts-gpios: true 69 - dtr-gpios: true 70 - dsr-gpios: true 71 - rng-gpios: true 72 - dcd-gpios: true 73 67 rs485-rts-active-high: true 74 - rts-gpio: true 75 68 power-domains: true 76 69 clock-frequency: true 77 70 current-speed: true
+3
Documentation/devicetree/bindings/serial/amlogic,meson-uart.yaml
··· 56 56 items: 57 57 - enum: 58 58 - amlogic,a4-uart 59 + - amlogic,s6-uart 60 + - amlogic,s7-uart 61 + - amlogic,s7d-uart 59 62 - amlogic,t7-uart 60 63 - const: amlogic,meson-s4-uart 61 64
-25
Documentation/devicetree/bindings/serial/arc-uart.txt
··· 1 - * Synopsys ARC UART : Non standard UART used in some of the ARC FPGA boards 2 - 3 - Required properties: 4 - - compatible : "snps,arc-uart" 5 - - reg : offset and length of the register set for the device. 6 - - interrupts : device interrupt 7 - - clock-frequency : the input clock frequency for the UART 8 - - current-speed : baud rate for UART 9 - 10 - e.g. 11 - 12 - arcuart0: serial@c0fc1000 { 13 - compatible = "snps,arc-uart"; 14 - reg = <0xc0fc1000 0x100>; 15 - interrupts = <5>; 16 - clock-frequency = <80000000>; 17 - current-speed = <115200>; 18 - }; 19 - 20 - Note: Each port should have an alias correctly numbered in "aliases" node. 21 - 22 - e.g. 23 - aliases { 24 - serial0 = &arcuart0; 25 - };
-19
Documentation/devicetree/bindings/serial/arm,mps2-uart.txt
··· 1 - ARM MPS2 UART 2 - 3 - Required properties: 4 - - compatible : Should be "arm,mps2-uart" 5 - - reg : Address and length of the register set 6 - - interrupts : Reference to the UART RX, TX and overrun interrupts 7 - 8 - Required clocking property: 9 - - clocks : The input clock of the UART 10 - 11 - 12 - Examples: 13 - 14 - uart0: serial@40004000 { 15 - compatible = "arm,mps2-uart"; 16 - reg = <0x40004000 0x1000>; 17 - interrupts = <0 1 12>; 18 - clocks = <&sysclk>; 19 - };
+46
Documentation/devicetree/bindings/serial/arm,mps2-uart.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/serial/arm,mps2-uart.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Arm MPS2 UART 8 + 9 + maintainers: 10 + - Vladimir Murzin <vladimir.murzin@arm.com> 11 + 12 + allOf: 13 + - $ref: /schemas/serial/serial.yaml# 14 + 15 + properties: 16 + compatible: 17 + const: arm,mps2-uart 18 + 19 + reg: 20 + maxItems: 1 21 + 22 + interrupts: 23 + items: 24 + - description: RX interrupt 25 + - description: TX interrupt 26 + - description: Overrun interrupt 27 + 28 + clocks: 29 + maxItems: 1 30 + 31 + required: 32 + - compatible 33 + - reg 34 + - interrupts 35 + - clocks 36 + 37 + unevaluatedProperties: false 38 + 39 + examples: 40 + - | 41 + serial@40004000 { 42 + compatible = "arm,mps2-uart"; 43 + reg = <0x40004000 0x1000>; 44 + interrupts = <0>, <1>, <12>; 45 + clocks = <&sysclk>; 46 + };
+38
Documentation/devicetree/bindings/serial/arm,sbsa-uart.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + --- 3 + $id: http://devicetree.org/schemas/serial/arm,sbsa-uart.yaml# 4 + $schema: http://devicetree.org/meta-schemas/core.yaml# 5 + 6 + title: ARM SBSA UART 7 + 8 + maintainers: 9 + - Andre Przywara <andre.przywara@arm.com> 10 + 11 + description: 12 + This UART uses a subset of the PL011 registers and consequently lives in the 13 + PL011 driver. It's baudrate and other communication parameters cannot be 14 + adjusted at runtime, so it lacks a clock specifier here. 15 + 16 + allOf: 17 + - $ref: /schemas/serial/serial.yaml# 18 + 19 + properties: 20 + compatible: 21 + const: arm,sbsa-uart 22 + 23 + reg: 24 + maxItems: 1 25 + 26 + interrupts: 27 + maxItems: 1 28 + 29 + current-speed: 30 + description: fixed baud rate set by the firmware 31 + 32 + required: 33 + - compatible 34 + - reg 35 + - interrupts 36 + - current-speed 37 + 38 + unevaluatedProperties: false
-10
Documentation/devicetree/bindings/serial/arm_sbsa_uart.txt
··· 1 - * ARM SBSA defined generic UART 2 - This UART uses a subset of the PL011 registers and consequently lives 3 - in the PL011 driver. It's baudrate and other communication parameters 4 - cannot be adjusted at runtime, so it lacks a clock specifier here. 5 - 6 - Required properties: 7 - - compatible: must be "arm,sbsa-uart" 8 - - reg: exactly one register range 9 - - interrupts: exactly one interrupt specifier 10 - - current-speed: the (fixed) baud rate set by the firmware
+1
Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml
··· 26 26 - enum: 27 27 - microchip,sam9x60-usart 28 28 - microchip,sam9x7-usart 29 + - microchip,sama7d65-usart 29 30 - const: atmel,at91sam9260-usart 30 31 - items: 31 32 - const: microchip,sam9x60-dbgu
-31
Documentation/devicetree/bindings/serial/cirrus,clps711x-uart.txt
··· 1 - * Cirrus Logic CLPS711X Universal Asynchronous Receiver/Transmitter (UART) 2 - 3 - Required properties: 4 - - compatible: Should be "cirrus,ep7209-uart". 5 - - reg: Address and length of the register set for the device. 6 - - interrupts: Should contain UART TX and RX interrupt. 7 - - clocks: Should contain UART core clock number. 8 - - syscon: Phandle to SYSCON node, which contain UART control bits. 9 - 10 - Optional properties: 11 - - {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD 12 - line respectively. 13 - 14 - Note: Each UART port should have an alias correctly numbered 15 - in "aliases" node. 16 - 17 - Example: 18 - aliases { 19 - serial0 = &uart1; 20 - }; 21 - 22 - uart1: uart@80000480 { 23 - compatible = "cirrus,ep7312-uart","cirrus,ep7209-uart"; 24 - reg = <0x80000480 0x80>; 25 - interrupts = <12 13>; 26 - clocks = <&clks 11>; 27 - syscon = <&syscon1>; 28 - cts-gpios = <&sysgpio 0 GPIO_ACTIVE_LOW>; 29 - dsr-gpios = <&sysgpio 1 GPIO_ACTIVE_LOW>; 30 - dcd-gpios = <&sysgpio 2 GPIO_ACTIVE_LOW>; 31 - };
+56
Documentation/devicetree/bindings/serial/cirrus,ep7209-uart.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/serial/cirrus,ep7209-uart.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Cirrus Logic CLPS711X Universal Asynchronous Receiver/Transmitter (UART) 8 + 9 + maintainers: 10 + - Alexander Shiyan <shc_work@mail.ru> 11 + 12 + allOf: 13 + - $ref: /schemas/serial/serial.yaml# 14 + 15 + properties: 16 + compatible: 17 + const: cirrus,ep7209-uart 18 + 19 + reg: 20 + maxItems: 1 21 + 22 + interrupts: 23 + items: 24 + - description: UART TX interrupt 25 + - description: UART RX interrupt 26 + 27 + clocks: 28 + maxItems: 1 29 + 30 + syscon: 31 + description: Phandle to SYSCON node, which contains UART control bits. 32 + $ref: /schemas/types.yaml#/definitions/phandle 33 + 34 + required: 35 + - compatible 36 + - reg 37 + - interrupts 38 + - clocks 39 + - syscon 40 + 41 + unevaluatedProperties: false 42 + 43 + examples: 44 + - | 45 + #include <dt-bindings/gpio/gpio.h> 46 + 47 + serial@80000480 { 48 + compatible = "cirrus,ep7209-uart"; 49 + reg = <0x80000480 0x80>; 50 + interrupts = <12>, <13>; 51 + clocks = <&clks 11>; 52 + syscon = <&syscon1>; 53 + cts-gpios = <&sysgpio 0 GPIO_ACTIVE_LOW>; 54 + dsr-gpios = <&sysgpio 1 GPIO_ACTIVE_LOW>; 55 + dcd-gpios = <&sysgpio 2 GPIO_ACTIVE_LOW>; 56 + };
+48
Documentation/devicetree/bindings/serial/cnxt,cx92755-usart.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/serial/cnxt,cx92755-usart.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Conexant Digicolor USART 8 + 9 + maintainers: 10 + - Baruch Siach <baruch@tkos.co.il> 11 + 12 + description: > 13 + Note: this binding is only applicable for using the USART peripheral as UART. 14 + USART also support synchronous serial protocols like SPI and I2S. 15 + Use the binding that matches the wiring of your system. 16 + 17 + allOf: 18 + - $ref: /schemas/serial/serial.yaml# 19 + 20 + properties: 21 + compatible: 22 + const: cnxt,cx92755-usart 23 + 24 + reg: 25 + maxItems: 1 26 + 27 + clocks: 28 + maxItems: 1 29 + 30 + interrupts: 31 + maxItems: 1 32 + 33 + required: 34 + - compatible 35 + - reg 36 + - clocks 37 + - interrupts 38 + 39 + unevaluatedProperties: false 40 + 41 + examples: 42 + - | 43 + serial@f0000740 { 44 + compatible = "cnxt,cx92755-usart"; 45 + reg = <0xf0000740 0x20>; 46 + clocks = <&main_clk>; 47 + interrupts = <44>; 48 + };
-27
Documentation/devicetree/bindings/serial/digicolor-usart.txt
··· 1 - Binding for Conexant Digicolor USART 2 - 3 - Note: this binding is only applicable for using the USART peripheral as 4 - UART. USART also support synchronous serial protocols like SPI and I2S. Use 5 - the binding that matches the wiring of your system. 6 - 7 - Required properties: 8 - - compatible : should be "cnxt,cx92755-usart". 9 - - reg: Should contain USART controller registers location and length. 10 - - interrupts: Should contain a single USART controller interrupt. 11 - - clocks: Must contain phandles to the USART clock 12 - See ../clocks/clock-bindings.txt for details. 13 - 14 - Note: Each UART port should have an alias correctly numbered 15 - in "aliases" node. 16 - 17 - Example: 18 - aliases { 19 - serial0 = &uart0; 20 - }; 21 - 22 - uart0: uart@f0000740 { 23 - compatible = "cnxt,cx92755-usart"; 24 - reg = <0xf0000740 0x20>; 25 - clocks = <&main_clk>; 26 - interrupts = <44>; 27 - };
+56
Documentation/devicetree/bindings/serial/lantiq,asc.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/serial/lantiq,asc.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Lantiq SoC ASC serial controller 8 + 9 + maintainers: 10 + - John Crispin <john@phrozen.org> 11 + - Songjun Wu <songjun.wu@linux.intel.com> 12 + 13 + allOf: 14 + - $ref: /schemas/serial/serial.yaml# 15 + 16 + properties: 17 + compatible: 18 + const: lantiq,asc 19 + 20 + reg: 21 + maxItems: 1 22 + 23 + interrupts: 24 + items: 25 + - description: TX interrupt 26 + - description: RX interrupt 27 + - description: Error interrupt 28 + 29 + clocks: 30 + items: 31 + - description: Frequency clock 32 + - description: Gate clock 33 + 34 + clock-names: 35 + items: 36 + - const: freq 37 + - const: asc 38 + 39 + required: 40 + - compatible 41 + - reg 42 + - interrupts 43 + 44 + unevaluatedProperties: false 45 + 46 + examples: 47 + - | 48 + #include <dt-bindings/interrupt-controller/mips-gic.h> 49 + 50 + serial@16600000 { 51 + compatible = "lantiq,asc"; 52 + reg = <0x16600000 0x100000>; 53 + interrupts = <GIC_SHARED 103 IRQ_TYPE_LEVEL_HIGH>, 54 + <GIC_SHARED 105 IRQ_TYPE_LEVEL_HIGH>, 55 + <GIC_SHARED 106 IRQ_TYPE_LEVEL_HIGH>; 56 + };
-31
Documentation/devicetree/bindings/serial/lantiq_asc.txt
··· 1 - Lantiq SoC ASC serial controller 2 - 3 - Required properties: 4 - - compatible : Should be "lantiq,asc" 5 - - reg : Address and length of the register set for the device 6 - - interrupts: the 3 (tx rx err) interrupt numbers. The interrupt specifier 7 - depends on the interrupt-parent interrupt controller. 8 - 9 - Optional properties: 10 - - clocks: Should contain frequency clock and gate clock 11 - - clock-names: Should be "freq" and "asc" 12 - 13 - Example: 14 - 15 - asc0: serial@16600000 { 16 - compatible = "lantiq,asc"; 17 - reg = <0x16600000 0x100000>; 18 - interrupt-parent = <&gic>; 19 - interrupts = <GIC_SHARED 103 IRQ_TYPE_LEVEL_HIGH>, 20 - <GIC_SHARED 105 IRQ_TYPE_LEVEL_HIGH>, 21 - <GIC_SHARED 106 IRQ_TYPE_LEVEL_HIGH>; 22 - clocks = <&cgu CLK_SSX4>, <&cgu GCLK_UART>; 23 - clock-names = "freq", "asc"; 24 - }; 25 - 26 - asc1: serial@e100c00 { 27 - compatible = "lantiq,asc"; 28 - reg = <0xE100C00 0x400>; 29 - interrupt-parent = <&icu0>; 30 - interrupts = <112 113 114>; 31 - };
+102
Documentation/devicetree/bindings/serial/marvell,armada-3700-uart.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/serial/marvell,armada-3700-uart.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Marvell Armada-3700 UART 8 + 9 + maintainers: 10 + - Pali Rohár <pali@kernel.org> 11 + 12 + description: 13 + Marvell UART is a non standard UART used in some of Marvell EBU SoCs (e.g. 14 + Armada-3700). 15 + 16 + properties: 17 + compatible: 18 + enum: 19 + - marvell,armada-3700-uart 20 + - marvell,armada-3700-uart-ext 21 + 22 + reg: 23 + maxItems: 1 24 + 25 + clocks: 26 + maxItems: 1 27 + description: 28 + UART reference clock used to derive the baud rate. If absent, only fixed 29 + baud rate from the bootloader is supported. 30 + 31 + interrupts: 32 + minItems: 2 33 + items: 34 + - description: UART sum interrupt 35 + - description: UART TX interrupt 36 + - description: UART RX interrupt 37 + 38 + interrupt-names: 39 + minItems: 2 40 + maxItems: 3 41 + 42 + required: 43 + - compatible 44 + - reg 45 + - interrupts 46 + - interrupt-names 47 + 48 + unevaluatedProperties: false 49 + 50 + allOf: 51 + - $ref: /schemas/serial/serial.yaml# 52 + - if: 53 + properties: 54 + compatible: 55 + const: marvell,armada-3700-uart-ext 56 + then: 57 + properties: 58 + interrupts: 59 + maxItems: 2 60 + 61 + interrupt-names: 62 + items: 63 + - const: uart-tx 64 + - const: uart-rx 65 + else: 66 + properties: 67 + interrupts: 68 + minItems: 3 69 + 70 + interrupt-names: 71 + items: 72 + - const: uart-sum 73 + - const: uart-tx 74 + - const: uart-rx 75 + 76 + examples: 77 + - | 78 + #include <dt-bindings/interrupt-controller/arm-gic.h> 79 + 80 + serial@12000 { 81 + compatible = "marvell,armada-3700-uart"; 82 + reg = <0x12000 0x18>; 83 + clocks = <&uartclk 0>; 84 + interrupts = 85 + <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>, 86 + <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>, 87 + <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>; 88 + interrupt-names = "uart-sum", "uart-tx", "uart-rx"; 89 + }; 90 + 91 + - | 92 + #include <dt-bindings/interrupt-controller/arm-gic.h> 93 + 94 + serial@12200 { 95 + compatible = "marvell,armada-3700-uart-ext"; 96 + reg = <0x12200 0x30>; 97 + clocks = <&uartclk 1>; 98 + interrupts = 99 + <GIC_SPI 30 IRQ_TYPE_EDGE_RISING>, 100 + <GIC_SPI 31 IRQ_TYPE_EDGE_RISING>; 101 + interrupt-names = "uart-tx", "uart-rx"; 102 + };
+1
Documentation/devicetree/bindings/serial/mediatek,uart.yaml
··· 33 33 - mediatek,mt6779-uart 34 34 - mediatek,mt6795-uart 35 35 - mediatek,mt6797-uart 36 + - mediatek,mt6893-uart 36 37 - mediatek,mt7622-uart 37 38 - mediatek,mt7623-uart 38 39 - mediatek,mt7629-uart
-29
Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt
··· 1 - * Microchip Universal Asynchronous Receiver Transmitter (UART) 2 - 3 - Required properties: 4 - - compatible: Should be "microchip,pic32mzda-uart" 5 - - reg: Should contain registers location and length 6 - - interrupts: Should contain interrupt 7 - - clocks: Phandle to the clock. 8 - See: Documentation/devicetree/bindings/clock/clock-bindings.txt 9 - - pinctrl-names: A pinctrl state names "default" must be defined. 10 - - pinctrl-0: Phandle referencing pin configuration of the UART peripheral. 11 - See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt 12 - 13 - Optional properties: 14 - - cts-gpios: CTS pin for UART 15 - 16 - Example: 17 - uart1: serial@1f822000 { 18 - compatible = "microchip,pic32mzda-uart"; 19 - reg = <0x1f822000 0x50>; 20 - interrupts = <112 IRQ_TYPE_LEVEL_HIGH>, 21 - <113 IRQ_TYPE_LEVEL_HIGH>, 22 - <114 IRQ_TYPE_LEVEL_HIGH>; 23 - clocks = <&rootclk PB2CLK>; 24 - pinctrl-names = "default"; 25 - pinctrl-0 = <&pinctrl_uart1 26 - &pinctrl_uart1_cts 27 - &pinctrl_uart1_rts>; 28 - cts-gpios = <&gpio1 15 0>; 29 - };
+53
Documentation/devicetree/bindings/serial/microchip,pic32mzda-uart.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/serial/microchip,pic32mzda-uart.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Microchip PIC32 UART 8 + 9 + maintainers: 10 + - Andrei Pistirica <andrei.pistirica@microchip.com> 11 + - Purna Chandra Mandal <purna.mandal@microchip.com> 12 + 13 + allOf: 14 + - $ref: /schemas/serial/serial.yaml# 15 + 16 + properties: 17 + compatible: 18 + const: microchip,pic32mzda-uart 19 + 20 + reg: 21 + maxItems: 1 22 + 23 + interrupts: 24 + items: 25 + - description: Fault 26 + - description: RX 27 + - description: TX 28 + 29 + clocks: 30 + maxItems: 1 31 + 32 + required: 33 + - compatible 34 + - reg 35 + - interrupts 36 + - clocks 37 + 38 + unevaluatedProperties: false 39 + 40 + examples: 41 + - | 42 + #include <dt-bindings/interrupt-controller/irq.h> 43 + #include <dt-bindings/clock/microchip,pic32-clock.h> 44 + 45 + serial@1f822000 { 46 + compatible = "microchip,pic32mzda-uart"; 47 + reg = <0x1f822000 0x50>; 48 + interrupts = <112 IRQ_TYPE_LEVEL_HIGH>, 49 + <113 IRQ_TYPE_LEVEL_HIGH>, 50 + <114 IRQ_TYPE_LEVEL_HIGH>; 51 + clocks = <&rootclk PB2CLK>; 52 + cts-gpios = <&gpio1 15 0>; 53 + };
-21
Documentation/devicetree/bindings/serial/milbeaut-uart.txt
··· 1 - Socionext Milbeaut UART controller 2 - 3 - Required properties: 4 - - compatible: should be "socionext,milbeaut-usio-uart". 5 - - reg: offset and length of the register set for the device. 6 - - interrupts: two interrupts specifier. 7 - - interrupt-names: should be "rx", "tx". 8 - - clocks: phandle to the input clock. 9 - 10 - Optional properties: 11 - - auto-flow-control: flow control enable. 12 - 13 - Example: 14 - usio1: usio_uart@1e700010 { 15 - compatible = "socionext,milbeaut-usio-uart"; 16 - reg = <0x1e700010 0x10>; 17 - interrupts = <0 141 0x4>, <0 149 0x4>; 18 - interrupt-names = "rx", "tx"; 19 - clocks = <&clk 2>; 20 - auto-flow-control; 21 - };
-56
Documentation/devicetree/bindings/serial/mvebu-uart.txt
··· 1 - * Marvell UART : Non standard UART used in some of Marvell EBU SoCs 2 - e.g., Armada-3700. 3 - 4 - Required properties: 5 - - compatible: 6 - - "marvell,armada-3700-uart" for the standard variant of the UART 7 - (32 bytes FIFO, no DMA, level interrupts, 8-bit access to the 8 - FIFO), called also UART1. 9 - - "marvell,armada-3700-uart-ext" for the extended variant of the 10 - UART (128 bytes FIFO, DMA, front interrupts, 8-bit or 32-bit 11 - accesses to the FIFO), called also UART2. 12 - - reg: offset and length of the register set for the device. 13 - - clocks: UART reference clock used to derive the baudrate. If no clock 14 - is provided (possible only with the "marvell,armada-3700-uart" 15 - compatible string for backward compatibility), it will only work 16 - if the baudrate was initialized by the bootloader and no baudrate 17 - change will then be possible. When provided it should be UART1-clk 18 - for standard variant of UART and UART2-clk for extended variant 19 - of UART. TBG clock (with UART TBG divisors d1=d2=1) or xtal clock 20 - should not be used and are supported only for backward compatibility. 21 - - interrupts: 22 - - Must contain three elements for the standard variant of the IP 23 - (marvell,armada-3700-uart): "uart-sum", "uart-tx" and "uart-rx", 24 - respectively the UART sum interrupt, the UART TX interrupt and 25 - UART RX interrupt. A corresponding interrupt-names property must 26 - be defined. 27 - - Must contain two elements for the extended variant of the IP 28 - (marvell,armada-3700-uart-ext): "uart-tx" and "uart-rx", 29 - respectively the UART TX interrupt and the UART RX interrupt. A 30 - corresponding interrupt-names property must be defined. 31 - - For backward compatibility reasons, a single element interrupts 32 - property is also supported for the standard variant of the IP, 33 - containing only the UART sum interrupt. This form is deprecated 34 - and should no longer be used. 35 - 36 - Example: 37 - uart0: serial@12000 { 38 - compatible = "marvell,armada-3700-uart"; 39 - reg = <0x12000 0x18>; 40 - clocks = <&uartclk 0>; 41 - interrupts = 42 - <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>, 43 - <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>, 44 - <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>; 45 - interrupt-names = "uart-sum", "uart-tx", "uart-rx"; 46 - }; 47 - 48 - uart1: serial@12200 { 49 - compatible = "marvell,armada-3700-uart-ext"; 50 - reg = <0x12200 0x30>; 51 - clocks = <&uartclk 1>; 52 - interrupts = 53 - <GIC_SPI 30 IRQ_TYPE_EDGE_RISING>, 54 - <GIC_SPI 31 IRQ_TYPE_EDGE_RISING>; 55 - interrupt-names = "uart-tx", "uart-rx"; 56 - };
+39
Documentation/devicetree/bindings/serial/nxp,lpc3220-hsuart.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/serial/nxp,lpc3220-hsuart.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: NXP LPC32xx SoC High Speed UART 8 + 9 + maintainers: 10 + - Vladimir Zapolskiy <vz@mleia.com> 11 + - Piotr Wojtaszczyk <piotr.wojtaszczyk@timesys.com> 12 + 13 + allOf: 14 + - $ref: /schemas/serial/serial.yaml# 15 + 16 + properties: 17 + compatible: 18 + const: nxp,lpc3220-hsuart 19 + 20 + reg: 21 + maxItems: 1 22 + 23 + interrupts: 24 + maxItems: 1 25 + 26 + required: 27 + - compatible 28 + - reg 29 + - interrupts 30 + 31 + unevaluatedProperties: false 32 + 33 + examples: 34 + - | 35 + serial@40014000 { 36 + compatible = "nxp,lpc3220-hsuart"; 37 + reg = <0x40014000 0x1000>; 38 + interrupts = <26 0>; 39 + };
-14
Documentation/devicetree/bindings/serial/nxp-lpc32xx-hsuart.txt
··· 1 - * NXP LPC32xx SoC High Speed UART 2 - 3 - Required properties: 4 - - compatible: Should be "nxp,lpc3220-hsuart" 5 - - reg: Should contain registers location and length 6 - - interrupts: Should contain interrupt 7 - 8 - Example: 9 - 10 - uart1: serial@40014000 { 11 - compatible = "nxp,lpc3220-hsuart"; 12 - reg = <0x40014000 0x1000>; 13 - interrupts = <26 0>; 14 - };
+78
Documentation/devicetree/bindings/serial/renesas,rsci.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/serial/renesas,rsci.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Renesas RSCI Serial Communication Interface 8 + 9 + maintainers: 10 + - Geert Uytterhoeven <geert+renesas@glider.be> 11 + - Thierry Bultel <thierry.bultel.yh@bp.renesas.com> 12 + 13 + allOf: 14 + - $ref: serial.yaml# 15 + 16 + properties: 17 + compatible: 18 + const: renesas,r9a09g077-rsci # RZ/T2H 19 + 20 + reg: 21 + maxItems: 1 22 + 23 + interrupts: 24 + items: 25 + - description: Error interrupt 26 + - description: Receive buffer full interrupt 27 + - description: Transmit buffer empty interrupt 28 + - description: Transmit end interrupt 29 + 30 + interrupt-names: 31 + items: 32 + - const: eri 33 + - const: rxi 34 + - const: txi 35 + - const: tei 36 + 37 + clocks: 38 + maxItems: 1 39 + 40 + clock-names: 41 + const: fck # UART functional clock 42 + 43 + power-domains: 44 + maxItems: 1 45 + 46 + uart-has-rtscts: false 47 + 48 + required: 49 + - compatible 50 + - reg 51 + - interrupts 52 + - clocks 53 + - clock-names 54 + - power-domains 55 + 56 + unevaluatedProperties: false 57 + 58 + examples: 59 + - | 60 + #include <dt-bindings/interrupt-controller/arm-gic.h> 61 + #include <dt-bindings/clock/renesas-cpg-mssr.h> 62 + 63 + aliases { 64 + serial0 = &sci0; 65 + }; 66 + 67 + sci0: serial@80005000 { 68 + compatible = "renesas,r9a09g077-rsci"; 69 + reg = <0x80005000 0x400>; 70 + interrupts = <GIC_SPI 590 IRQ_TYPE_LEVEL_HIGH>, 71 + <GIC_SPI 591 IRQ_TYPE_EDGE_RISING>, 72 + <GIC_SPI 592 IRQ_TYPE_EDGE_RISING>, 73 + <GIC_SPI 593 IRQ_TYPE_LEVEL_HIGH>; 74 + interrupt-names = "eri", "rxi", "txi", "tei"; 75 + clocks = <&cpg CPG_MOD 108>; 76 + clock-names = "fck"; 77 + power-domains = <&cpg>; 78 + };
+51
Documentation/devicetree/bindings/serial/snps,arc-uart.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/serial/snps,arc-uart.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Synopsys ARC UART 8 + 9 + maintainers: 10 + - Vineet Gupta <vgupta@kernel.org> 11 + 12 + description: 13 + Synopsys ARC UART is a non-standard UART used in some of the ARC FPGA boards. 14 + 15 + allOf: 16 + - $ref: /schemas/serial/serial.yaml# 17 + 18 + properties: 19 + compatible: 20 + const: snps,arc-uart 21 + 22 + reg: 23 + maxItems: 1 24 + 25 + interrupts: 26 + maxItems: 1 27 + 28 + clock-frequency: 29 + description: the input clock frequency for the UART 30 + 31 + current-speed: 32 + description: baud rate for UART 33 + 34 + required: 35 + - compatible 36 + - reg 37 + - interrupts 38 + - clock-frequency 39 + - current-speed 40 + 41 + unevaluatedProperties: false 42 + 43 + examples: 44 + - | 45 + serial@c0fc1000 { 46 + compatible = "snps,arc-uart"; 47 + reg = <0xc0fc1000 0x100>; 48 + interrupts = <5>; 49 + clock-frequency = <80000000>; 50 + current-speed = <115200>; 51 + };
+1 -1
Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
··· 17 17 properties: 18 18 compatible: 19 19 items: 20 - - const: renesas,r9a06g032-uart 20 + - {} 21 21 - const: renesas,rzn1-uart 22 22 - const: snps,dw-apb-uart 23 23 then:
+56
Documentation/devicetree/bindings/serial/socionext,milbeaut-usio-uart.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/serial/socionext,milbeaut-usio-uart.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Socionext Milbeaut UART controller 8 + 9 + maintainers: 10 + - Sugaya Taichi <sugaya.taichi@socionext.com> 11 + 12 + allOf: 13 + - $ref: /schemas/serial/serial.yaml# 14 + 15 + properties: 16 + compatible: 17 + const: socionext,milbeaut-usio-uart 18 + 19 + reg: 20 + maxItems: 1 21 + 22 + interrupts: 23 + items: 24 + - description: RX interrupt specifier 25 + - description: TX interrupt specifier 26 + 27 + interrupt-names: 28 + items: 29 + - const: rx 30 + - const: tx 31 + 32 + clocks: 33 + maxItems: 1 34 + 35 + auto-flow-control: 36 + description: Enable automatic flow control. 37 + type: boolean 38 + 39 + required: 40 + - compatible 41 + - reg 42 + - interrupts 43 + - interrupt-names 44 + 45 + unevaluatedProperties: false 46 + 47 + examples: 48 + - | 49 + serial@1e700010 { 50 + compatible = "socionext,milbeaut-usio-uart"; 51 + reg = <0x1e700010 0x10>; 52 + interrupts = <0 141 0x4>, <0 149 0x4>; 53 + interrupt-names = "rx", "tx"; 54 + clocks = <&clk 2>; 55 + auto-flow-control; 56 + };
+1 -1
MAINTAINERS
··· 14503 14503 M: Pali Rohár <pali@kernel.org> 14504 14504 S: Maintained 14505 14505 F: Documentation/devicetree/bindings/clock/marvell,armada-3700-uart-clock.yaml 14506 - F: Documentation/devicetree/bindings/serial/mvebu-uart.txt 14506 + F: Documentation/devicetree/bindings/serial/marvell,armada-3700-uart.yaml 14507 14507 F: drivers/tty/serial/mvebu-uart.c 14508 14508 14509 14509 MARVELL ARMADA DRM SUPPORT
+2 -2
drivers/tty/mxser.c
··· 1812 1812 1813 1813 /* io address */ 1814 1814 ioaddress = pci_resource_start(pdev, 2); 1815 - retval = pci_request_region(pdev, 2, "mxser(IO)"); 1815 + retval = pcim_request_region(pdev, 2, "mxser(IO)"); 1816 1816 if (retval) 1817 1817 goto err_zero; 1818 1818 ··· 1822 1822 1823 1823 /* vector */ 1824 1824 ioaddress = pci_resource_start(pdev, 3); 1825 - retval = pci_request_region(pdev, 3, "mxser(vector)"); 1825 + retval = pcim_request_region(pdev, 3, "mxser(vector)"); 1826 1826 if (retval) 1827 1827 goto err_zero; 1828 1828 brd->vector = ioaddress;
+3 -5
drivers/tty/serdev/core.c
··· 118 118 119 119 err = device_add(&serdev->dev); 120 120 if (err < 0) { 121 - dev_err(&serdev->dev, "Can't add %s, status %pe\n", 122 - dev_name(&serdev->dev), ERR_PTR(err)); 121 + dev_err(&serdev->dev, "Failed to add serdev: %d\n", err); 123 122 goto err_clear_serdev; 124 123 } 125 124 126 - dev_dbg(&serdev->dev, "device %s registered\n", dev_name(&serdev->dev)); 125 + dev_dbg(&serdev->dev, "serdev registered successfully\n"); 127 126 128 127 return 0; 129 128 ··· 782 783 goto err_rpm_disable; 783 784 } 784 785 785 - dev_dbg(&ctrl->dev, "serdev%d registered: dev:%p\n", 786 - ctrl->nr, &ctrl->dev); 786 + dev_dbg(&ctrl->dev, "serdev controller registered: dev:%p\n", &ctrl->dev); 787 787 return 0; 788 788 789 789 err_rpm_disable:
-6
drivers/tty/serial/8250/8250.h
··· 223 223 struct uart_8250_port *serial8250_setup_port(int index); 224 224 struct uart_8250_port *serial8250_get_port(int line); 225 225 226 - void serial8250_rpm_get(struct uart_8250_port *p); 227 - void serial8250_rpm_put(struct uart_8250_port *p); 228 - 229 - void serial8250_rpm_get_tx(struct uart_8250_port *p); 230 - void serial8250_rpm_put_tx(struct uart_8250_port *p); 231 - 232 226 int serial8250_em485_config(struct uart_port *port, struct ktermios *termios, 233 227 struct serial_rs485 *rs485); 234 228 void serial8250_em485_start_tx(struct uart_8250_port *p, bool toggle_ier);
+1 -1
drivers/tty/serial/8250/8250_core.c
··· 461 461 char *options) 462 462 { 463 463 char match[] = "uart"; /* 8250-specific earlycon name */ 464 - unsigned char iotype; 464 + enum uart_iotype iotype; 465 465 resource_size_t addr; 466 466 int i; 467 467
+2
drivers/tty/serial/8250/8250_early.c
··· 77 77 outb(value, port->iobase + offset); 78 78 break; 79 79 #endif 80 + default: 81 + break; 80 82 } 81 83 } 82 84
+37 -52
drivers/tty/serial/8250/8250_ni.c
··· 10 10 * Copyright 2012-2023 National Instruments Corporation 11 11 */ 12 12 13 - #include <linux/acpi.h> 14 13 #include <linux/bitfield.h> 14 + #include <linux/bits.h> 15 + #include <linux/clk.h> 15 16 #include <linux/device.h> 16 17 #include <linux/io.h> 17 18 #include <linux/init.h> 19 + #include <linux/mod_devicetable.h> 18 20 #include <linux/module.h> 21 + #include <linux/platform_device.h> 19 22 #include <linux/property.h> 20 - #include <linux/clk.h> 23 + #include <linux/serial_core.h> 24 + #include <linux/types.h> 21 25 22 26 #include "8250.h" 23 27 ··· 94 90 { 95 91 u8 pcr; 96 92 97 - pcr = port->serial_in(port, NI16550_PCR_OFFSET); 93 + pcr = serial_port_in(port, NI16550_PCR_OFFSET); 98 94 pcr &= ~NI16550_PCR_TXVR_ENABLE_BIT; 99 95 dev_dbg(port->dev, "disable transceivers: write pcr: 0x%02x\n", pcr); 100 - port->serial_out(port, NI16550_PCR_OFFSET, pcr); 96 + serial_port_out(port, NI16550_PCR_OFFSET, pcr); 101 97 102 98 return 0; 103 99 } ··· 109 105 struct uart_8250_port *up = container_of(port, struct uart_8250_port, port); 110 106 u8 pcr; 111 107 112 - pcr = serial_in(up, NI16550_PCR_OFFSET); 108 + pcr = serial_port_in(port, NI16550_PCR_OFFSET); 113 109 pcr &= ~NI16550_PCR_WIRE_MODE_MASK; 114 110 115 111 if ((rs485->flags & SER_RS485_MODE_RS422) || ··· 124 120 } 125 121 126 122 dev_dbg(port->dev, "config rs485: write pcr: 0x%02x, acr: %02x\n", pcr, up->acr); 127 - serial_out(up, NI16550_PCR_OFFSET, pcr); 123 + serial_port_out(port, NI16550_PCR_OFFSET, pcr); 128 124 serial_icr_write(up, UART_ACR, up->acr); 129 125 130 126 return 0; ··· 228 224 { 229 225 struct resource *regs; 230 226 231 - regs = platform_get_resource(pdev, IORESOURCE_IO, 0); 232 - if (regs) { 227 + regs = platform_get_mem_or_io(pdev, 0); 228 + if (!regs) 229 + return dev_err_probe(&pdev->dev, -EINVAL, "no registers defined\n"); 230 + 231 + switch (resource_type(regs)) { 232 + case IORESOURCE_IO: 233 233 port->iotype = UPIO_PORT; 234 234 port->iobase = regs->start; 235 235 236 236 return 0; 237 - } 238 - 239 - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 240 - if (regs) { 237 + case IORESOURCE_MEM: 241 238 port->iotype = UPIO_MEM; 242 239 port->mapbase = regs->start; 243 240 port->mapsize = resource_size(regs); 244 241 port->flags |= UPF_IOREMAP; 245 242 246 - port->membase = devm_ioremap(&pdev->dev, port->mapbase, 247 - port->mapsize); 248 - if (!port->membase) 249 - return -ENOMEM; 250 - 251 243 return 0; 244 + default: 245 + return -EINVAL; 252 246 } 253 - 254 - dev_err(&pdev->dev, "no registers defined\n"); 255 - return -EINVAL; 256 247 } 257 248 258 249 /* ··· 279 280 struct device *dev = &pdev->dev; 280 281 struct uart_8250_port uart = {}; 281 282 unsigned int txfifosz, rxfifosz; 282 - unsigned int prescaler = 0; 283 + unsigned int prescaler; 283 284 struct ni16550_data *data; 284 285 const char *portmode; 285 286 bool rs232_property; 286 287 int ret; 287 - int irq; 288 288 289 289 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 290 290 if (!data) 291 291 return -ENOMEM; 292 292 293 293 spin_lock_init(&uart.port.lock); 294 - 295 - irq = platform_get_irq(pdev, 0); 296 - if (irq < 0) 297 - return irq; 298 294 299 295 ret = ni16550_get_regs(pdev, &uart.port); 300 296 if (ret < 0) ··· 301 307 info = device_get_match_data(dev); 302 308 303 309 uart.port.dev = dev; 304 - uart.port.irq = irq; 305 - uart.port.irqflags = IRQF_SHARED; 306 - uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF 307 - | UPF_FIXED_PORT | UPF_FIXED_TYPE; 310 + uart.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_FIXED_TYPE; 308 311 uart.port.startup = ni16550_port_startup; 309 312 uart.port.shutdown = ni16550_port_shutdown; 310 313 ··· 323 332 /* 324 333 * Declaration of the base clock frequency can come from one of: 325 334 * - static declaration in this driver (for older ACPI IDs) 326 - * - a "clock-frquency" ACPI 335 + * - a "clock-frequency" ACPI 327 336 */ 328 - if (info->uartclk) 329 - uart.port.uartclk = info->uartclk; 330 - if (device_property_read_u32(dev, "clock-frequency", 331 - &uart.port.uartclk)) { 337 + uart.port.uartclk = info->uartclk; 338 + 339 + ret = uart_read_port_properties(&uart.port); 340 + if (ret) 341 + return ret; 342 + 343 + if (!uart.port.uartclk) { 332 344 data->clk = devm_clk_get_enabled(dev, NULL); 333 345 if (!IS_ERR(data->clk)) 334 346 uart.port.uartclk = clk_get_rate(data->clk); 335 347 } 336 348 337 - if (!uart.port.uartclk) { 338 - dev_err(dev, "unable to determine clock frequency!\n"); 339 - ret = -ENODEV; 340 - goto err; 341 - } 349 + if (!uart.port.uartclk) 350 + return dev_err_probe(dev, -ENODEV, "unable to determine clock frequency!\n"); 342 351 343 - if (info->prescaler) 344 - prescaler = info->prescaler; 352 + prescaler = info->prescaler; 345 353 device_property_read_u32(dev, "clock-prescaler", &prescaler); 346 - 347 - if (prescaler != 0) { 354 + if (prescaler) { 348 355 uart.port.set_mctrl = ni16550_set_mctrl; 349 356 ni16550_config_prescaler(&uart, (u8)prescaler); 350 357 } ··· 382 393 383 394 ret = serial8250_register_8250_port(&uart); 384 395 if (ret < 0) 385 - goto err; 396 + return ret; 386 397 data->line = ret; 387 398 388 399 platform_set_drvdata(pdev, data); 389 400 return 0; 390 - 391 - err: 392 - return ret; 393 401 } 394 402 395 403 static void ni16550_remove(struct platform_device *pdev) ··· 396 410 serial8250_unregister_port(data->line); 397 411 } 398 412 399 - #ifdef CONFIG_ACPI 400 413 /* NI 16550 RS-485 Interface */ 401 414 static const struct ni16550_device_info nic7750 = { 402 415 .uartclk = 33333333, ··· 420 435 .uartclk = 29629629, 421 436 .prescaler = 0x09, 422 437 }; 438 + 423 439 static const struct acpi_device_id ni16550_acpi_match[] = { 424 440 { "NIC7750", (kernel_ulong_t)&nic7750 }, 425 441 { "NIC7772", (kernel_ulong_t)&nic7772 }, 426 442 { "NIC792B", (kernel_ulong_t)&nic792b }, 427 443 { "NIC7A69", (kernel_ulong_t)&nic7a69 }, 428 - { }, 444 + { } 429 445 }; 430 446 MODULE_DEVICE_TABLE(acpi, ni16550_acpi_match); 431 - #endif 432 447 433 448 static struct platform_driver ni16550_driver = { 434 449 .driver = { 435 450 .name = "ni16550", 436 - .acpi_match_table = ACPI_PTR(ni16550_acpi_match), 451 + .acpi_match_table = ni16550_acpi_match, 437 452 }, 438 453 .probe = ni16550_probe, 439 454 .remove = ni16550_remove,
+14 -1
drivers/tty/serial/8250/8250_of.c
··· 24 24 25 25 struct of_serial_info { 26 26 struct clk *clk; 27 + struct clk *bus_clk; 27 28 struct reset_control *rst; 28 29 int type; 29 30 int line; ··· 124 123 125 124 /* Get clk rate through clk driver if present */ 126 125 if (!port->uartclk) { 127 - info->clk = devm_clk_get_enabled(dev, NULL); 126 + struct clk *bus_clk; 127 + 128 + bus_clk = devm_clk_get_optional_enabled(dev, "bus"); 129 + if (IS_ERR(bus_clk)) { 130 + ret = dev_err_probe(dev, PTR_ERR(bus_clk), "failed to get bus clock\n"); 131 + goto err_pmruntime; 132 + } 133 + 134 + /* If the bus clock is required, core clock must be named */ 135 + info->clk = devm_clk_get_enabled(dev, bus_clk ? "core" : NULL); 128 136 if (IS_ERR(info->clk)) { 129 137 ret = dev_err_probe(dev, PTR_ERR(info->clk), "failed to get clock\n"); 130 138 goto err_pmruntime; 131 139 } 132 140 141 + info->bus_clk = bus_clk; 133 142 port->uartclk = clk_get_rate(info->clk); 134 143 } 135 144 /* If current-speed was set, then try not to change it. */ ··· 301 290 if (!uart_console(port) || console_suspend_enabled) { 302 291 pm_runtime_put_sync(dev); 303 292 clk_disable_unprepare(info->clk); 293 + clk_disable_unprepare(info->bus_clk); 304 294 } 305 295 return 0; 306 296 } ··· 314 302 315 303 if (!uart_console(port) || console_suspend_enabled) { 316 304 pm_runtime_get_sync(dev); 305 + clk_prepare_enable(info->bus_clk); 317 306 clk_prepare_enable(info->clk); 318 307 } 319 308
+10 -15
drivers/tty/serial/8250/8250_omap.c
··· 1173 1173 return 0; 1174 1174 } 1175 1175 1176 - sg_init_table(&sg, 1); 1177 - ret = kfifo_dma_out_prepare_mapped(&tport->xmit_fifo, &sg, 1, 1178 - UART_XMIT_SIZE, dma->tx_addr); 1179 - if (ret != 1) { 1180 - serial8250_clear_THRI(p); 1181 - return 0; 1182 - } 1183 - 1184 - dma->tx_size = sg_dma_len(&sg); 1185 - 1186 1176 if (priv->habit & OMAP_DMA_TX_KICK) { 1187 1177 unsigned char c; 1188 1178 u8 tx_lvl; ··· 1197 1207 ret = -EBUSY; 1198 1208 goto err; 1199 1209 } 1200 - if (dma->tx_size < 4) { 1210 + if (kfifo_len(&tport->xmit_fifo) < 4) { 1201 1211 ret = -EINVAL; 1202 1212 goto err; 1203 1213 } 1204 - if (!kfifo_get(&tport->xmit_fifo, &c)) { 1214 + if (!uart_fifo_out(&p->port, &c, 1)) { 1205 1215 ret = -EINVAL; 1206 1216 goto err; 1207 1217 } 1208 1218 skip_byte = c; 1209 - /* now we need to recompute due to kfifo_get */ 1210 - kfifo_dma_out_prepare_mapped(&tport->xmit_fifo, &sg, 1, 1211 - UART_XMIT_SIZE, dma->tx_addr); 1219 + } 1220 + 1221 + sg_init_table(&sg, 1); 1222 + ret = kfifo_dma_out_prepare_mapped(&tport->xmit_fifo, &sg, 1, UART_XMIT_SIZE, dma->tx_addr); 1223 + if (ret != 1) { 1224 + ret = -EINVAL; 1225 + goto err; 1212 1226 } 1213 1227 1214 1228 desc = dmaengine_prep_slave_sg(dma->txchan, &sg, 1, DMA_MEM_TO_DEV, ··· 1222 1228 goto err; 1223 1229 } 1224 1230 1231 + dma->tx_size = sg_dma_len(&sg); 1225 1232 dma->tx_running = 1; 1226 1233 1227 1234 desc->callback = omap_8250_dma_tx_complete;
+10
drivers/tty/serial/8250/8250_pci1xxxx.c
··· 115 115 116 116 #define UART_RESET_REG 0x94 117 117 #define UART_RESET_D3_RESET_DISABLE BIT(16) 118 + #define UART_RESET_HOT_RESET_DISABLE BIT(17) 118 119 119 120 #define UART_BURST_STATUS_REG 0x9C 120 121 #define UART_TX_BURST_FIFO 0xA0 ··· 621 620 } 622 621 623 622 data = readl(p + UART_RESET_REG); 623 + 624 + if (priv->dev_rev >= 0xC0) 625 + data |= UART_RESET_HOT_RESET_DISABLE; 626 + 624 627 writel(data | UART_RESET_D3_RESET_DISABLE, p + UART_RESET_REG); 625 628 626 629 if (wakeup) ··· 652 647 } 653 648 654 649 data = readl(p + UART_RESET_REG); 650 + 651 + if (priv->dev_rev >= 0xC0) 652 + data &= ~UART_RESET_HOT_RESET_DISABLE; 653 + 655 654 writel(data & ~UART_RESET_D3_RESET_DISABLE, p + UART_RESET_REG); 655 + 656 656 iounmap(p); 657 657 658 658 for (i = 0; i < priv->nr; i++) {
+8 -8
drivers/tty/serial/8250/8250_port.c
··· 517 517 } 518 518 EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos); 519 519 520 - void serial8250_rpm_get(struct uart_8250_port *p) 520 + static void serial8250_rpm_get(struct uart_8250_port *p) 521 521 { 522 522 if (!(p->capabilities & UART_CAP_RPM)) 523 523 return; 524 524 pm_runtime_get_sync(p->port.dev); 525 525 } 526 - EXPORT_SYMBOL_GPL(serial8250_rpm_get); 527 526 528 - void serial8250_rpm_put(struct uart_8250_port *p) 527 + static void serial8250_rpm_put(struct uart_8250_port *p) 529 528 { 530 529 if (!(p->capabilities & UART_CAP_RPM)) 531 530 return; 532 531 pm_runtime_mark_last_busy(p->port.dev); 533 532 pm_runtime_put_autosuspend(p->port.dev); 534 533 } 535 - EXPORT_SYMBOL_GPL(serial8250_rpm_put); 536 534 537 535 /** 538 536 * serial8250_em485_init() - put uart_8250_port into rs485 emulating ··· 645 647 * once and disable_runtime_pm_tx() will still disable RPM because the fifo is 646 648 * empty and the HW can idle again. 647 649 */ 648 - void serial8250_rpm_get_tx(struct uart_8250_port *p) 650 + static void serial8250_rpm_get_tx(struct uart_8250_port *p) 649 651 { 650 652 unsigned char rpm_active; 651 653 ··· 657 659 return; 658 660 pm_runtime_get_sync(p->port.dev); 659 661 } 660 - EXPORT_SYMBOL_GPL(serial8250_rpm_get_tx); 661 662 662 - void serial8250_rpm_put_tx(struct uart_8250_port *p) 663 + static void serial8250_rpm_put_tx(struct uart_8250_port *p) 663 664 { 664 665 unsigned char rpm_active; 665 666 ··· 671 674 pm_runtime_mark_last_busy(p->port.dev); 672 675 pm_runtime_put_autosuspend(p->port.dev); 673 676 } 674 - EXPORT_SYMBOL_GPL(serial8250_rpm_put_tx); 675 677 676 678 /* 677 679 * IER sleep support. UARTs which have EFRs need the "extended ··· 2989 2993 if (!request_region(port->iobase, size, "serial")) 2990 2994 return -EBUSY; 2991 2995 return 0; 2996 + case UPIO_UNKNOWN: 2997 + break; 2992 2998 } 2993 2999 2994 3000 return 0; ··· 3022 3024 case UPIO_HUB6: 3023 3025 case UPIO_PORT: 3024 3026 release_region(port->iobase, size); 3027 + break; 3028 + case UPIO_UNKNOWN: 3025 3029 break; 3026 3030 } 3027 3031 }
+2
drivers/tty/serial/8250/8250_rsa.c
··· 43 43 case UPIO_PORT: 44 44 release_region(port->iobase + offset, size); 45 45 break; 46 + default: 47 + break; 46 48 } 47 49 } 48 50
+1 -1
drivers/tty/serial/8250/Kconfig
··· 572 572 config SERIAL_8250_NI 573 573 tristate "NI 16550 based serial port" 574 574 depends on SERIAL_8250 575 - depends on (X86 && ACPI) || COMPILE_TEST 575 + depends on X86 || COMPILE_TEST 576 576 help 577 577 This driver supports the integrated serial ports on National 578 578 Instruments (NI) controller hardware. This is required for all NI
+1 -1
drivers/tty/serial/amba-pl011.c
··· 2476 2476 static int pl011_console_match(struct console *co, char *name, int idx, 2477 2477 char *options) 2478 2478 { 2479 - unsigned char iotype; 2479 + enum uart_iotype iotype; 2480 2480 resource_size_t addr; 2481 2481 int i; 2482 2482
+4 -1
drivers/tty/serial/fsl_lpuart.c
··· 403 403 case UPIO_MEM32BE: 404 404 iowrite32be(val, port->membase + off); 405 405 break; 406 + default: 407 + break; 406 408 } 407 409 } 408 410 ··· 565 563 return sport->port.mapbase + UARTDATA; 566 564 case UPIO_MEM32BE: 567 565 return sport->port.mapbase + UARTDATA + sizeof(u32) - 1; 566 + default: 567 + return sport->port.mapbase + UARTDR; 568 568 } 569 - return sport->port.mapbase + UARTDR; 570 569 } 571 570 572 571 static int lpuart_dma_tx_request(struct uart_port *port)
+1
drivers/tty/serial/jsm/jsm_tty.c
··· 451 451 if (!brd->channels[i]) 452 452 continue; 453 453 454 + brd->channels[i]->uart_port.dev = &brd->pci_dev->dev; 454 455 brd->channels[i]->uart_port.irq = brd->irq; 455 456 brd->channels[i]->uart_port.uartclk = 14745600; 456 457 brd->channels[i]->uart_port.type = PORT_JSM;
+1 -3
drivers/tty/serial/lantiq.c
··· 773 773 int ret; 774 774 775 775 ret = platform_get_irq(to_platform_device(dev), 0); 776 - if (ret < 0) { 777 - dev_err(dev, "failed to fetch IRQ for serial port\n"); 776 + if (ret < 0) 778 777 return ret; 779 - } 780 778 ltq_port->common_irq = ret; 781 779 port->irq = ret; 782 780
+2 -1
drivers/tty/serial/max3100.c
··· 16 16 /* 4 MAX3100s should be enough for everyone */ 17 17 #define MAX_MAX3100 4 18 18 19 + #include <linux/bitops.h> 19 20 #include <linux/container_of.h> 20 21 #include <linux/delay.h> 21 22 #include <linux/device.h> ··· 134 133 else 135 134 c &= 0xff; 136 135 137 - parity = parity ^ (hweight8(c) & 1); 136 + parity = parity ^ parity8(c); 138 137 return parity; 139 138 } 140 139
+5 -2
drivers/tty/serial/max310x.c
··· 1189 1189 return !!((val >> 4) & (1 << (offset % 4))); 1190 1190 } 1191 1191 1192 - static void max310x_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) 1192 + static int max310x_gpio_set(struct gpio_chip *chip, unsigned int offset, 1193 + int value) 1193 1194 { 1194 1195 struct max310x_port *s = gpiochip_get_data(chip); 1195 1196 struct uart_port *port = &s->p[offset / 4].port; 1196 1197 1197 1198 max310x_port_update(port, MAX310X_GPIODATA_REG, 1 << (offset % 4), 1198 1199 value ? 1 << (offset % 4) : 0); 1200 + 1201 + return 0; 1199 1202 } 1200 1203 1201 1204 static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) ··· 1414 1411 s->gpio.direction_input = max310x_gpio_direction_input; 1415 1412 s->gpio.get = max310x_gpio_get; 1416 1413 s->gpio.direction_output= max310x_gpio_direction_output; 1417 - s->gpio.set = max310x_gpio_set; 1414 + s->gpio.set_rv = max310x_gpio_set; 1418 1415 s->gpio.set_config = max310x_gpio_set_config; 1419 1416 s->gpio.base = -1; 1420 1417 s->gpio.ngpio = devtype->nr * 4;
+4 -1
drivers/tty/serial/milbeaut_usio.c
··· 523 523 } 524 524 port->membase = devm_ioremap(&pdev->dev, res->start, 525 525 resource_size(res)); 526 - 526 + if (!port->membase) { 527 + ret = -ENOMEM; 528 + goto failed; 529 + } 527 530 ret = platform_get_irq_byname(pdev, "rx"); 528 531 mlb_usio_irq[index][RX] = ret; 529 532
+22 -3
drivers/tty/serial/qcom_geni_serial.c
··· 98 98 99 99 #define DMA_RX_BUF_SIZE 2048 100 100 101 + static DEFINE_IDA(port_ida); 102 + 101 103 struct qcom_geni_device_data { 102 104 bool console; 103 105 enum geni_se_xfer_mode mode; ··· 255 253 struct qcom_geni_serial_port *port; 256 254 int nr_ports = console ? GENI_UART_CONS_PORTS : GENI_UART_PORTS; 257 255 258 - if (line < 0 || line >= nr_ports) 259 - return ERR_PTR(-ENXIO); 256 + if (console) { 257 + if (line < 0 || line >= nr_ports) 258 + return ERR_PTR(-ENXIO); 260 259 261 - port = console ? &qcom_geni_console_port : &qcom_geni_uart_ports[line]; 260 + port = &qcom_geni_console_port; 261 + } else { 262 + int max_alias_num = of_alias_get_highest_id("serial"); 263 + 264 + if (line < 0 || line >= nr_ports) 265 + line = ida_alloc_range(&port_ida, max_alias_num + 1, nr_ports, GFP_KERNEL); 266 + else 267 + line = ida_alloc_range(&port_ida, line, nr_ports, GFP_KERNEL); 268 + 269 + if (line < 0) 270 + return ERR_PTR(-ENXIO); 271 + 272 + port = &qcom_geni_uart_ports[line]; 273 + } 262 274 return port; 263 275 } 264 276 ··· 1777 1761 port->wakeup_irq); 1778 1762 if (ret) { 1779 1763 device_init_wakeup(&pdev->dev, false); 1764 + ida_free(&port_ida, uport->line); 1780 1765 uart_remove_one_port(drv, uport); 1781 1766 return ret; 1782 1767 } ··· 1789 1772 static void qcom_geni_serial_remove(struct platform_device *pdev) 1790 1773 { 1791 1774 struct qcom_geni_serial_port *port = platform_get_drvdata(pdev); 1775 + struct uart_port *uport = &port->uport; 1792 1776 struct uart_driver *drv = port->private_data.drv; 1793 1777 1794 1778 dev_pm_clear_wake_irq(&pdev->dev); 1795 1779 device_init_wakeup(&pdev->dev, false); 1780 + ida_free(&port_ida, uport->line); 1796 1781 uart_remove_one_port(drv, &port->uport); 1797 1782 } 1798 1783
+5 -1
drivers/tty/serial/samsung_tty.c
··· 52 52 #define S3C24XX_SERIAL_MINOR 64 53 53 54 54 #ifdef CONFIG_ARM64 55 - #define UART_NR 12 55 + #define UART_NR 18 56 56 #else 57 57 #define UART_NR CONFIG_SERIAL_SAMSUNG_UARTS 58 58 #endif ··· 189 189 break; 190 190 case UPIO_MEM32: 191 191 writel_relaxed(val, portaddr(port, reg)); 192 + break; 193 + default: 192 194 break; 193 195 } 194 196 } ··· 2714 2712 break; 2715 2713 case UPIO_MEM32: 2716 2714 writel(val, portaddr(port, reg)); 2715 + break; 2716 + default: 2717 2717 break; 2718 2718 } 2719 2719 }
+5 -2
drivers/tty/serial/sc16is7xx.c
··· 1333 1333 return !!(val & BIT(offset)); 1334 1334 } 1335 1335 1336 - static void sc16is7xx_gpio_set(struct gpio_chip *chip, unsigned offset, int val) 1336 + static int sc16is7xx_gpio_set(struct gpio_chip *chip, unsigned int offset, 1337 + int val) 1337 1338 { 1338 1339 struct sc16is7xx_port *s = gpiochip_get_data(chip); 1339 1340 struct uart_port *port = &s->p[0].port; 1340 1341 1341 1342 sc16is7xx_port_update(port, SC16IS7XX_IOSTATE_REG, BIT(offset), 1342 1343 val ? BIT(offset) : 0); 1344 + 1345 + return 0; 1343 1346 } 1344 1347 1345 1348 static int sc16is7xx_gpio_direction_input(struct gpio_chip *chip, ··· 1425 1422 s->gpio.direction_input = sc16is7xx_gpio_direction_input; 1426 1423 s->gpio.get = sc16is7xx_gpio_get; 1427 1424 s->gpio.direction_output = sc16is7xx_gpio_direction_output; 1428 - s->gpio.set = sc16is7xx_gpio_set; 1425 + s->gpio.set_rv = sc16is7xx_gpio_set; 1429 1426 s->gpio.base = -1; 1430 1427 s->gpio.ngpio = s->devtype->nr_gpio; 1431 1428 s->gpio.can_sleep = 1;
+47 -48
drivers/tty/serial/serial_core.c
··· 75 75 wake_up(&uport->state->remove_wait); 76 76 } 77 77 78 - #define uart_port_lock(state, flags) \ 79 - ({ \ 80 - struct uart_port *__uport = uart_port_ref(state); \ 81 - if (__uport) \ 82 - uart_port_lock_irqsave(__uport, &flags); \ 83 - __uport; \ 84 - }) 78 + static inline struct uart_port *uart_port_ref_lock(struct uart_state *state, unsigned long *flags) 79 + { 80 + struct uart_port *uport = uart_port_ref(state); 85 81 86 - #define uart_port_unlock(uport, flags) \ 87 - ({ \ 88 - struct uart_port *__uport = uport; \ 89 - if (__uport) { \ 90 - uart_port_unlock_irqrestore(__uport, flags); \ 91 - uart_port_deref(__uport); \ 92 - } \ 93 - }) 82 + if (uport) 83 + uart_port_lock_irqsave(uport, flags); 84 + 85 + return uport; 86 + } 87 + 88 + static inline void uart_port_unlock_deref(struct uart_port *uport, unsigned long flags) 89 + { 90 + if (uport) { 91 + uart_port_unlock_irqrestore(uport, flags); 92 + uart_port_deref(uport); 93 + } 94 + } 94 95 95 96 static inline struct uart_port *uart_port_check(struct uart_state *state) 96 97 { ··· 128 127 struct uart_port *port; 129 128 unsigned long flags; 130 129 131 - port = uart_port_lock(state, flags); 130 + port = uart_port_ref_lock(state, &flags); 132 131 if (port) 133 132 port->ops->stop_tx(port); 134 - uart_port_unlock(port, flags); 133 + uart_port_unlock_deref(port, flags); 135 134 } 136 135 137 136 static void __uart_start(struct uart_state *state) ··· 169 168 struct uart_port *port; 170 169 unsigned long flags; 171 170 172 - port = uart_port_lock(state, flags); 171 + port = uart_port_ref_lock(state, &flags); 173 172 __uart_start(state); 174 - uart_port_unlock(port, flags); 173 + uart_port_unlock_deref(port, flags); 175 174 } 176 175 177 176 static void ··· 259 258 if (!page) 260 259 return -ENOMEM; 261 260 262 - uport = uart_port_lock(state, flags); 261 + uport = uart_port_ref_lock(state, &flags); 263 262 if (!state->port.xmit_buf) { 264 263 state->port.xmit_buf = (unsigned char *)page; 265 264 kfifo_init(&state->port.xmit_fifo, state->port.xmit_buf, 266 265 PAGE_SIZE); 267 - uart_port_unlock(uport, flags); 266 + uart_port_unlock_deref(uport, flags); 268 267 } else { 269 - uart_port_unlock(uport, flags); 268 + uart_port_unlock_deref(uport, flags); 270 269 /* 271 270 * Do not free() the page under the port lock, see 272 271 * uart_free_xmit_buf(). ··· 290 289 * console driver may need to allocate/free a debug object, which 291 290 * can end up in printk() recursion. 292 291 */ 293 - uport = uart_port_lock(state, flags); 292 + uport = uart_port_ref_lock(state, &flags); 294 293 xmit_buf = port->xmit_buf; 295 294 port->xmit_buf = NULL; 296 295 INIT_KFIFO(port->xmit_fifo); 297 - uart_port_unlock(uport, flags); 296 + uart_port_unlock_deref(uport, flags); 298 297 299 298 free_page((unsigned long)xmit_buf); 300 299 } ··· 593 592 unsigned long flags; 594 593 int ret = 0; 595 594 596 - port = uart_port_lock(state, flags); 595 + port = uart_port_ref_lock(state, &flags); 597 596 if (!state->port.xmit_buf) { 598 - uart_port_unlock(port, flags); 597 + uart_port_unlock_deref(port, flags); 599 598 return 0; 600 599 } 601 600 602 601 if (port) 603 602 ret = kfifo_put(&state->port.xmit_fifo, c); 604 - uart_port_unlock(port, flags); 603 + uart_port_unlock_deref(port, flags); 605 604 return ret; 606 605 } 607 606 ··· 624 623 if (WARN_ON(!state)) 625 624 return -EL3HLT; 626 625 627 - port = uart_port_lock(state, flags); 626 + port = uart_port_ref_lock(state, &flags); 628 627 if (!state->port.xmit_buf) { 629 - uart_port_unlock(port, flags); 628 + uart_port_unlock_deref(port, flags); 630 629 return 0; 631 630 } 632 631 ··· 634 633 ret = kfifo_in(&state->port.xmit_fifo, buf, count); 635 634 636 635 __uart_start(state); 637 - uart_port_unlock(port, flags); 636 + uart_port_unlock_deref(port, flags); 638 637 return ret; 639 638 } 640 639 ··· 645 644 unsigned long flags; 646 645 unsigned int ret; 647 646 648 - port = uart_port_lock(state, flags); 647 + port = uart_port_ref_lock(state, &flags); 649 648 ret = kfifo_avail(&state->port.xmit_fifo); 650 - uart_port_unlock(port, flags); 649 + uart_port_unlock_deref(port, flags); 651 650 return ret; 652 651 } 653 652 ··· 658 657 unsigned long flags; 659 658 unsigned int ret; 660 659 661 - port = uart_port_lock(state, flags); 660 + port = uart_port_ref_lock(state, &flags); 662 661 ret = kfifo_len(&state->port.xmit_fifo); 663 - uart_port_unlock(port, flags); 662 + uart_port_unlock_deref(port, flags); 664 663 return ret; 665 664 } 666 665 ··· 679 678 680 679 pr_debug("uart_flush_buffer(%d) called\n", tty->index); 681 680 682 - port = uart_port_lock(state, flags); 681 + port = uart_port_ref_lock(state, &flags); 683 682 if (!port) 684 683 return; 685 684 kfifo_reset(&state->port.xmit_fifo); 686 685 if (port->ops->flush_buffer) 687 686 port->ops->flush_buffer(port); 688 - uart_port_unlock(port, flags); 687 + uart_port_unlock_deref(port, flags); 689 688 tty_port_tty_wakeup(&state->port); 690 689 } 691 690 ··· 1276 1275 struct uart_state *state = tty->driver_data; 1277 1276 struct uart_icount cnow; 1278 1277 struct uart_port *uport; 1278 + unsigned long flags; 1279 1279 1280 - uport = uart_port_ref(state); 1280 + uport = uart_port_ref_lock(state, &flags); 1281 1281 if (!uport) 1282 1282 return -EIO; 1283 - uart_port_lock_irq(uport); 1284 1283 memcpy(&cnow, &uport->icount, sizeof(struct uart_icount)); 1285 - uart_port_unlock_irq(uport); 1286 - uart_port_deref(uport); 1284 + uart_port_unlock_deref(uport, flags); 1287 1285 1288 1286 icount->cts = cnow.cts; 1289 1287 icount->dsr = cnow.dsr; ··· 1914 1914 { 1915 1915 struct uart_state *state = container_of(port, struct uart_state, port); 1916 1916 struct uart_port *uport; 1917 + unsigned long flags; 1917 1918 int mctrl; 1918 1919 1919 - uport = uart_port_ref(state); 1920 + uport = uart_port_ref_lock(state, &flags); 1920 1921 /* 1921 1922 * Should never observe uport == NULL since checks for hangup should 1922 1923 * abort the tty_port_block_til_ready() loop before checking for carrier ··· 1926 1925 */ 1927 1926 if (WARN_ON(!uport)) 1928 1927 return true; 1929 - uart_port_lock_irq(uport); 1930 1928 uart_enable_ms(uport); 1931 1929 mctrl = uport->ops->get_mctrl(uport); 1932 - uart_port_unlock_irq(uport); 1933 - uart_port_deref(uport); 1930 + uart_port_unlock_deref(uport, flags); 1934 1931 1935 1932 return mctrl & TIOCM_CAR; 1936 1933 } ··· 2177 2178 * 2178 2179 * Returns: 0 on success or -%EINVAL on failure 2179 2180 */ 2180 - int uart_parse_earlycon(char *p, unsigned char *iotype, resource_size_t *addr, 2181 - char **options) 2181 + int uart_parse_earlycon(char *p, enum uart_iotype *iotype, 2182 + resource_size_t *addr, char **options) 2182 2183 { 2183 2184 if (strncmp(p, "mmio,", 5) == 0) { 2184 2185 *iotype = UPIO_MEM; ··· 3288 3289 case UPIO_AU: 3289 3290 case UPIO_TSI: 3290 3291 return port1->mapbase == port2->mapbase; 3292 + default: 3293 + return false; 3291 3294 } 3292 - 3293 - return false; 3294 3295 } 3295 3296 EXPORT_SYMBOL(uart_match_port); 3296 3297
+167
drivers/tty/serial/sh-sci-common.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + 3 + #ifndef __SH_SCI_COMMON_H__ 4 + #define __SH_SCI_COMMON_H__ 5 + 6 + #include <linux/serial_core.h> 7 + 8 + enum SCI_CLKS { 9 + SCI_FCK, /* Functional Clock */ 10 + SCI_SCK, /* Optional External Clock */ 11 + SCI_BRG_INT, /* Optional BRG Internal Clock Source */ 12 + SCI_SCIF_CLK, /* Optional BRG External Clock Source */ 13 + SCI_NUM_CLKS 14 + }; 15 + 16 + /* Offsets into the sci_port->irqs array */ 17 + enum { 18 + SCIx_ERI_IRQ, 19 + SCIx_RXI_IRQ, 20 + SCIx_TXI_IRQ, 21 + SCIx_BRI_IRQ, 22 + SCIx_DRI_IRQ, 23 + SCIx_TEI_IRQ, 24 + SCIx_NR_IRQS, 25 + 26 + SCIx_MUX_IRQ = SCIx_NR_IRQS, /* special case */ 27 + }; 28 + 29 + /* Bit x set means sampling rate x + 1 is supported */ 30 + #define SCI_SR(x) BIT((x) - 1) 31 + #define SCI_SR_RANGE(x, y) GENMASK((y) - 1, (x) - 1) 32 + 33 + void sci_release_port(struct uart_port *port); 34 + int sci_request_port(struct uart_port *port); 35 + void sci_config_port(struct uart_port *port, int flags); 36 + int sci_verify_port(struct uart_port *port, struct serial_struct *ser); 37 + void sci_pm(struct uart_port *port, unsigned int state, 38 + unsigned int oldstate); 39 + 40 + struct plat_sci_reg { 41 + u8 offset; 42 + u8 size; 43 + }; 44 + 45 + struct sci_port_params_bits { 46 + unsigned int rxtx_enable; 47 + unsigned int te_clear; 48 + unsigned int poll_sent_bits; 49 + }; 50 + 51 + struct sci_common_regs { 52 + unsigned int status; 53 + unsigned int control; 54 + }; 55 + 56 + /* The actual number of needed registers. This is used by sci only */ 57 + #define SCI_NR_REGS 20 58 + 59 + struct sci_port_params { 60 + const struct plat_sci_reg regs[SCI_NR_REGS]; 61 + const struct sci_common_regs *common_regs; 62 + const struct sci_port_params_bits *param_bits; 63 + unsigned int fifosize; 64 + unsigned int overrun_reg; 65 + unsigned int overrun_mask; 66 + unsigned int sampling_rate_mask; 67 + unsigned int error_mask; 68 + unsigned int error_clear; 69 + }; 70 + 71 + struct sci_port_ops { 72 + u32 (*read_reg)(struct uart_port *port, int reg); 73 + void (*write_reg)(struct uart_port *port, int reg, int value); 74 + void (*clear_SCxSR)(struct uart_port *port, unsigned int mask); 75 + 76 + void (*transmit_chars)(struct uart_port *port); 77 + void (*receive_chars)(struct uart_port *port); 78 + 79 + void (*poll_put_char)(struct uart_port *port, unsigned char c); 80 + 81 + int (*set_rtrg)(struct uart_port *port, int rx_trig); 82 + int (*rtrg_enabled)(struct uart_port *port); 83 + 84 + void (*shutdown_complete)(struct uart_port *port); 85 + 86 + void (*prepare_console_write)(struct uart_port *port, u32 ctrl); 87 + void (*console_save)(struct uart_port *port); 88 + void (*console_restore)(struct uart_port *port); 89 + size_t (*suspend_regs_size)(void); 90 + }; 91 + 92 + struct sci_of_data { 93 + const struct sci_port_params *params; 94 + const struct uart_ops *uart_ops; 95 + const struct sci_port_ops *ops; 96 + unsigned short regtype; 97 + unsigned short type; 98 + }; 99 + 100 + struct sci_port { 101 + struct uart_port port; 102 + 103 + /* Platform configuration */ 104 + const struct sci_port_params *params; 105 + const struct plat_sci_port *cfg; 106 + 107 + unsigned int sampling_rate_mask; 108 + resource_size_t reg_size; 109 + struct mctrl_gpios *gpios; 110 + 111 + /* Clocks */ 112 + struct clk *clks[SCI_NUM_CLKS]; 113 + unsigned long clk_rates[SCI_NUM_CLKS]; 114 + 115 + int irqs[SCIx_NR_IRQS]; 116 + char *irqstr[SCIx_NR_IRQS]; 117 + 118 + struct dma_chan *chan_tx; 119 + struct dma_chan *chan_rx; 120 + 121 + struct reset_control *rstc; 122 + struct sci_suspend_regs *suspend_regs; 123 + 124 + #ifdef CONFIG_SERIAL_SH_SCI_DMA 125 + struct dma_chan *chan_tx_saved; 126 + struct dma_chan *chan_rx_saved; 127 + dma_cookie_t cookie_tx; 128 + dma_cookie_t cookie_rx[2]; 129 + dma_cookie_t active_rx; 130 + dma_addr_t tx_dma_addr; 131 + unsigned int tx_dma_len; 132 + struct scatterlist sg_rx[2]; 133 + void *rx_buf[2]; 134 + size_t buf_len_rx; 135 + struct work_struct work_tx; 136 + struct hrtimer rx_timer; 137 + unsigned int rx_timeout; /* microseconds */ 138 + #endif 139 + unsigned int rx_frame; 140 + int rx_trigger; 141 + struct timer_list rx_fifo_timer; 142 + int rx_fifo_timeout; 143 + u16 hscif_tot; 144 + 145 + const struct sci_port_ops *ops; 146 + 147 + bool has_rtscts; 148 + bool autorts; 149 + bool tx_occurred; 150 + }; 151 + 152 + #define to_sci_port(uart) container_of((uart), struct sci_port, port) 153 + 154 + void sci_port_disable(struct sci_port *sci_port); 155 + void sci_port_enable(struct sci_port *sci_port); 156 + 157 + int sci_startup(struct uart_port *port); 158 + void sci_shutdown(struct uart_port *port); 159 + 160 + #define min_sr(_port) ffs((_port)->sampling_rate_mask) 161 + #define max_sr(_port) fls((_port)->sampling_rate_mask) 162 + 163 + #ifdef CONFIG_SERIAL_SH_SCI_EARLYCON 164 + int __init scix_early_console_setup(struct earlycon_device *device, const struct sci_of_data *data); 165 + #endif 166 + 167 + #endif /* __SH_SCI_COMMON_H__ */
+361 -269
drivers/tty/serial/sh-sci.c
··· 56 56 57 57 #include "serial_mctrl_gpio.h" 58 58 #include "sh-sci.h" 59 - 60 - /* Offsets into the sci_port->irqs array */ 61 - enum { 62 - SCIx_ERI_IRQ, 63 - SCIx_RXI_IRQ, 64 - SCIx_TXI_IRQ, 65 - SCIx_BRI_IRQ, 66 - SCIx_DRI_IRQ, 67 - SCIx_TEI_IRQ, 68 - SCIx_NR_IRQS, 69 - 70 - SCIx_MUX_IRQ = SCIx_NR_IRQS, /* special case */ 71 - }; 59 + #include "sh-sci-common.h" 72 60 73 61 #define SCIx_IRQ_IS_MUXED(port) \ 74 62 ((port)->irqs[SCIx_ERI_IRQ] == \ ··· 64 76 ((port)->irqs[SCIx_ERI_IRQ] && \ 65 77 ((port)->irqs[SCIx_RXI_IRQ] < 0)) 66 78 67 - enum SCI_CLKS { 68 - SCI_FCK, /* Functional Clock */ 69 - SCI_SCK, /* Optional External Clock */ 70 - SCI_BRG_INT, /* Optional BRG Internal Clock Source */ 71 - SCI_SCIF_CLK, /* Optional BRG External Clock Source */ 72 - SCI_NUM_CLKS 73 - }; 74 - 75 - /* Bit x set means sampling rate x + 1 is supported */ 76 - #define SCI_SR(x) BIT((x) - 1) 77 - #define SCI_SR_RANGE(x, y) GENMASK((y) - 1, (x) - 1) 78 - 79 79 #define SCI_SR_SCIFAB SCI_SR(5) | SCI_SR(7) | SCI_SR(11) | \ 80 80 SCI_SR(13) | SCI_SR(16) | SCI_SR(17) | \ 81 81 SCI_SR(19) | SCI_SR(27) 82 - 83 - #define min_sr(_port) ffs((_port)->sampling_rate_mask) 84 - #define max_sr(_port) fls((_port)->sampling_rate_mask) 85 82 86 83 /* Iterate over all supported sampling rates, from high to low */ 87 84 #define for_each_sr(_sr, _port) \ 88 85 for ((_sr) = max_sr(_port); (_sr) >= min_sr(_port); (_sr)--) \ 89 86 if ((_port)->sampling_rate_mask & SCI_SR((_sr))) 90 87 91 - struct plat_sci_reg { 92 - u8 offset, size; 88 + #define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS 89 + 90 + static struct sci_port sci_ports[SCI_NPORTS]; 91 + static unsigned long sci_ports_in_use; 92 + static struct uart_driver sci_uart_driver; 93 + static bool sci_uart_earlycon; 94 + static bool sci_uart_earlycon_dev_probing; 95 + 96 + static const struct sci_port_params_bits sci_sci_port_params_bits = { 97 + .rxtx_enable = SCSCR_RE | SCSCR_TE, 98 + .te_clear = SCSCR_TE | SCSCR_TEIE, 99 + .poll_sent_bits = SCI_TDRE | SCI_TEND 100 + }; 101 + 102 + static const struct sci_port_params_bits sci_scif_port_params_bits = { 103 + .rxtx_enable = SCSCR_RE | SCSCR_TE, 104 + .te_clear = SCSCR_TE | SCSCR_TEIE, 105 + .poll_sent_bits = SCIF_TDFE | SCIF_TEND 106 + }; 107 + 108 + static const struct sci_common_regs sci_common_regs = { 109 + .status = SCxSR, 110 + .control = SCSCR, 93 111 }; 94 112 95 113 struct sci_suspend_regs { ··· 112 118 u8 semr; 113 119 }; 114 120 115 - struct sci_port_params { 116 - const struct plat_sci_reg regs[SCIx_NR_REGS]; 117 - unsigned int fifosize; 118 - unsigned int overrun_reg; 119 - unsigned int overrun_mask; 120 - unsigned int sampling_rate_mask; 121 - unsigned int error_mask; 122 - unsigned int error_clear; 123 - }; 124 - 125 - struct sci_port { 126 - struct uart_port port; 127 - 128 - /* Platform configuration */ 129 - const struct sci_port_params *params; 130 - const struct plat_sci_port *cfg; 131 - unsigned int sampling_rate_mask; 132 - resource_size_t reg_size; 133 - struct mctrl_gpios *gpios; 134 - 135 - /* Clocks */ 136 - struct clk *clks[SCI_NUM_CLKS]; 137 - unsigned long clk_rates[SCI_NUM_CLKS]; 138 - 139 - int irqs[SCIx_NR_IRQS]; 140 - char *irqstr[SCIx_NR_IRQS]; 141 - 142 - struct dma_chan *chan_tx; 143 - struct dma_chan *chan_rx; 144 - 145 - struct reset_control *rstc; 146 - 147 - #ifdef CONFIG_SERIAL_SH_SCI_DMA 148 - struct dma_chan *chan_tx_saved; 149 - struct dma_chan *chan_rx_saved; 150 - dma_cookie_t cookie_tx; 151 - dma_cookie_t cookie_rx[2]; 152 - dma_cookie_t active_rx; 153 - dma_addr_t tx_dma_addr; 154 - unsigned int tx_dma_len; 155 - struct scatterlist sg_rx[2]; 156 - void *rx_buf[2]; 157 - size_t buf_len_rx; 158 - struct work_struct work_tx; 159 - struct hrtimer rx_timer; 160 - unsigned int rx_timeout; /* microseconds */ 161 - #endif 162 - unsigned int rx_frame; 163 - int rx_trigger; 164 - struct timer_list rx_fifo_timer; 165 - int rx_fifo_timeout; 166 - struct sci_suspend_regs suspend_regs; 167 - u16 hscif_tot; 168 - 169 - bool has_rtscts; 170 - bool autorts; 171 - bool tx_occurred; 172 - }; 173 - 174 - #define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS 175 - 176 - static struct sci_port sci_ports[SCI_NPORTS]; 177 - static unsigned long sci_ports_in_use; 178 - static struct uart_driver sci_uart_driver; 179 - static bool sci_uart_earlycon; 180 - static bool sci_uart_earlycon_dev_probing; 181 - 182 - static inline struct sci_port * 183 - to_sci_port(struct uart_port *uart) 121 + static size_t sci_suspend_regs_size(void) 184 122 { 185 - return container_of(uart, struct sci_port, port); 123 + return sizeof(struct sci_suspend_regs); 186 124 } 187 125 188 126 static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = { ··· 137 211 .sampling_rate_mask = SCI_SR(32), 138 212 .error_mask = SCI_DEFAULT_ERROR_MASK | SCI_ORER, 139 213 .error_clear = SCI_ERROR_CLEAR & ~SCI_ORER, 214 + .param_bits = &sci_sci_port_params_bits, 215 + .common_regs = &sci_common_regs, 140 216 }, 141 217 142 218 /* ··· 161 233 .sampling_rate_mask = SCI_SR(32), 162 234 .error_mask = SCI_DEFAULT_ERROR_MASK | SCI_ORER, 163 235 .error_clear = SCI_ERROR_CLEAR & ~SCI_ORER, 236 + .param_bits = &sci_scif_port_params_bits, 237 + .common_regs = &sci_common_regs, 164 238 }, 165 239 166 240 /* ··· 187 257 .sampling_rate_mask = SCI_SR_SCIFAB, 188 258 .error_mask = SCIF_DEFAULT_ERROR_MASK | SCIFA_ORER, 189 259 .error_clear = SCIF_ERROR_CLEAR & ~SCIFA_ORER, 260 + .param_bits = &sci_scif_port_params_bits, 261 + .common_regs = &sci_common_regs, 190 262 }, 191 263 192 264 /* ··· 214 282 .sampling_rate_mask = SCI_SR_SCIFAB, 215 283 .error_mask = SCIF_DEFAULT_ERROR_MASK | SCIFA_ORER, 216 284 .error_clear = SCIF_ERROR_CLEAR & ~SCIFA_ORER, 285 + .param_bits = &sci_scif_port_params_bits, 286 + .common_regs = &sci_common_regs, 217 287 }, 218 288 219 289 /* ··· 241 307 .sampling_rate_mask = SCI_SR(32), 242 308 .error_mask = SCIF_DEFAULT_ERROR_MASK, 243 309 .error_clear = SCIF_ERROR_CLEAR, 310 + .param_bits = &sci_scif_port_params_bits, 311 + .common_regs = &sci_common_regs, 244 312 }, 245 313 246 314 /* 247 - * The "SCIFA" that is in RZ/A2, RZ/G2L and RZ/T. 315 + * The "SCIFA" that is in RZ/A2, RZ/G2L and RZ/T1. 248 316 * It looks like a normal SCIF with FIFO data, but with a 249 317 * compressed address space. Also, the break out of interrupts 250 318 * are different: ERI/BRI, RXI, TXI, TEI, DRI. ··· 271 335 .sampling_rate_mask = SCI_SR(32), 272 336 .error_mask = SCIF_DEFAULT_ERROR_MASK, 273 337 .error_clear = SCIF_ERROR_CLEAR, 338 + .param_bits = &sci_scif_port_params_bits, 339 + .common_regs = &sci_common_regs, 274 340 }, 275 341 276 342 /* ··· 304 366 .sampling_rate_mask = SCI_SR(32), 305 367 .error_mask = SCIF_DEFAULT_ERROR_MASK, 306 368 .error_clear = SCIF_ERROR_CLEAR, 369 + .param_bits = &sci_scif_port_params_bits, 370 + .common_regs = &sci_common_regs, 307 371 }, 308 372 309 373 /* ··· 328 388 .sampling_rate_mask = SCI_SR(32), 329 389 .error_mask = SCIF_DEFAULT_ERROR_MASK, 330 390 .error_clear = SCIF_ERROR_CLEAR, 391 + .param_bits = &sci_scif_port_params_bits, 392 + .common_regs = &sci_common_regs, 331 393 }, 332 394 333 395 /* ··· 354 412 .sampling_rate_mask = SCI_SR(32), 355 413 .error_mask = SCIF_DEFAULT_ERROR_MASK, 356 414 .error_clear = SCIF_ERROR_CLEAR, 415 + .param_bits = &sci_scif_port_params_bits, 416 + .common_regs = &sci_common_regs, 357 417 }, 358 418 359 419 /* ··· 383 439 .sampling_rate_mask = SCI_SR(32), 384 440 .error_mask = SCIF_DEFAULT_ERROR_MASK, 385 441 .error_clear = SCIF_ERROR_CLEAR, 442 + .param_bits = &sci_scif_port_params_bits, 443 + .common_regs = &sci_common_regs, 386 444 }, 387 445 388 446 /* ··· 414 468 .sampling_rate_mask = SCI_SR_RANGE(8, 32), 415 469 .error_mask = SCIF_DEFAULT_ERROR_MASK, 416 470 .error_clear = SCIF_ERROR_CLEAR, 471 + .param_bits = &sci_scif_port_params_bits, 472 + .common_regs = &sci_common_regs, 417 473 }, 418 474 419 475 /* ··· 440 492 .sampling_rate_mask = SCI_SR(32), 441 493 .error_mask = SCIF_DEFAULT_ERROR_MASK, 442 494 .error_clear = SCIF_ERROR_CLEAR, 495 + .param_bits = &sci_scif_port_params_bits, 496 + .common_regs = &sci_common_regs, 443 497 }, 444 498 445 499 /* ··· 469 519 .sampling_rate_mask = SCI_SR(32), 470 520 .error_mask = SCIF_DEFAULT_ERROR_MASK, 471 521 .error_clear = SCIF_ERROR_CLEAR, 522 + .param_bits = &sci_scif_port_params_bits, 523 + .common_regs = &sci_common_regs, 472 524 }, 473 525 474 526 /* ··· 494 542 .sampling_rate_mask = SCI_SR(16), 495 543 .error_mask = SCIF_DEFAULT_ERROR_MASK | SCIFA_ORER, 496 544 .error_clear = SCIF_ERROR_CLEAR & ~SCIFA_ORER, 545 + .param_bits = &sci_scif_port_params_bits, 546 + .common_regs = &sci_common_regs, 497 547 }, 498 548 }; 499 549 ··· 533 579 WARN(1, "Invalid register access\n"); 534 580 } 535 581 536 - static void sci_port_enable(struct sci_port *sci_port) 582 + void sci_port_enable(struct sci_port *sci_port) 537 583 { 538 584 unsigned int i; 539 585 ··· 549 595 sci_port->port.uartclk = sci_port->clk_rates[SCI_FCK]; 550 596 } 551 597 552 - static void sci_port_disable(struct sci_port *sci_port) 598 + void sci_port_disable(struct sci_port *sci_port) 553 599 { 554 600 unsigned int i; 555 601 ··· 689 735 static int sci_poll_get_char(struct uart_port *port) 690 736 { 691 737 unsigned short status; 738 + struct sci_port *s = to_sci_port(port); 692 739 int c; 693 740 694 741 do { 695 742 status = sci_serial_in(port, SCxSR); 696 743 if (status & SCxSR_ERRORS(port)) { 697 - sci_clear_SCxSR(port, SCxSR_ERROR_CLEAR(port)); 744 + s->ops->clear_SCxSR(port, SCxSR_ERROR_CLEAR(port)); 698 745 continue; 699 746 } 700 747 break; ··· 708 753 709 754 /* Dummy read */ 710 755 sci_serial_in(port, SCxSR); 711 - sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port)); 756 + s->ops->clear_SCxSR(port, SCxSR_RDxF_CLEAR(port)); 712 757 713 758 return c; 714 759 } ··· 716 761 717 762 static void sci_poll_put_char(struct uart_port *port, unsigned char c) 718 763 { 719 - unsigned short status; 764 + struct sci_port *s = to_sci_port(port); 765 + const struct sci_common_regs *regs = s->params->common_regs; 766 + unsigned int status; 720 767 721 768 do { 722 - status = sci_serial_in(port, SCxSR); 769 + status = s->ops->read_reg(port, regs->status); 723 770 } while (!(status & SCxSR_TDxE(port))); 724 771 725 772 sci_serial_out(port, SCxTDR, c); 726 - sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port)); 773 + s->ops->clear_SCxSR(port, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port)); 727 774 } 728 775 #endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE || 729 776 CONFIG_SERIAL_SH_SCI_EARLYCON */ ··· 868 911 port->icount.tx++; 869 912 } while (--count > 0); 870 913 871 - sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port)); 914 + s->ops->clear_SCxSR(port, SCxSR_TDxE_CLEAR(port)); 872 915 873 916 if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) 874 917 uart_write_wakeup(port); ··· 887 930 static void sci_receive_chars(struct uart_port *port) 888 931 { 889 932 struct tty_port *tport = &port->state->port; 933 + struct sci_port *s = to_sci_port(port); 890 934 int i, count, copied = 0; 891 935 unsigned short status; 892 936 unsigned char flag; ··· 942 984 } 943 985 944 986 sci_serial_in(port, SCxSR); /* dummy read */ 945 - sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port)); 987 + s->ops->clear_SCxSR(port, SCxSR_RDxF_CLEAR(port)); 946 988 947 989 copied += count; 948 990 port->icount.rx += count; ··· 955 997 /* TTY buffers full; read from RX reg to prevent lockup */ 956 998 sci_serial_in(port, SCxRDR); 957 999 sci_serial_in(port, SCxSR); /* dummy read */ 958 - sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port)); 1000 + s->ops->clear_SCxSR(port, SCxSR_RDxF_CLEAR(port)); 959 1001 } 960 1002 } 961 1003 962 1004 static int sci_handle_errors(struct uart_port *port) 963 1005 { 964 1006 int copied = 0; 965 - unsigned short status = sci_serial_in(port, SCxSR); 966 - struct tty_port *tport = &port->state->port; 967 1007 struct sci_port *s = to_sci_port(port); 1008 + const struct sci_common_regs *regs = s->params->common_regs; 1009 + unsigned int status = s->ops->read_reg(port, regs->status); 1010 + struct tty_port *tport = &port->state->port; 968 1011 969 1012 /* Handle overruns */ 970 1013 if (status & s->params->overrun_mask) { ··· 1124 1165 struct uart_port *port = &s->port; 1125 1166 1126 1167 dev_dbg(port->dev, "Rx timed out\n"); 1127 - scif_set_rtrg(port, 1); 1168 + s->ops->set_rtrg(port, 1); 1128 1169 } 1129 1170 1130 1171 static ssize_t rx_fifo_trigger_show(struct device *dev, ··· 1149 1190 if (ret) 1150 1191 return ret; 1151 1192 1152 - sci->rx_trigger = scif_set_rtrg(port, r); 1193 + sci->rx_trigger = sci->ops->set_rtrg(port, r); 1153 1194 if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) 1154 - scif_set_rtrg(port, 1); 1195 + sci->ops->set_rtrg(port, 1); 1155 1196 1156 1197 return count; 1157 1198 } ··· 1194 1235 sci->hscif_tot = r << HSSCR_TOT_SHIFT; 1195 1236 } else { 1196 1237 sci->rx_fifo_timeout = r; 1197 - scif_set_rtrg(port, 1); 1238 + sci->ops->set_rtrg(port, 1); 1198 1239 if (r > 0) 1199 1240 timer_setup(&sci->rx_fifo_timer, rx_fifo_timer_fn, 0); 1200 1241 } ··· 1319 1360 s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) { 1320 1361 enable_irq(s->irqs[SCIx_RXI_IRQ]); 1321 1362 if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) 1322 - scif_set_rtrg(port, s->rx_trigger); 1363 + s->ops->set_rtrg(port, s->rx_trigger); 1323 1364 else 1324 1365 scr &= ~SCSCR_RDRQE; 1325 1366 } ··· 1757 1798 s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) { 1758 1799 disable_irq_nosync(s->irqs[SCIx_RXI_IRQ]); 1759 1800 if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) { 1760 - scif_set_rtrg(port, 1); 1801 + s->ops->set_rtrg(port, 1); 1761 1802 scr |= SCSCR_RIE; 1762 1803 } else { 1763 1804 scr |= SCSCR_RDRQE; ··· 1783 1824 #endif 1784 1825 1785 1826 if (s->rx_trigger > 1 && s->rx_fifo_timeout > 0) { 1786 - if (!scif_rtrg_enabled(port)) 1787 - scif_set_rtrg(port, s->rx_trigger); 1827 + if (!s->ops->rtrg_enabled(port)) 1828 + s->ops->set_rtrg(port, s->rx_trigger); 1788 1829 1789 1830 mod_timer(&s->rx_fifo_timer, jiffies + DIV_ROUND_UP( 1790 1831 s->rx_frame * HZ * s->rx_fifo_timeout, 1000000)); ··· 1794 1835 * of whether the I_IXOFF is set, otherwise, how is the interrupt 1795 1836 * to be disabled? 1796 1837 */ 1797 - sci_receive_chars(port); 1838 + s->ops->receive_chars(port); 1798 1839 1799 1840 return IRQ_HANDLED; 1800 1841 } ··· 1803 1844 { 1804 1845 struct uart_port *port = ptr; 1805 1846 unsigned long flags; 1847 + struct sci_port *s = to_sci_port(port); 1806 1848 1807 1849 uart_port_lock_irqsave(port, &flags); 1808 - sci_transmit_chars(port); 1850 + s->ops->transmit_chars(port); 1809 1851 uart_port_unlock_irqrestore(port, flags); 1810 1852 1811 1853 return IRQ_HANDLED; ··· 1815 1855 static irqreturn_t sci_tx_end_interrupt(int irq, void *ptr) 1816 1856 { 1817 1857 struct uart_port *port = ptr; 1858 + struct sci_port *s = to_sci_port(port); 1859 + const struct sci_common_regs *regs = s->params->common_regs; 1818 1860 unsigned long flags; 1819 - unsigned short ctrl; 1861 + u32 ctrl; 1820 1862 1821 1863 if (port->type != PORT_SCI) 1822 1864 return sci_tx_interrupt(irq, ptr); 1823 1865 1824 1866 uart_port_lock_irqsave(port, &flags); 1825 - ctrl = sci_serial_in(port, SCSCR); 1826 - ctrl &= ~(SCSCR_TE | SCSCR_TEIE); 1827 - sci_serial_out(port, SCSCR, ctrl); 1867 + ctrl = s->ops->read_reg(port, regs->control) & 1868 + ~(s->params->param_bits->te_clear); 1869 + s->ops->write_reg(port, regs->control, ctrl); 1828 1870 uart_port_unlock_irqrestore(port, flags); 1829 1871 1830 1872 return IRQ_HANDLED; ··· 1835 1873 static irqreturn_t sci_br_interrupt(int irq, void *ptr) 1836 1874 { 1837 1875 struct uart_port *port = ptr; 1876 + struct sci_port *s = to_sci_port(port); 1838 1877 1839 1878 /* Handle BREAKs */ 1840 1879 sci_handle_breaks(port); ··· 1843 1880 /* drop invalid character received before break was detected */ 1844 1881 sci_serial_in(port, SCxRDR); 1845 1882 1846 - sci_clear_SCxSR(port, SCxSR_BREAK_CLEAR(port)); 1883 + s->ops->clear_SCxSR(port, SCxSR_BREAK_CLEAR(port)); 1847 1884 1848 1885 return IRQ_HANDLED; 1849 1886 } ··· 1871 1908 if (sci_handle_errors(port)) { 1872 1909 /* discard character in rx buffer */ 1873 1910 sci_serial_in(port, SCxSR); 1874 - sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port)); 1911 + s->ops->clear_SCxSR(port, SCxSR_RDxF_CLEAR(port)); 1875 1912 } 1876 1913 } else { 1877 1914 sci_handle_fifo_overrun(port); 1878 1915 if (!s->chan_rx) 1879 - sci_receive_chars(port); 1916 + s->ops->receive_chars(port); 1880 1917 } 1881 1918 1882 - sci_clear_SCxSR(port, SCxSR_ERROR_CLEAR(port)); 1919 + s->ops->clear_SCxSR(port, SCxSR_ERROR_CLEAR(port)); 1883 1920 1884 1921 /* Kick the transmission */ 1885 1922 if (!s->chan_tx) ··· 2249 2286 uart_port_unlock_irqrestore(port, flags); 2250 2287 } 2251 2288 2252 - static int sci_startup(struct uart_port *port) 2289 + static void sci_shutdown_complete(struct uart_port *port) 2290 + { 2291 + struct sci_port *s = to_sci_port(port); 2292 + u16 scr; 2293 + 2294 + scr = sci_serial_in(port, SCSCR); 2295 + sci_serial_out(port, SCSCR, 2296 + scr & (SCSCR_CKE1 | SCSCR_CKE0 | s->hscif_tot)); 2297 + } 2298 + 2299 + int sci_startup(struct uart_port *port) 2253 2300 { 2254 2301 struct sci_port *s = to_sci_port(port); 2255 2302 int ret; ··· 2278 2305 return 0; 2279 2306 } 2280 2307 2281 - static void sci_shutdown(struct uart_port *port) 2308 + void sci_shutdown(struct uart_port *port) 2282 2309 { 2283 2310 struct sci_port *s = to_sci_port(port); 2284 2311 unsigned long flags; 2285 - u16 scr; 2286 2312 2287 2313 dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); 2288 2314 ··· 2291 2319 uart_port_lock_irqsave(port, &flags); 2292 2320 sci_stop_rx(port); 2293 2321 sci_stop_tx(port); 2294 - /* 2295 - * Stop RX and TX, disable related interrupts, keep clock source 2296 - * and HSCIF TOT bits 2297 - */ 2298 - scr = sci_serial_in(port, SCSCR); 2299 - sci_serial_out(port, SCSCR, 2300 - scr & (SCSCR_CKE1 | SCSCR_CKE0 | s->hscif_tot)); 2322 + s->ops->shutdown_complete(port); 2301 2323 uart_port_unlock_irqrestore(port, flags); 2302 2324 2303 2325 #ifdef CONFIG_SERIAL_SH_SCI_DMA ··· 2368 2402 2369 2403 /* calculate sample rate, BRR, and clock select */ 2370 2404 static int sci_scbrr_calc(struct sci_port *s, unsigned int bps, 2371 - unsigned int *brr, unsigned int *srr, 2372 - unsigned int *cks) 2405 + unsigned int *brr, unsigned int *srr, 2406 + unsigned int *cks) 2373 2407 { 2374 2408 unsigned long freq = s->clk_rates[SCI_FCK]; 2375 2409 unsigned int sr, br, prediv, scrate, c; ··· 2446 2480 if (reg->size) 2447 2481 sci_serial_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); 2448 2482 2449 - sci_clear_SCxSR(port, 2450 - SCxSR_RDxF_CLEAR(port) & SCxSR_ERROR_CLEAR(port) & 2451 - SCxSR_BREAK_CLEAR(port)); 2483 + s->ops->clear_SCxSR(port, 2484 + SCxSR_RDxF_CLEAR(port) & SCxSR_ERROR_CLEAR(port) & 2485 + SCxSR_BREAK_CLEAR(port)); 2452 2486 if (sci_getreg(port, SCLSR)->size) { 2453 2487 status = sci_serial_in(port, SCLSR); 2454 2488 status &= ~(SCLSR_TO | SCLSR_ORER); ··· 2457 2491 2458 2492 if (s->rx_trigger > 1) { 2459 2493 if (s->rx_fifo_timeout) { 2460 - scif_set_rtrg(port, 1); 2494 + s->ops->set_rtrg(port, 1); 2461 2495 timer_setup(&s->rx_fifo_timer, rx_fifo_timer_fn, 0); 2462 2496 } else { 2463 2497 if (port->type == PORT_SCIFA || 2464 2498 port->type == PORT_SCIFB) 2465 - scif_set_rtrg(port, 1); 2499 + s->ops->set_rtrg(port, 1); 2466 2500 else 2467 - scif_set_rtrg(port, s->rx_trigger); 2501 + s->ops->set_rtrg(port, s->rx_trigger); 2468 2502 } 2469 2503 } 2470 2504 } ··· 2724 2758 sci_enable_ms(port); 2725 2759 } 2726 2760 2727 - static void sci_pm(struct uart_port *port, unsigned int state, 2761 + void sci_pm(struct uart_port *port, unsigned int state, 2728 2762 unsigned int oldstate) 2729 2763 { 2730 2764 struct sci_port *sci_port = to_sci_port(port); ··· 2787 2821 return 0; 2788 2822 } 2789 2823 2790 - static void sci_release_port(struct uart_port *port) 2824 + void sci_release_port(struct uart_port *port) 2791 2825 { 2792 2826 struct sci_port *sport = to_sci_port(port); 2793 2827 ··· 2799 2833 release_mem_region(port->mapbase, sport->reg_size); 2800 2834 } 2801 2835 2802 - static int sci_request_port(struct uart_port *port) 2836 + int sci_request_port(struct uart_port *port) 2803 2837 { 2804 2838 struct resource *res; 2805 2839 struct sci_port *sport = to_sci_port(port); ··· 2821 2855 return 0; 2822 2856 } 2823 2857 2824 - static void sci_config_port(struct uart_port *port, int flags) 2858 + void sci_config_port(struct uart_port *port, int flags) 2825 2859 { 2826 2860 if (flags & UART_CONFIG_TYPE) { 2827 2861 struct sci_port *sport = to_sci_port(port); ··· 2831 2865 } 2832 2866 } 2833 2867 2834 - static int sci_verify_port(struct uart_port *port, struct serial_struct *ser) 2868 + int sci_verify_port(struct uart_port *port, struct serial_struct *ser) 2835 2869 { 2836 2870 if (ser->baud_base < 2400) 2837 2871 /* No paper tape reader for Mitch.. */ 2838 2872 return -EINVAL; 2839 2873 2840 2874 return 0; 2875 + } 2876 + 2877 + static void sci_prepare_console_write(struct uart_port *port, u32 ctrl) 2878 + { 2879 + struct sci_port *s = to_sci_port(port); 2880 + u32 ctrl_temp = 2881 + s->params->param_bits->rxtx_enable | 2882 + (s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)) | 2883 + (ctrl & (SCSCR_CKE1 | SCSCR_CKE0)) | 2884 + s->hscif_tot; 2885 + sci_serial_out(port, SCSCR, ctrl_temp); 2886 + } 2887 + 2888 + static void sci_console_save(struct uart_port *port) 2889 + { 2890 + struct sci_port *s = to_sci_port(port); 2891 + struct sci_suspend_regs *regs = s->suspend_regs; 2892 + 2893 + if (sci_getreg(port, SCDL)->size) 2894 + regs->scdl = sci_serial_in(port, SCDL); 2895 + if (sci_getreg(port, SCCKS)->size) 2896 + regs->sccks = sci_serial_in(port, SCCKS); 2897 + if (sci_getreg(port, SCSMR)->size) 2898 + regs->scsmr = sci_serial_in(port, SCSMR); 2899 + if (sci_getreg(port, SCSCR)->size) 2900 + regs->scscr = sci_serial_in(port, SCSCR); 2901 + if (sci_getreg(port, SCFCR)->size) 2902 + regs->scfcr = sci_serial_in(port, SCFCR); 2903 + if (sci_getreg(port, SCSPTR)->size) 2904 + regs->scsptr = sci_serial_in(port, SCSPTR); 2905 + if (sci_getreg(port, SCBRR)->size) 2906 + regs->scbrr = sci_serial_in(port, SCBRR); 2907 + if (sci_getreg(port, HSSRR)->size) 2908 + regs->hssrr = sci_serial_in(port, HSSRR); 2909 + if (sci_getreg(port, SCPCR)->size) 2910 + regs->scpcr = sci_serial_in(port, SCPCR); 2911 + if (sci_getreg(port, SCPDR)->size) 2912 + regs->scpdr = sci_serial_in(port, SCPDR); 2913 + if (sci_getreg(port, SEMR)->size) 2914 + regs->semr = sci_serial_in(port, SEMR); 2915 + } 2916 + 2917 + static void sci_console_restore(struct uart_port *port) 2918 + { 2919 + struct sci_port *s = to_sci_port(port); 2920 + struct sci_suspend_regs *regs = s->suspend_regs; 2921 + 2922 + if (sci_getreg(port, SCDL)->size) 2923 + sci_serial_out(port, SCDL, regs->scdl); 2924 + if (sci_getreg(port, SCCKS)->size) 2925 + sci_serial_out(port, SCCKS, regs->sccks); 2926 + if (sci_getreg(port, SCSMR)->size) 2927 + sci_serial_out(port, SCSMR, regs->scsmr); 2928 + if (sci_getreg(port, SCSCR)->size) 2929 + sci_serial_out(port, SCSCR, regs->scscr); 2930 + if (sci_getreg(port, SCFCR)->size) 2931 + sci_serial_out(port, SCFCR, regs->scfcr); 2932 + if (sci_getreg(port, SCSPTR)->size) 2933 + sci_serial_out(port, SCSPTR, regs->scsptr); 2934 + if (sci_getreg(port, SCBRR)->size) 2935 + sci_serial_out(port, SCBRR, regs->scbrr); 2936 + if (sci_getreg(port, HSSRR)->size) 2937 + sci_serial_out(port, HSSRR, regs->hssrr); 2938 + if (sci_getreg(port, SCPCR)->size) 2939 + sci_serial_out(port, SCPCR, regs->scpcr); 2940 + if (sci_getreg(port, SCPDR)->size) 2941 + sci_serial_out(port, SCPDR, regs->scpdr); 2942 + if (sci_getreg(port, SEMR)->size) 2943 + sci_serial_out(port, SEMR, regs->semr); 2841 2944 } 2842 2945 2843 2946 static const struct uart_ops sci_uart_ops = { ··· 2932 2897 .poll_get_char = sci_poll_get_char, 2933 2898 .poll_put_char = sci_poll_put_char, 2934 2899 #endif 2900 + }; 2901 + 2902 + static const struct sci_port_ops sci_port_ops = { 2903 + .read_reg = sci_serial_in, 2904 + .write_reg = sci_serial_out, 2905 + .clear_SCxSR = sci_clear_SCxSR, 2906 + .transmit_chars = sci_transmit_chars, 2907 + .receive_chars = sci_receive_chars, 2908 + #if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) || \ 2909 + defined(CONFIG_SERIAL_SH_SCI_EARLYCON) 2910 + .poll_put_char = sci_poll_put_char, 2911 + #endif 2912 + .set_rtrg = scif_set_rtrg, 2913 + .rtrg_enabled = scif_rtrg_enabled, 2914 + .shutdown_complete = sci_shutdown_complete, 2915 + .prepare_console_write = sci_prepare_console_write, 2916 + .console_save = sci_console_save, 2917 + .console_restore = sci_console_restore, 2918 + .suspend_regs_size = sci_suspend_regs_size, 2935 2919 }; 2936 2920 2937 2921 static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) ··· 2996 2942 } 2997 2943 2998 2944 static const struct sci_port_params * 2999 - sci_probe_regmap(const struct plat_sci_port *cfg) 2945 + sci_probe_regmap(const struct plat_sci_port *cfg, struct sci_port *sci_port) 3000 2946 { 3001 2947 unsigned int regtype; 2948 + 2949 + sci_port->ops = &sci_port_ops; 2950 + sci_port->port.ops = &sci_uart_ops; 3002 2951 3003 2952 if (cfg->regtype != SCIx_PROBE_REGTYPE) 3004 2953 return &sci_port_params[cfg->regtype]; ··· 3050 2993 3051 2994 sci_port->cfg = p; 3052 2995 3053 - port->ops = &sci_uart_ops; 3054 2996 port->iotype = UPIO_MEM; 3055 2997 port->line = index; 3056 2998 port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_SH_SCI_CONSOLE); ··· 3088 3032 if (sci_port->irqs[1] < 0) 3089 3033 for (i = 1; i < ARRAY_SIZE(sci_port->irqs); i++) 3090 3034 sci_port->irqs[i] = sci_port->irqs[0]; 3091 - 3092 - sci_port->params = sci_probe_regmap(p); 3093 - if (unlikely(sci_port->params == NULL)) 3094 - return -EINVAL; 3095 3035 3096 3036 switch (p->type) { 3097 3037 case PORT_SCIFB: ··· 3156 3104 defined(CONFIG_SERIAL_SH_SCI_EARLYCON) 3157 3105 static void serial_console_putchar(struct uart_port *port, unsigned char ch) 3158 3106 { 3159 - sci_poll_put_char(port, ch); 3107 + to_sci_port(port)->ops->poll_put_char(port, ch); 3160 3108 } 3161 3109 3162 3110 /* ··· 3168 3116 { 3169 3117 struct sci_port *sci_port = &sci_ports[co->index]; 3170 3118 struct uart_port *port = &sci_port->port; 3171 - unsigned short bits, ctrl, ctrl_temp; 3119 + const struct sci_common_regs *regs = sci_port->params->common_regs; 3120 + unsigned int bits; 3121 + u32 ctrl; 3172 3122 unsigned long flags; 3173 3123 int locked = 1; 3174 3124 ··· 3182 3128 uart_port_lock_irqsave(port, &flags); 3183 3129 3184 3130 /* first save SCSCR then disable interrupts, keep clock source */ 3185 - ctrl = sci_serial_in(port, SCSCR); 3186 - ctrl_temp = SCSCR_RE | SCSCR_TE | 3187 - (sci_port->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)) | 3188 - (ctrl & (SCSCR_CKE1 | SCSCR_CKE0)); 3189 - sci_serial_out(port, SCSCR, ctrl_temp | sci_port->hscif_tot); 3131 + 3132 + ctrl = sci_port->ops->read_reg(port, regs->control); 3133 + sci_port->ops->prepare_console_write(port, ctrl); 3190 3134 3191 3135 uart_console_write(port, s, count, serial_console_putchar); 3192 3136 3193 3137 /* wait until fifo is empty and last bit has been transmitted */ 3194 - bits = SCxSR_TDxE(port) | SCxSR_TEND(port); 3195 - while ((sci_serial_in(port, SCxSR) & bits) != bits) 3138 + 3139 + bits = sci_port->params->param_bits->poll_sent_bits; 3140 + 3141 + while ((sci_port->ops->read_reg(port, regs->status) & bits) != bits) 3196 3142 cpu_relax(); 3197 3143 3198 3144 /* restore the SCSCR */ 3199 - sci_serial_out(port, SCSCR, ctrl); 3145 + sci_port->ops->write_reg(port, regs->control, ctrl); 3200 3146 3201 3147 if (locked) 3202 3148 uart_port_unlock_irqrestore(port, flags); ··· 3274 3220 static int sci_probe_earlyprintk(struct platform_device *pdev) 3275 3221 { 3276 3222 const struct plat_sci_port *cfg = dev_get_platdata(&pdev->dev); 3223 + struct sci_port *sp = &sci_ports[pdev->id]; 3277 3224 3278 3225 if (early_serial_console.data) 3279 3226 return -EEXIST; 3280 3227 3281 3228 early_serial_console.index = pdev->id; 3282 3229 3283 - sci_init_single(pdev, &sci_ports[pdev->id], pdev->id, cfg, true); 3230 + sp->params = sci_probe_regmap(cfg, sp); 3231 + if (!sp->params) 3232 + return -ENODEV; 3233 + 3234 + sci_init_single(pdev, sp, pdev->id, cfg, true); 3284 3235 3285 3236 if (!strstr(early_serial_buf, "keep")) 3286 3237 early_serial_console.flags |= CON_BOOT; ··· 3334 3275 device_remove_file(&dev->dev, &dev_attr_rx_fifo_timeout); 3335 3276 } 3336 3277 3278 + static const struct sci_of_data of_sci_scif_sh2 = { 3279 + .type = PORT_SCIF, 3280 + .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE, 3281 + .ops = &sci_port_ops, 3282 + .uart_ops = &sci_uart_ops, 3283 + .params = &sci_port_params[SCIx_SH2_SCIF_FIFODATA_REGTYPE], 3284 + }; 3337 3285 3338 - #define SCI_OF_DATA(type, regtype) (void *)((type) << 16 | (regtype)) 3339 - #define SCI_OF_TYPE(data) ((unsigned long)(data) >> 16) 3340 - #define SCI_OF_REGTYPE(data) ((unsigned long)(data) & 0xffff) 3286 + static const struct sci_of_data of_sci_scif_rz_scifa = { 3287 + .type = PORT_SCIF, 3288 + .regtype = SCIx_RZ_SCIFA_REGTYPE, 3289 + .ops = &sci_port_ops, 3290 + .uart_ops = &sci_uart_ops, 3291 + .params = &sci_port_params[SCIx_RZ_SCIFA_REGTYPE], 3292 + }; 3293 + 3294 + static const struct sci_of_data of_sci_scif_rzv2h = { 3295 + .type = PORT_SCIF, 3296 + .regtype = SCIx_RZV2H_SCIF_REGTYPE, 3297 + .ops = &sci_port_ops, 3298 + .uart_ops = &sci_uart_ops, 3299 + .params = &sci_port_params[SCIx_RZV2H_SCIF_REGTYPE], 3300 + }; 3301 + 3302 + static const struct sci_of_data of_sci_rcar_scif = { 3303 + .type = PORT_SCIF, 3304 + .regtype = SCIx_SH4_SCIF_BRG_REGTYPE, 3305 + .ops = &sci_port_ops, 3306 + .uart_ops = &sci_uart_ops, 3307 + .params = &sci_port_params[SCIx_SH4_SCIF_BRG_REGTYPE], 3308 + }; 3309 + 3310 + static const struct sci_of_data of_sci_scif_sh4 = { 3311 + .type = PORT_SCIF, 3312 + .regtype = SCIx_SH4_SCIF_REGTYPE, 3313 + .ops = &sci_port_ops, 3314 + .uart_ops = &sci_uart_ops, 3315 + .params = &sci_port_params[SCIx_SH4_SCIF_REGTYPE], 3316 + }; 3317 + 3318 + static const struct sci_of_data of_sci_scifa = { 3319 + .type = PORT_SCIFA, 3320 + .regtype = SCIx_SCIFA_REGTYPE, 3321 + .ops = &sci_port_ops, 3322 + .uart_ops = &sci_uart_ops, 3323 + .params = &sci_port_params[SCIx_SCIFA_REGTYPE], 3324 + }; 3325 + 3326 + static const struct sci_of_data of_sci_scifb = { 3327 + .type = PORT_SCIFB, 3328 + .regtype = SCIx_SCIFB_REGTYPE, 3329 + .ops = &sci_port_ops, 3330 + .uart_ops = &sci_uart_ops, 3331 + .params = &sci_port_params[SCIx_SCIFB_REGTYPE], 3332 + }; 3333 + 3334 + static const struct sci_of_data of_sci_hscif = { 3335 + .type = PORT_HSCIF, 3336 + .regtype = SCIx_HSCIF_REGTYPE, 3337 + .ops = &sci_port_ops, 3338 + .uart_ops = &sci_uart_ops, 3339 + .params = &sci_port_params[SCIx_HSCIF_REGTYPE], 3340 + }; 3341 + 3342 + static const struct sci_of_data of_sci_sci = { 3343 + .type = PORT_SCI, 3344 + .regtype = SCIx_SCI_REGTYPE, 3345 + .ops = &sci_port_ops, 3346 + .uart_ops = &sci_uart_ops, 3347 + .params = &sci_port_params[SCIx_SCI_REGTYPE], 3348 + }; 3341 3349 3342 3350 static const struct of_device_id of_sci_match[] __maybe_unused = { 3343 3351 /* SoC-specific types */ 3344 3352 { 3345 3353 .compatible = "renesas,scif-r7s72100", 3346 - .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH2_SCIF_FIFODATA_REGTYPE), 3354 + .data = &of_sci_scif_sh2, 3347 3355 }, 3348 3356 { 3349 3357 .compatible = "renesas,scif-r7s9210", 3350 - .data = SCI_OF_DATA(PORT_SCIF, SCIx_RZ_SCIFA_REGTYPE), 3358 + .data = &of_sci_scif_rz_scifa, 3351 3359 }, 3352 3360 { 3353 3361 .compatible = "renesas,scif-r9a07g044", 3354 - .data = SCI_OF_DATA(PORT_SCIF, SCIx_RZ_SCIFA_REGTYPE), 3362 + .data = &of_sci_scif_rz_scifa, 3355 3363 }, 3356 3364 { 3357 3365 .compatible = "renesas,scif-r9a09g057", 3358 - .data = SCI_OF_DATA(PORT_SCIF, SCIx_RZV2H_SCIF_REGTYPE), 3366 + .data = &of_sci_scif_rzv2h, 3359 3367 }, 3360 3368 /* Family-specific types */ 3361 3369 { 3362 3370 .compatible = "renesas,rcar-gen1-scif", 3363 - .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_BRG_REGTYPE), 3371 + .data = &of_sci_rcar_scif, 3364 3372 }, { 3365 3373 .compatible = "renesas,rcar-gen2-scif", 3366 - .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_BRG_REGTYPE), 3374 + .data = &of_sci_rcar_scif, 3367 3375 }, { 3368 3376 .compatible = "renesas,rcar-gen3-scif", 3369 - .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_BRG_REGTYPE), 3377 + .data = &of_sci_rcar_scif 3370 3378 }, { 3371 3379 .compatible = "renesas,rcar-gen4-scif", 3372 - .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_BRG_REGTYPE), 3380 + .data = &of_sci_rcar_scif 3373 3381 }, 3374 3382 /* Generic types */ 3375 3383 { 3376 3384 .compatible = "renesas,scif", 3377 - .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_REGTYPE), 3385 + .data = &of_sci_scif_sh4, 3378 3386 }, { 3379 3387 .compatible = "renesas,scifa", 3380 - .data = SCI_OF_DATA(PORT_SCIFA, SCIx_SCIFA_REGTYPE), 3388 + .data = &of_sci_scifa, 3381 3389 }, { 3382 3390 .compatible = "renesas,scifb", 3383 - .data = SCI_OF_DATA(PORT_SCIFB, SCIx_SCIFB_REGTYPE), 3391 + .data = &of_sci_scifb, 3384 3392 }, { 3385 3393 .compatible = "renesas,hscif", 3386 - .data = SCI_OF_DATA(PORT_HSCIF, SCIx_HSCIF_REGTYPE), 3394 + .data = &of_sci_hscif, 3387 3395 }, { 3388 3396 .compatible = "renesas,sci", 3389 - .data = SCI_OF_DATA(PORT_SCI, SCIx_SCI_REGTYPE), 3397 + .data = &of_sci_sci, 3390 3398 }, { 3391 3399 /* Terminator */ 3392 3400 }, ··· 3472 3346 struct reset_control *rstc; 3473 3347 struct plat_sci_port *p; 3474 3348 struct sci_port *sp; 3475 - const void *data; 3349 + const struct sci_of_data *data; 3476 3350 int id, ret; 3477 3351 3478 3352 if (!IS_ENABLED(CONFIG_OF) || !np) ··· 3519 3393 sp->rstc = rstc; 3520 3394 *dev_id = id; 3521 3395 3522 - p->type = SCI_OF_TYPE(data); 3523 - p->regtype = SCI_OF_REGTYPE(data); 3396 + p->type = data->type; 3397 + p->regtype = data->regtype; 3398 + 3399 + sp->ops = data->ops; 3400 + sp->port.ops = data->uart_ops; 3401 + sp->params = data->params; 3524 3402 3525 3403 sp->has_rtscts = of_property_read_bool(np, "uart-has-rtscts"); 3526 3404 ··· 3631 3501 p = sci_parse_dt(dev, &dev_id); 3632 3502 if (IS_ERR(p)) 3633 3503 return PTR_ERR(p); 3504 + sp = &sci_ports[dev_id]; 3634 3505 } else { 3635 3506 p = dev->dev.platform_data; 3636 3507 if (p == NULL) { ··· 3640 3509 } 3641 3510 3642 3511 dev_id = dev->id; 3512 + sp = &sci_ports[dev_id]; 3513 + sp->params = sci_probe_regmap(p, sp); 3514 + if (!sp->params) 3515 + return -ENODEV; 3643 3516 } 3644 3517 3645 - sp = &sci_ports[dev_id]; 3518 + sp->suspend_regs = devm_kzalloc(&dev->dev, 3519 + sp->ops->suspend_regs_size(), 3520 + GFP_KERNEL); 3521 + if (!sp->suspend_regs) 3522 + return -ENOMEM; 3646 3523 3647 3524 /* 3648 3525 * In case: ··· 3702 3563 return 0; 3703 3564 } 3704 3565 3705 - static void sci_console_save(struct sci_port *s) 3706 - { 3707 - struct sci_suspend_regs *regs = &s->suspend_regs; 3708 - struct uart_port *port = &s->port; 3709 - 3710 - if (sci_getreg(port, SCDL)->size) 3711 - regs->scdl = sci_serial_in(port, SCDL); 3712 - if (sci_getreg(port, SCCKS)->size) 3713 - regs->sccks = sci_serial_in(port, SCCKS); 3714 - if (sci_getreg(port, SCSMR)->size) 3715 - regs->scsmr = sci_serial_in(port, SCSMR); 3716 - if (sci_getreg(port, SCSCR)->size) 3717 - regs->scscr = sci_serial_in(port, SCSCR); 3718 - if (sci_getreg(port, SCFCR)->size) 3719 - regs->scfcr = sci_serial_in(port, SCFCR); 3720 - if (sci_getreg(port, SCSPTR)->size) 3721 - regs->scsptr = sci_serial_in(port, SCSPTR); 3722 - if (sci_getreg(port, SCBRR)->size) 3723 - regs->scbrr = sci_serial_in(port, SCBRR); 3724 - if (sci_getreg(port, HSSRR)->size) 3725 - regs->hssrr = sci_serial_in(port, HSSRR); 3726 - if (sci_getreg(port, SCPCR)->size) 3727 - regs->scpcr = sci_serial_in(port, SCPCR); 3728 - if (sci_getreg(port, SCPDR)->size) 3729 - regs->scpdr = sci_serial_in(port, SCPDR); 3730 - if (sci_getreg(port, SEMR)->size) 3731 - regs->semr = sci_serial_in(port, SEMR); 3732 - } 3733 - 3734 - static void sci_console_restore(struct sci_port *s) 3735 - { 3736 - struct sci_suspend_regs *regs = &s->suspend_regs; 3737 - struct uart_port *port = &s->port; 3738 - 3739 - if (sci_getreg(port, SCDL)->size) 3740 - sci_serial_out(port, SCDL, regs->scdl); 3741 - if (sci_getreg(port, SCCKS)->size) 3742 - sci_serial_out(port, SCCKS, regs->sccks); 3743 - if (sci_getreg(port, SCSMR)->size) 3744 - sci_serial_out(port, SCSMR, regs->scsmr); 3745 - if (sci_getreg(port, SCSCR)->size) 3746 - sci_serial_out(port, SCSCR, regs->scscr); 3747 - if (sci_getreg(port, SCFCR)->size) 3748 - sci_serial_out(port, SCFCR, regs->scfcr); 3749 - if (sci_getreg(port, SCSPTR)->size) 3750 - sci_serial_out(port, SCSPTR, regs->scsptr); 3751 - if (sci_getreg(port, SCBRR)->size) 3752 - sci_serial_out(port, SCBRR, regs->scbrr); 3753 - if (sci_getreg(port, HSSRR)->size) 3754 - sci_serial_out(port, HSSRR, regs->hssrr); 3755 - if (sci_getreg(port, SCPCR)->size) 3756 - sci_serial_out(port, SCPCR, regs->scpcr); 3757 - if (sci_getreg(port, SCPDR)->size) 3758 - sci_serial_out(port, SCPDR, regs->scpdr); 3759 - if (sci_getreg(port, SEMR)->size) 3760 - sci_serial_out(port, SEMR, regs->semr); 3761 - } 3762 - 3763 3566 static __maybe_unused int sci_suspend(struct device *dev) 3764 3567 { 3765 3568 struct sci_port *sport = dev_get_drvdata(dev); ··· 3709 3628 if (sport) { 3710 3629 uart_suspend_port(&sci_uart_driver, &sport->port); 3711 3630 3712 - if (!console_suspend_enabled && uart_console(&sport->port)) 3713 - sci_console_save(sport); 3631 + if (!console_suspend_enabled && uart_console(&sport->port)) { 3632 + if (sport->ops->console_save) 3633 + sport->ops->console_save(&sport->port); 3634 + } 3714 3635 else 3715 3636 return reset_control_assert(sport->rstc); 3716 3637 } ··· 3726 3643 3727 3644 if (sport) { 3728 3645 if (!console_suspend_enabled && uart_console(&sport->port)) { 3729 - sci_console_restore(sport); 3646 + if (sport->ops->console_restore) 3647 + sport->ops->console_restore(&sport->port); 3730 3648 } else { 3731 3649 int ret = reset_control_deassert(sport->rstc); 3732 3650 ··· 3791 3707 return 0; 3792 3708 } 3793 3709 3794 - static int __init early_console_setup(struct earlycon_device *device, 3795 - int type) 3710 + int __init scix_early_console_setup(struct earlycon_device *device, 3711 + const struct sci_of_data *data) 3796 3712 { 3713 + const struct sci_common_regs *regs; 3714 + 3797 3715 if (!device->port.membase) 3798 3716 return -ENODEV; 3799 3717 3800 - device->port.type = type; 3718 + device->port.type = data->type; 3801 3719 sci_ports[0].port = device->port; 3802 - port_cfg.type = type; 3720 + 3721 + port_cfg.type = data->type; 3722 + port_cfg.regtype = data->regtype; 3723 + 3803 3724 sci_ports[0].cfg = &port_cfg; 3804 - sci_ports[0].params = sci_probe_regmap(&port_cfg); 3725 + sci_ports[0].params = data->params; 3726 + sci_ports[0].ops = data->ops; 3727 + sci_ports[0].port.ops = data->uart_ops; 3805 3728 sci_uart_earlycon = true; 3806 - port_cfg.scscr = sci_serial_in(&sci_ports[0].port, SCSCR); 3807 - sci_serial_out(&sci_ports[0].port, SCSCR, 3808 - SCSCR_RE | SCSCR_TE | port_cfg.scscr); 3729 + regs = sci_ports[0].params->common_regs; 3730 + 3731 + port_cfg.scscr = sci_ports[0].ops->read_reg(&sci_ports[0].port, regs->control); 3732 + sci_ports[0].ops->write_reg(&sci_ports[0].port, 3733 + regs->control, 3734 + sci_ports[0].params->param_bits->rxtx_enable | port_cfg.scscr); 3809 3735 3810 3736 device->con->write = serial_console_write; 3811 3737 device->con->exit = early_console_exit; ··· 3825 3731 static int __init sci_early_console_setup(struct earlycon_device *device, 3826 3732 const char *opt) 3827 3733 { 3828 - return early_console_setup(device, PORT_SCI); 3734 + return scix_early_console_setup(device, &of_sci_sci); 3829 3735 } 3830 3736 static int __init scif_early_console_setup(struct earlycon_device *device, 3831 3737 const char *opt) 3832 3738 { 3833 - return early_console_setup(device, PORT_SCIF); 3739 + return scix_early_console_setup(device, &of_sci_scif_sh4); 3834 3740 } 3835 3741 static int __init rzscifa_early_console_setup(struct earlycon_device *device, 3836 3742 const char *opt) 3837 3743 { 3838 - port_cfg.regtype = SCIx_RZ_SCIFA_REGTYPE; 3839 - return early_console_setup(device, PORT_SCIF); 3744 + return scix_early_console_setup(device, &of_sci_scif_rz_scifa); 3840 3745 } 3841 3746 3842 3747 static int __init rzv2hscif_early_console_setup(struct earlycon_device *device, 3843 3748 const char *opt) 3844 3749 { 3845 - port_cfg.regtype = SCIx_RZV2H_SCIF_REGTYPE; 3846 - return early_console_setup(device, PORT_SCIF); 3750 + return scix_early_console_setup(device, &of_sci_scif_rzv2h); 3847 3751 } 3848 3752 3849 3753 static int __init scifa_early_console_setup(struct earlycon_device *device, 3850 3754 const char *opt) 3851 3755 { 3852 - return early_console_setup(device, PORT_SCIFA); 3756 + return scix_early_console_setup(device, &of_sci_scifa); 3853 3757 } 3854 3758 static int __init scifb_early_console_setup(struct earlycon_device *device, 3855 3759 const char *opt) 3856 3760 { 3857 - return early_console_setup(device, PORT_SCIFB); 3761 + return scix_early_console_setup(device, &of_sci_scifb); 3858 3762 } 3859 3763 static int __init hscif_early_console_setup(struct earlycon_device *device, 3860 3764 const char *opt) 3861 3765 { 3862 - return early_console_setup(device, PORT_HSCIF); 3766 + return scix_early_console_setup(device, &of_sci_hscif); 3863 3767 } 3864 3768 3865 3769 OF_EARLYCON_DECLARE(sci, "renesas,sci", sci_early_console_setup);
-2
drivers/tty/serial/sh-sci.h
··· 32 32 HSRTRGR, /* Rx FIFO Data Count Trigger Register */ 33 33 HSTTRGR, /* Tx FIFO Data Count Trigger Register */ 34 34 SEMR, /* Serial extended mode register */ 35 - 36 - SCIx_NR_REGS, 37 35 }; 38 36 39 37
+75 -13
drivers/tty/serial/sifive.c
··· 141 141 * @baud_rate: UART serial line rate (e.g., 115200 baud) 142 142 * @clk: reference to this device's clock 143 143 * @clk_notifier: clock rate change notifier for upstream clock changes 144 + * @console_line_ended: indicate that the console line is fully written 144 145 * 145 146 * Configuration data specific to this SiFive UART. 146 147 */ ··· 152 151 unsigned long baud_rate; 153 152 struct clk *clk; 154 153 struct notifier_block clk_notifier; 154 + bool console_line_ended; 155 155 }; 156 156 157 157 /* ··· 787 785 788 786 __ssp_wait_for_xmitr(ssp); 789 787 __ssp_transmit_char(ssp, ch); 788 + 789 + ssp->console_line_ended = (ch == '\n'); 790 790 } 791 791 792 - static void sifive_serial_console_write(struct console *co, const char *s, 793 - unsigned int count) 792 + static void sifive_serial_device_lock(struct console *co, unsigned long *flags) 793 + { 794 + struct uart_port *up = &sifive_serial_console_ports[co->index]->port; 795 + 796 + __uart_port_lock_irqsave(up, flags); 797 + } 798 + 799 + static void sifive_serial_device_unlock(struct console *co, unsigned long flags) 800 + { 801 + struct uart_port *up = &sifive_serial_console_ports[co->index]->port; 802 + 803 + __uart_port_unlock_irqrestore(up, flags); 804 + } 805 + 806 + static void sifive_serial_console_write_atomic(struct console *co, 807 + struct nbcon_write_context *wctxt) 794 808 { 795 809 struct sifive_serial_port *ssp = sifive_serial_console_ports[co->index]; 796 - unsigned long flags; 810 + struct uart_port *port = &ssp->port; 797 811 unsigned int ier; 798 - int locked = 1; 799 812 800 813 if (!ssp) 801 814 return; 802 815 803 - if (oops_in_progress) 804 - locked = uart_port_trylock_irqsave(&ssp->port, &flags); 805 - else 806 - uart_port_lock_irqsave(&ssp->port, &flags); 816 + if (!nbcon_enter_unsafe(wctxt)) 817 + return; 807 818 808 819 ier = __ssp_readl(ssp, SIFIVE_SERIAL_IE_OFFS); 809 820 __ssp_writel(0, SIFIVE_SERIAL_IE_OFFS, ssp); 810 821 811 - uart_console_write(&ssp->port, s, count, sifive_serial_console_putchar); 822 + if (!ssp->console_line_ended) 823 + uart_console_write(port, "\n", 1, sifive_serial_console_putchar); 824 + uart_console_write(port, wctxt->outbuf, wctxt->len, 825 + sifive_serial_console_putchar); 812 826 813 827 __ssp_writel(ier, SIFIVE_SERIAL_IE_OFFS, ssp); 814 828 815 - if (locked) 816 - uart_port_unlock_irqrestore(&ssp->port, flags); 829 + nbcon_exit_unsafe(wctxt); 830 + } 831 + 832 + static void sifive_serial_console_write_thread(struct console *co, 833 + struct nbcon_write_context *wctxt) 834 + { 835 + struct sifive_serial_port *ssp = sifive_serial_console_ports[co->index]; 836 + struct uart_port *port = &ssp->port; 837 + unsigned int ier; 838 + 839 + if (!ssp) 840 + return; 841 + 842 + if (!nbcon_enter_unsafe(wctxt)) 843 + return; 844 + 845 + ier = __ssp_readl(ssp, SIFIVE_SERIAL_IE_OFFS); 846 + __ssp_writel(0, SIFIVE_SERIAL_IE_OFFS, ssp); 847 + 848 + if (nbcon_exit_unsafe(wctxt)) { 849 + int len = READ_ONCE(wctxt->len); 850 + int i; 851 + 852 + for (i = 0; i < len; i++) { 853 + if (!nbcon_enter_unsafe(wctxt)) 854 + break; 855 + 856 + uart_console_write(port, wctxt->outbuf + i, 1, 857 + sifive_serial_console_putchar); 858 + 859 + if (!nbcon_exit_unsafe(wctxt)) 860 + break; 861 + } 862 + } 863 + 864 + while (!nbcon_enter_unsafe(wctxt)) 865 + nbcon_reacquire_nobuf(wctxt); 866 + 867 + __ssp_writel(ier, SIFIVE_SERIAL_IE_OFFS, ssp); 868 + 869 + nbcon_exit_unsafe(wctxt); 817 870 } 818 871 819 872 static int sifive_serial_console_setup(struct console *co, char *options) ··· 886 829 if (!ssp) 887 830 return -ENODEV; 888 831 832 + ssp->console_line_ended = true; 833 + 889 834 if (options) 890 835 uart_parse_options(options, &baud, &parity, &bits, &flow); 891 836 ··· 898 839 899 840 static struct console sifive_serial_console = { 900 841 .name = SIFIVE_TTY_PREFIX, 901 - .write = sifive_serial_console_write, 842 + .write_atomic = sifive_serial_console_write_atomic, 843 + .write_thread = sifive_serial_console_write_thread, 844 + .device_lock = sifive_serial_device_lock, 845 + .device_unlock = sifive_serial_device_unlock, 902 846 .device = uart_console_device, 903 847 .setup = sifive_serial_console_setup, 904 - .flags = CON_PRINTBUFFER, 848 + .flags = CON_PRINTBUFFER | CON_NBCON, 905 849 .index = -1, 906 850 .data = &sifive_serial_uart_driver, 907 851 };
+1 -1
drivers/tty/serial/tegra-utc.c
··· 434 434 435 435 outbuf += burst_size; 436 436 len -= burst_size; 437 - }; 437 + } 438 438 439 439 nbcon_exit_unsafe(wctxt); 440 440 }
+12 -13
drivers/tty/serial/uartlite.c
··· 880 880 pm_runtime_set_active(&pdev->dev); 881 881 pm_runtime_enable(&pdev->dev); 882 882 883 - if (!ulite_uart_driver.state) { 884 - dev_dbg(&pdev->dev, "uartlite: calling uart_register_driver()\n"); 885 - ret = uart_register_driver(&ulite_uart_driver); 886 - if (ret < 0) { 887 - dev_err(&pdev->dev, "Failed to register driver\n"); 888 - clk_disable_unprepare(pdata->clk); 889 - return ret; 890 - } 891 - } 892 - 893 883 ret = ulite_assign(&pdev->dev, id, res->start, irq, pdata); 894 884 895 885 pm_runtime_mark_last_busy(&pdev->dev); ··· 919 929 920 930 static int __init ulite_init(void) 921 931 { 932 + int ret; 933 + 934 + pr_debug("uartlite: calling uart_register_driver()\n"); 935 + ret = uart_register_driver(&ulite_uart_driver); 936 + if (ret) 937 + return ret; 922 938 923 939 pr_debug("uartlite: calling platform_driver_register()\n"); 924 - return platform_driver_register(&ulite_platform_driver); 940 + ret = platform_driver_register(&ulite_platform_driver); 941 + if (ret) 942 + uart_unregister_driver(&ulite_uart_driver); 943 + 944 + return ret; 925 945 } 926 946 927 947 static void __exit ulite_exit(void) 928 948 { 929 949 platform_driver_unregister(&ulite_platform_driver); 930 - if (ulite_uart_driver.state) 931 - uart_unregister_driver(&ulite_uart_driver); 950 + uart_unregister_driver(&ulite_uart_driver); 932 951 } 933 952 934 953 module_init(ulite_init);
+40 -56
drivers/tty/tty_io.c
··· 276 276 struct list_head *p; 277 277 int count = 0, kopen_count = 0; 278 278 279 - spin_lock(&tty->files_lock); 280 - list_for_each(p, &tty->tty_files) { 281 - count++; 282 - } 283 - spin_unlock(&tty->files_lock); 279 + scoped_guard(spinlock, &tty->files_lock) 280 + list_for_each(p, &tty->tty_files) 281 + count++; 282 + 284 283 if (tty->driver->type == TTY_DRIVER_TYPE_PTY && 285 284 tty->driver->subtype == PTY_TYPE_SLAVE && 286 285 tty->link && tty->link->count) ··· 377 378 */ 378 379 struct tty_driver *tty_find_polling_driver(char *name, int *line) 379 380 { 380 - struct tty_driver *p, *res = NULL; 381 + struct tty_driver *p; 381 382 int tty_line = 0; 382 383 int len; 383 384 char *str, *stp; ··· 391 392 len = str - name; 392 393 tty_line = simple_strtoul(str, &str, 10); 393 394 394 - mutex_lock(&tty_mutex); 395 + guard(mutex)(&tty_mutex); 396 + 395 397 /* Search through the tty devices to look for a match */ 396 398 list_for_each_entry(p, &tty_drivers, tty_drivers) { 397 399 if (!len || strncmp(name, p->name, len) != 0) ··· 405 405 406 406 if (tty_line >= 0 && tty_line < p->num && p->ops && 407 407 p->ops->poll_init && !p->ops->poll_init(p, tty_line, stp)) { 408 - res = tty_driver_kref_get(p); 409 408 *line = tty_line; 410 - break; 409 + return tty_driver_kref_get(p); 411 410 } 412 411 } 413 - mutex_unlock(&tty_mutex); 414 412 415 - return res; 413 + return NULL; 416 414 } 417 415 EXPORT_SYMBOL_GPL(tty_find_polling_driver); 418 416 #endif ··· 529 531 */ 530 532 static struct file *tty_release_redirect(struct tty_struct *tty) 531 533 { 532 - struct file *f = NULL; 534 + guard(spinlock)(&redirect_lock); 533 535 534 - spin_lock(&redirect_lock); 535 536 if (redirect && file_tty(redirect) == tty) { 536 - f = redirect; 537 + struct file *f = redirect; 537 538 redirect = NULL; 539 + return f; 538 540 } 539 - spin_unlock(&redirect_lock); 540 541 541 - return f; 542 + return NULL; 542 543 } 543 544 544 545 /** ··· 762 765 */ 763 766 void stop_tty(struct tty_struct *tty) 764 767 { 765 - unsigned long flags; 766 - 767 - spin_lock_irqsave(&tty->flow.lock, flags); 768 + guard(spinlock_irqsave)(&tty->flow.lock); 768 769 __stop_tty(tty); 769 - spin_unlock_irqrestore(&tty->flow.lock, flags); 770 770 } 771 771 EXPORT_SYMBOL(stop_tty); 772 772 ··· 790 796 */ 791 797 void start_tty(struct tty_struct *tty) 792 798 { 793 - unsigned long flags; 794 - 795 - spin_lock_irqsave(&tty->flow.lock, flags); 799 + guard(spinlock_irqsave)(&tty->flow.lock); 796 800 __start_tty(tty); 797 - spin_unlock_irqrestore(&tty->flow.lock, flags); 798 801 } 799 802 EXPORT_SYMBOL(start_tty); 800 803 ··· 800 809 time64_t sec = ktime_get_real_seconds(); 801 810 struct tty_file_private *priv; 802 811 803 - spin_lock(&tty->files_lock); 812 + guard(spinlock)(&tty->files_lock); 813 + 804 814 list_for_each_entry(priv, &tty->tty_files, list) { 805 815 struct inode *inode = file_inode(priv->file); 806 816 struct timespec64 time = mtime ? inode_get_mtime(inode) : inode_get_atime(inode); ··· 819 827 inode_set_atime(inode, sec, 0); 820 828 } 821 829 } 822 - spin_unlock(&tty->files_lock); 823 830 } 824 831 825 832 /* ··· 2305 2314 */ 2306 2315 static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg) 2307 2316 { 2308 - int err; 2317 + guard(mutex)(&tty->winsize_mutex); 2309 2318 2310 - mutex_lock(&tty->winsize_mutex); 2311 - err = copy_to_user(arg, &tty->winsize, sizeof(*arg)); 2312 - mutex_unlock(&tty->winsize_mutex); 2319 + if (copy_to_user(arg, &tty->winsize, sizeof(*arg))) 2320 + return -EFAULT; 2313 2321 2314 - return err ? -EFAULT : 0; 2322 + return 0; 2315 2323 } 2316 2324 2317 2325 /** ··· 2325 2335 { 2326 2336 struct pid *pgrp; 2327 2337 2328 - /* Lock the tty */ 2329 - mutex_lock(&tty->winsize_mutex); 2338 + guard(mutex)(&tty->winsize_mutex); 2339 + 2330 2340 if (!memcmp(ws, &tty->winsize, sizeof(*ws))) 2331 - goto done; 2341 + return 0; 2332 2342 2333 2343 /* Signal the foreground process group */ 2334 2344 pgrp = tty_get_pgrp(tty); ··· 2337 2347 put_pid(pgrp); 2338 2348 2339 2349 tty->winsize = *ws; 2340 - done: 2341 - mutex_unlock(&tty->winsize_mutex); 2350 + 2342 2351 return 0; 2343 2352 } 2344 2353 EXPORT_SYMBOL(tty_do_resize); ··· 2398 2409 return -EBADF; 2399 2410 if (!(file->f_mode & FMODE_CAN_WRITE)) 2400 2411 return -EINVAL; 2401 - spin_lock(&redirect_lock); 2402 - if (redirect) { 2403 - spin_unlock(&redirect_lock); 2412 + 2413 + guard(spinlock)(&redirect_lock); 2414 + 2415 + if (redirect) 2404 2416 return -EBUSY; 2405 - } 2417 + 2406 2418 redirect = get_file(file); 2407 - spin_unlock(&redirect_lock); 2419 + 2408 2420 return 0; 2409 2421 } 2410 2422 ··· 3018 3028 struct task_struct *g, *p; 3019 3029 struct pid *session; 3020 3030 int i; 3021 - unsigned long flags; 3022 3031 3023 - spin_lock_irqsave(&tty->ctrl.lock, flags); 3024 - session = get_pid(tty->ctrl.session); 3025 - spin_unlock_irqrestore(&tty->ctrl.lock, flags); 3032 + scoped_guard(spinlock_irqsave, &tty->ctrl.lock) 3033 + session = get_pid(tty->ctrl.session); 3026 3034 3027 3035 tty_ldisc_flush(tty); 3028 3036 ··· 3043 3055 PIDTYPE_SID); 3044 3056 continue; 3045 3057 } 3046 - task_lock(p); 3058 + guard(task_lock)(p); 3047 3059 i = iterate_fd(p->files, 0, this_tty, tty); 3048 3060 if (i != 0) { 3049 3061 tty_notice(tty, "SAK: killed process %d (%s): by fd#%d\n", ··· 3051 3063 group_send_sig_info(SIGKILL, SEND_SIG_PRIV, p, 3052 3064 PIDTYPE_SID); 3053 3065 } 3054 - task_unlock(p); 3055 3066 } 3056 3067 read_unlock(&tasklist_lock); 3057 3068 put_pid(session); ··· 3452 3465 goto err_unreg_char; 3453 3466 } 3454 3467 3455 - mutex_lock(&tty_mutex); 3456 - list_add(&driver->tty_drivers, &tty_drivers); 3457 - mutex_unlock(&tty_mutex); 3468 + scoped_guard(mutex, &tty_mutex) 3469 + list_add(&driver->tty_drivers, &tty_drivers); 3458 3470 3459 3471 if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) { 3460 3472 for (i = 0; i < driver->num; i++) { ··· 3472 3486 for (i--; i >= 0; i--) 3473 3487 tty_unregister_device(driver, i); 3474 3488 3475 - mutex_lock(&tty_mutex); 3476 - list_del(&driver->tty_drivers); 3477 - mutex_unlock(&tty_mutex); 3489 + scoped_guard(mutex, &tty_mutex) 3490 + list_del(&driver->tty_drivers); 3478 3491 3479 3492 err_unreg_char: 3480 3493 unregister_chrdev_region(dev, driver->num); ··· 3492 3507 { 3493 3508 unregister_chrdev_region(MKDEV(driver->major, driver->minor_start), 3494 3509 driver->num); 3495 - mutex_lock(&tty_mutex); 3496 - list_del(&driver->tty_drivers); 3497 - mutex_unlock(&tty_mutex); 3510 + scoped_guard(mutex, &tty_mutex) 3511 + list_del(&driver->tty_drivers); 3498 3512 } 3499 3513 EXPORT_SYMBOL(tty_unregister_driver); 3500 3514
+22 -26
drivers/tty/tty_ioctl.c
··· 122 122 */ 123 123 bool tty_throttle_safe(struct tty_struct *tty) 124 124 { 125 - bool ret = true; 125 + guard(mutex)(&tty->throttle_mutex); 126 126 127 - mutex_lock(&tty->throttle_mutex); 128 - if (!tty_throttled(tty)) { 129 - if (tty->flow_change != TTY_THROTTLE_SAFE) 130 - ret = false; 131 - else { 132 - set_bit(TTY_THROTTLED, &tty->flags); 133 - if (tty->ops->throttle) 134 - tty->ops->throttle(tty); 135 - } 136 - } 137 - mutex_unlock(&tty->throttle_mutex); 127 + if (tty_throttled(tty)) 128 + return true; 138 129 139 - return ret; 130 + if (tty->flow_change != TTY_THROTTLE_SAFE) 131 + return false; 132 + 133 + set_bit(TTY_THROTTLED, &tty->flags); 134 + if (tty->ops->throttle) 135 + tty->ops->throttle(tty); 136 + 137 + return true; 140 138 } 141 139 142 140 /** ··· 150 152 */ 151 153 bool tty_unthrottle_safe(struct tty_struct *tty) 152 154 { 153 - bool ret = true; 155 + guard(mutex)(&tty->throttle_mutex); 154 156 155 - mutex_lock(&tty->throttle_mutex); 156 - if (tty_throttled(tty)) { 157 - if (tty->flow_change != TTY_UNTHROTTLE_SAFE) 158 - ret = false; 159 - else { 160 - clear_bit(TTY_THROTTLED, &tty->flags); 161 - if (tty->ops->unthrottle) 162 - tty->ops->unthrottle(tty); 163 - } 164 - } 165 - mutex_unlock(&tty->throttle_mutex); 157 + if (!tty_throttled(tty)) 158 + return true; 166 159 167 - return ret; 160 + if (tty->flow_change != TTY_UNTHROTTLE_SAFE) 161 + return false; 162 + 163 + clear_bit(TTY_THROTTLED, &tty->flags); 164 + if (tty->ops->unthrottle) 165 + tty->ops->unthrottle(tty); 166 + 167 + return true; 168 168 } 169 169 170 170 /**
-20
drivers/tty/tty_port.c
··· 200 200 EXPORT_SYMBOL_GPL(tty_port_register_device_attr_serdev); 201 201 202 202 /** 203 - * tty_port_register_device_serdev - register tty or serdev device 204 - * @port: tty_port of the device 205 - * @driver: tty_driver for this device 206 - * @index: index of the tty 207 - * @host: serial port hardware controller device 208 - * @parent: parent if exists, otherwise NULL 209 - * 210 - * Register a serdev or tty device depending on if the parent device has any 211 - * defined serdev clients or not. 212 - */ 213 - struct device *tty_port_register_device_serdev(struct tty_port *port, 214 - struct tty_driver *driver, unsigned index, 215 - struct device *host, struct device *parent) 216 - { 217 - return tty_port_register_device_attr_serdev(port, driver, index, 218 - host, parent, NULL, NULL); 219 - } 220 - EXPORT_SYMBOL_GPL(tty_port_register_device_serdev); 221 - 222 - /** 223 203 * tty_port_unregister_device - deregister a tty or serdev device 224 204 * @port: tty_port of the device 225 205 * @driver: tty_driver for this device
+3
drivers/tty/vt/.gitignore
··· 2 2 /conmakehash 3 3 /consolemap_deftbl.c 4 4 /defkeymap.c 5 + /ucs_fallback_table.h 6 + /ucs_recompose_table.h 7 + /ucs_width_table.h
+32 -2
drivers/tty/vt/Makefile
··· 7 7 obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o \ 8 8 selection.o keyboard.o \ 9 9 vt.o defkeymap.o 10 - obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o 10 + obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o \ 11 + ucs.o 11 12 12 13 # Files generated that shall be removed upon make clean 13 - clean-files := consolemap_deftbl.c defkeymap.c 14 + clean-files := consolemap_deftbl.c defkeymap.c \ 15 + ucs_width_table.h ucs_recompose_table.h ucs_fallback_table.h 14 16 15 17 hostprogs += conmakehash 16 18 ··· 33 31 34 32 $(obj)/defkeymap.c: $(obj)/%.c: $(src)/%.map 35 33 loadkeys --mktable --unicode $< > $@ 34 + 35 + endif 36 + 37 + $(obj)/ucs.o: $(src)/ucs.c $(obj)/ucs_width_table.h \ 38 + $(obj)/ucs_recompose_table.h $(obj)/ucs_fallback_table.h 39 + 40 + # You may uncomment one of those to have the UCS tables be regenerated 41 + # during the build process. By default the _shipped versions are used. 42 + # 43 + #GENERATE_UCS_TABLES := 1 44 + #GENERATE_UCS_TABLES := 2 # invokes gen_ucs_recompose_table.py with --full 45 + 46 + ifdef GENERATE_UCS_TABLES 47 + 48 + $(obj)/ucs_width_table.h: $(src)/gen_ucs_width_table.py 49 + $(PYTHON3) $< -o $@ 50 + 51 + ifeq ($(GENERATE_UCS_TABLES),2) 52 + gen_recomp_arg := --full 53 + else 54 + gen_recomp_arg := 55 + endif 56 + 57 + $(obj)/ucs_recompose_table.h: $(src)/gen_ucs_recompose_table.py 58 + $(PYTHON3) $< -o $@ $(gen_recomp_arg) 59 + 60 + $(obj)/ucs_fallback_table.h: $(src)/gen_ucs_fallback_table.py 61 + $(PYTHON3) $< -o $@ 36 62 37 63 endif
-2
drivers/tty/vt/consolemap.c
··· 870 870 return -4; /* Not found */ 871 871 else if (ucs < 0x20) 872 872 return -1; /* Not a printable character */ 873 - else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f)) 874 - return -2; /* Zero-width space */ 875 873 /* 876 874 * UNI_DIRECT_BASE indicates the start of the region in the User Zone 877 875 * which always has a 1:1 mapping to the currently loaded font. The
+360
drivers/tty/vt/gen_ucs_fallback_table.py
··· 1 + #!/usr/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # 4 + # Leverage Python's unidecode module to generate ucs_fallback_table.h 5 + # 6 + # The generated table maps complex characters to their simpler fallback forms 7 + # for a terminal display when corresponding glyphs are unavailable. 8 + # 9 + # Usage: 10 + # python3 gen_ucs_fallback_table.py # Generate fallback tables 11 + # python3 gen_ucs_fallback_table.py -o FILE # Specify output file 12 + 13 + import unicodedata 14 + from unidecode import unidecode 15 + import sys 16 + import argparse 17 + from collections import defaultdict 18 + 19 + # Try to get unidecode version 20 + try: 21 + from importlib.metadata import version 22 + unidecode_version = version('unidecode') 23 + except: 24 + unidecode_version = 'unknown' 25 + 26 + # This script's file name 27 + from pathlib import Path 28 + this_file = Path(__file__).name 29 + 30 + # Default output file name 31 + DEFAULT_OUT_FILE = "ucs_fallback_table.h" 32 + 33 + # Define the range marker value 34 + RANGE_MARKER = 0x00 35 + 36 + def generate_fallback_map(): 37 + """Generate a fallback map using unidecode for all relevant Unicode points.""" 38 + fallback_map = {} 39 + 40 + # Process BMP characters (0x0000 - 0xFFFF) to keep table size manageable 41 + for cp in range(0x0080, 0x10000): # Skip ASCII range (0x00-0x7F) 42 + char = chr(cp) 43 + 44 + # Skip unassigned/control characters 45 + try: 46 + if not unicodedata.name(char, ''): 47 + continue 48 + except ValueError: 49 + continue 50 + 51 + # Get the unidecode transliteration 52 + ascii_version = unidecode(char) 53 + 54 + # Only store if it results in a single character mapping 55 + if len(ascii_version) == 1: 56 + fallback_map[cp] = ord(ascii_version) 57 + 58 + # Apply manual overrides for special cases 59 + fallback_map.update(get_special_overrides()) 60 + 61 + return fallback_map 62 + 63 + def get_special_overrides(): 64 + """Get special case overrides that need different handling than unidecode 65 + provides... or doesn't provide at all.""" 66 + 67 + overrides = {} 68 + 69 + # Multi-character unidecode output 70 + # These map to single chars instead of unidecode's multiple-char mappings 71 + # In a terminal fallback context, we need a single character rather than multiple 72 + overrides[0x00C6] = ord('E') # Æ LATIN CAPITAL LETTER AE -> E (unidecode: "AE") 73 + overrides[0x00E6] = ord('e') # æ LATIN SMALL LETTER AE -> e (unidecode: "ae") 74 + overrides[0x0152] = ord('E') # Œ LATIN CAPITAL LIGATURE OE -> E (unidecode: "OE") 75 + overrides[0x0153] = ord('e') # œ LATIN SMALL LETTER LIGATURE OE -> e (unidecode: "oe") 76 + overrides[0x00DF] = ord('s') # ß LATIN SMALL LETTER SHARP S -> s (unidecode: "ss") 77 + 78 + # Comparison operators that unidecode renders as multiple characters 79 + overrides[0x2264] = ord('<') # ≤ LESS-THAN OR EQUAL TO -> < (unidecode: "<=") 80 + overrides[0x2265] = ord('>') # ≥ GREATER-THAN OR EQUAL TO -> > (unidecode: ">=") 81 + 82 + # Unidecode returns an empty string for these 83 + overrides[0x2260] = ord('#') # ≠ NOT EQUAL TO -> # (unidecode: empty string) 84 + 85 + # Quadrant block characters that unidecode doesn't map 86 + for cp in range(0x2596, 0x259F+1): 87 + overrides[cp] = ord('#') # ▖ ▗ ▘ ▙ etc. - map to # (unidecode: empty string) 88 + 89 + # Directional arrows 90 + # These provide better semantic meaning than unidecode's mappings 91 + overrides[0x2192] = ord('>') # → RIGHTWARDS ARROW -> > (unidecode: "-") 92 + overrides[0x2190] = ord('<') # ← LEFTWARDS ARROW -> < (unidecode: "-") 93 + overrides[0x2191] = ord('^') # ↑ UPWARDS ARROW -> ^ (unidecode: "|") 94 + overrides[0x2193] = ord('v') # ↓ DOWNWARDS ARROW -> v (unidecode: "|") 95 + 96 + # Double arrows with their directional semantic mappings 97 + overrides[0x21D0] = ord('<') # ⇐ LEFTWARDS DOUBLE ARROW -> < 98 + overrides[0x21D1] = ord('^') # ⇑ UPWARDS DOUBLE ARROW -> ^ 99 + overrides[0x21D2] = ord('>') # ⇒ RIGHTWARDS DOUBLE ARROW -> > 100 + overrides[0x21D3] = ord('v') # ⇓ DOWNWARDS DOUBLE ARROW -> v 101 + 102 + # Halfwidth arrows 103 + # These need the same treatment as their normal-width counterparts 104 + overrides[0xFFE9] = ord('<') # ← HALFWIDTH LEFTWARDS ARROW -> < (unidecode: "-") 105 + overrides[0xFFEA] = ord('^') # ↑ HALFWIDTH UPWARDS ARROW -> ^ (unidecode: "|") 106 + overrides[0xFFEB] = ord('>') # → HALFWIDTH RIGHTWARDS ARROW -> > (unidecode: "-") 107 + overrides[0xFFEC] = ord('v') # ↓ HALFWIDTH DOWNWARDS ARROW -> v (unidecode: "|") 108 + 109 + # Currency symbols - each mapped to a representative letter 110 + overrides[0x00A2] = ord('c') # ¢ CENT SIGN -> c 111 + overrides[0x00A3] = ord('L') # £ POUND SIGN -> L 112 + overrides[0x00A5] = ord('Y') # ¥ YEN SIGN -> Y 113 + overrides[0x20AC] = ord('E') # € EURO SIGN -> E 114 + 115 + # Symbols mapped to letters 116 + overrides[0x00A7] = ord('S') # § SECTION SIGN -> S 117 + overrides[0x00A9] = ord('C') # © COPYRIGHT SIGN -> C 118 + overrides[0x00AE] = ord('R') # ® REGISTERED SIGN -> R 119 + overrides[0x2122] = ord('T') # ™ TRADE MARK SIGN -> T 120 + 121 + # Degree-related symbols 122 + overrides[0x00B0] = ord('o') # ° DEGREE SIGN -> o 123 + overrides[0x2103] = ord('C') # ℃ DEGREE CELSIUS -> C 124 + overrides[0x2109] = ord('F') # ℉ DEGREE FAHRENHEIT -> F 125 + 126 + # Angle quotation marks 127 + overrides[0x00AB] = ord('<') # « LEFT-POINTING DOUBLE ANGLE QUOTATION MARK -> < 128 + overrides[0x00BB] = ord('>') # » RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK -> > 129 + 130 + # Operators with circular shape 131 + overrides[0x2218] = ord('o') # ∘ RING OPERATOR -> o 132 + overrides[0x2219] = ord('.') # ∙ BULLET OPERATOR -> . 133 + 134 + # Negated mathematical symbols (preserving the negation semantics) 135 + # Negated symbols mapped to exclamation mark (semantically "not") 136 + for cp in (0x2204, 0x2209, 0x220C, 0x2224, 0x2226, 0x226E, 0x226F, 0x2280, 0x2281, 0x2284, 0x2285): 137 + overrides[cp] = ord('!') # Negated math symbols -> ! (not) 138 + 139 + # Negated symbols mapped to hash sign (semantically "not equal") 140 + for cp in (0x2241, 0x2244, 0x2249, 0x2262, 0x2268, 0x2269, 0x226D, 0x228A, 0x228B): 141 + overrides[cp] = ord('#') # Negated equality symbols -> # (not equal) 142 + 143 + # Negated arrows - all mapped to exclamation mark 144 + for cp in (0x219A, 0x219B, 0x21AE, 0x21CD, 0x21CE, 0x21CF): 145 + overrides[cp] = ord('!') # Negated arrows -> ! (not) 146 + 147 + # Dashes and hyphens 148 + for cp in (0x2010, 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2043, 0x2052): 149 + overrides[cp] = ord('-') # Dashes and hyphens -> - 150 + 151 + # Question mark punctuation 152 + for cp in (0x203D, 0x2047, 0x2048): 153 + overrides[cp] = ord('?') # Question marks -> ? 154 + 155 + # Exclamation mark punctuation 156 + for cp in (0x203C, 0x2049): 157 + overrides[cp] = ord('!') # Exclamation marks -> ! 158 + 159 + # Asterisk-like symbols 160 + for cp in (0x2042, 0x2051, 0x2055): 161 + overrides[cp] = ord('*') 162 + 163 + # Other specific punctuation with unique mappings 164 + overrides[0x201E] = ord('"') # „ DOUBLE LOW-9 QUOTATION MARK 165 + overrides[0x2023] = ord('>') # ‣ TRIANGULAR BULLET 166 + overrides[0x2026] = ord('.') # … HORIZONTAL ELLIPSIS 167 + overrides[0x2033] = ord('"') # ″ DOUBLE PRIME 168 + overrides[0x204B] = ord('P') # ⁋ REVERSED PILCROW SIGN 169 + overrides[0x204C] = ord('<') # ⁌ BLACK LEFTWARDS BULLET 170 + overrides[0x204D] = ord('>') # ⁍ BLACK RIGHTWARDS BULLET 171 + overrides[0x204F] = ord(';') # ⁏ REVERSED SEMICOLON 172 + overrides[0x205B] = ord(':') # ⁛ FOUR DOT MARK 173 + 174 + # Check marks 175 + overrides[0x2713] = ord('v') # ✓ CHECK MARK 176 + overrides[0x2714] = ord('V') # ✔ HEAVY CHECK MARK 177 + 178 + # X marks - lowercase for regular, uppercase for heavy 179 + for cp in (0x2715, 0x2717): 180 + overrides[cp] = ord('x') # Regular X marks -> x 181 + for cp in (0x2716, 0x2718): 182 + overrides[cp] = ord('X') # Heavy X marks -> X 183 + 184 + # Stars and asterisk-like symbols mapped to '*' 185 + for cp in (0x2605, 0x2606, 0x262A, 0x269D, 0x2698): 186 + overrides[cp] = ord('*') # All star and asterisk symbols -> * 187 + for cp in range(0x2721, 0x2746+1): 188 + overrides[cp] = ord('*') # All star and asterisk symbols -> * 189 + for cp in range(0x2749, 0x274B+1): 190 + overrides[cp] = ord('*') # Last set of asterisk symbols -> * 191 + for cp in (0x229B, 0x22C6, 0x235F, 0x2363): 192 + overrides[cp] = ord('*') # Star operators -> * 193 + 194 + # Special exclusions with fallback value of 0 195 + # These will be filtered out in organize_by_pages() 196 + 197 + # Exclude U+2028 (LINE SEPARATOR) 198 + overrides[0x2028] = 0 # LINE SEPARATOR (unidecode: '\n') 199 + 200 + # Full-width to ASCII mapping (covering all printable ASCII 33-126) 201 + # 0xFF01 (!) to 0xFF5E (~) -> ASCII 33 (!) to 126 (~) 202 + # Those are excluded here to reduce the table size. 203 + # It is more efficient to process them programmatically in 204 + # ucs.c:ucs_get_fallback(). 205 + for cp in range(0xFF01, 0xFF5E + 1): 206 + overrides[cp] = 0 # Double-width ASCII characters 207 + 208 + return overrides 209 + 210 + def organize_by_pages(fallback_map): 211 + """Organize the fallback mappings by their high byte (page).""" 212 + # Group by high byte (page) 213 + page_groups = defaultdict(list) 214 + for code, fallback in fallback_map.items(): 215 + # Skip characters with fallback value of 0 (excluded characters) 216 + if fallback == 0: 217 + continue 218 + 219 + page = code >> 8 # Get the high byte (page) 220 + offset = code & 0xFF # Get the low byte (offset within page) 221 + page_groups[page].append((offset, fallback)) 222 + 223 + # Sort each page's entries by offset 224 + for page in page_groups: 225 + page_groups[page].sort() 226 + 227 + return page_groups 228 + 229 + def compress_ranges(page_groups): 230 + """Compress consecutive entries with the same fallback character into ranges. 231 + A range is only compressed if it contains 3 or more consecutive entries.""" 232 + 233 + compressed_pages = {} 234 + 235 + for page, entries in page_groups.items(): 236 + compressed_entries = [] 237 + i = 0 238 + while i < len(entries): 239 + start_offset, fallback = entries[i] 240 + 241 + # Look ahead to find consecutive entries with the same fallback 242 + j = i + 1 243 + while (j < len(entries) and 244 + entries[j][0] == entries[j-1][0] + 1 and # consecutive offsets 245 + entries[j][1] == fallback): # same fallback 246 + j += 1 247 + 248 + # Calculate the range end 249 + end_offset = entries[j-1][0] 250 + 251 + # If we found a range with 3 or more entries (worth compressing) 252 + if j - i >= 3: 253 + # Add a range entry 254 + compressed_entries.append((start_offset, RANGE_MARKER)) 255 + compressed_entries.append((end_offset, fallback)) 256 + else: 257 + # Add the individual entries as is 258 + for k in range(i, j): 259 + compressed_entries.append(entries[k]) 260 + 261 + i = j 262 + 263 + compressed_pages[page] = compressed_entries 264 + 265 + return compressed_pages 266 + 267 + def cp_name(cp): 268 + """Get the Unicode character name for a code point.""" 269 + try: 270 + return unicodedata.name(chr(cp)) 271 + except: 272 + return f"U+{cp:04X}" 273 + 274 + def generate_fallback_tables(out_file=DEFAULT_OUT_FILE): 275 + """Generate the fallback character tables.""" 276 + # Generate fallback map using unidecode 277 + fallback_map = generate_fallback_map() 278 + print(f"Generated {len(fallback_map)} total fallback mappings") 279 + 280 + # Organize by pages 281 + page_groups = organize_by_pages(fallback_map) 282 + print(f"Organized into {len(page_groups)} pages") 283 + 284 + # Compress ranges 285 + compressed_pages = compress_ranges(page_groups) 286 + total_compressed_entries = sum(len(entries) for entries in compressed_pages.values()) 287 + print(f"Total compressed entries: {total_compressed_entries}") 288 + 289 + # Create output file 290 + with open(out_file, 'w') as f: 291 + f.write(f"""\ 292 + /* SPDX-License-Identifier: GPL-2.0 */ 293 + /* 294 + * {out_file} - Unicode character fallback table 295 + * 296 + * Auto-generated by {this_file} 297 + * 298 + * Unicode Version: {unicodedata.unidata_version} 299 + * Unidecode Version: {unidecode_version} 300 + * 301 + * This file contains optimized tables that map complex Unicode characters 302 + * to simpler fallback characters for terminal display when corresponding 303 + * glyphs are unavailable. 304 + */ 305 + 306 + static const struct ucs_page_desc ucs_fallback_pages[] = {{ 307 + """) 308 + 309 + # Convert compressed_pages to a sorted list of (page, entries) tuples 310 + sorted_pages = sorted(compressed_pages.items()) 311 + 312 + # Track the start index for each page 313 + start_index = 0 314 + 315 + # Write page descriptors 316 + for page, entries in sorted_pages: 317 + count = len(entries) 318 + f.write(f"\t{{ 0x{page:02X}, {count}, {start_index} }},\n") 319 + start_index += count 320 + 321 + # Write entries array 322 + f.write("""\ 323 + }; 324 + 325 + /* Page entries array (referenced by page descriptors) */ 326 + static const struct ucs_page_entry ucs_fallback_entries[] = { 327 + """) 328 + 329 + # Write all entries 330 + for page, entries in sorted_pages: 331 + page_hex = f"0x{page:02X}" 332 + f.write(f"\t/* Entries for page {page_hex} */\n") 333 + 334 + for i, (offset, fallback) in enumerate(entries): 335 + # Convert to hex for better readability 336 + offset_hex = f"0x{offset:02X}" 337 + fallback_hex = f"0x{fallback:02X}" 338 + 339 + # Handle comments 340 + codepoint = (page << 8) | offset 341 + 342 + if fallback == RANGE_MARKER: 343 + comment = f"{cp_name(codepoint)} -> ..." 344 + else: 345 + comment = f"{cp_name(codepoint)} -> '{chr(fallback)}'" 346 + f.write(f"\t{{ 0x{offset:02X}, 0x{fallback:02X} }}, /* {comment} */\n") 347 + 348 + f.write(f"""\ 349 + }}; 350 + 351 + #define UCS_PAGE_ENTRY_RANGE_MARKER {RANGE_MARKER} 352 + """) 353 + 354 + if __name__ == "__main__": 355 + parser = argparse.ArgumentParser(description="Generate Unicode fallback character tables") 356 + parser.add_argument("-o", "--output", dest="output_file", default=DEFAULT_OUT_FILE, 357 + help=f"Output file name (default: {DEFAULT_OUT_FILE})") 358 + args = parser.parse_args() 359 + 360 + generate_fallback_tables(out_file=args.output_file)
+257
drivers/tty/vt/gen_ucs_recompose_table.py
··· 1 + #!/usr/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # 4 + # Leverage Python's unicodedata module to generate ucs_recompose_table.h 5 + # 6 + # The generated table maps base character + combining mark pairs to their 7 + # precomposed equivalents. 8 + # 9 + # Usage: 10 + # python3 gen_ucs_recompose_table.py # Generate with common recomposition pairs 11 + # python3 gen_ucs_recompose_table.py --full # Generate with all recomposition pairs 12 + 13 + import unicodedata 14 + import sys 15 + import argparse 16 + import textwrap 17 + 18 + # This script's file name 19 + from pathlib import Path 20 + this_file = Path(__file__).name 21 + 22 + # Default output file name 23 + DEFAULT_OUT_FILE = "ucs_recompose_table.h" 24 + 25 + common_recompose_description = "most commonly used Latin, Greek, and Cyrillic recomposition pairs only" 26 + COMMON_RECOMPOSITION_PAIRS = [ 27 + # Latin letters with accents - uppercase 28 + (0x0041, 0x0300, 0x00C0), # A + COMBINING GRAVE ACCENT = LATIN CAPITAL LETTER A WITH GRAVE 29 + (0x0041, 0x0301, 0x00C1), # A + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER A WITH ACUTE 30 + (0x0041, 0x0302, 0x00C2), # A + COMBINING CIRCUMFLEX ACCENT = LATIN CAPITAL LETTER A WITH CIRCUMFLEX 31 + (0x0041, 0x0303, 0x00C3), # A + COMBINING TILDE = LATIN CAPITAL LETTER A WITH TILDE 32 + (0x0041, 0x0308, 0x00C4), # A + COMBINING DIAERESIS = LATIN CAPITAL LETTER A WITH DIAERESIS 33 + (0x0041, 0x030A, 0x00C5), # A + COMBINING RING ABOVE = LATIN CAPITAL LETTER A WITH RING ABOVE 34 + (0x0043, 0x0327, 0x00C7), # C + COMBINING CEDILLA = LATIN CAPITAL LETTER C WITH CEDILLA 35 + (0x0045, 0x0300, 0x00C8), # E + COMBINING GRAVE ACCENT = LATIN CAPITAL LETTER E WITH GRAVE 36 + (0x0045, 0x0301, 0x00C9), # E + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER E WITH ACUTE 37 + (0x0045, 0x0302, 0x00CA), # E + COMBINING CIRCUMFLEX ACCENT = LATIN CAPITAL LETTER E WITH CIRCUMFLEX 38 + (0x0045, 0x0308, 0x00CB), # E + COMBINING DIAERESIS = LATIN CAPITAL LETTER E WITH DIAERESIS 39 + (0x0049, 0x0300, 0x00CC), # I + COMBINING GRAVE ACCENT = LATIN CAPITAL LETTER I WITH GRAVE 40 + (0x0049, 0x0301, 0x00CD), # I + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER I WITH ACUTE 41 + (0x0049, 0x0302, 0x00CE), # I + COMBINING CIRCUMFLEX ACCENT = LATIN CAPITAL LETTER I WITH CIRCUMFLEX 42 + (0x0049, 0x0308, 0x00CF), # I + COMBINING DIAERESIS = LATIN CAPITAL LETTER I WITH DIAERESIS 43 + (0x004E, 0x0303, 0x00D1), # N + COMBINING TILDE = LATIN CAPITAL LETTER N WITH TILDE 44 + (0x004F, 0x0300, 0x00D2), # O + COMBINING GRAVE ACCENT = LATIN CAPITAL LETTER O WITH GRAVE 45 + (0x004F, 0x0301, 0x00D3), # O + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER O WITH ACUTE 46 + (0x004F, 0x0302, 0x00D4), # O + COMBINING CIRCUMFLEX ACCENT = LATIN CAPITAL LETTER O WITH CIRCUMFLEX 47 + (0x004F, 0x0303, 0x00D5), # O + COMBINING TILDE = LATIN CAPITAL LETTER O WITH TILDE 48 + (0x004F, 0x0308, 0x00D6), # O + COMBINING DIAERESIS = LATIN CAPITAL LETTER O WITH DIAERESIS 49 + (0x0055, 0x0300, 0x00D9), # U + COMBINING GRAVE ACCENT = LATIN CAPITAL LETTER U WITH GRAVE 50 + (0x0055, 0x0301, 0x00DA), # U + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER U WITH ACUTE 51 + (0x0055, 0x0302, 0x00DB), # U + COMBINING CIRCUMFLEX ACCENT = LATIN CAPITAL LETTER U WITH CIRCUMFLEX 52 + (0x0055, 0x0308, 0x00DC), # U + COMBINING DIAERESIS = LATIN CAPITAL LETTER U WITH DIAERESIS 53 + (0x0059, 0x0301, 0x00DD), # Y + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER Y WITH ACUTE 54 + 55 + # Latin letters with accents - lowercase 56 + (0x0061, 0x0300, 0x00E0), # a + COMBINING GRAVE ACCENT = LATIN SMALL LETTER A WITH GRAVE 57 + (0x0061, 0x0301, 0x00E1), # a + COMBINING ACUTE ACCENT = LATIN SMALL LETTER A WITH ACUTE 58 + (0x0061, 0x0302, 0x00E2), # a + COMBINING CIRCUMFLEX ACCENT = LATIN SMALL LETTER A WITH CIRCUMFLEX 59 + (0x0061, 0x0303, 0x00E3), # a + COMBINING TILDE = LATIN SMALL LETTER A WITH TILDE 60 + (0x0061, 0x0308, 0x00E4), # a + COMBINING DIAERESIS = LATIN SMALL LETTER A WITH DIAERESIS 61 + (0x0061, 0x030A, 0x00E5), # a + COMBINING RING ABOVE = LATIN SMALL LETTER A WITH RING ABOVE 62 + (0x0063, 0x0327, 0x00E7), # c + COMBINING CEDILLA = LATIN SMALL LETTER C WITH CEDILLA 63 + (0x0065, 0x0300, 0x00E8), # e + COMBINING GRAVE ACCENT = LATIN SMALL LETTER E WITH GRAVE 64 + (0x0065, 0x0301, 0x00E9), # e + COMBINING ACUTE ACCENT = LATIN SMALL LETTER E WITH ACUTE 65 + (0x0065, 0x0302, 0x00EA), # e + COMBINING CIRCUMFLEX ACCENT = LATIN SMALL LETTER E WITH CIRCUMFLEX 66 + (0x0065, 0x0308, 0x00EB), # e + COMBINING DIAERESIS = LATIN SMALL LETTER E WITH DIAERESIS 67 + (0x0069, 0x0300, 0x00EC), # i + COMBINING GRAVE ACCENT = LATIN SMALL LETTER I WITH GRAVE 68 + (0x0069, 0x0301, 0x00ED), # i + COMBINING ACUTE ACCENT = LATIN SMALL LETTER I WITH ACUTE 69 + (0x0069, 0x0302, 0x00EE), # i + COMBINING CIRCUMFLEX ACCENT = LATIN SMALL LETTER I WITH CIRCUMFLEX 70 + (0x0069, 0x0308, 0x00EF), # i + COMBINING DIAERESIS = LATIN SMALL LETTER I WITH DIAERESIS 71 + (0x006E, 0x0303, 0x00F1), # n + COMBINING TILDE = LATIN SMALL LETTER N WITH TILDE 72 + (0x006F, 0x0300, 0x00F2), # o + COMBINING GRAVE ACCENT = LATIN SMALL LETTER O WITH GRAVE 73 + (0x006F, 0x0301, 0x00F3), # o + COMBINING ACUTE ACCENT = LATIN SMALL LETTER O WITH ACUTE 74 + (0x006F, 0x0302, 0x00F4), # o + COMBINING CIRCUMFLEX ACCENT = LATIN SMALL LETTER O WITH CIRCUMFLEX 75 + (0x006F, 0x0303, 0x00F5), # o + COMBINING TILDE = LATIN SMALL LETTER O WITH TILDE 76 + (0x006F, 0x0308, 0x00F6), # o + COMBINING DIAERESIS = LATIN SMALL LETTER O WITH DIAERESIS 77 + (0x0075, 0x0300, 0x00F9), # u + COMBINING GRAVE ACCENT = LATIN SMALL LETTER U WITH GRAVE 78 + (0x0075, 0x0301, 0x00FA), # u + COMBINING ACUTE ACCENT = LATIN SMALL LETTER U WITH ACUTE 79 + (0x0075, 0x0302, 0x00FB), # u + COMBINING CIRCUMFLEX ACCENT = LATIN SMALL LETTER U WITH CIRCUMFLEX 80 + (0x0075, 0x0308, 0x00FC), # u + COMBINING DIAERESIS = LATIN SMALL LETTER U WITH DIAERESIS 81 + (0x0079, 0x0301, 0x00FD), # y + COMBINING ACUTE ACCENT = LATIN SMALL LETTER Y WITH ACUTE 82 + (0x0079, 0x0308, 0x00FF), # y + COMBINING DIAERESIS = LATIN SMALL LETTER Y WITH DIAERESIS 83 + 84 + # Common Greek characters 85 + (0x0391, 0x0301, 0x0386), # Α + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER ALPHA WITH TONOS 86 + (0x0395, 0x0301, 0x0388), # Ε + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER EPSILON WITH TONOS 87 + (0x0397, 0x0301, 0x0389), # Η + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER ETA WITH TONOS 88 + (0x0399, 0x0301, 0x038A), # Ι + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER IOTA WITH TONOS 89 + (0x039F, 0x0301, 0x038C), # Ο + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER OMICRON WITH TONOS 90 + (0x03A5, 0x0301, 0x038E), # Υ + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER UPSILON WITH TONOS 91 + (0x03A9, 0x0301, 0x038F), # Ω + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER OMEGA WITH TONOS 92 + (0x03B1, 0x0301, 0x03AC), # α + COMBINING ACUTE ACCENT = GREEK SMALL LETTER ALPHA WITH TONOS 93 + (0x03B5, 0x0301, 0x03AD), # ε + COMBINING ACUTE ACCENT = GREEK SMALL LETTER EPSILON WITH TONOS 94 + (0x03B7, 0x0301, 0x03AE), # η + COMBINING ACUTE ACCENT = GREEK SMALL LETTER ETA WITH TONOS 95 + (0x03B9, 0x0301, 0x03AF), # ι + COMBINING ACUTE ACCENT = GREEK SMALL LETTER IOTA WITH TONOS 96 + (0x03BF, 0x0301, 0x03CC), # ο + COMBINING ACUTE ACCENT = GREEK SMALL LETTER OMICRON WITH TONOS 97 + (0x03C5, 0x0301, 0x03CD), # υ + COMBINING ACUTE ACCENT = GREEK SMALL LETTER UPSILON WITH TONOS 98 + (0x03C9, 0x0301, 0x03CE), # ω + COMBINING ACUTE ACCENT = GREEK SMALL LETTER OMEGA WITH TONOS 99 + 100 + # Common Cyrillic characters 101 + (0x0418, 0x0306, 0x0419), # И + COMBINING BREVE = CYRILLIC CAPITAL LETTER SHORT I 102 + (0x0438, 0x0306, 0x0439), # и + COMBINING BREVE = CYRILLIC SMALL LETTER SHORT I 103 + (0x0423, 0x0306, 0x040E), # У + COMBINING BREVE = CYRILLIC CAPITAL LETTER SHORT U 104 + (0x0443, 0x0306, 0x045E), # у + COMBINING BREVE = CYRILLIC SMALL LETTER SHORT U 105 + ] 106 + 107 + full_recompose_description = "all possible recomposition pairs from the Unicode BMP" 108 + def collect_all_recomposition_pairs(): 109 + """Collect all possible recomposition pairs from the Unicode data.""" 110 + # Map to store recomposition pairs: (base, combining) -> recomposed 111 + recompose_map = {} 112 + 113 + # Process all assigned Unicode code points in BMP (Basic Multilingual Plane) 114 + # We limit to BMP (0x0000-0xFFFF) to keep our table smaller with uint16_t 115 + for cp in range(0, 0x10000): 116 + try: 117 + char = chr(cp) 118 + 119 + # Skip unassigned or control characters 120 + if not unicodedata.name(char, ''): 121 + continue 122 + 123 + # Find decomposition 124 + decomp = unicodedata.decomposition(char) 125 + if not decomp or '<' in decomp: # Skip compatibility decompositions 126 + continue 127 + 128 + # Parse the decomposition 129 + parts = decomp.split() 130 + if len(parts) == 2: # Simple base + combining mark 131 + base = int(parts[0], 16) 132 + combining = int(parts[1], 16) 133 + 134 + # Only store if both are in BMP 135 + if base < 0x10000 and combining < 0x10000: 136 + recompose_map[(base, combining)] = cp 137 + 138 + except (ValueError, TypeError): 139 + continue 140 + 141 + # Convert to a list of tuples and sort for binary search 142 + recompose_list = [(base, combining, recomposed) 143 + for (base, combining), recomposed in recompose_map.items()] 144 + recompose_list.sort() 145 + 146 + return recompose_list 147 + 148 + def validate_common_pairs(full_list): 149 + """Validate that all common pairs are in the full list. 150 + 151 + Raises: 152 + ValueError: If any common pair is missing or has a different recomposition 153 + value than what's in the full table. 154 + """ 155 + full_pairs = {(base, combining): recomposed for base, combining, recomposed in full_list} 156 + for base, combining, recomposed in COMMON_RECOMPOSITION_PAIRS: 157 + full_recomposed = full_pairs.get((base, combining)) 158 + if full_recomposed is None: 159 + error_msg = f"Error: Common pair (0x{base:04X}, 0x{combining:04X}) not found in full data" 160 + print(error_msg) 161 + raise ValueError(error_msg) 162 + elif full_recomposed != recomposed: 163 + error_msg = (f"Error: Common pair (0x{base:04X}, 0x{combining:04X}) has different recomposition: " 164 + f"0x{recomposed:04X} vs 0x{full_recomposed:04X}") 165 + print(error_msg) 166 + raise ValueError(error_msg) 167 + 168 + def generate_recomposition_table(use_full_list=False, out_file=DEFAULT_OUT_FILE): 169 + """Generate the recomposition C table.""" 170 + 171 + # Collect all recomposition pairs for validation 172 + full_recompose_list = collect_all_recomposition_pairs() 173 + 174 + # Decide which list to use 175 + if use_full_list: 176 + print("Using full recomposition list...") 177 + recompose_list = full_recompose_list 178 + table_description = full_recompose_description 179 + alt_list = COMMON_RECOMPOSITION_PAIRS 180 + alt_description = common_recompose_description 181 + else: 182 + print("Using common recomposition list...") 183 + # Validate that all common pairs are in the full list 184 + validate_common_pairs(full_recompose_list) 185 + recompose_list = sorted(COMMON_RECOMPOSITION_PAIRS) 186 + table_description = common_recompose_description 187 + alt_list = full_recompose_list 188 + alt_description = full_recompose_description 189 + generation_mode = " --full" if use_full_list else "" 190 + alternative_mode = " --full" if not use_full_list else "" 191 + table_description_detail = f"{table_description} ({len(recompose_list)} entries)" 192 + alt_description_detail = f"{alt_description} ({len(alt_list)} entries)" 193 + 194 + # Calculate min/max values for boundary checks 195 + min_base = min(base for base, _, _ in recompose_list) 196 + max_base = max(base for base, _, _ in recompose_list) 197 + min_combining = min(combining for _, combining, _ in recompose_list) 198 + max_combining = max(combining for _, combining, _ in recompose_list) 199 + 200 + # Generate implementation file 201 + with open(out_file, 'w') as f: 202 + f.write(f"""\ 203 + /* SPDX-License-Identifier: GPL-2.0 */ 204 + /* 205 + * {out_file} - Unicode character recomposition 206 + * 207 + * Auto-generated by {this_file}{generation_mode} 208 + * 209 + * Unicode Version: {unicodedata.unidata_version} 210 + * 211 + {textwrap.fill( 212 + f"This file contains a table with {table_description_detail}. " + 213 + f"To generate a table with {alt_description_detail} instead, run:", 214 + width=75, initial_indent=" * ", subsequent_indent=" * ")} 215 + * 216 + * python3 {this_file}{alternative_mode} 217 + */ 218 + 219 + /* 220 + * Table of {table_description} 221 + * Sorted by base character and then combining mark for binary search 222 + */ 223 + static const struct ucs_recomposition ucs_recomposition_table[] = {{ 224 + """) 225 + 226 + for base, combining, recomposed in recompose_list: 227 + try: 228 + base_name = unicodedata.name(chr(base)) 229 + combining_name = unicodedata.name(chr(combining)) 230 + recomposed_name = unicodedata.name(chr(recomposed)) 231 + comment = f"/* {base_name} + {combining_name} = {recomposed_name} */" 232 + except ValueError: 233 + comment = f"/* U+{base:04X} + U+{combining:04X} = U+{recomposed:04X} */" 234 + f.write(f"\t{{ 0x{base:04X}, 0x{combining:04X}, 0x{recomposed:04X} }}, {comment}\n") 235 + 236 + f.write(f"""\ 237 + }}; 238 + 239 + /* 240 + * Boundary values for quick rejection 241 + * These are calculated by analyzing the table during generation 242 + */ 243 + #define UCS_RECOMPOSE_MIN_BASE 0x{min_base:04X} 244 + #define UCS_RECOMPOSE_MAX_BASE 0x{max_base:04X} 245 + #define UCS_RECOMPOSE_MIN_MARK 0x{min_combining:04X} 246 + #define UCS_RECOMPOSE_MAX_MARK 0x{max_combining:04X} 247 + """) 248 + 249 + if __name__ == "__main__": 250 + parser = argparse.ArgumentParser(description="Generate Unicode recomposition table") 251 + parser.add_argument("--full", action="store_true", 252 + help="Generate a full recomposition table (default: common pairs only)") 253 + parser.add_argument("-o", "--output", dest="output_file", default=DEFAULT_OUT_FILE, 254 + help=f"Output file name (default: {DEFAULT_OUT_FILE})") 255 + args = parser.parse_args() 256 + 257 + generate_recomposition_table(use_full_list=args.full, out_file=args.output_file)
+307
drivers/tty/vt/gen_ucs_width_table.py
··· 1 + #!/usr/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # 4 + # Leverage Python's unicodedata module to generate ucs_width_table.h 5 + 6 + import unicodedata 7 + import sys 8 + import argparse 9 + 10 + # This script's file name 11 + from pathlib import Path 12 + this_file = Path(__file__).name 13 + 14 + # Default output file name 15 + DEFAULT_OUT_FILE = "ucs_width_table.h" 16 + 17 + # --- Global Constants for Width Assignments --- 18 + 19 + # Known zero-width characters 20 + KNOWN_ZERO_WIDTH = ( 21 + 0x200B, # ZERO WIDTH SPACE 22 + 0x200C, # ZERO WIDTH NON-JOINER 23 + 0x200D, # ZERO WIDTH JOINER 24 + 0x2060, # WORD JOINER 25 + 0xFEFF # ZERO WIDTH NO-BREAK SPACE (BOM) 26 + ) 27 + 28 + # Zero-width emoji modifiers and components 29 + # NOTE: Some of these characters would normally be single-width according to 30 + # East Asian Width properties, but we deliberately override them to be 31 + # zero-width because they function as modifiers in emoji sequences. 32 + EMOJI_ZERO_WIDTH = [ 33 + # Skin tone modifiers 34 + (0x1F3FB, 0x1F3FF), # Emoji modifiers (skin tones) 35 + 36 + # Variation selectors (note: VS16 is treated specially in vt.c) 37 + (0xFE00, 0xFE0F), # Variation Selectors 1-16 38 + 39 + # Gender and hair style modifiers 40 + # These would be single-width by Unicode properties, but are zero-width 41 + # when part of emoji 42 + (0x2640, 0x2640), # Female sign 43 + (0x2642, 0x2642), # Male sign 44 + (0x26A7, 0x26A7), # Transgender symbol 45 + (0x1F9B0, 0x1F9B3), # Hair components (red, curly, white, bald) 46 + 47 + # Tag characters 48 + (0xE0020, 0xE007E), # Tags 49 + ] 50 + 51 + # Regional indicators (flag components) 52 + REGIONAL_INDICATORS = (0x1F1E6, 0x1F1FF) # Regional indicator symbols A-Z 53 + 54 + # Double-width emoji ranges 55 + # 56 + # Many emoji characters are classified as single-width according to Unicode 57 + # Standard Annex #11 East Asian Width property (N or Neutral), but we 58 + # deliberately override them to be double-width. References: 59 + # 1. Unicode Technical Standard #51: Unicode Emoji 60 + # (https://www.unicode.org/reports/tr51/) 61 + # 2. Principle of "emoji presentation" in WHATWG CSS Text specification 62 + # (https://drafts.csswg.org/css-text-3/#character-properties) 63 + # 3. Terminal emulator implementations (iTerm2, Windows Terminal, etc.) which 64 + # universally render emoji as double-width characters regardless of their 65 + # Unicode EAW property 66 + # 4. W3C Work Item: Requirements for Japanese Text Layout - Section 3.8.1 67 + # Emoji width (https://www.w3.org/TR/jlreq/) 68 + EMOJI_RANGES = [ 69 + (0x1F000, 0x1F02F), # Mahjong Tiles (EAW: N, but displayed as double-width) 70 + (0x1F0A0, 0x1F0FF), # Playing Cards (EAW: N, but displayed as double-width) 71 + (0x1F300, 0x1F5FF), # Miscellaneous Symbols and Pictographs 72 + (0x1F600, 0x1F64F), # Emoticons 73 + (0x1F680, 0x1F6FF), # Transport and Map Symbols 74 + (0x1F700, 0x1F77F), # Alchemical Symbols 75 + (0x1F780, 0x1F7FF), # Geometric Shapes Extended 76 + (0x1F800, 0x1F8FF), # Supplemental Arrows-C 77 + (0x1F900, 0x1F9FF), # Supplemental Symbols and Pictographs 78 + (0x1FA00, 0x1FA6F), # Chess Symbols 79 + (0x1FA70, 0x1FAFF), # Symbols and Pictographs Extended-A 80 + ] 81 + 82 + def create_width_tables(): 83 + """ 84 + Creates Unicode character width tables and returns the data structures. 85 + 86 + Returns: 87 + tuple: (zero_width_ranges, double_width_ranges) 88 + """ 89 + 90 + # Width data mapping 91 + width_map = {} # Maps code points to width (0, 1, 2) 92 + 93 + # Mark emoji modifiers as zero-width 94 + for start, end in EMOJI_ZERO_WIDTH: 95 + for cp in range(start, end + 1): 96 + width_map[cp] = 0 97 + 98 + # Mark all regional indicators as single-width as they are usually paired 99 + # providing a combined width of 2 when displayed together. 100 + start, end = REGIONAL_INDICATORS 101 + for cp in range(start, end + 1): 102 + width_map[cp] = 1 103 + 104 + # Process all assigned Unicode code points (Basic Multilingual Plane + 105 + # Supplementary Planes) Range 0x0 to 0x10FFFF (the full Unicode range) 106 + for block_start in range(0, 0x110000, 0x1000): 107 + block_end = block_start + 0x1000 108 + for cp in range(block_start, block_end): 109 + try: 110 + char = chr(cp) 111 + 112 + # Skip if already processed 113 + if cp in width_map: 114 + continue 115 + 116 + # Check for combining marks and a format characters 117 + category = unicodedata.category(char) 118 + 119 + # Combining marks 120 + if category.startswith('M'): 121 + width_map[cp] = 0 122 + continue 123 + 124 + # Format characters 125 + # Since we have no support for bidirectional text, all format 126 + # characters (category Cf) can be treated with width 0 (zero) 127 + # for simplicity, as they don't need to occupy visual space 128 + # in a non-bidirectional text environment. 129 + if category == 'Cf': 130 + width_map[cp] = 0 131 + continue 132 + 133 + # Known zero-width characters 134 + if cp in KNOWN_ZERO_WIDTH: 135 + width_map[cp] = 0 136 + continue 137 + 138 + # Use East Asian Width property 139 + eaw = unicodedata.east_asian_width(char) 140 + if eaw in ('F', 'W'): # Fullwidth or Wide 141 + width_map[cp] = 2 142 + elif eaw in ('Na', 'H', 'N', 'A'): # Narrow, Halfwidth, Neutral, Ambiguous 143 + width_map[cp] = 1 144 + else: 145 + # Default to single-width for unknown 146 + width_map[cp] = 1 147 + 148 + except (ValueError, OverflowError): 149 + # Skip invalid code points 150 + continue 151 + 152 + # Process Emoji - generally double-width 153 + for start, end in EMOJI_RANGES: 154 + for cp in range(start, end + 1): 155 + if cp not in width_map or width_map[cp] != 0: # Don't override zero-width 156 + try: 157 + char = chr(cp) 158 + width_map[cp] = 2 159 + except (ValueError, OverflowError): 160 + continue 161 + 162 + # Optimize to create range tables 163 + def ranges_optimize(width_data, target_width): 164 + points = sorted([cp for cp, width in width_data.items() if width == target_width]) 165 + if not points: 166 + return [] 167 + 168 + # Group consecutive code points into ranges 169 + ranges = [] 170 + start = points[0] 171 + prev = start 172 + 173 + for cp in points[1:]: 174 + if cp > prev + 1: 175 + ranges.append((start, prev)) 176 + start = cp 177 + prev = cp 178 + 179 + # Add the last range 180 + ranges.append((start, prev)) 181 + return ranges 182 + 183 + # Extract ranges for each width 184 + zero_width_ranges = ranges_optimize(width_map, 0) 185 + double_width_ranges = ranges_optimize(width_map, 2) 186 + 187 + return zero_width_ranges, double_width_ranges 188 + 189 + def write_tables(zero_width_ranges, double_width_ranges, out_file=DEFAULT_OUT_FILE): 190 + """ 191 + Write the generated tables to C header file. 192 + 193 + Args: 194 + zero_width_ranges: List of (start, end) ranges for zero-width characters 195 + double_width_ranges: List of (start, end) ranges for double-width characters 196 + out_file: Output file name (default: DEFAULT_OUT_FILE) 197 + """ 198 + 199 + # Function to split ranges into BMP (16-bit) and non-BMP (above 16-bit) 200 + def split_ranges_by_size(ranges): 201 + bmp_ranges = [] 202 + non_bmp_ranges = [] 203 + 204 + for start, end in ranges: 205 + if end <= 0xFFFF: 206 + bmp_ranges.append((start, end)) 207 + elif start > 0xFFFF: 208 + non_bmp_ranges.append((start, end)) 209 + else: 210 + # Split the range at 0xFFFF 211 + bmp_ranges.append((start, 0xFFFF)) 212 + non_bmp_ranges.append((0x10000, end)) 213 + 214 + return bmp_ranges, non_bmp_ranges 215 + 216 + # Split ranges into BMP and non-BMP 217 + zero_width_bmp, zero_width_non_bmp = split_ranges_by_size(zero_width_ranges) 218 + double_width_bmp, double_width_non_bmp = split_ranges_by_size(double_width_ranges) 219 + 220 + # Function to generate code point description comments 221 + def get_code_point_comment(start, end): 222 + try: 223 + start_char_desc = unicodedata.name(chr(start)) 224 + if start == end: 225 + return f"/* {start_char_desc} */" 226 + else: 227 + end_char_desc = unicodedata.name(chr(end)) 228 + return f"/* {start_char_desc} - {end_char_desc} */" 229 + except: 230 + if start == end: 231 + return f"/* U+{start:04X} */" 232 + else: 233 + return f"/* U+{start:04X} - U+{end:04X} */" 234 + 235 + # Generate C tables 236 + with open(out_file, 'w') as f: 237 + f.write(f"""\ 238 + /* SPDX-License-Identifier: GPL-2.0 */ 239 + /* 240 + * {out_file} - Unicode character width 241 + * 242 + * Auto-generated by {this_file} 243 + * 244 + * Unicode Version: {unicodedata.unidata_version} 245 + */ 246 + 247 + /* Zero-width character ranges (BMP - Basic Multilingual Plane, U+0000 to U+FFFF) */ 248 + static const struct ucs_interval16 ucs_zero_width_bmp_ranges[] = {{ 249 + """) 250 + 251 + for start, end in zero_width_bmp: 252 + comment = get_code_point_comment(start, end) 253 + f.write(f"\t{{ 0x{start:04X}, 0x{end:04X} }}, {comment}\n") 254 + 255 + f.write("""\ 256 + }; 257 + 258 + /* Zero-width character ranges (non-BMP, U+10000 and above) */ 259 + static const struct ucs_interval32 ucs_zero_width_non_bmp_ranges[] = { 260 + """) 261 + 262 + for start, end in zero_width_non_bmp: 263 + comment = get_code_point_comment(start, end) 264 + f.write(f"\t{{ 0x{start:05X}, 0x{end:05X} }}, {comment}\n") 265 + 266 + f.write("""\ 267 + }; 268 + 269 + /* Double-width character ranges (BMP - Basic Multilingual Plane, U+0000 to U+FFFF) */ 270 + static const struct ucs_interval16 ucs_double_width_bmp_ranges[] = { 271 + """) 272 + 273 + for start, end in double_width_bmp: 274 + comment = get_code_point_comment(start, end) 275 + f.write(f"\t{{ 0x{start:04X}, 0x{end:04X} }}, {comment}\n") 276 + 277 + f.write("""\ 278 + }; 279 + 280 + /* Double-width character ranges (non-BMP, U+10000 and above) */ 281 + static const struct ucs_interval32 ucs_double_width_non_bmp_ranges[] = { 282 + """) 283 + 284 + for start, end in double_width_non_bmp: 285 + comment = get_code_point_comment(start, end) 286 + f.write(f"\t{{ 0x{start:05X}, 0x{end:05X} }}, {comment}\n") 287 + 288 + f.write("};\n") 289 + 290 + if __name__ == "__main__": 291 + # Parse command line arguments 292 + parser = argparse.ArgumentParser(description="Generate Unicode width tables") 293 + parser.add_argument("-o", "--output", dest="output_file", default=DEFAULT_OUT_FILE, 294 + help=f"Output file name (default: {DEFAULT_OUT_FILE})") 295 + args = parser.parse_args() 296 + 297 + # Write tables to header file 298 + zero_width_ranges, double_width_ranges = create_width_tables() 299 + write_tables(zero_width_ranges, double_width_ranges, out_file=args.output_file) 300 + 301 + # Print summary 302 + zero_width_count = sum(end - start + 1 for start, end in zero_width_ranges) 303 + double_width_count = sum(end - start + 1 for start, end in double_width_ranges) 304 + print(f"Generated {args.output_file} with:") 305 + print(f"- {len(zero_width_ranges)} zero-width ranges covering ~{zero_width_count} code points") 306 + print(f"- {len(double_width_ranges)} double-width ranges covering ~{double_width_count} code points") 307 + print(f"- Unicode Version: {unicodedata.unidata_version}")
+15 -22
drivers/tty/vt/keyboard.c
··· 376 376 } 377 377 } 378 378 379 + static void put_queue_utf8(struct vc_data *vc, u32 value) 380 + { 381 + if (kbd->kbdmode == VC_UNICODE) 382 + to_utf8(vc, value); 383 + else { 384 + int c = conv_uni_to_8bit(value); 385 + if (c != -1) 386 + put_queue(vc, c); 387 + } 388 + } 389 + 379 390 /* FIXME: review locking for vt.c callers */ 380 391 static void set_leds(void) 381 392 { ··· 465 454 if (ch == ' ' || ch == (BRL_UC_ROW|0) || ch == d) 466 455 return d; 467 456 468 - if (kbd->kbdmode == VC_UNICODE) 469 - to_utf8(vc, d); 470 - else { 471 - int c = conv_uni_to_8bit(d); 472 - if (c != -1) 473 - put_queue(vc, c); 474 - } 457 + put_queue_utf8(vc, d); 475 458 476 459 return ch; 477 460 } ··· 476 471 static void fn_enter(struct vc_data *vc) 477 472 { 478 473 if (diacr) { 479 - if (kbd->kbdmode == VC_UNICODE) 480 - to_utf8(vc, diacr); 481 - else { 482 - int c = conv_uni_to_8bit(diacr); 483 - if (c != -1) 484 - put_queue(vc, c); 485 - } 474 + put_queue_utf8(vc, diacr); 486 475 diacr = 0; 487 476 } 488 477 ··· 684 685 diacr = value; 685 686 return; 686 687 } 687 - if (kbd->kbdmode == VC_UNICODE) 688 - to_utf8(vc, value); 689 - else { 690 - int c = conv_uni_to_8bit(value); 691 - if (c != -1) 692 - put_queue(vc, c); 693 - } 688 + put_queue_utf8(vc, value); 694 689 } 695 690 696 691 /* ··· 1512 1519 if ((raw_mode || kbd->kbdmode == VC_OFF) && type != KT_SPEC && type != KT_SHIFT) 1513 1520 return; 1514 1521 1515 - (*k_handler[type])(vc, keysym & 0xff, !down); 1522 + (*k_handler[type])(vc, KVAL(keysym), !down); 1516 1523 1517 1524 param.ledstate = kbd->ledflagstate; 1518 1525 atomic_notifier_call_chain(&keyboard_notifier_list, KBD_POST_KEYSYM, &param);
+27 -4
drivers/tty/vt/selection.c
··· 403 403 DECLARE_WAITQUEUE(wait, current); 404 404 int ret = 0; 405 405 406 + bool bp = vc->vc_bracketed_paste; 407 + static const char bracketed_paste_start[] = "\033[200~"; 408 + static const char bracketed_paste_end[] = "\033[201~"; 409 + const char *bps = bp ? bracketed_paste_start : NULL; 410 + const char *bpe = bp ? bracketed_paste_end : NULL; 411 + 406 412 console_lock(); 407 413 poke_blanked_console(); 408 414 console_unlock(); ··· 420 414 421 415 add_wait_queue(&vc->paste_wait, &wait); 422 416 mutex_lock(&vc_sel.lock); 423 - while (vc_sel.buffer && vc_sel.buf_len > pasted) { 417 + while (vc_sel.buffer && (vc_sel.buf_len > pasted || bpe)) { 424 418 set_current_state(TASK_INTERRUPTIBLE); 425 419 if (signal_pending(current)) { 426 420 ret = -EINTR; ··· 433 427 continue; 434 428 } 435 429 __set_current_state(TASK_RUNNING); 430 + 431 + if (bps) { 432 + bps += tty_ldisc_receive_buf(ld, bps, NULL, strlen(bps)); 433 + if (*bps != '\0') 434 + continue; 435 + bps = NULL; 436 + } 437 + 436 438 count = vc_sel.buf_len - pasted; 437 - count = tty_ldisc_receive_buf(ld, vc_sel.buffer + pasted, NULL, 438 - count); 439 - pasted += count; 439 + if (count) { 440 + pasted += tty_ldisc_receive_buf(ld, vc_sel.buffer + pasted, 441 + NULL, count); 442 + if (vc_sel.buf_len > pasted) 443 + continue; 444 + } 445 + 446 + if (bpe) { 447 + bpe += tty_ldisc_receive_buf(ld, bpe, NULL, strlen(bpe)); 448 + if (*bpe == '\0') 449 + bpe = NULL; 450 + } 440 451 } 441 452 mutex_unlock(&vc_sel.lock); 442 453 remove_wait_queue(&vc->paste_wait, &wait);
+251
drivers/tty/vt/ucs.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * ucs.c - Universal Character Set processing 4 + */ 5 + 6 + #include <linux/array_size.h> 7 + #include <linux/bsearch.h> 8 + #include <linux/consolemap.h> 9 + #include <linux/minmax.h> 10 + 11 + struct ucs_interval16 { 12 + u16 first; 13 + u16 last; 14 + }; 15 + 16 + struct ucs_interval32 { 17 + u32 first; 18 + u32 last; 19 + }; 20 + 21 + #include "ucs_width_table.h" 22 + 23 + static int interval16_cmp(const void *key, const void *element) 24 + { 25 + u16 cp = *(u16 *)key; 26 + const struct ucs_interval16 *entry = element; 27 + 28 + if (cp < entry->first) 29 + return -1; 30 + if (cp > entry->last) 31 + return 1; 32 + return 0; 33 + } 34 + 35 + static int interval32_cmp(const void *key, const void *element) 36 + { 37 + u32 cp = *(u32 *)key; 38 + const struct ucs_interval32 *entry = element; 39 + 40 + if (cp < entry->first) 41 + return -1; 42 + if (cp > entry->last) 43 + return 1; 44 + return 0; 45 + } 46 + 47 + static bool cp_in_range16(u16 cp, const struct ucs_interval16 *ranges, size_t size) 48 + { 49 + if (cp < ranges[0].first || cp > ranges[size - 1].last) 50 + return false; 51 + 52 + return __inline_bsearch(&cp, ranges, size, sizeof(*ranges), 53 + interval16_cmp) != NULL; 54 + } 55 + 56 + static bool cp_in_range32(u32 cp, const struct ucs_interval32 *ranges, size_t size) 57 + { 58 + if (cp < ranges[0].first || cp > ranges[size - 1].last) 59 + return false; 60 + 61 + return __inline_bsearch(&cp, ranges, size, sizeof(*ranges), 62 + interval32_cmp) != NULL; 63 + } 64 + 65 + #define UCS_IS_BMP(cp) ((cp) <= 0xffff) 66 + 67 + /** 68 + * ucs_is_zero_width() - Determine if a Unicode code point is zero-width. 69 + * @cp: Unicode code point (UCS-4) 70 + * 71 + * Return: true if the character is zero-width, false otherwise 72 + */ 73 + bool ucs_is_zero_width(u32 cp) 74 + { 75 + if (UCS_IS_BMP(cp)) 76 + return cp_in_range16(cp, ucs_zero_width_bmp_ranges, 77 + ARRAY_SIZE(ucs_zero_width_bmp_ranges)); 78 + else 79 + return cp_in_range32(cp, ucs_zero_width_non_bmp_ranges, 80 + ARRAY_SIZE(ucs_zero_width_non_bmp_ranges)); 81 + } 82 + 83 + /** 84 + * ucs_is_double_width() - Determine if a Unicode code point is double-width. 85 + * @cp: Unicode code point (UCS-4) 86 + * 87 + * Return: true if the character is double-width, false otherwise 88 + */ 89 + bool ucs_is_double_width(u32 cp) 90 + { 91 + if (UCS_IS_BMP(cp)) 92 + return cp_in_range16(cp, ucs_double_width_bmp_ranges, 93 + ARRAY_SIZE(ucs_double_width_bmp_ranges)); 94 + else 95 + return cp_in_range32(cp, ucs_double_width_non_bmp_ranges, 96 + ARRAY_SIZE(ucs_double_width_non_bmp_ranges)); 97 + } 98 + 99 + /* 100 + * Structure for base with combining mark pairs and resulting recompositions. 101 + * Using u16 to save space since all values are within BMP range. 102 + */ 103 + struct ucs_recomposition { 104 + u16 base; /* base character */ 105 + u16 mark; /* combining mark */ 106 + u16 recomposed; /* corresponding recomposed character */ 107 + }; 108 + 109 + #include "ucs_recompose_table.h" 110 + 111 + struct compare_key { 112 + u16 base; 113 + u16 mark; 114 + }; 115 + 116 + static int recomposition_cmp(const void *key, const void *element) 117 + { 118 + const struct compare_key *search_key = key; 119 + const struct ucs_recomposition *entry = element; 120 + 121 + /* Compare base character first */ 122 + if (search_key->base < entry->base) 123 + return -1; 124 + if (search_key->base > entry->base) 125 + return 1; 126 + 127 + /* Base characters match, now compare combining character */ 128 + if (search_key->mark < entry->mark) 129 + return -1; 130 + if (search_key->mark > entry->mark) 131 + return 1; 132 + 133 + /* Both match */ 134 + return 0; 135 + } 136 + 137 + /** 138 + * ucs_recompose() - Attempt to recompose two Unicode characters into a single character. 139 + * @base: Base Unicode code point (UCS-4) 140 + * @mark: Combining mark Unicode code point (UCS-4) 141 + * 142 + * Return: Recomposed Unicode code point, or 0 if no recomposition is possible 143 + */ 144 + u32 ucs_recompose(u32 base, u32 mark) 145 + { 146 + /* Check if characters are within the range of our table */ 147 + if (base < UCS_RECOMPOSE_MIN_BASE || base > UCS_RECOMPOSE_MAX_BASE || 148 + mark < UCS_RECOMPOSE_MIN_MARK || mark > UCS_RECOMPOSE_MAX_MARK) 149 + return 0; 150 + 151 + struct compare_key key = { base, mark }; 152 + struct ucs_recomposition *result = 153 + __inline_bsearch(&key, ucs_recomposition_table, 154 + ARRAY_SIZE(ucs_recomposition_table), 155 + sizeof(*ucs_recomposition_table), 156 + recomposition_cmp); 157 + 158 + return result ? result->recomposed : 0; 159 + } 160 + 161 + /* 162 + * The fallback table structures implement a 2-level lookup. 163 + */ 164 + 165 + struct ucs_page_desc { 166 + u8 page; /* Page index (high byte of code points) */ 167 + u8 count; /* Number of entries in this page */ 168 + u16 start; /* Start index in entries array */ 169 + }; 170 + 171 + struct ucs_page_entry { 172 + u8 offset; /* Offset within page (0-255) */ 173 + u8 fallback; /* Fallback character or range start marker */ 174 + }; 175 + 176 + #include "ucs_fallback_table.h" 177 + 178 + static int ucs_page_desc_cmp(const void *key, const void *element) 179 + { 180 + u8 page = *(u8 *)key; 181 + const struct ucs_page_desc *entry = element; 182 + 183 + if (page < entry->page) 184 + return -1; 185 + if (page > entry->page) 186 + return 1; 187 + return 0; 188 + } 189 + 190 + static int ucs_page_entry_cmp(const void *key, const void *element) 191 + { 192 + u8 offset = *(u8 *)key; 193 + const struct ucs_page_entry *entry = element; 194 + 195 + if (offset < entry->offset) 196 + return -1; 197 + if (entry->fallback == UCS_PAGE_ENTRY_RANGE_MARKER) { 198 + if (offset > entry[1].offset) 199 + return 1; 200 + } else { 201 + if (offset > entry->offset) 202 + return 1; 203 + } 204 + return 0; 205 + } 206 + 207 + /** 208 + * ucs_get_fallback() - Get a substitution for the provided Unicode character 209 + * @base: Base Unicode code point (UCS-4) 210 + * 211 + * Get a simpler fallback character for the provided Unicode character. 212 + * This is used for terminal display when corresponding glyph is unavailable. 213 + * The substitution may not be as good as the actual glyph for the original 214 + * character but still way more helpful than a squared question mark. 215 + * 216 + * Return: Fallback Unicode code point, or 0 if none is available 217 + */ 218 + u32 ucs_get_fallback(u32 cp) 219 + { 220 + const struct ucs_page_desc *page; 221 + const struct ucs_page_entry *entry; 222 + u8 page_idx = cp >> 8, offset = cp; 223 + 224 + if (!UCS_IS_BMP(cp)) 225 + return 0; 226 + 227 + /* 228 + * Full-width to ASCII mapping (covering all printable ASCII 33-126) 229 + * 0xFF01 (!) to 0xFF5E (~) -> ASCII 33 (!) to 126 (~) 230 + * We process them programmatically to reduce the table size. 231 + */ 232 + if (cp >= 0xFF01 && cp <= 0xFF5E) 233 + return cp - 0xFF01 + 33; 234 + 235 + page = __inline_bsearch(&page_idx, ucs_fallback_pages, 236 + ARRAY_SIZE(ucs_fallback_pages), 237 + sizeof(*ucs_fallback_pages), 238 + ucs_page_desc_cmp); 239 + if (!page) 240 + return 0; 241 + 242 + entry = __inline_bsearch(&offset, ucs_fallback_entries + page->start, 243 + page->count, sizeof(*ucs_fallback_entries), 244 + ucs_page_entry_cmp); 245 + if (!entry) 246 + return 0; 247 + 248 + if (entry->fallback == UCS_PAGE_ENTRY_RANGE_MARKER) 249 + entry++; 250 + return entry->fallback; 251 + }
+3346
drivers/tty/vt/ucs_fallback_table.h_shipped
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * ucs_fallback_table.h - Unicode character fallback table 4 + * 5 + * Auto-generated by gen_ucs_fallback_table.py 6 + * 7 + * Unicode Version: 16.0.0 8 + * Unidecode Version: 1.3.8 9 + * 10 + * This file contains optimized tables that map complex Unicode characters 11 + * to simpler fallback characters for terminal display when corresponding 12 + * glyphs are unavailable. 13 + */ 14 + 15 + static const struct ucs_page_desc ucs_fallback_pages[] = { 16 + { 0x00, 62, 0 }, 17 + { 0x01, 218, 62 }, 18 + { 0x02, 196, 280 }, 19 + { 0x03, 96, 476 }, 20 + { 0x04, 113, 572 }, 21 + { 0x05, 100, 685 }, 22 + { 0x06, 119, 785 }, 23 + { 0x07, 91, 904 }, 24 + { 0x09, 99, 995 }, 25 + { 0x0A, 78, 1094 }, 26 + { 0x0B, 79, 1172 }, 27 + { 0x0C, 85, 1251 }, 28 + { 0x0D, 73, 1336 }, 29 + { 0x0E, 83, 1409 }, 30 + { 0x0F, 69, 1492 }, 31 + { 0x10, 93, 1561 }, 32 + { 0x11, 51, 1654 }, 33 + { 0x13, 22, 1705 }, 34 + { 0x14, 30, 1727 }, 35 + { 0x15, 17, 1757 }, 36 + { 0x16, 81, 1774 }, 37 + { 0x17, 47, 1855 }, 38 + { 0x18, 96, 1902 }, 39 + { 0x1D, 105, 1998 }, 40 + { 0x1E, 246, 2103 }, 41 + { 0x1F, 94, 2349 }, 42 + { 0x20, 107, 2443 }, 43 + { 0x21, 136, 2550 }, 44 + { 0x22, 34, 2686 }, 45 + { 0x23, 4, 2720 }, 46 + { 0x24, 72, 2724 }, 47 + { 0x25, 60, 2796 }, 48 + { 0x26, 6, 2856 }, 49 + { 0x27, 18, 2862 }, 50 + { 0x28, 64, 2880 }, 51 + { 0x29, 1, 2944 }, 52 + { 0x2C, 15, 2945 }, 53 + { 0x2E, 29, 2960 }, 54 + { 0x30, 53, 2989 }, 55 + { 0x31, 50, 3042 }, 56 + { 0x32, 5, 3092 }, 57 + { 0xA0, 4, 3097 }, 58 + { 0xC5, 2, 3101 }, 59 + { 0xC6, 2, 3103 }, 60 + { 0xC7, 1, 3105 }, 61 + { 0xFB, 35, 3106 }, 62 + { 0xFE, 37, 3141 }, 63 + { 0xFF, 50, 3178 }, 64 + }; 65 + 66 + /* Page entries array (referenced by page descriptors) */ 67 + static const struct ucs_page_entry ucs_fallback_entries[] = { 68 + /* Entries for page 0x00 */ 69 + { 0xA0, 0x20 }, /* NO-BREAK SPACE -> ' ' */ 70 + { 0xA1, 0x21 }, /* INVERTED EXCLAMATION MARK -> '!' */ 71 + { 0xA2, 0x63 }, /* CENT SIGN -> 'c' */ 72 + { 0xA3, 0x4C }, /* POUND SIGN -> 'L' */ 73 + { 0xA5, 0x59 }, /* YEN SIGN -> 'Y' */ 74 + { 0xA6, 0x7C }, /* BROKEN BAR -> '|' */ 75 + { 0xA7, 0x53 }, /* SECTION SIGN -> 'S' */ 76 + { 0xA8, 0x22 }, /* DIAERESIS -> '"' */ 77 + { 0xA9, 0x43 }, /* COPYRIGHT SIGN -> 'C' */ 78 + { 0xAA, 0x61 }, /* FEMININE ORDINAL INDICATOR -> 'a' */ 79 + { 0xAB, 0x3C }, /* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK -> '<' */ 80 + { 0xAC, 0x21 }, /* NOT SIGN -> '!' */ 81 + { 0xAE, 0x52 }, /* REGISTERED SIGN -> 'R' */ 82 + { 0xAF, 0x2D }, /* MACRON -> '-' */ 83 + { 0xB0, 0x6F }, /* DEGREE SIGN -> 'o' */ 84 + { 0xB2, 0x32 }, /* SUPERSCRIPT TWO -> '2' */ 85 + { 0xB3, 0x33 }, /* SUPERSCRIPT THREE -> '3' */ 86 + { 0xB4, 0x27 }, /* ACUTE ACCENT -> ''' */ 87 + { 0xB5, 0x75 }, /* MICRO SIGN -> 'u' */ 88 + { 0xB6, 0x50 }, /* PILCROW SIGN -> 'P' */ 89 + { 0xB7, 0x2A }, /* MIDDLE DOT -> '*' */ 90 + { 0xB8, 0x2C }, /* CEDILLA -> ',' */ 91 + { 0xB9, 0x31 }, /* SUPERSCRIPT ONE -> '1' */ 92 + { 0xBA, 0x6F }, /* MASCULINE ORDINAL INDICATOR -> 'o' */ 93 + { 0xBB, 0x3E }, /* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK -> '>' */ 94 + { 0xBF, 0x3F }, /* INVERTED QUESTION MARK -> '?' */ 95 + { 0xC0, 0x00 }, /* LATIN CAPITAL LETTER A WITH GRAVE -> ... */ 96 + { 0xC5, 0x41 }, /* LATIN CAPITAL LETTER A WITH RING ABOVE -> 'A' */ 97 + { 0xC6, 0x45 }, /* LATIN CAPITAL LETTER AE -> 'E' */ 98 + { 0xC7, 0x43 }, /* LATIN CAPITAL LETTER C WITH CEDILLA -> 'C' */ 99 + { 0xC8, 0x00 }, /* LATIN CAPITAL LETTER E WITH GRAVE -> ... */ 100 + { 0xCB, 0x45 }, /* LATIN CAPITAL LETTER E WITH DIAERESIS -> 'E' */ 101 + { 0xCC, 0x00 }, /* LATIN CAPITAL LETTER I WITH GRAVE -> ... */ 102 + { 0xCF, 0x49 }, /* LATIN CAPITAL LETTER I WITH DIAERESIS -> 'I' */ 103 + { 0xD0, 0x44 }, /* LATIN CAPITAL LETTER ETH -> 'D' */ 104 + { 0xD1, 0x4E }, /* LATIN CAPITAL LETTER N WITH TILDE -> 'N' */ 105 + { 0xD2, 0x00 }, /* LATIN CAPITAL LETTER O WITH GRAVE -> ... */ 106 + { 0xD6, 0x4F }, /* LATIN CAPITAL LETTER O WITH DIAERESIS -> 'O' */ 107 + { 0xD7, 0x78 }, /* MULTIPLICATION SIGN -> 'x' */ 108 + { 0xD8, 0x4F }, /* LATIN CAPITAL LETTER O WITH STROKE -> 'O' */ 109 + { 0xD9, 0x00 }, /* LATIN CAPITAL LETTER U WITH GRAVE -> ... */ 110 + { 0xDC, 0x55 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS -> 'U' */ 111 + { 0xDD, 0x59 }, /* LATIN CAPITAL LETTER Y WITH ACUTE -> 'Y' */ 112 + { 0xDF, 0x73 }, /* LATIN SMALL LETTER SHARP S -> 's' */ 113 + { 0xE0, 0x00 }, /* LATIN SMALL LETTER A WITH GRAVE -> ... */ 114 + { 0xE5, 0x61 }, /* LATIN SMALL LETTER A WITH RING ABOVE -> 'a' */ 115 + { 0xE6, 0x65 }, /* LATIN SMALL LETTER AE -> 'e' */ 116 + { 0xE7, 0x63 }, /* LATIN SMALL LETTER C WITH CEDILLA -> 'c' */ 117 + { 0xE8, 0x00 }, /* LATIN SMALL LETTER E WITH GRAVE -> ... */ 118 + { 0xEB, 0x65 }, /* LATIN SMALL LETTER E WITH DIAERESIS -> 'e' */ 119 + { 0xEC, 0x00 }, /* LATIN SMALL LETTER I WITH GRAVE -> ... */ 120 + { 0xEF, 0x69 }, /* LATIN SMALL LETTER I WITH DIAERESIS -> 'i' */ 121 + { 0xF0, 0x64 }, /* LATIN SMALL LETTER ETH -> 'd' */ 122 + { 0xF1, 0x6E }, /* LATIN SMALL LETTER N WITH TILDE -> 'n' */ 123 + { 0xF2, 0x00 }, /* LATIN SMALL LETTER O WITH GRAVE -> ... */ 124 + { 0xF6, 0x6F }, /* LATIN SMALL LETTER O WITH DIAERESIS -> 'o' */ 125 + { 0xF7, 0x2F }, /* DIVISION SIGN -> '/' */ 126 + { 0xF8, 0x6F }, /* LATIN SMALL LETTER O WITH STROKE -> 'o' */ 127 + { 0xF9, 0x00 }, /* LATIN SMALL LETTER U WITH GRAVE -> ... */ 128 + { 0xFC, 0x75 }, /* LATIN SMALL LETTER U WITH DIAERESIS -> 'u' */ 129 + { 0xFD, 0x79 }, /* LATIN SMALL LETTER Y WITH ACUTE -> 'y' */ 130 + { 0xFF, 0x79 }, /* LATIN SMALL LETTER Y WITH DIAERESIS -> 'y' */ 131 + /* Entries for page 0x01 */ 132 + { 0x00, 0x41 }, /* LATIN CAPITAL LETTER A WITH MACRON -> 'A' */ 133 + { 0x01, 0x61 }, /* LATIN SMALL LETTER A WITH MACRON -> 'a' */ 134 + { 0x02, 0x41 }, /* LATIN CAPITAL LETTER A WITH BREVE -> 'A' */ 135 + { 0x03, 0x61 }, /* LATIN SMALL LETTER A WITH BREVE -> 'a' */ 136 + { 0x04, 0x41 }, /* LATIN CAPITAL LETTER A WITH OGONEK -> 'A' */ 137 + { 0x05, 0x61 }, /* LATIN SMALL LETTER A WITH OGONEK -> 'a' */ 138 + { 0x06, 0x43 }, /* LATIN CAPITAL LETTER C WITH ACUTE -> 'C' */ 139 + { 0x07, 0x63 }, /* LATIN SMALL LETTER C WITH ACUTE -> 'c' */ 140 + { 0x08, 0x43 }, /* LATIN CAPITAL LETTER C WITH CIRCUMFLEX -> 'C' */ 141 + { 0x09, 0x63 }, /* LATIN SMALL LETTER C WITH CIRCUMFLEX -> 'c' */ 142 + { 0x0A, 0x43 }, /* LATIN CAPITAL LETTER C WITH DOT ABOVE -> 'C' */ 143 + { 0x0B, 0x63 }, /* LATIN SMALL LETTER C WITH DOT ABOVE -> 'c' */ 144 + { 0x0C, 0x43 }, /* LATIN CAPITAL LETTER C WITH CARON -> 'C' */ 145 + { 0x0D, 0x63 }, /* LATIN SMALL LETTER C WITH CARON -> 'c' */ 146 + { 0x0E, 0x44 }, /* LATIN CAPITAL LETTER D WITH CARON -> 'D' */ 147 + { 0x0F, 0x64 }, /* LATIN SMALL LETTER D WITH CARON -> 'd' */ 148 + { 0x10, 0x44 }, /* LATIN CAPITAL LETTER D WITH STROKE -> 'D' */ 149 + { 0x11, 0x64 }, /* LATIN SMALL LETTER D WITH STROKE -> 'd' */ 150 + { 0x12, 0x45 }, /* LATIN CAPITAL LETTER E WITH MACRON -> 'E' */ 151 + { 0x13, 0x65 }, /* LATIN SMALL LETTER E WITH MACRON -> 'e' */ 152 + { 0x14, 0x45 }, /* LATIN CAPITAL LETTER E WITH BREVE -> 'E' */ 153 + { 0x15, 0x65 }, /* LATIN SMALL LETTER E WITH BREVE -> 'e' */ 154 + { 0x16, 0x45 }, /* LATIN CAPITAL LETTER E WITH DOT ABOVE -> 'E' */ 155 + { 0x17, 0x65 }, /* LATIN SMALL LETTER E WITH DOT ABOVE -> 'e' */ 156 + { 0x18, 0x45 }, /* LATIN CAPITAL LETTER E WITH OGONEK -> 'E' */ 157 + { 0x19, 0x65 }, /* LATIN SMALL LETTER E WITH OGONEK -> 'e' */ 158 + { 0x1A, 0x45 }, /* LATIN CAPITAL LETTER E WITH CARON -> 'E' */ 159 + { 0x1B, 0x65 }, /* LATIN SMALL LETTER E WITH CARON -> 'e' */ 160 + { 0x1C, 0x47 }, /* LATIN CAPITAL LETTER G WITH CIRCUMFLEX -> 'G' */ 161 + { 0x1D, 0x67 }, /* LATIN SMALL LETTER G WITH CIRCUMFLEX -> 'g' */ 162 + { 0x1E, 0x47 }, /* LATIN CAPITAL LETTER G WITH BREVE -> 'G' */ 163 + { 0x1F, 0x67 }, /* LATIN SMALL LETTER G WITH BREVE -> 'g' */ 164 + { 0x20, 0x47 }, /* LATIN CAPITAL LETTER G WITH DOT ABOVE -> 'G' */ 165 + { 0x21, 0x67 }, /* LATIN SMALL LETTER G WITH DOT ABOVE -> 'g' */ 166 + { 0x22, 0x47 }, /* LATIN CAPITAL LETTER G WITH CEDILLA -> 'G' */ 167 + { 0x23, 0x67 }, /* LATIN SMALL LETTER G WITH CEDILLA -> 'g' */ 168 + { 0x24, 0x48 }, /* LATIN CAPITAL LETTER H WITH CIRCUMFLEX -> 'H' */ 169 + { 0x25, 0x68 }, /* LATIN SMALL LETTER H WITH CIRCUMFLEX -> 'h' */ 170 + { 0x26, 0x48 }, /* LATIN CAPITAL LETTER H WITH STROKE -> 'H' */ 171 + { 0x27, 0x68 }, /* LATIN SMALL LETTER H WITH STROKE -> 'h' */ 172 + { 0x28, 0x49 }, /* LATIN CAPITAL LETTER I WITH TILDE -> 'I' */ 173 + { 0x29, 0x69 }, /* LATIN SMALL LETTER I WITH TILDE -> 'i' */ 174 + { 0x2A, 0x49 }, /* LATIN CAPITAL LETTER I WITH MACRON -> 'I' */ 175 + { 0x2B, 0x69 }, /* LATIN SMALL LETTER I WITH MACRON -> 'i' */ 176 + { 0x2C, 0x49 }, /* LATIN CAPITAL LETTER I WITH BREVE -> 'I' */ 177 + { 0x2D, 0x69 }, /* LATIN SMALL LETTER I WITH BREVE -> 'i' */ 178 + { 0x2E, 0x49 }, /* LATIN CAPITAL LETTER I WITH OGONEK -> 'I' */ 179 + { 0x2F, 0x69 }, /* LATIN SMALL LETTER I WITH OGONEK -> 'i' */ 180 + { 0x30, 0x49 }, /* LATIN CAPITAL LETTER I WITH DOT ABOVE -> 'I' */ 181 + { 0x31, 0x69 }, /* LATIN SMALL LETTER DOTLESS I -> 'i' */ 182 + { 0x34, 0x4A }, /* LATIN CAPITAL LETTER J WITH CIRCUMFLEX -> 'J' */ 183 + { 0x35, 0x6A }, /* LATIN SMALL LETTER J WITH CIRCUMFLEX -> 'j' */ 184 + { 0x36, 0x4B }, /* LATIN CAPITAL LETTER K WITH CEDILLA -> 'K' */ 185 + { 0x37, 0x6B }, /* LATIN SMALL LETTER K WITH CEDILLA -> 'k' */ 186 + { 0x38, 0x6B }, /* LATIN SMALL LETTER KRA -> 'k' */ 187 + { 0x39, 0x4C }, /* LATIN CAPITAL LETTER L WITH ACUTE -> 'L' */ 188 + { 0x3A, 0x6C }, /* LATIN SMALL LETTER L WITH ACUTE -> 'l' */ 189 + { 0x3B, 0x4C }, /* LATIN CAPITAL LETTER L WITH CEDILLA -> 'L' */ 190 + { 0x3C, 0x6C }, /* LATIN SMALL LETTER L WITH CEDILLA -> 'l' */ 191 + { 0x3D, 0x4C }, /* LATIN CAPITAL LETTER L WITH CARON -> 'L' */ 192 + { 0x3E, 0x6C }, /* LATIN SMALL LETTER L WITH CARON -> 'l' */ 193 + { 0x3F, 0x4C }, /* LATIN CAPITAL LETTER L WITH MIDDLE DOT -> 'L' */ 194 + { 0x40, 0x6C }, /* LATIN SMALL LETTER L WITH MIDDLE DOT -> 'l' */ 195 + { 0x41, 0x4C }, /* LATIN CAPITAL LETTER L WITH STROKE -> 'L' */ 196 + { 0x42, 0x6C }, /* LATIN SMALL LETTER L WITH STROKE -> 'l' */ 197 + { 0x43, 0x4E }, /* LATIN CAPITAL LETTER N WITH ACUTE -> 'N' */ 198 + { 0x44, 0x6E }, /* LATIN SMALL LETTER N WITH ACUTE -> 'n' */ 199 + { 0x45, 0x4E }, /* LATIN CAPITAL LETTER N WITH CEDILLA -> 'N' */ 200 + { 0x46, 0x6E }, /* LATIN SMALL LETTER N WITH CEDILLA -> 'n' */ 201 + { 0x47, 0x4E }, /* LATIN CAPITAL LETTER N WITH CARON -> 'N' */ 202 + { 0x48, 0x6E }, /* LATIN SMALL LETTER N WITH CARON -> 'n' */ 203 + { 0x4C, 0x4F }, /* LATIN CAPITAL LETTER O WITH MACRON -> 'O' */ 204 + { 0x4D, 0x6F }, /* LATIN SMALL LETTER O WITH MACRON -> 'o' */ 205 + { 0x4E, 0x4F }, /* LATIN CAPITAL LETTER O WITH BREVE -> 'O' */ 206 + { 0x4F, 0x6F }, /* LATIN SMALL LETTER O WITH BREVE -> 'o' */ 207 + { 0x50, 0x4F }, /* LATIN CAPITAL LETTER O WITH DOUBLE ACUTE -> 'O' */ 208 + { 0x51, 0x6F }, /* LATIN SMALL LETTER O WITH DOUBLE ACUTE -> 'o' */ 209 + { 0x52, 0x45 }, /* LATIN CAPITAL LIGATURE OE -> 'E' */ 210 + { 0x53, 0x65 }, /* LATIN SMALL LIGATURE OE -> 'e' */ 211 + { 0x54, 0x52 }, /* LATIN CAPITAL LETTER R WITH ACUTE -> 'R' */ 212 + { 0x55, 0x72 }, /* LATIN SMALL LETTER R WITH ACUTE -> 'r' */ 213 + { 0x56, 0x52 }, /* LATIN CAPITAL LETTER R WITH CEDILLA -> 'R' */ 214 + { 0x57, 0x72 }, /* LATIN SMALL LETTER R WITH CEDILLA -> 'r' */ 215 + { 0x58, 0x52 }, /* LATIN CAPITAL LETTER R WITH CARON -> 'R' */ 216 + { 0x59, 0x72 }, /* LATIN SMALL LETTER R WITH CARON -> 'r' */ 217 + { 0x5A, 0x53 }, /* LATIN CAPITAL LETTER S WITH ACUTE -> 'S' */ 218 + { 0x5B, 0x73 }, /* LATIN SMALL LETTER S WITH ACUTE -> 's' */ 219 + { 0x5C, 0x53 }, /* LATIN CAPITAL LETTER S WITH CIRCUMFLEX -> 'S' */ 220 + { 0x5D, 0x73 }, /* LATIN SMALL LETTER S WITH CIRCUMFLEX -> 's' */ 221 + { 0x5E, 0x53 }, /* LATIN CAPITAL LETTER S WITH CEDILLA -> 'S' */ 222 + { 0x5F, 0x73 }, /* LATIN SMALL LETTER S WITH CEDILLA -> 's' */ 223 + { 0x60, 0x53 }, /* LATIN CAPITAL LETTER S WITH CARON -> 'S' */ 224 + { 0x61, 0x73 }, /* LATIN SMALL LETTER S WITH CARON -> 's' */ 225 + { 0x62, 0x54 }, /* LATIN CAPITAL LETTER T WITH CEDILLA -> 'T' */ 226 + { 0x63, 0x74 }, /* LATIN SMALL LETTER T WITH CEDILLA -> 't' */ 227 + { 0x64, 0x54 }, /* LATIN CAPITAL LETTER T WITH CARON -> 'T' */ 228 + { 0x65, 0x74 }, /* LATIN SMALL LETTER T WITH CARON -> 't' */ 229 + { 0x66, 0x54 }, /* LATIN CAPITAL LETTER T WITH STROKE -> 'T' */ 230 + { 0x67, 0x74 }, /* LATIN SMALL LETTER T WITH STROKE -> 't' */ 231 + { 0x68, 0x55 }, /* LATIN CAPITAL LETTER U WITH TILDE -> 'U' */ 232 + { 0x69, 0x75 }, /* LATIN SMALL LETTER U WITH TILDE -> 'u' */ 233 + { 0x6A, 0x55 }, /* LATIN CAPITAL LETTER U WITH MACRON -> 'U' */ 234 + { 0x6B, 0x75 }, /* LATIN SMALL LETTER U WITH MACRON -> 'u' */ 235 + { 0x6C, 0x55 }, /* LATIN CAPITAL LETTER U WITH BREVE -> 'U' */ 236 + { 0x6D, 0x75 }, /* LATIN SMALL LETTER U WITH BREVE -> 'u' */ 237 + { 0x6E, 0x55 }, /* LATIN CAPITAL LETTER U WITH RING ABOVE -> 'U' */ 238 + { 0x6F, 0x75 }, /* LATIN SMALL LETTER U WITH RING ABOVE -> 'u' */ 239 + { 0x70, 0x55 }, /* LATIN CAPITAL LETTER U WITH DOUBLE ACUTE -> 'U' */ 240 + { 0x71, 0x75 }, /* LATIN SMALL LETTER U WITH DOUBLE ACUTE -> 'u' */ 241 + { 0x72, 0x55 }, /* LATIN CAPITAL LETTER U WITH OGONEK -> 'U' */ 242 + { 0x73, 0x75 }, /* LATIN SMALL LETTER U WITH OGONEK -> 'u' */ 243 + { 0x74, 0x57 }, /* LATIN CAPITAL LETTER W WITH CIRCUMFLEX -> 'W' */ 244 + { 0x75, 0x77 }, /* LATIN SMALL LETTER W WITH CIRCUMFLEX -> 'w' */ 245 + { 0x76, 0x59 }, /* LATIN CAPITAL LETTER Y WITH CIRCUMFLEX -> 'Y' */ 246 + { 0x77, 0x79 }, /* LATIN SMALL LETTER Y WITH CIRCUMFLEX -> 'y' */ 247 + { 0x78, 0x59 }, /* LATIN CAPITAL LETTER Y WITH DIAERESIS -> 'Y' */ 248 + { 0x79, 0x5A }, /* LATIN CAPITAL LETTER Z WITH ACUTE -> 'Z' */ 249 + { 0x7A, 0x7A }, /* LATIN SMALL LETTER Z WITH ACUTE -> 'z' */ 250 + { 0x7B, 0x5A }, /* LATIN CAPITAL LETTER Z WITH DOT ABOVE -> 'Z' */ 251 + { 0x7C, 0x7A }, /* LATIN SMALL LETTER Z WITH DOT ABOVE -> 'z' */ 252 + { 0x7D, 0x5A }, /* LATIN CAPITAL LETTER Z WITH CARON -> 'Z' */ 253 + { 0x7E, 0x7A }, /* LATIN SMALL LETTER Z WITH CARON -> 'z' */ 254 + { 0x7F, 0x73 }, /* LATIN SMALL LETTER LONG S -> 's' */ 255 + { 0x80, 0x62 }, /* LATIN SMALL LETTER B WITH STROKE -> 'b' */ 256 + { 0x81, 0x42 }, /* LATIN CAPITAL LETTER B WITH HOOK -> 'B' */ 257 + { 0x82, 0x42 }, /* LATIN CAPITAL LETTER B WITH TOPBAR -> 'B' */ 258 + { 0x83, 0x62 }, /* LATIN SMALL LETTER B WITH TOPBAR -> 'b' */ 259 + { 0x84, 0x36 }, /* LATIN CAPITAL LETTER TONE SIX -> '6' */ 260 + { 0x85, 0x36 }, /* LATIN SMALL LETTER TONE SIX -> '6' */ 261 + { 0x86, 0x4F }, /* LATIN CAPITAL LETTER OPEN O -> 'O' */ 262 + { 0x87, 0x43 }, /* LATIN CAPITAL LETTER C WITH HOOK -> 'C' */ 263 + { 0x88, 0x63 }, /* LATIN SMALL LETTER C WITH HOOK -> 'c' */ 264 + { 0x89, 0x00 }, /* LATIN CAPITAL LETTER AFRICAN D -> ... */ 265 + { 0x8B, 0x44 }, /* LATIN CAPITAL LETTER D WITH TOPBAR -> 'D' */ 266 + { 0x8C, 0x64 }, /* LATIN SMALL LETTER D WITH TOPBAR -> 'd' */ 267 + { 0x8D, 0x64 }, /* LATIN SMALL LETTER TURNED DELTA -> 'd' */ 268 + { 0x8E, 0x33 }, /* LATIN CAPITAL LETTER REVERSED E -> '3' */ 269 + { 0x8F, 0x40 }, /* LATIN CAPITAL LETTER SCHWA -> '@' */ 270 + { 0x90, 0x45 }, /* LATIN CAPITAL LETTER OPEN E -> 'E' */ 271 + { 0x91, 0x46 }, /* LATIN CAPITAL LETTER F WITH HOOK -> 'F' */ 272 + { 0x92, 0x66 }, /* LATIN SMALL LETTER F WITH HOOK -> 'f' */ 273 + { 0x93, 0x47 }, /* LATIN CAPITAL LETTER G WITH HOOK -> 'G' */ 274 + { 0x94, 0x47 }, /* LATIN CAPITAL LETTER GAMMA -> 'G' */ 275 + { 0x96, 0x49 }, /* LATIN CAPITAL LETTER IOTA -> 'I' */ 276 + { 0x97, 0x49 }, /* LATIN CAPITAL LETTER I WITH STROKE -> 'I' */ 277 + { 0x98, 0x4B }, /* LATIN CAPITAL LETTER K WITH HOOK -> 'K' */ 278 + { 0x99, 0x6B }, /* LATIN SMALL LETTER K WITH HOOK -> 'k' */ 279 + { 0x9A, 0x6C }, /* LATIN SMALL LETTER L WITH BAR -> 'l' */ 280 + { 0x9B, 0x6C }, /* LATIN SMALL LETTER LAMBDA WITH STROKE -> 'l' */ 281 + { 0x9C, 0x57 }, /* LATIN CAPITAL LETTER TURNED M -> 'W' */ 282 + { 0x9D, 0x4E }, /* LATIN CAPITAL LETTER N WITH LEFT HOOK -> 'N' */ 283 + { 0x9E, 0x6E }, /* LATIN SMALL LETTER N WITH LONG RIGHT LEG -> 'n' */ 284 + { 0x9F, 0x4F }, /* LATIN CAPITAL LETTER O WITH MIDDLE TILDE -> 'O' */ 285 + { 0xA0, 0x4F }, /* LATIN CAPITAL LETTER O WITH HORN -> 'O' */ 286 + { 0xA1, 0x6F }, /* LATIN SMALL LETTER O WITH HORN -> 'o' */ 287 + { 0xA4, 0x50 }, /* LATIN CAPITAL LETTER P WITH HOOK -> 'P' */ 288 + { 0xA5, 0x70 }, /* LATIN SMALL LETTER P WITH HOOK -> 'p' */ 289 + { 0xA7, 0x32 }, /* LATIN CAPITAL LETTER TONE TWO -> '2' */ 290 + { 0xA8, 0x32 }, /* LATIN SMALL LETTER TONE TWO -> '2' */ 291 + { 0xAB, 0x74 }, /* LATIN SMALL LETTER T WITH PALATAL HOOK -> 't' */ 292 + { 0xAC, 0x54 }, /* LATIN CAPITAL LETTER T WITH HOOK -> 'T' */ 293 + { 0xAD, 0x74 }, /* LATIN SMALL LETTER T WITH HOOK -> 't' */ 294 + { 0xAE, 0x54 }, /* LATIN CAPITAL LETTER T WITH RETROFLEX HOOK -> 'T' */ 295 + { 0xAF, 0x55 }, /* LATIN CAPITAL LETTER U WITH HORN -> 'U' */ 296 + { 0xB0, 0x75 }, /* LATIN SMALL LETTER U WITH HORN -> 'u' */ 297 + { 0xB1, 0x59 }, /* LATIN CAPITAL LETTER UPSILON -> 'Y' */ 298 + { 0xB2, 0x56 }, /* LATIN CAPITAL LETTER V WITH HOOK -> 'V' */ 299 + { 0xB3, 0x59 }, /* LATIN CAPITAL LETTER Y WITH HOOK -> 'Y' */ 300 + { 0xB4, 0x79 }, /* LATIN SMALL LETTER Y WITH HOOK -> 'y' */ 301 + { 0xB5, 0x5A }, /* LATIN CAPITAL LETTER Z WITH STROKE -> 'Z' */ 302 + { 0xB6, 0x7A }, /* LATIN SMALL LETTER Z WITH STROKE -> 'z' */ 303 + { 0xBB, 0x32 }, /* LATIN LETTER TWO WITH STROKE -> '2' */ 304 + { 0xBC, 0x35 }, /* LATIN CAPITAL LETTER TONE FIVE -> '5' */ 305 + { 0xBD, 0x35 }, /* LATIN SMALL LETTER TONE FIVE -> '5' */ 306 + { 0xBF, 0x77 }, /* LATIN LETTER WYNN -> 'w' */ 307 + { 0xC0, 0x7C }, /* LATIN LETTER DENTAL CLICK -> '|' */ 308 + { 0xC3, 0x21 }, /* LATIN LETTER RETROFLEX CLICK -> '!' */ 309 + { 0xCD, 0x41 }, /* LATIN CAPITAL LETTER A WITH CARON -> 'A' */ 310 + { 0xCE, 0x61 }, /* LATIN SMALL LETTER A WITH CARON -> 'a' */ 311 + { 0xCF, 0x49 }, /* LATIN CAPITAL LETTER I WITH CARON -> 'I' */ 312 + { 0xD0, 0x69 }, /* LATIN SMALL LETTER I WITH CARON -> 'i' */ 313 + { 0xD1, 0x4F }, /* LATIN CAPITAL LETTER O WITH CARON -> 'O' */ 314 + { 0xD2, 0x6F }, /* LATIN SMALL LETTER O WITH CARON -> 'o' */ 315 + { 0xD3, 0x55 }, /* LATIN CAPITAL LETTER U WITH CARON -> 'U' */ 316 + { 0xD4, 0x75 }, /* LATIN SMALL LETTER U WITH CARON -> 'u' */ 317 + { 0xD5, 0x55 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON -> 'U' */ 318 + { 0xD6, 0x75 }, /* LATIN SMALL LETTER U WITH DIAERESIS AND MACRON -> 'u' */ 319 + { 0xD7, 0x55 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE -> 'U' */ 320 + { 0xD8, 0x75 }, /* LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE -> 'u' */ 321 + { 0xD9, 0x55 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON -> 'U' */ 322 + { 0xDA, 0x75 }, /* LATIN SMALL LETTER U WITH DIAERESIS AND CARON -> 'u' */ 323 + { 0xDB, 0x55 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE -> 'U' */ 324 + { 0xDC, 0x75 }, /* LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE -> 'u' */ 325 + { 0xDD, 0x40 }, /* LATIN SMALL LETTER TURNED E -> '@' */ 326 + { 0xDE, 0x41 }, /* LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON -> 'A' */ 327 + { 0xDF, 0x61 }, /* LATIN SMALL LETTER A WITH DIAERESIS AND MACRON -> 'a' */ 328 + { 0xE0, 0x41 }, /* LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON -> 'A' */ 329 + { 0xE1, 0x61 }, /* LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON -> 'a' */ 330 + { 0xE4, 0x47 }, /* LATIN CAPITAL LETTER G WITH STROKE -> 'G' */ 331 + { 0xE5, 0x67 }, /* LATIN SMALL LETTER G WITH STROKE -> 'g' */ 332 + { 0xE6, 0x47 }, /* LATIN CAPITAL LETTER G WITH CARON -> 'G' */ 333 + { 0xE7, 0x67 }, /* LATIN SMALL LETTER G WITH CARON -> 'g' */ 334 + { 0xE8, 0x4B }, /* LATIN CAPITAL LETTER K WITH CARON -> 'K' */ 335 + { 0xE9, 0x6B }, /* LATIN SMALL LETTER K WITH CARON -> 'k' */ 336 + { 0xEA, 0x4F }, /* LATIN CAPITAL LETTER O WITH OGONEK -> 'O' */ 337 + { 0xEB, 0x6F }, /* LATIN SMALL LETTER O WITH OGONEK -> 'o' */ 338 + { 0xEC, 0x4F }, /* LATIN CAPITAL LETTER O WITH OGONEK AND MACRON -> 'O' */ 339 + { 0xED, 0x6F }, /* LATIN SMALL LETTER O WITH OGONEK AND MACRON -> 'o' */ 340 + { 0xF0, 0x6A }, /* LATIN SMALL LETTER J WITH CARON -> 'j' */ 341 + { 0xF4, 0x47 }, /* LATIN CAPITAL LETTER G WITH ACUTE -> 'G' */ 342 + { 0xF5, 0x67 }, /* LATIN SMALL LETTER G WITH ACUTE -> 'g' */ 343 + { 0xF7, 0x57 }, /* LATIN CAPITAL LETTER WYNN -> 'W' */ 344 + { 0xF8, 0x4E }, /* LATIN CAPITAL LETTER N WITH GRAVE -> 'N' */ 345 + { 0xF9, 0x6E }, /* LATIN SMALL LETTER N WITH GRAVE -> 'n' */ 346 + { 0xFA, 0x41 }, /* LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE -> 'A' */ 347 + { 0xFB, 0x61 }, /* LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE -> 'a' */ 348 + { 0xFE, 0x4F }, /* LATIN CAPITAL LETTER O WITH STROKE AND ACUTE -> 'O' */ 349 + { 0xFF, 0x6F }, /* LATIN SMALL LETTER O WITH STROKE AND ACUTE -> 'o' */ 350 + /* Entries for page 0x02 */ 351 + { 0x00, 0x41 }, /* LATIN CAPITAL LETTER A WITH DOUBLE GRAVE -> 'A' */ 352 + { 0x01, 0x61 }, /* LATIN SMALL LETTER A WITH DOUBLE GRAVE -> 'a' */ 353 + { 0x02, 0x41 }, /* LATIN CAPITAL LETTER A WITH INVERTED BREVE -> 'A' */ 354 + { 0x03, 0x61 }, /* LATIN SMALL LETTER A WITH INVERTED BREVE -> 'a' */ 355 + { 0x04, 0x45 }, /* LATIN CAPITAL LETTER E WITH DOUBLE GRAVE -> 'E' */ 356 + { 0x05, 0x65 }, /* LATIN SMALL LETTER E WITH DOUBLE GRAVE -> 'e' */ 357 + { 0x06, 0x45 }, /* LATIN CAPITAL LETTER E WITH INVERTED BREVE -> 'E' */ 358 + { 0x07, 0x65 }, /* LATIN SMALL LETTER E WITH INVERTED BREVE -> 'e' */ 359 + { 0x08, 0x49 }, /* LATIN CAPITAL LETTER I WITH DOUBLE GRAVE -> 'I' */ 360 + { 0x09, 0x69 }, /* LATIN SMALL LETTER I WITH DOUBLE GRAVE -> 'i' */ 361 + { 0x0A, 0x49 }, /* LATIN CAPITAL LETTER I WITH INVERTED BREVE -> 'I' */ 362 + { 0x0B, 0x69 }, /* LATIN SMALL LETTER I WITH INVERTED BREVE -> 'i' */ 363 + { 0x0C, 0x4F }, /* LATIN CAPITAL LETTER O WITH DOUBLE GRAVE -> 'O' */ 364 + { 0x0D, 0x6F }, /* LATIN SMALL LETTER O WITH DOUBLE GRAVE -> 'o' */ 365 + { 0x0E, 0x4F }, /* LATIN CAPITAL LETTER O WITH INVERTED BREVE -> 'O' */ 366 + { 0x0F, 0x6F }, /* LATIN SMALL LETTER O WITH INVERTED BREVE -> 'o' */ 367 + { 0x10, 0x52 }, /* LATIN CAPITAL LETTER R WITH DOUBLE GRAVE -> 'R' */ 368 + { 0x11, 0x72 }, /* LATIN SMALL LETTER R WITH DOUBLE GRAVE -> 'r' */ 369 + { 0x12, 0x52 }, /* LATIN CAPITAL LETTER R WITH INVERTED BREVE -> 'R' */ 370 + { 0x13, 0x72 }, /* LATIN SMALL LETTER R WITH INVERTED BREVE -> 'r' */ 371 + { 0x14, 0x55 }, /* LATIN CAPITAL LETTER U WITH DOUBLE GRAVE -> 'U' */ 372 + { 0x15, 0x75 }, /* LATIN SMALL LETTER U WITH DOUBLE GRAVE -> 'u' */ 373 + { 0x16, 0x55 }, /* LATIN CAPITAL LETTER U WITH INVERTED BREVE -> 'U' */ 374 + { 0x17, 0x75 }, /* LATIN SMALL LETTER U WITH INVERTED BREVE -> 'u' */ 375 + { 0x18, 0x53 }, /* LATIN CAPITAL LETTER S WITH COMMA BELOW -> 'S' */ 376 + { 0x19, 0x73 }, /* LATIN SMALL LETTER S WITH COMMA BELOW -> 's' */ 377 + { 0x1A, 0x54 }, /* LATIN CAPITAL LETTER T WITH COMMA BELOW -> 'T' */ 378 + { 0x1B, 0x74 }, /* LATIN SMALL LETTER T WITH COMMA BELOW -> 't' */ 379 + { 0x1C, 0x59 }, /* LATIN CAPITAL LETTER YOGH -> 'Y' */ 380 + { 0x1D, 0x79 }, /* LATIN SMALL LETTER YOGH -> 'y' */ 381 + { 0x1E, 0x48 }, /* LATIN CAPITAL LETTER H WITH CARON -> 'H' */ 382 + { 0x1F, 0x68 }, /* LATIN SMALL LETTER H WITH CARON -> 'h' */ 383 + { 0x20, 0x4E }, /* LATIN CAPITAL LETTER N WITH LONG RIGHT LEG -> 'N' */ 384 + { 0x21, 0x64 }, /* LATIN SMALL LETTER D WITH CURL -> 'd' */ 385 + { 0x24, 0x5A }, /* LATIN CAPITAL LETTER Z WITH HOOK -> 'Z' */ 386 + { 0x25, 0x7A }, /* LATIN SMALL LETTER Z WITH HOOK -> 'z' */ 387 + { 0x26, 0x41 }, /* LATIN CAPITAL LETTER A WITH DOT ABOVE -> 'A' */ 388 + { 0x27, 0x61 }, /* LATIN SMALL LETTER A WITH DOT ABOVE -> 'a' */ 389 + { 0x28, 0x45 }, /* LATIN CAPITAL LETTER E WITH CEDILLA -> 'E' */ 390 + { 0x29, 0x65 }, /* LATIN SMALL LETTER E WITH CEDILLA -> 'e' */ 391 + { 0x2A, 0x4F }, /* LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON -> 'O' */ 392 + { 0x2B, 0x6F }, /* LATIN SMALL LETTER O WITH DIAERESIS AND MACRON -> 'o' */ 393 + { 0x2C, 0x4F }, /* LATIN CAPITAL LETTER O WITH TILDE AND MACRON -> 'O' */ 394 + { 0x2D, 0x6F }, /* LATIN SMALL LETTER O WITH TILDE AND MACRON -> 'o' */ 395 + { 0x2E, 0x4F }, /* LATIN CAPITAL LETTER O WITH DOT ABOVE -> 'O' */ 396 + { 0x2F, 0x6F }, /* LATIN SMALL LETTER O WITH DOT ABOVE -> 'o' */ 397 + { 0x30, 0x4F }, /* LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON -> 'O' */ 398 + { 0x31, 0x6F }, /* LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON -> 'o' */ 399 + { 0x32, 0x59 }, /* LATIN CAPITAL LETTER Y WITH MACRON -> 'Y' */ 400 + { 0x33, 0x79 }, /* LATIN SMALL LETTER Y WITH MACRON -> 'y' */ 401 + { 0x34, 0x6C }, /* LATIN SMALL LETTER L WITH CURL -> 'l' */ 402 + { 0x35, 0x6E }, /* LATIN SMALL LETTER N WITH CURL -> 'n' */ 403 + { 0x36, 0x74 }, /* LATIN SMALL LETTER T WITH CURL -> 't' */ 404 + { 0x37, 0x6A }, /* LATIN SMALL LETTER DOTLESS J -> 'j' */ 405 + { 0x3A, 0x41 }, /* LATIN CAPITAL LETTER A WITH STROKE -> 'A' */ 406 + { 0x3B, 0x43 }, /* LATIN CAPITAL LETTER C WITH STROKE -> 'C' */ 407 + { 0x3C, 0x63 }, /* LATIN SMALL LETTER C WITH STROKE -> 'c' */ 408 + { 0x3D, 0x4C }, /* LATIN CAPITAL LETTER L WITH BAR -> 'L' */ 409 + { 0x3E, 0x54 }, /* LATIN CAPITAL LETTER T WITH DIAGONAL STROKE -> 'T' */ 410 + { 0x3F, 0x73 }, /* LATIN SMALL LETTER S WITH SWASH TAIL -> 's' */ 411 + { 0x40, 0x7A }, /* LATIN SMALL LETTER Z WITH SWASH TAIL -> 'z' */ 412 + { 0x43, 0x42 }, /* LATIN CAPITAL LETTER B WITH STROKE -> 'B' */ 413 + { 0x44, 0x55 }, /* LATIN CAPITAL LETTER U BAR -> 'U' */ 414 + { 0x45, 0x5E }, /* LATIN CAPITAL LETTER TURNED V -> '^' */ 415 + { 0x46, 0x45 }, /* LATIN CAPITAL LETTER E WITH STROKE -> 'E' */ 416 + { 0x47, 0x65 }, /* LATIN SMALL LETTER E WITH STROKE -> 'e' */ 417 + { 0x48, 0x4A }, /* LATIN CAPITAL LETTER J WITH STROKE -> 'J' */ 418 + { 0x49, 0x6A }, /* LATIN SMALL LETTER J WITH STROKE -> 'j' */ 419 + { 0x4A, 0x71 }, /* LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL -> 'q' */ 420 + { 0x4B, 0x71 }, /* LATIN SMALL LETTER Q WITH HOOK TAIL -> 'q' */ 421 + { 0x4C, 0x52 }, /* LATIN CAPITAL LETTER R WITH STROKE -> 'R' */ 422 + { 0x4D, 0x72 }, /* LATIN SMALL LETTER R WITH STROKE -> 'r' */ 423 + { 0x4E, 0x59 }, /* LATIN CAPITAL LETTER Y WITH STROKE -> 'Y' */ 424 + { 0x4F, 0x79 }, /* LATIN SMALL LETTER Y WITH STROKE -> 'y' */ 425 + { 0x50, 0x00 }, /* LATIN SMALL LETTER TURNED A -> ... */ 426 + { 0x52, 0x61 }, /* LATIN SMALL LETTER TURNED ALPHA -> 'a' */ 427 + { 0x53, 0x62 }, /* LATIN SMALL LETTER B WITH HOOK -> 'b' */ 428 + { 0x54, 0x6F }, /* LATIN SMALL LETTER OPEN O -> 'o' */ 429 + { 0x55, 0x63 }, /* LATIN SMALL LETTER C WITH CURL -> 'c' */ 430 + { 0x56, 0x64 }, /* LATIN SMALL LETTER D WITH TAIL -> 'd' */ 431 + { 0x57, 0x64 }, /* LATIN SMALL LETTER D WITH HOOK -> 'd' */ 432 + { 0x58, 0x65 }, /* LATIN SMALL LETTER REVERSED E -> 'e' */ 433 + { 0x59, 0x40 }, /* LATIN SMALL LETTER SCHWA -> '@' */ 434 + { 0x5A, 0x40 }, /* LATIN SMALL LETTER SCHWA WITH HOOK -> '@' */ 435 + { 0x5B, 0x00 }, /* LATIN SMALL LETTER OPEN E -> ... */ 436 + { 0x5E, 0x65 }, /* LATIN SMALL LETTER CLOSED REVERSED OPEN E -> 'e' */ 437 + { 0x5F, 0x6A }, /* LATIN SMALL LETTER DOTLESS J WITH STROKE -> 'j' */ 438 + { 0x60, 0x00 }, /* LATIN SMALL LETTER G WITH HOOK -> ... */ 439 + { 0x63, 0x67 }, /* LATIN SMALL LETTER GAMMA -> 'g' */ 440 + { 0x64, 0x75 }, /* LATIN SMALL LETTER RAMS HORN -> 'u' */ 441 + { 0x65, 0x59 }, /* LATIN SMALL LETTER TURNED H -> 'Y' */ 442 + { 0x66, 0x68 }, /* LATIN SMALL LETTER H WITH HOOK -> 'h' */ 443 + { 0x67, 0x68 }, /* LATIN SMALL LETTER HENG WITH HOOK -> 'h' */ 444 + { 0x68, 0x69 }, /* LATIN SMALL LETTER I WITH STROKE -> 'i' */ 445 + { 0x69, 0x69 }, /* LATIN SMALL LETTER IOTA -> 'i' */ 446 + { 0x6A, 0x49 }, /* LATIN LETTER SMALL CAPITAL I -> 'I' */ 447 + { 0x6B, 0x00 }, /* LATIN SMALL LETTER L WITH MIDDLE TILDE -> ... */ 448 + { 0x6D, 0x6C }, /* LATIN SMALL LETTER L WITH RETROFLEX HOOK -> 'l' */ 449 + { 0x6F, 0x57 }, /* LATIN SMALL LETTER TURNED M -> 'W' */ 450 + { 0x70, 0x57 }, /* LATIN SMALL LETTER TURNED M WITH LONG LEG -> 'W' */ 451 + { 0x71, 0x6D }, /* LATIN SMALL LETTER M WITH HOOK -> 'm' */ 452 + { 0x72, 0x00 }, /* LATIN SMALL LETTER N WITH LEFT HOOK -> ... */ 453 + { 0x74, 0x6E }, /* LATIN LETTER SMALL CAPITAL N -> 'n' */ 454 + { 0x75, 0x6F }, /* LATIN SMALL LETTER BARRED O -> 'o' */ 455 + { 0x77, 0x4F }, /* LATIN SMALL LETTER CLOSED OMEGA -> 'O' */ 456 + { 0x78, 0x46 }, /* LATIN SMALL LETTER PHI -> 'F' */ 457 + { 0x79, 0x00 }, /* LATIN SMALL LETTER TURNED R -> ... */ 458 + { 0x7F, 0x72 }, /* LATIN SMALL LETTER REVERSED R WITH FISHHOOK -> 'r' */ 459 + { 0x80, 0x52 }, /* LATIN LETTER SMALL CAPITAL R -> 'R' */ 460 + { 0x81, 0x52 }, /* LATIN LETTER SMALL CAPITAL INVERTED R -> 'R' */ 461 + { 0x82, 0x73 }, /* LATIN SMALL LETTER S WITH HOOK -> 's' */ 462 + { 0x83, 0x53 }, /* LATIN SMALL LETTER ESH -> 'S' */ 463 + { 0x84, 0x6A }, /* LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK -> 'j' */ 464 + { 0x85, 0x53 }, /* LATIN SMALL LETTER SQUAT REVERSED ESH -> 'S' */ 465 + { 0x86, 0x53 }, /* LATIN SMALL LETTER ESH WITH CURL -> 'S' */ 466 + { 0x87, 0x74 }, /* LATIN SMALL LETTER TURNED T -> 't' */ 467 + { 0x88, 0x74 }, /* LATIN SMALL LETTER T WITH RETROFLEX HOOK -> 't' */ 468 + { 0x89, 0x75 }, /* LATIN SMALL LETTER U BAR -> 'u' */ 469 + { 0x8A, 0x55 }, /* LATIN SMALL LETTER UPSILON -> 'U' */ 470 + { 0x8B, 0x76 }, /* LATIN SMALL LETTER V WITH HOOK -> 'v' */ 471 + { 0x8C, 0x5E }, /* LATIN SMALL LETTER TURNED V -> '^' */ 472 + { 0x8D, 0x77 }, /* LATIN SMALL LETTER TURNED W -> 'w' */ 473 + { 0x8E, 0x79 }, /* LATIN SMALL LETTER TURNED Y -> 'y' */ 474 + { 0x8F, 0x59 }, /* LATIN LETTER SMALL CAPITAL Y -> 'Y' */ 475 + { 0x90, 0x7A }, /* LATIN SMALL LETTER Z WITH RETROFLEX HOOK -> 'z' */ 476 + { 0x91, 0x7A }, /* LATIN SMALL LETTER Z WITH CURL -> 'z' */ 477 + { 0x92, 0x5A }, /* LATIN SMALL LETTER EZH -> 'Z' */ 478 + { 0x93, 0x5A }, /* LATIN SMALL LETTER EZH WITH CURL -> 'Z' */ 479 + { 0x94, 0x00 }, /* LATIN LETTER GLOTTAL STOP -> ... */ 480 + { 0x96, 0x3F }, /* LATIN LETTER INVERTED GLOTTAL STOP -> '?' */ 481 + { 0x97, 0x43 }, /* LATIN LETTER STRETCHED C -> 'C' */ 482 + { 0x98, 0x40 }, /* LATIN LETTER BILABIAL CLICK -> '@' */ 483 + { 0x99, 0x42 }, /* LATIN LETTER SMALL CAPITAL B -> 'B' */ 484 + { 0x9A, 0x45 }, /* LATIN SMALL LETTER CLOSED OPEN E -> 'E' */ 485 + { 0x9B, 0x47 }, /* LATIN LETTER SMALL CAPITAL G WITH HOOK -> 'G' */ 486 + { 0x9C, 0x48 }, /* LATIN LETTER SMALL CAPITAL H -> 'H' */ 487 + { 0x9D, 0x6A }, /* LATIN SMALL LETTER J WITH CROSSED-TAIL -> 'j' */ 488 + { 0x9E, 0x6B }, /* LATIN SMALL LETTER TURNED K -> 'k' */ 489 + { 0x9F, 0x4C }, /* LATIN LETTER SMALL CAPITAL L -> 'L' */ 490 + { 0xA0, 0x71 }, /* LATIN SMALL LETTER Q WITH HOOK -> 'q' */ 491 + { 0xA1, 0x3F }, /* LATIN LETTER GLOTTAL STOP WITH STROKE -> '?' */ 492 + { 0xA2, 0x3F }, /* LATIN LETTER REVERSED GLOTTAL STOP WITH STROKE -> '?' */ 493 + { 0xAE, 0x00 }, /* LATIN SMALL LETTER TURNED H WITH FISHHOOK -> ... */ 494 + { 0xB1, 0x68 }, /* MODIFIER LETTER SMALL H WITH HOOK -> 'h' */ 495 + { 0xB2, 0x6A }, /* MODIFIER LETTER SMALL J -> 'j' */ 496 + { 0xB3, 0x00 }, /* MODIFIER LETTER SMALL R -> ... */ 497 + { 0xB6, 0x72 }, /* MODIFIER LETTER SMALL CAPITAL INVERTED R -> 'r' */ 498 + { 0xB7, 0x77 }, /* MODIFIER LETTER SMALL W -> 'w' */ 499 + { 0xB8, 0x79 }, /* MODIFIER LETTER SMALL Y -> 'y' */ 500 + { 0xB9, 0x27 }, /* MODIFIER LETTER PRIME -> ''' */ 501 + { 0xBA, 0x22 }, /* MODIFIER LETTER DOUBLE PRIME -> '"' */ 502 + { 0xBB, 0x60 }, /* MODIFIER LETTER TURNED COMMA -> '`' */ 503 + { 0xBC, 0x27 }, /* MODIFIER LETTER APOSTROPHE -> ''' */ 504 + { 0xBD, 0x60 }, /* MODIFIER LETTER REVERSED COMMA -> '`' */ 505 + { 0xBE, 0x60 }, /* MODIFIER LETTER RIGHT HALF RING -> '`' */ 506 + { 0xBF, 0x27 }, /* MODIFIER LETTER LEFT HALF RING -> ''' */ 507 + { 0xC0, 0x3F }, /* MODIFIER LETTER GLOTTAL STOP -> '?' */ 508 + { 0xC1, 0x3F }, /* MODIFIER LETTER REVERSED GLOTTAL STOP -> '?' */ 509 + { 0xC2, 0x3C }, /* MODIFIER LETTER LEFT ARROWHEAD -> '<' */ 510 + { 0xC3, 0x3E }, /* MODIFIER LETTER RIGHT ARROWHEAD -> '>' */ 511 + { 0xC4, 0x5E }, /* MODIFIER LETTER UP ARROWHEAD -> '^' */ 512 + { 0xC5, 0x56 }, /* MODIFIER LETTER DOWN ARROWHEAD -> 'V' */ 513 + { 0xC6, 0x5E }, /* MODIFIER LETTER CIRCUMFLEX ACCENT -> '^' */ 514 + { 0xC7, 0x56 }, /* CARON -> 'V' */ 515 + { 0xC8, 0x27 }, /* MODIFIER LETTER VERTICAL LINE -> ''' */ 516 + { 0xC9, 0x2D }, /* MODIFIER LETTER MACRON -> '-' */ 517 + { 0xCA, 0x2F }, /* MODIFIER LETTER ACUTE ACCENT -> '/' */ 518 + { 0xCB, 0x5C }, /* MODIFIER LETTER GRAVE ACCENT -> '\' */ 519 + { 0xCC, 0x2C }, /* MODIFIER LETTER LOW VERTICAL LINE -> ',' */ 520 + { 0xCD, 0x5F }, /* MODIFIER LETTER LOW MACRON -> '_' */ 521 + { 0xCE, 0x5C }, /* MODIFIER LETTER LOW GRAVE ACCENT -> '\' */ 522 + { 0xCF, 0x2F }, /* MODIFIER LETTER LOW ACUTE ACCENT -> '/' */ 523 + { 0xD0, 0x3A }, /* MODIFIER LETTER TRIANGULAR COLON -> ':' */ 524 + { 0xD1, 0x2E }, /* MODIFIER LETTER HALF TRIANGULAR COLON -> '.' */ 525 + { 0xD2, 0x60 }, /* MODIFIER LETTER CENTRED RIGHT HALF RING -> '`' */ 526 + { 0xD3, 0x27 }, /* MODIFIER LETTER CENTRED LEFT HALF RING -> ''' */ 527 + { 0xD4, 0x5E }, /* MODIFIER LETTER UP TACK -> '^' */ 528 + { 0xD5, 0x56 }, /* MODIFIER LETTER DOWN TACK -> 'V' */ 529 + { 0xD6, 0x2B }, /* MODIFIER LETTER PLUS SIGN -> '+' */ 530 + { 0xD7, 0x2D }, /* MODIFIER LETTER MINUS SIGN -> '-' */ 531 + { 0xD8, 0x56 }, /* BREVE -> 'V' */ 532 + { 0xD9, 0x2E }, /* DOT ABOVE -> '.' */ 533 + { 0xDA, 0x40 }, /* RING ABOVE -> '@' */ 534 + { 0xDB, 0x2C }, /* OGONEK -> ',' */ 535 + { 0xDC, 0x7E }, /* SMALL TILDE -> '~' */ 536 + { 0xDD, 0x22 }, /* DOUBLE ACUTE ACCENT -> '"' */ 537 + { 0xDE, 0x52 }, /* MODIFIER LETTER RHOTIC HOOK -> 'R' */ 538 + { 0xDF, 0x58 }, /* MODIFIER LETTER CROSS ACCENT -> 'X' */ 539 + { 0xE0, 0x47 }, /* MODIFIER LETTER SMALL GAMMA -> 'G' */ 540 + { 0xE1, 0x6C }, /* MODIFIER LETTER SMALL L -> 'l' */ 541 + { 0xE2, 0x73 }, /* MODIFIER LETTER SMALL S -> 's' */ 542 + { 0xE3, 0x78 }, /* MODIFIER LETTER SMALL X -> 'x' */ 543 + { 0xE4, 0x3F }, /* MODIFIER LETTER SMALL REVERSED GLOTTAL STOP -> '?' */ 544 + { 0xEC, 0x56 }, /* MODIFIER LETTER VOICING -> 'V' */ 545 + { 0xED, 0x3D }, /* MODIFIER LETTER UNASPIRATED -> '=' */ 546 + { 0xEE, 0x22 }, /* MODIFIER LETTER DOUBLE APOSTROPHE -> '"' */ 547 + /* Entries for page 0x03 */ 548 + { 0x63, 0x61 }, /* COMBINING LATIN SMALL LETTER A -> 'a' */ 549 + { 0x64, 0x65 }, /* COMBINING LATIN SMALL LETTER E -> 'e' */ 550 + { 0x65, 0x69 }, /* COMBINING LATIN SMALL LETTER I -> 'i' */ 551 + { 0x66, 0x6F }, /* COMBINING LATIN SMALL LETTER O -> 'o' */ 552 + { 0x67, 0x75 }, /* COMBINING LATIN SMALL LETTER U -> 'u' */ 553 + { 0x68, 0x63 }, /* COMBINING LATIN SMALL LETTER C -> 'c' */ 554 + { 0x69, 0x64 }, /* COMBINING LATIN SMALL LETTER D -> 'd' */ 555 + { 0x6A, 0x68 }, /* COMBINING LATIN SMALL LETTER H -> 'h' */ 556 + { 0x6B, 0x6D }, /* COMBINING LATIN SMALL LETTER M -> 'm' */ 557 + { 0x6C, 0x72 }, /* COMBINING LATIN SMALL LETTER R -> 'r' */ 558 + { 0x6D, 0x74 }, /* COMBINING LATIN SMALL LETTER T -> 't' */ 559 + { 0x6E, 0x76 }, /* COMBINING LATIN SMALL LETTER V -> 'v' */ 560 + { 0x6F, 0x78 }, /* COMBINING LATIN SMALL LETTER X -> 'x' */ 561 + { 0x74, 0x27 }, /* GREEK NUMERAL SIGN -> ''' */ 562 + { 0x75, 0x2C }, /* GREEK LOWER NUMERAL SIGN -> ',' */ 563 + { 0x7E, 0x3F }, /* GREEK QUESTION MARK -> '?' */ 564 + { 0x86, 0x41 }, /* GREEK CAPITAL LETTER ALPHA WITH TONOS -> 'A' */ 565 + { 0x87, 0x3B }, /* GREEK ANO TELEIA -> ';' */ 566 + { 0x88, 0x45 }, /* GREEK CAPITAL LETTER EPSILON WITH TONOS -> 'E' */ 567 + { 0x89, 0x45 }, /* GREEK CAPITAL LETTER ETA WITH TONOS -> 'E' */ 568 + { 0x8A, 0x49 }, /* GREEK CAPITAL LETTER IOTA WITH TONOS -> 'I' */ 569 + { 0x8C, 0x4F }, /* GREEK CAPITAL LETTER OMICRON WITH TONOS -> 'O' */ 570 + { 0x8E, 0x55 }, /* GREEK CAPITAL LETTER UPSILON WITH TONOS -> 'U' */ 571 + { 0x8F, 0x4F }, /* GREEK CAPITAL LETTER OMEGA WITH TONOS -> 'O' */ 572 + { 0x90, 0x49 }, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS -> 'I' */ 573 + { 0x91, 0x41 }, /* GREEK CAPITAL LETTER ALPHA -> 'A' */ 574 + { 0x92, 0x42 }, /* GREEK CAPITAL LETTER BETA -> 'B' */ 575 + { 0x93, 0x47 }, /* GREEK CAPITAL LETTER GAMMA -> 'G' */ 576 + { 0x94, 0x44 }, /* GREEK CAPITAL LETTER DELTA -> 'D' */ 577 + { 0x95, 0x45 }, /* GREEK CAPITAL LETTER EPSILON -> 'E' */ 578 + { 0x96, 0x5A }, /* GREEK CAPITAL LETTER ZETA -> 'Z' */ 579 + { 0x97, 0x45 }, /* GREEK CAPITAL LETTER ETA -> 'E' */ 580 + { 0x99, 0x49 }, /* GREEK CAPITAL LETTER IOTA -> 'I' */ 581 + { 0x9A, 0x4B }, /* GREEK CAPITAL LETTER KAPPA -> 'K' */ 582 + { 0x9B, 0x4C }, /* GREEK CAPITAL LETTER LAMDA -> 'L' */ 583 + { 0x9C, 0x4D }, /* GREEK CAPITAL LETTER MU -> 'M' */ 584 + { 0x9D, 0x4E }, /* GREEK CAPITAL LETTER NU -> 'N' */ 585 + { 0x9F, 0x4F }, /* GREEK CAPITAL LETTER OMICRON -> 'O' */ 586 + { 0xA0, 0x50 }, /* GREEK CAPITAL LETTER PI -> 'P' */ 587 + { 0xA1, 0x52 }, /* GREEK CAPITAL LETTER RHO -> 'R' */ 588 + { 0xA3, 0x53 }, /* GREEK CAPITAL LETTER SIGMA -> 'S' */ 589 + { 0xA4, 0x54 }, /* GREEK CAPITAL LETTER TAU -> 'T' */ 590 + { 0xA5, 0x55 }, /* GREEK CAPITAL LETTER UPSILON -> 'U' */ 591 + { 0xA9, 0x4F }, /* GREEK CAPITAL LETTER OMEGA -> 'O' */ 592 + { 0xAA, 0x49 }, /* GREEK CAPITAL LETTER IOTA WITH DIALYTIKA -> 'I' */ 593 + { 0xAB, 0x55 }, /* GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA -> 'U' */ 594 + { 0xAC, 0x61 }, /* GREEK SMALL LETTER ALPHA WITH TONOS -> 'a' */ 595 + { 0xAD, 0x65 }, /* GREEK SMALL LETTER EPSILON WITH TONOS -> 'e' */ 596 + { 0xAE, 0x65 }, /* GREEK SMALL LETTER ETA WITH TONOS -> 'e' */ 597 + { 0xAF, 0x69 }, /* GREEK SMALL LETTER IOTA WITH TONOS -> 'i' */ 598 + { 0xB0, 0x75 }, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS -> 'u' */ 599 + { 0xB1, 0x61 }, /* GREEK SMALL LETTER ALPHA -> 'a' */ 600 + { 0xB2, 0x62 }, /* GREEK SMALL LETTER BETA -> 'b' */ 601 + { 0xB3, 0x67 }, /* GREEK SMALL LETTER GAMMA -> 'g' */ 602 + { 0xB4, 0x64 }, /* GREEK SMALL LETTER DELTA -> 'd' */ 603 + { 0xB5, 0x65 }, /* GREEK SMALL LETTER EPSILON -> 'e' */ 604 + { 0xB6, 0x7A }, /* GREEK SMALL LETTER ZETA -> 'z' */ 605 + { 0xB7, 0x65 }, /* GREEK SMALL LETTER ETA -> 'e' */ 606 + { 0xB9, 0x69 }, /* GREEK SMALL LETTER IOTA -> 'i' */ 607 + { 0xBA, 0x6B }, /* GREEK SMALL LETTER KAPPA -> 'k' */ 608 + { 0xBB, 0x6C }, /* GREEK SMALL LETTER LAMDA -> 'l' */ 609 + { 0xBC, 0x6D }, /* GREEK SMALL LETTER MU -> 'm' */ 610 + { 0xBD, 0x6E }, /* GREEK SMALL LETTER NU -> 'n' */ 611 + { 0xBE, 0x78 }, /* GREEK SMALL LETTER XI -> 'x' */ 612 + { 0xBF, 0x6F }, /* GREEK SMALL LETTER OMICRON -> 'o' */ 613 + { 0xC0, 0x70 }, /* GREEK SMALL LETTER PI -> 'p' */ 614 + { 0xC1, 0x72 }, /* GREEK SMALL LETTER RHO -> 'r' */ 615 + { 0xC2, 0x73 }, /* GREEK SMALL LETTER FINAL SIGMA -> 's' */ 616 + { 0xC3, 0x73 }, /* GREEK SMALL LETTER SIGMA -> 's' */ 617 + { 0xC4, 0x74 }, /* GREEK SMALL LETTER TAU -> 't' */ 618 + { 0xC5, 0x75 }, /* GREEK SMALL LETTER UPSILON -> 'u' */ 619 + { 0xC9, 0x6F }, /* GREEK SMALL LETTER OMEGA -> 'o' */ 620 + { 0xCA, 0x69 }, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA -> 'i' */ 621 + { 0xCB, 0x75 }, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA -> 'u' */ 622 + { 0xCC, 0x6F }, /* GREEK SMALL LETTER OMICRON WITH TONOS -> 'o' */ 623 + { 0xCD, 0x75 }, /* GREEK SMALL LETTER UPSILON WITH TONOS -> 'u' */ 624 + { 0xCE, 0x6F }, /* GREEK SMALL LETTER OMEGA WITH TONOS -> 'o' */ 625 + { 0xD0, 0x62 }, /* GREEK BETA SYMBOL -> 'b' */ 626 + { 0xD2, 0x00 }, /* GREEK UPSILON WITH HOOK SYMBOL -> ... */ 627 + { 0xD4, 0x55 }, /* GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL -> 'U' */ 628 + { 0xD6, 0x70 }, /* GREEK PI SYMBOL -> 'p' */ 629 + { 0xD7, 0x26 }, /* GREEK KAI SYMBOL -> '&' */ 630 + { 0xDC, 0x57 }, /* GREEK LETTER DIGAMMA -> 'W' */ 631 + { 0xDD, 0x77 }, /* GREEK SMALL LETTER DIGAMMA -> 'w' */ 632 + { 0xDE, 0x51 }, /* GREEK LETTER KOPPA -> 'Q' */ 633 + { 0xDF, 0x71 }, /* GREEK SMALL LETTER KOPPA -> 'q' */ 634 + { 0xE4, 0x46 }, /* COPTIC CAPITAL LETTER FEI -> 'F' */ 635 + { 0xE5, 0x66 }, /* COPTIC SMALL LETTER FEI -> 'f' */ 636 + { 0xE8, 0x48 }, /* COPTIC CAPITAL LETTER HORI -> 'H' */ 637 + { 0xE9, 0x68 }, /* COPTIC SMALL LETTER HORI -> 'h' */ 638 + { 0xEA, 0x47 }, /* COPTIC CAPITAL LETTER GANGIA -> 'G' */ 639 + { 0xEB, 0x67 }, /* COPTIC SMALL LETTER GANGIA -> 'g' */ 640 + { 0xF0, 0x6B }, /* GREEK KAPPA SYMBOL -> 'k' */ 641 + { 0xF1, 0x72 }, /* GREEK RHO SYMBOL -> 'r' */ 642 + { 0xF2, 0x63 }, /* GREEK LUNATE SIGMA SYMBOL -> 'c' */ 643 + { 0xF3, 0x6A }, /* GREEK LETTER YOT -> 'j' */ 644 + /* Entries for page 0x04 */ 645 + { 0x06, 0x49 }, /* CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I -> 'I' */ 646 + { 0x08, 0x4A }, /* CYRILLIC CAPITAL LETTER JE -> 'J' */ 647 + { 0x0D, 0x49 }, /* CYRILLIC CAPITAL LETTER I WITH GRAVE -> 'I' */ 648 + { 0x0E, 0x55 }, /* CYRILLIC CAPITAL LETTER SHORT U -> 'U' */ 649 + { 0x10, 0x41 }, /* CYRILLIC CAPITAL LETTER A -> 'A' */ 650 + { 0x11, 0x42 }, /* CYRILLIC CAPITAL LETTER BE -> 'B' */ 651 + { 0x12, 0x56 }, /* CYRILLIC CAPITAL LETTER VE -> 'V' */ 652 + { 0x13, 0x47 }, /* CYRILLIC CAPITAL LETTER GHE -> 'G' */ 653 + { 0x14, 0x44 }, /* CYRILLIC CAPITAL LETTER DE -> 'D' */ 654 + { 0x15, 0x45 }, /* CYRILLIC CAPITAL LETTER IE -> 'E' */ 655 + { 0x17, 0x5A }, /* CYRILLIC CAPITAL LETTER ZE -> 'Z' */ 656 + { 0x18, 0x49 }, /* CYRILLIC CAPITAL LETTER I -> 'I' */ 657 + { 0x19, 0x49 }, /* CYRILLIC CAPITAL LETTER SHORT I -> 'I' */ 658 + { 0x1A, 0x4B }, /* CYRILLIC CAPITAL LETTER KA -> 'K' */ 659 + { 0x1B, 0x4C }, /* CYRILLIC CAPITAL LETTER EL -> 'L' */ 660 + { 0x1C, 0x4D }, /* CYRILLIC CAPITAL LETTER EM -> 'M' */ 661 + { 0x1D, 0x4E }, /* CYRILLIC CAPITAL LETTER EN -> 'N' */ 662 + { 0x1E, 0x4F }, /* CYRILLIC CAPITAL LETTER O -> 'O' */ 663 + { 0x1F, 0x50 }, /* CYRILLIC CAPITAL LETTER PE -> 'P' */ 664 + { 0x20, 0x52 }, /* CYRILLIC CAPITAL LETTER ER -> 'R' */ 665 + { 0x21, 0x53 }, /* CYRILLIC CAPITAL LETTER ES -> 'S' */ 666 + { 0x22, 0x54 }, /* CYRILLIC CAPITAL LETTER TE -> 'T' */ 667 + { 0x23, 0x55 }, /* CYRILLIC CAPITAL LETTER U -> 'U' */ 668 + { 0x24, 0x46 }, /* CYRILLIC CAPITAL LETTER EF -> 'F' */ 669 + { 0x2A, 0x27 }, /* CYRILLIC CAPITAL LETTER HARD SIGN -> ''' */ 670 + { 0x2B, 0x59 }, /* CYRILLIC CAPITAL LETTER YERU -> 'Y' */ 671 + { 0x2C, 0x27 }, /* CYRILLIC CAPITAL LETTER SOFT SIGN -> ''' */ 672 + { 0x2D, 0x45 }, /* CYRILLIC CAPITAL LETTER E -> 'E' */ 673 + { 0x30, 0x61 }, /* CYRILLIC SMALL LETTER A -> 'a' */ 674 + { 0x31, 0x62 }, /* CYRILLIC SMALL LETTER BE -> 'b' */ 675 + { 0x32, 0x76 }, /* CYRILLIC SMALL LETTER VE -> 'v' */ 676 + { 0x33, 0x67 }, /* CYRILLIC SMALL LETTER GHE -> 'g' */ 677 + { 0x34, 0x64 }, /* CYRILLIC SMALL LETTER DE -> 'd' */ 678 + { 0x35, 0x65 }, /* CYRILLIC SMALL LETTER IE -> 'e' */ 679 + { 0x37, 0x7A }, /* CYRILLIC SMALL LETTER ZE -> 'z' */ 680 + { 0x38, 0x69 }, /* CYRILLIC SMALL LETTER I -> 'i' */ 681 + { 0x39, 0x69 }, /* CYRILLIC SMALL LETTER SHORT I -> 'i' */ 682 + { 0x3A, 0x6B }, /* CYRILLIC SMALL LETTER KA -> 'k' */ 683 + { 0x3B, 0x6C }, /* CYRILLIC SMALL LETTER EL -> 'l' */ 684 + { 0x3C, 0x6D }, /* CYRILLIC SMALL LETTER EM -> 'm' */ 685 + { 0x3D, 0x6E }, /* CYRILLIC SMALL LETTER EN -> 'n' */ 686 + { 0x3E, 0x6F }, /* CYRILLIC SMALL LETTER O -> 'o' */ 687 + { 0x3F, 0x70 }, /* CYRILLIC SMALL LETTER PE -> 'p' */ 688 + { 0x40, 0x72 }, /* CYRILLIC SMALL LETTER ER -> 'r' */ 689 + { 0x41, 0x73 }, /* CYRILLIC SMALL LETTER ES -> 's' */ 690 + { 0x42, 0x74 }, /* CYRILLIC SMALL LETTER TE -> 't' */ 691 + { 0x43, 0x75 }, /* CYRILLIC SMALL LETTER U -> 'u' */ 692 + { 0x44, 0x66 }, /* CYRILLIC SMALL LETTER EF -> 'f' */ 693 + { 0x4A, 0x27 }, /* CYRILLIC SMALL LETTER HARD SIGN -> ''' */ 694 + { 0x4B, 0x79 }, /* CYRILLIC SMALL LETTER YERU -> 'y' */ 695 + { 0x4C, 0x27 }, /* CYRILLIC SMALL LETTER SOFT SIGN -> ''' */ 696 + { 0x4D, 0x65 }, /* CYRILLIC SMALL LETTER E -> 'e' */ 697 + { 0x56, 0x69 }, /* CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I -> 'i' */ 698 + { 0x58, 0x6A }, /* CYRILLIC SMALL LETTER JE -> 'j' */ 699 + { 0x5D, 0x69 }, /* CYRILLIC SMALL LETTER I WITH GRAVE -> 'i' */ 700 + { 0x5E, 0x75 }, /* CYRILLIC SMALL LETTER SHORT U -> 'u' */ 701 + { 0x60, 0x4F }, /* CYRILLIC CAPITAL LETTER OMEGA -> 'O' */ 702 + { 0x61, 0x6F }, /* CYRILLIC SMALL LETTER OMEGA -> 'o' */ 703 + { 0x62, 0x45 }, /* CYRILLIC CAPITAL LETTER YAT -> 'E' */ 704 + { 0x63, 0x65 }, /* CYRILLIC SMALL LETTER YAT -> 'e' */ 705 + { 0x66, 0x45 }, /* CYRILLIC CAPITAL LETTER LITTLE YUS -> 'E' */ 706 + { 0x67, 0x65 }, /* CYRILLIC SMALL LETTER LITTLE YUS -> 'e' */ 707 + { 0x6A, 0x4F }, /* CYRILLIC CAPITAL LETTER BIG YUS -> 'O' */ 708 + { 0x6B, 0x6F }, /* CYRILLIC SMALL LETTER BIG YUS -> 'o' */ 709 + { 0x72, 0x46 }, /* CYRILLIC CAPITAL LETTER FITA -> 'F' */ 710 + { 0x73, 0x66 }, /* CYRILLIC SMALL LETTER FITA -> 'f' */ 711 + { 0x74, 0x59 }, /* CYRILLIC CAPITAL LETTER IZHITSA -> 'Y' */ 712 + { 0x75, 0x79 }, /* CYRILLIC SMALL LETTER IZHITSA -> 'y' */ 713 + { 0x76, 0x59 }, /* CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT -> 'Y' */ 714 + { 0x77, 0x79 }, /* CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT -> 'y' */ 715 + { 0x78, 0x75 }, /* CYRILLIC CAPITAL LETTER UK -> 'u' */ 716 + { 0x79, 0x75 }, /* CYRILLIC SMALL LETTER UK -> 'u' */ 717 + { 0x7A, 0x4F }, /* CYRILLIC CAPITAL LETTER ROUND OMEGA -> 'O' */ 718 + { 0x7B, 0x6F }, /* CYRILLIC SMALL LETTER ROUND OMEGA -> 'o' */ 719 + { 0x7C, 0x4F }, /* CYRILLIC CAPITAL LETTER OMEGA WITH TITLO -> 'O' */ 720 + { 0x7D, 0x6F }, /* CYRILLIC SMALL LETTER OMEGA WITH TITLO -> 'o' */ 721 + { 0x80, 0x51 }, /* CYRILLIC CAPITAL LETTER KOPPA -> 'Q' */ 722 + { 0x81, 0x71 }, /* CYRILLIC SMALL LETTER KOPPA -> 'q' */ 723 + { 0x8C, 0x22 }, /* CYRILLIC CAPITAL LETTER SEMISOFT SIGN -> '"' */ 724 + { 0x8D, 0x22 }, /* CYRILLIC SMALL LETTER SEMISOFT SIGN -> '"' */ 725 + { 0xAE, 0x55 }, /* CYRILLIC CAPITAL LETTER STRAIGHT U -> 'U' */ 726 + { 0xAF, 0x75 }, /* CYRILLIC SMALL LETTER STRAIGHT U -> 'u' */ 727 + { 0xBA, 0x48 }, /* CYRILLIC CAPITAL LETTER SHHA -> 'H' */ 728 + { 0xBB, 0x68 }, /* CYRILLIC SMALL LETTER SHHA -> 'h' */ 729 + { 0xC0, 0x60 }, /* CYRILLIC LETTER PALOCHKA -> '`' */ 730 + { 0xD0, 0x61 }, /* CYRILLIC CAPITAL LETTER A WITH BREVE -> 'a' */ 731 + { 0xD1, 0x61 }, /* CYRILLIC SMALL LETTER A WITH BREVE -> 'a' */ 732 + { 0xD2, 0x41 }, /* CYRILLIC CAPITAL LETTER A WITH DIAERESIS -> 'A' */ 733 + { 0xD3, 0x61 }, /* CYRILLIC SMALL LETTER A WITH DIAERESIS -> 'a' */ 734 + { 0xD8, 0x00 }, /* CYRILLIC CAPITAL LETTER SCHWA -> ... */ 735 + { 0xDB, 0x40 }, /* CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS -> '@' */ 736 + { 0xDE, 0x5A }, /* CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS -> 'Z' */ 737 + { 0xDF, 0x7A }, /* CYRILLIC SMALL LETTER ZE WITH DIAERESIS -> 'z' */ 738 + { 0xE2, 0x49 }, /* CYRILLIC CAPITAL LETTER I WITH MACRON -> 'I' */ 739 + { 0xE3, 0x69 }, /* CYRILLIC SMALL LETTER I WITH MACRON -> 'i' */ 740 + { 0xE4, 0x49 }, /* CYRILLIC CAPITAL LETTER I WITH DIAERESIS -> 'I' */ 741 + { 0xE5, 0x69 }, /* CYRILLIC SMALL LETTER I WITH DIAERESIS -> 'i' */ 742 + { 0xE6, 0x4F }, /* CYRILLIC CAPITAL LETTER O WITH DIAERESIS -> 'O' */ 743 + { 0xE7, 0x6F }, /* CYRILLIC SMALL LETTER O WITH DIAERESIS -> 'o' */ 744 + { 0xE8, 0x4F }, /* CYRILLIC CAPITAL LETTER BARRED O -> 'O' */ 745 + { 0xE9, 0x6F }, /* CYRILLIC SMALL LETTER BARRED O -> 'o' */ 746 + { 0xEA, 0x4F }, /* CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS -> 'O' */ 747 + { 0xEB, 0x6F }, /* CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS -> 'o' */ 748 + { 0xEC, 0x45 }, /* CYRILLIC CAPITAL LETTER E WITH DIAERESIS -> 'E' */ 749 + { 0xED, 0x65 }, /* CYRILLIC SMALL LETTER E WITH DIAERESIS -> 'e' */ 750 + { 0xEE, 0x55 }, /* CYRILLIC CAPITAL LETTER U WITH MACRON -> 'U' */ 751 + { 0xEF, 0x75 }, /* CYRILLIC SMALL LETTER U WITH MACRON -> 'u' */ 752 + { 0xF0, 0x55 }, /* CYRILLIC CAPITAL LETTER U WITH DIAERESIS -> 'U' */ 753 + { 0xF1, 0x75 }, /* CYRILLIC SMALL LETTER U WITH DIAERESIS -> 'u' */ 754 + { 0xF2, 0x55 }, /* CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE -> 'U' */ 755 + { 0xF3, 0x75 }, /* CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE -> 'u' */ 756 + { 0xF8, 0x59 }, /* CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS -> 'Y' */ 757 + { 0xF9, 0x79 }, /* CYRILLIC SMALL LETTER YERU WITH DIAERESIS -> 'y' */ 758 + /* Entries for page 0x05 */ 759 + { 0x31, 0x41 }, /* ARMENIAN CAPITAL LETTER AYB -> 'A' */ 760 + { 0x32, 0x42 }, /* ARMENIAN CAPITAL LETTER BEN -> 'B' */ 761 + { 0x33, 0x47 }, /* ARMENIAN CAPITAL LETTER GIM -> 'G' */ 762 + { 0x34, 0x44 }, /* ARMENIAN CAPITAL LETTER DA -> 'D' */ 763 + { 0x35, 0x45 }, /* ARMENIAN CAPITAL LETTER ECH -> 'E' */ 764 + { 0x36, 0x5A }, /* ARMENIAN CAPITAL LETTER ZA -> 'Z' */ 765 + { 0x37, 0x45 }, /* ARMENIAN CAPITAL LETTER EH -> 'E' */ 766 + { 0x38, 0x45 }, /* ARMENIAN CAPITAL LETTER ET -> 'E' */ 767 + { 0x3B, 0x49 }, /* ARMENIAN CAPITAL LETTER INI -> 'I' */ 768 + { 0x3C, 0x4C }, /* ARMENIAN CAPITAL LETTER LIWN -> 'L' */ 769 + { 0x3F, 0x4B }, /* ARMENIAN CAPITAL LETTER KEN -> 'K' */ 770 + { 0x40, 0x48 }, /* ARMENIAN CAPITAL LETTER HO -> 'H' */ 771 + { 0x44, 0x4D }, /* ARMENIAN CAPITAL LETTER MEN -> 'M' */ 772 + { 0x45, 0x59 }, /* ARMENIAN CAPITAL LETTER YI -> 'Y' */ 773 + { 0x46, 0x4E }, /* ARMENIAN CAPITAL LETTER NOW -> 'N' */ 774 + { 0x48, 0x4F }, /* ARMENIAN CAPITAL LETTER VO -> 'O' */ 775 + { 0x4A, 0x50 }, /* ARMENIAN CAPITAL LETTER PEH -> 'P' */ 776 + { 0x4B, 0x4A }, /* ARMENIAN CAPITAL LETTER JHEH -> 'J' */ 777 + { 0x4D, 0x53 }, /* ARMENIAN CAPITAL LETTER SEH -> 'S' */ 778 + { 0x4E, 0x56 }, /* ARMENIAN CAPITAL LETTER VEW -> 'V' */ 779 + { 0x4F, 0x54 }, /* ARMENIAN CAPITAL LETTER TIWN -> 'T' */ 780 + { 0x50, 0x52 }, /* ARMENIAN CAPITAL LETTER REH -> 'R' */ 781 + { 0x52, 0x57 }, /* ARMENIAN CAPITAL LETTER YIWN -> 'W' */ 782 + { 0x55, 0x4F }, /* ARMENIAN CAPITAL LETTER OH -> 'O' */ 783 + { 0x56, 0x46 }, /* ARMENIAN CAPITAL LETTER FEH -> 'F' */ 784 + { 0x59, 0x3C }, /* ARMENIAN MODIFIER LETTER LEFT HALF RING -> '<' */ 785 + { 0x5A, 0x27 }, /* ARMENIAN APOSTROPHE -> ''' */ 786 + { 0x5B, 0x2F }, /* ARMENIAN EMPHASIS MARK -> '/' */ 787 + { 0x5C, 0x21 }, /* ARMENIAN EXCLAMATION MARK -> '!' */ 788 + { 0x5D, 0x2C }, /* ARMENIAN COMMA -> ',' */ 789 + { 0x5E, 0x3F }, /* ARMENIAN QUESTION MARK -> '?' */ 790 + { 0x5F, 0x2E }, /* ARMENIAN ABBREVIATION MARK -> '.' */ 791 + { 0x61, 0x61 }, /* ARMENIAN SMALL LETTER AYB -> 'a' */ 792 + { 0x62, 0x62 }, /* ARMENIAN SMALL LETTER BEN -> 'b' */ 793 + { 0x63, 0x67 }, /* ARMENIAN SMALL LETTER GIM -> 'g' */ 794 + { 0x64, 0x64 }, /* ARMENIAN SMALL LETTER DA -> 'd' */ 795 + { 0x65, 0x65 }, /* ARMENIAN SMALL LETTER ECH -> 'e' */ 796 + { 0x66, 0x7A }, /* ARMENIAN SMALL LETTER ZA -> 'z' */ 797 + { 0x67, 0x65 }, /* ARMENIAN SMALL LETTER EH -> 'e' */ 798 + { 0x68, 0x65 }, /* ARMENIAN SMALL LETTER ET -> 'e' */ 799 + { 0x6B, 0x69 }, /* ARMENIAN SMALL LETTER INI -> 'i' */ 800 + { 0x6C, 0x6C }, /* ARMENIAN SMALL LETTER LIWN -> 'l' */ 801 + { 0x6F, 0x6B }, /* ARMENIAN SMALL LETTER KEN -> 'k' */ 802 + { 0x70, 0x68 }, /* ARMENIAN SMALL LETTER HO -> 'h' */ 803 + { 0x74, 0x6D }, /* ARMENIAN SMALL LETTER MEN -> 'm' */ 804 + { 0x75, 0x79 }, /* ARMENIAN SMALL LETTER YI -> 'y' */ 805 + { 0x76, 0x6E }, /* ARMENIAN SMALL LETTER NOW -> 'n' */ 806 + { 0x78, 0x6F }, /* ARMENIAN SMALL LETTER VO -> 'o' */ 807 + { 0x7A, 0x70 }, /* ARMENIAN SMALL LETTER PEH -> 'p' */ 808 + { 0x7B, 0x6A }, /* ARMENIAN SMALL LETTER JHEH -> 'j' */ 809 + { 0x7D, 0x73 }, /* ARMENIAN SMALL LETTER SEH -> 's' */ 810 + { 0x7E, 0x76 }, /* ARMENIAN SMALL LETTER VEW -> 'v' */ 811 + { 0x7F, 0x74 }, /* ARMENIAN SMALL LETTER TIWN -> 't' */ 812 + { 0x80, 0x72 }, /* ARMENIAN SMALL LETTER REH -> 'r' */ 813 + { 0x82, 0x77 }, /* ARMENIAN SMALL LETTER YIWN -> 'w' */ 814 + { 0x85, 0x6F }, /* ARMENIAN SMALL LETTER OH -> 'o' */ 815 + { 0x86, 0x66 }, /* ARMENIAN SMALL LETTER FEH -> 'f' */ 816 + { 0x89, 0x3A }, /* ARMENIAN FULL STOP -> ':' */ 817 + { 0x8A, 0x2D }, /* ARMENIAN HYPHEN -> '-' */ 818 + { 0xB1, 0x65 }, /* HEBREW POINT HATAF SEGOL -> 'e' */ 819 + { 0xB2, 0x61 }, /* HEBREW POINT HATAF PATAH -> 'a' */ 820 + { 0xB3, 0x6F }, /* HEBREW POINT HATAF QAMATS -> 'o' */ 821 + { 0xB4, 0x69 }, /* HEBREW POINT HIRIQ -> 'i' */ 822 + { 0xB5, 0x65 }, /* HEBREW POINT TSERE -> 'e' */ 823 + { 0xB6, 0x65 }, /* HEBREW POINT SEGOL -> 'e' */ 824 + { 0xB7, 0x61 }, /* HEBREW POINT PATAH -> 'a' */ 825 + { 0xB8, 0x61 }, /* HEBREW POINT QAMATS -> 'a' */ 826 + { 0xB9, 0x6F }, /* HEBREW POINT HOLAM -> 'o' */ 827 + { 0xBA, 0x6F }, /* HEBREW POINT HOLAM HASER FOR VAV -> 'o' */ 828 + { 0xBB, 0x75 }, /* HEBREW POINT QUBUTS -> 'u' */ 829 + { 0xBE, 0x2D }, /* HEBREW PUNCTUATION MAQAF -> '-' */ 830 + { 0xC0, 0x7C }, /* HEBREW PUNCTUATION PASEQ -> '|' */ 831 + { 0xC3, 0x2E }, /* HEBREW PUNCTUATION SOF PASUQ -> '.' */ 832 + { 0xC6, 0x6E }, /* HEBREW PUNCTUATION NUN HAFUKHA -> 'n' */ 833 + { 0xC7, 0x6F }, /* HEBREW POINT QAMATS QATAN -> 'o' */ 834 + { 0xD0, 0x41 }, /* HEBREW LETTER ALEF -> 'A' */ 835 + { 0xD1, 0x62 }, /* HEBREW LETTER BET -> 'b' */ 836 + { 0xD2, 0x67 }, /* HEBREW LETTER GIMEL -> 'g' */ 837 + { 0xD3, 0x64 }, /* HEBREW LETTER DALET -> 'd' */ 838 + { 0xD4, 0x68 }, /* HEBREW LETTER HE -> 'h' */ 839 + { 0xD5, 0x76 }, /* HEBREW LETTER VAV -> 'v' */ 840 + { 0xD6, 0x7A }, /* HEBREW LETTER ZAYIN -> 'z' */ 841 + { 0xD7, 0x48 }, /* HEBREW LETTER HET -> 'H' */ 842 + { 0xD8, 0x54 }, /* HEBREW LETTER TET -> 'T' */ 843 + { 0xD9, 0x79 }, /* HEBREW LETTER YOD -> 'y' */ 844 + { 0xDC, 0x6C }, /* HEBREW LETTER LAMED -> 'l' */ 845 + { 0xDD, 0x6D }, /* HEBREW LETTER FINAL MEM -> 'm' */ 846 + { 0xDE, 0x6D }, /* HEBREW LETTER MEM -> 'm' */ 847 + { 0xDF, 0x6E }, /* HEBREW LETTER FINAL NUN -> 'n' */ 848 + { 0xE0, 0x6E }, /* HEBREW LETTER NUN -> 'n' */ 849 + { 0xE1, 0x73 }, /* HEBREW LETTER SAMEKH -> 's' */ 850 + { 0xE2, 0x60 }, /* HEBREW LETTER AYIN -> '`' */ 851 + { 0xE3, 0x70 }, /* HEBREW LETTER FINAL PE -> 'p' */ 852 + { 0xE4, 0x70 }, /* HEBREW LETTER PE -> 'p' */ 853 + { 0xE7, 0x6B }, /* HEBREW LETTER QOF -> 'k' */ 854 + { 0xE8, 0x72 }, /* HEBREW LETTER RESH -> 'r' */ 855 + { 0xEA, 0x74 }, /* HEBREW LETTER TAV -> 't' */ 856 + { 0xF0, 0x56 }, /* HEBREW LIGATURE YIDDISH DOUBLE VAV -> 'V' */ 857 + { 0xF3, 0x27 }, /* HEBREW PUNCTUATION GERESH -> ''' */ 858 + { 0xF4, 0x22 }, /* HEBREW PUNCTUATION GERSHAYIM -> '"' */ 859 + /* Entries for page 0x06 */ 860 + { 0x0C, 0x2C }, /* ARABIC COMMA -> ',' */ 861 + { 0x1B, 0x3B }, /* ARABIC SEMICOLON -> ';' */ 862 + { 0x1F, 0x3F }, /* ARABIC QUESTION MARK -> '?' */ 863 + { 0x22, 0x61 }, /* ARABIC LETTER ALEF WITH MADDA ABOVE -> 'a' */ 864 + { 0x23, 0x27 }, /* ARABIC LETTER ALEF WITH HAMZA ABOVE -> ''' */ 865 + { 0x28, 0x62 }, /* ARABIC LETTER BEH -> 'b' */ 866 + { 0x29, 0x40 }, /* ARABIC LETTER TEH MARBUTA -> '@' */ 867 + { 0x2A, 0x74 }, /* ARABIC LETTER TEH -> 't' */ 868 + { 0x2C, 0x6A }, /* ARABIC LETTER JEEM -> 'j' */ 869 + { 0x2D, 0x48 }, /* ARABIC LETTER HAH -> 'H' */ 870 + { 0x2F, 0x64 }, /* ARABIC LETTER DAL -> 'd' */ 871 + { 0x31, 0x72 }, /* ARABIC LETTER REH -> 'r' */ 872 + { 0x32, 0x7A }, /* ARABIC LETTER ZAIN -> 'z' */ 873 + { 0x33, 0x73 }, /* ARABIC LETTER SEEN -> 's' */ 874 + { 0x35, 0x53 }, /* ARABIC LETTER SAD -> 'S' */ 875 + { 0x36, 0x44 }, /* ARABIC LETTER DAD -> 'D' */ 876 + { 0x37, 0x54 }, /* ARABIC LETTER TAH -> 'T' */ 877 + { 0x38, 0x5A }, /* ARABIC LETTER ZAH -> 'Z' */ 878 + { 0x39, 0x60 }, /* ARABIC LETTER AIN -> '`' */ 879 + { 0x3A, 0x47 }, /* ARABIC LETTER GHAIN -> 'G' */ 880 + { 0x41, 0x66 }, /* ARABIC LETTER FEH -> 'f' */ 881 + { 0x42, 0x71 }, /* ARABIC LETTER QAF -> 'q' */ 882 + { 0x43, 0x6B }, /* ARABIC LETTER KAF -> 'k' */ 883 + { 0x44, 0x6C }, /* ARABIC LETTER LAM -> 'l' */ 884 + { 0x45, 0x6D }, /* ARABIC LETTER MEEM -> 'm' */ 885 + { 0x46, 0x6E }, /* ARABIC LETTER NOON -> 'n' */ 886 + { 0x47, 0x68 }, /* ARABIC LETTER HEH -> 'h' */ 887 + { 0x48, 0x77 }, /* ARABIC LETTER WAW -> 'w' */ 888 + { 0x49, 0x7E }, /* ARABIC LETTER ALEF MAKSURA -> '~' */ 889 + { 0x4A, 0x79 }, /* ARABIC LETTER YEH -> 'y' */ 890 + { 0x4E, 0x61 }, /* ARABIC FATHA -> 'a' */ 891 + { 0x4F, 0x75 }, /* ARABIC DAMMA -> 'u' */ 892 + { 0x50, 0x69 }, /* ARABIC KASRA -> 'i' */ 893 + { 0x51, 0x57 }, /* ARABIC SHADDA -> 'W' */ 894 + { 0x54, 0x27 }, /* ARABIC HAMZA ABOVE -> ''' */ 895 + { 0x55, 0x27 }, /* ARABIC HAMZA BELOW -> ''' */ 896 + { 0x60, 0x30 }, /* ARABIC-INDIC DIGIT ZERO -> '0' */ 897 + { 0x61, 0x31 }, /* ARABIC-INDIC DIGIT ONE -> '1' */ 898 + { 0x62, 0x32 }, /* ARABIC-INDIC DIGIT TWO -> '2' */ 899 + { 0x63, 0x33 }, /* ARABIC-INDIC DIGIT THREE -> '3' */ 900 + { 0x64, 0x34 }, /* ARABIC-INDIC DIGIT FOUR -> '4' */ 901 + { 0x65, 0x35 }, /* ARABIC-INDIC DIGIT FIVE -> '5' */ 902 + { 0x66, 0x36 }, /* ARABIC-INDIC DIGIT SIX -> '6' */ 903 + { 0x67, 0x37 }, /* ARABIC-INDIC DIGIT SEVEN -> '7' */ 904 + { 0x68, 0x38 }, /* ARABIC-INDIC DIGIT EIGHT -> '8' */ 905 + { 0x69, 0x39 }, /* ARABIC-INDIC DIGIT NINE -> '9' */ 906 + { 0x6A, 0x25 }, /* ARABIC PERCENT SIGN -> '%' */ 907 + { 0x6B, 0x2E }, /* ARABIC DECIMAL SEPARATOR -> '.' */ 908 + { 0x6C, 0x2C }, /* ARABIC THOUSANDS SEPARATOR -> ',' */ 909 + { 0x6D, 0x2A }, /* ARABIC FIVE POINTED STAR -> '*' */ 910 + { 0x71, 0x00 }, /* ARABIC LETTER ALEF WASLA -> ... */ 911 + { 0x73, 0x27 }, /* ARABIC LETTER ALEF WITH WAVY HAMZA BELOW -> ''' */ 912 + { 0x75, 0x27 }, /* ARABIC LETTER HIGH HAMZA ALEF -> ''' */ 913 + { 0x7B, 0x62 }, /* ARABIC LETTER BEEH -> 'b' */ 914 + { 0x7C, 0x74 }, /* ARABIC LETTER TEH WITH RING -> 't' */ 915 + { 0x7D, 0x54 }, /* ARABIC LETTER TEH WITH THREE DOTS ABOVE DOWNWARDS -> 'T' */ 916 + { 0x7E, 0x70 }, /* ARABIC LETTER PEH -> 'p' */ 917 + { 0x82, 0x48 }, /* ARABIC LETTER HAH WITH TWO DOTS VERTICAL ABOVE -> 'H' */ 918 + { 0x85, 0x48 }, /* ARABIC LETTER HAH WITH THREE DOTS ABOVE -> 'H' */ 919 + { 0x89, 0x44 }, /* ARABIC LETTER DAL WITH RING -> 'D' */ 920 + { 0x8A, 0x44 }, /* ARABIC LETTER DAL WITH DOT BELOW -> 'D' */ 921 + { 0x8E, 0x64 }, /* ARABIC LETTER DUL -> 'd' */ 922 + { 0x8F, 0x44 }, /* ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARDS -> 'D' */ 923 + { 0x90, 0x44 }, /* ARABIC LETTER DAL WITH FOUR DOTS ABOVE -> 'D' */ 924 + { 0x92, 0x00 }, /* ARABIC LETTER REH WITH SMALL V -> ... */ 925 + { 0x97, 0x52 }, /* ARABIC LETTER REH WITH TWO DOTS ABOVE -> 'R' */ 926 + { 0x98, 0x6A }, /* ARABIC LETTER JEH -> 'j' */ 927 + { 0x99, 0x52 }, /* ARABIC LETTER REH WITH FOUR DOTS ABOVE -> 'R' */ 928 + { 0x9A, 0x00 }, /* ARABIC LETTER SEEN WITH DOT BELOW AND DOT ABOVE -> ... */ 929 + { 0x9E, 0x53 }, /* ARABIC LETTER SAD WITH THREE DOTS ABOVE -> 'S' */ 930 + { 0x9F, 0x54 }, /* ARABIC LETTER TAH WITH THREE DOTS ABOVE -> 'T' */ 931 + { 0xA1, 0x00 }, /* ARABIC LETTER DOTLESS FEH -> ... */ 932 + { 0xA3, 0x46 }, /* ARABIC LETTER FEH WITH DOT BELOW -> 'F' */ 933 + { 0xA4, 0x76 }, /* ARABIC LETTER VEH -> 'v' */ 934 + { 0xA5, 0x66 }, /* ARABIC LETTER FEH WITH THREE DOTS BELOW -> 'f' */ 935 + { 0xA7, 0x51 }, /* ARABIC LETTER QAF WITH DOT ABOVE -> 'Q' */ 936 + { 0xA8, 0x51 }, /* ARABIC LETTER QAF WITH THREE DOTS ABOVE -> 'Q' */ 937 + { 0xAA, 0x6B }, /* ARABIC LETTER SWASH KAF -> 'k' */ 938 + { 0xAB, 0x4B }, /* ARABIC LETTER KAF WITH RING -> 'K' */ 939 + { 0xAC, 0x4B }, /* ARABIC LETTER KAF WITH DOT ABOVE -> 'K' */ 940 + { 0xAE, 0x4B }, /* ARABIC LETTER KAF WITH THREE DOTS BELOW -> 'K' */ 941 + { 0xAF, 0x67 }, /* ARABIC LETTER GAF -> 'g' */ 942 + { 0xB0, 0x47 }, /* ARABIC LETTER GAF WITH RING -> 'G' */ 943 + { 0xB1, 0x4E }, /* ARABIC LETTER NGOEH -> 'N' */ 944 + { 0xB2, 0x00 }, /* ARABIC LETTER GAF WITH TWO DOTS BELOW -> ... */ 945 + { 0xB4, 0x47 }, /* ARABIC LETTER GAF WITH THREE DOTS ABOVE -> 'G' */ 946 + { 0xB5, 0x00 }, /* ARABIC LETTER LAM WITH SMALL V -> ... */ 947 + { 0xB8, 0x4C }, /* ARABIC LETTER LAM WITH THREE DOTS BELOW -> 'L' */ 948 + { 0xB9, 0x00 }, /* ARABIC LETTER NOON WITH DOT BELOW -> ... */ 949 + { 0xBD, 0x4E }, /* ARABIC LETTER NOON WITH THREE DOTS ABOVE -> 'N' */ 950 + { 0xBE, 0x68 }, /* ARABIC LETTER HEH DOACHASHMEE -> 'h' */ 951 + { 0xC1, 0x68 }, /* ARABIC LETTER HEH GOAL -> 'h' */ 952 + { 0xC2, 0x48 }, /* ARABIC LETTER HEH GOAL WITH HAMZA ABOVE -> 'H' */ 953 + { 0xC3, 0x40 }, /* ARABIC LETTER TEH MARBUTA GOAL -> '@' */ 954 + { 0xC4, 0x57 }, /* ARABIC LETTER WAW WITH RING -> 'W' */ 955 + { 0xC7, 0x75 }, /* ARABIC LETTER U -> 'u' */ 956 + { 0xCA, 0x57 }, /* ARABIC LETTER WAW WITH TWO DOTS ABOVE -> 'W' */ 957 + { 0xCB, 0x76 }, /* ARABIC LETTER VE -> 'v' */ 958 + { 0xCC, 0x79 }, /* ARABIC LETTER FARSI YEH -> 'y' */ 959 + { 0xCD, 0x59 }, /* ARABIC LETTER YEH WITH TAIL -> 'Y' */ 960 + { 0xCE, 0x59 }, /* ARABIC LETTER YEH WITH SMALL V -> 'Y' */ 961 + { 0xCF, 0x57 }, /* ARABIC LETTER WAW WITH DOT ABOVE -> 'W' */ 962 + { 0xD2, 0x79 }, /* ARABIC LETTER YEH BARREE -> 'y' */ 963 + { 0xD4, 0x2E }, /* ARABIC FULL STOP -> '.' */ 964 + { 0xDD, 0x40 }, /* ARABIC END OF AYAH -> '@' */ 965 + { 0xDE, 0x23 }, /* ARABIC START OF RUB EL HIZB -> '#' */ 966 + { 0xE9, 0x5E }, /* ARABIC PLACE OF SAJDAH -> '^' */ 967 + { 0xF0, 0x30 }, /* EXTENDED ARABIC-INDIC DIGIT ZERO -> '0' */ 968 + { 0xF1, 0x31 }, /* EXTENDED ARABIC-INDIC DIGIT ONE -> '1' */ 969 + { 0xF2, 0x32 }, /* EXTENDED ARABIC-INDIC DIGIT TWO -> '2' */ 970 + { 0xF3, 0x33 }, /* EXTENDED ARABIC-INDIC DIGIT THREE -> '3' */ 971 + { 0xF4, 0x34 }, /* EXTENDED ARABIC-INDIC DIGIT FOUR -> '4' */ 972 + { 0xF5, 0x35 }, /* EXTENDED ARABIC-INDIC DIGIT FIVE -> '5' */ 973 + { 0xF6, 0x36 }, /* EXTENDED ARABIC-INDIC DIGIT SIX -> '6' */ 974 + { 0xF7, 0x37 }, /* EXTENDED ARABIC-INDIC DIGIT SEVEN -> '7' */ 975 + { 0xF8, 0x38 }, /* EXTENDED ARABIC-INDIC DIGIT EIGHT -> '8' */ 976 + { 0xF9, 0x39 }, /* EXTENDED ARABIC-INDIC DIGIT NINE -> '9' */ 977 + { 0xFB, 0x44 }, /* ARABIC LETTER DAD WITH DOT BELOW -> 'D' */ 978 + { 0xFD, 0x26 }, /* ARABIC SIGN SINDHI AMPERSAND -> '&' */ 979 + /* Entries for page 0x07 */ 980 + { 0x01, 0x2F }, /* SYRIAC SUPRALINEAR FULL STOP -> '/' */ 981 + { 0x02, 0x2C }, /* SYRIAC SUBLINEAR FULL STOP -> ',' */ 982 + { 0x03, 0x21 }, /* SYRIAC SUPRALINEAR COLON -> '!' */ 983 + { 0x04, 0x21 }, /* SYRIAC SUBLINEAR COLON -> '!' */ 984 + { 0x05, 0x2D }, /* SYRIAC HORIZONTAL COLON -> '-' */ 985 + { 0x06, 0x2C }, /* SYRIAC COLON SKEWED LEFT -> ',' */ 986 + { 0x07, 0x2C }, /* SYRIAC COLON SKEWED RIGHT -> ',' */ 987 + { 0x08, 0x3B }, /* SYRIAC SUPRALINEAR COLON SKEWED LEFT -> ';' */ 988 + { 0x09, 0x3F }, /* SYRIAC SUBLINEAR COLON SKEWED RIGHT -> '?' */ 989 + { 0x0A, 0x7E }, /* SYRIAC CONTRACTION -> '~' */ 990 + { 0x0B, 0x7B }, /* SYRIAC HARKLEAN OBELUS -> '{' */ 991 + { 0x0C, 0x7D }, /* SYRIAC HARKLEAN METOBELUS -> '}' */ 992 + { 0x0D, 0x2A }, /* SYRIAC HARKLEAN ASTERISCUS -> '*' */ 993 + { 0x10, 0x27 }, /* SYRIAC LETTER ALAPH -> ''' */ 994 + { 0x12, 0x62 }, /* SYRIAC LETTER BETH -> 'b' */ 995 + { 0x13, 0x67 }, /* SYRIAC LETTER GAMAL -> 'g' */ 996 + { 0x14, 0x67 }, /* SYRIAC LETTER GAMAL GARSHUNI -> 'g' */ 997 + { 0x15, 0x64 }, /* SYRIAC LETTER DALATH -> 'd' */ 998 + { 0x16, 0x64 }, /* SYRIAC LETTER DOTLESS DALATH RISH -> 'd' */ 999 + { 0x17, 0x68 }, /* SYRIAC LETTER HE -> 'h' */ 1000 + { 0x18, 0x77 }, /* SYRIAC LETTER WAW -> 'w' */ 1001 + { 0x19, 0x7A }, /* SYRIAC LETTER ZAIN -> 'z' */ 1002 + { 0x1A, 0x48 }, /* SYRIAC LETTER HETH -> 'H' */ 1003 + { 0x1B, 0x74 }, /* SYRIAC LETTER TETH -> 't' */ 1004 + { 0x1C, 0x74 }, /* SYRIAC LETTER TETH GARSHUNI -> 't' */ 1005 + { 0x1D, 0x79 }, /* SYRIAC LETTER YUDH -> 'y' */ 1006 + { 0x1F, 0x6B }, /* SYRIAC LETTER KAPH -> 'k' */ 1007 + { 0x20, 0x6C }, /* SYRIAC LETTER LAMADH -> 'l' */ 1008 + { 0x21, 0x6D }, /* SYRIAC LETTER MIM -> 'm' */ 1009 + { 0x22, 0x6E }, /* SYRIAC LETTER NUN -> 'n' */ 1010 + { 0x23, 0x73 }, /* SYRIAC LETTER SEMKATH -> 's' */ 1011 + { 0x24, 0x73 }, /* SYRIAC LETTER FINAL SEMKATH -> 's' */ 1012 + { 0x25, 0x60 }, /* SYRIAC LETTER E -> '`' */ 1013 + { 0x26, 0x70 }, /* SYRIAC LETTER PE -> 'p' */ 1014 + { 0x27, 0x70 }, /* SYRIAC LETTER REVERSED PE -> 'p' */ 1015 + { 0x28, 0x53 }, /* SYRIAC LETTER SADHE -> 'S' */ 1016 + { 0x29, 0x71 }, /* SYRIAC LETTER QAPH -> 'q' */ 1017 + { 0x2A, 0x72 }, /* SYRIAC LETTER RISH -> 'r' */ 1018 + { 0x2C, 0x74 }, /* SYRIAC LETTER TAW -> 't' */ 1019 + { 0x30, 0x00 }, /* SYRIAC PTHAHA ABOVE -> ... */ 1020 + { 0x32, 0x61 }, /* SYRIAC PTHAHA DOTTED -> 'a' */ 1021 + { 0x33, 0x00 }, /* SYRIAC ZQAPHA ABOVE -> ... */ 1022 + { 0x35, 0x41 }, /* SYRIAC ZQAPHA DOTTED -> 'A' */ 1023 + { 0x36, 0x00 }, /* SYRIAC RBASA ABOVE -> ... */ 1024 + { 0x38, 0x65 }, /* SYRIAC DOTTED ZLAMA HORIZONTAL -> 'e' */ 1025 + { 0x39, 0x45 }, /* SYRIAC DOTTED ZLAMA ANGULAR -> 'E' */ 1026 + { 0x3A, 0x69 }, /* SYRIAC HBASA ABOVE -> 'i' */ 1027 + { 0x3B, 0x69 }, /* SYRIAC HBASA BELOW -> 'i' */ 1028 + { 0x3C, 0x00 }, /* SYRIAC HBASA-ESASA DOTTED -> ... */ 1029 + { 0x3E, 0x75 }, /* SYRIAC ESASA BELOW -> 'u' */ 1030 + { 0x3F, 0x6F }, /* SYRIAC RWAHA -> 'o' */ 1031 + { 0x41, 0x60 }, /* SYRIAC QUSHSHAYA -> '`' */ 1032 + { 0x42, 0x27 }, /* SYRIAC RUKKAKHA -> ''' */ 1033 + { 0x45, 0x58 }, /* SYRIAC THREE DOTS ABOVE -> 'X' */ 1034 + { 0x46, 0x51 }, /* SYRIAC THREE DOTS BELOW -> 'Q' */ 1035 + { 0x47, 0x40 }, /* SYRIAC OBLIQUE LINE ABOVE -> '@' */ 1036 + { 0x48, 0x40 }, /* SYRIAC OBLIQUE LINE BELOW -> '@' */ 1037 + { 0x49, 0x7C }, /* SYRIAC MUSIC -> '|' */ 1038 + { 0x4A, 0x2B }, /* SYRIAC BARREKH -> '+' */ 1039 + { 0x80, 0x68 }, /* THAANA LETTER HAA -> 'h' */ 1040 + { 0x82, 0x6E }, /* THAANA LETTER NOONU -> 'n' */ 1041 + { 0x83, 0x72 }, /* THAANA LETTER RAA -> 'r' */ 1042 + { 0x84, 0x62 }, /* THAANA LETTER BAA -> 'b' */ 1043 + { 0x85, 0x4C }, /* THAANA LETTER LHAVIYANI -> 'L' */ 1044 + { 0x86, 0x6B }, /* THAANA LETTER KAAFU -> 'k' */ 1045 + { 0x87, 0x27 }, /* THAANA LETTER ALIFU -> ''' */ 1046 + { 0x88, 0x76 }, /* THAANA LETTER VAAVU -> 'v' */ 1047 + { 0x89, 0x6D }, /* THAANA LETTER MEEMU -> 'm' */ 1048 + { 0x8A, 0x66 }, /* THAANA LETTER FAAFU -> 'f' */ 1049 + { 0x8D, 0x6C }, /* THAANA LETTER LAAMU -> 'l' */ 1050 + { 0x8E, 0x67 }, /* THAANA LETTER GAAFU -> 'g' */ 1051 + { 0x90, 0x73 }, /* THAANA LETTER SEENU -> 's' */ 1052 + { 0x91, 0x64 }, /* THAANA LETTER DAVIYANI -> 'd' */ 1053 + { 0x92, 0x7A }, /* THAANA LETTER ZAVIYANI -> 'z' */ 1054 + { 0x93, 0x74 }, /* THAANA LETTER TAVIYANI -> 't' */ 1055 + { 0x94, 0x79 }, /* THAANA LETTER YAA -> 'y' */ 1056 + { 0x95, 0x70 }, /* THAANA LETTER PAVIYANI -> 'p' */ 1057 + { 0x96, 0x6A }, /* THAANA LETTER JAVIYANI -> 'j' */ 1058 + { 0x9C, 0x7A }, /* THAANA LETTER ZAA -> 'z' */ 1059 + { 0x9E, 0x73 }, /* THAANA LETTER SAADHU -> 's' */ 1060 + { 0x9F, 0x64 }, /* THAANA LETTER DAADHU -> 'd' */ 1061 + { 0xA0, 0x74 }, /* THAANA LETTER TO -> 't' */ 1062 + { 0xA1, 0x7A }, /* THAANA LETTER ZO -> 'z' */ 1063 + { 0xA2, 0x60 }, /* THAANA LETTER AINU -> '`' */ 1064 + { 0xA4, 0x71 }, /* THAANA LETTER QAAFU -> 'q' */ 1065 + { 0xA5, 0x77 }, /* THAANA LETTER WAAVU -> 'w' */ 1066 + { 0xA6, 0x61 }, /* THAANA ABAFILI -> 'a' */ 1067 + { 0xA8, 0x69 }, /* THAANA IBIFILI -> 'i' */ 1068 + { 0xAA, 0x75 }, /* THAANA UBUFILI -> 'u' */ 1069 + { 0xAC, 0x65 }, /* THAANA EBEFILI -> 'e' */ 1070 + { 0xAE, 0x6F }, /* THAANA OBOFILI -> 'o' */ 1071 + /* Entries for page 0x09 */ 1072 + { 0x01, 0x4E }, /* DEVANAGARI SIGN CANDRABINDU -> 'N' */ 1073 + { 0x02, 0x4E }, /* DEVANAGARI SIGN ANUSVARA -> 'N' */ 1074 + { 0x03, 0x48 }, /* DEVANAGARI SIGN VISARGA -> 'H' */ 1075 + { 0x05, 0x61 }, /* DEVANAGARI LETTER A -> 'a' */ 1076 + { 0x07, 0x69 }, /* DEVANAGARI LETTER I -> 'i' */ 1077 + { 0x09, 0x75 }, /* DEVANAGARI LETTER U -> 'u' */ 1078 + { 0x0B, 0x52 }, /* DEVANAGARI LETTER VOCALIC R -> 'R' */ 1079 + { 0x0C, 0x4C }, /* DEVANAGARI LETTER VOCALIC L -> 'L' */ 1080 + { 0x0E, 0x65 }, /* DEVANAGARI LETTER SHORT E -> 'e' */ 1081 + { 0x0F, 0x65 }, /* DEVANAGARI LETTER E -> 'e' */ 1082 + { 0x12, 0x6F }, /* DEVANAGARI LETTER SHORT O -> 'o' */ 1083 + { 0x13, 0x6F }, /* DEVANAGARI LETTER O -> 'o' */ 1084 + { 0x15, 0x6B }, /* DEVANAGARI LETTER KA -> 'k' */ 1085 + { 0x17, 0x67 }, /* DEVANAGARI LETTER GA -> 'g' */ 1086 + { 0x1A, 0x63 }, /* DEVANAGARI LETTER CA -> 'c' */ 1087 + { 0x1C, 0x6A }, /* DEVANAGARI LETTER JA -> 'j' */ 1088 + { 0x24, 0x74 }, /* DEVANAGARI LETTER TA -> 't' */ 1089 + { 0x26, 0x64 }, /* DEVANAGARI LETTER DA -> 'd' */ 1090 + { 0x28, 0x6E }, /* DEVANAGARI LETTER NA -> 'n' */ 1091 + { 0x2A, 0x70 }, /* DEVANAGARI LETTER PA -> 'p' */ 1092 + { 0x2C, 0x62 }, /* DEVANAGARI LETTER BA -> 'b' */ 1093 + { 0x2E, 0x6D }, /* DEVANAGARI LETTER MA -> 'm' */ 1094 + { 0x2F, 0x79 }, /* DEVANAGARI LETTER YA -> 'y' */ 1095 + { 0x30, 0x72 }, /* DEVANAGARI LETTER RA -> 'r' */ 1096 + { 0x32, 0x6C }, /* DEVANAGARI LETTER LA -> 'l' */ 1097 + { 0x33, 0x6C }, /* DEVANAGARI LETTER LLA -> 'l' */ 1098 + { 0x35, 0x76 }, /* DEVANAGARI LETTER VA -> 'v' */ 1099 + { 0x38, 0x73 }, /* DEVANAGARI LETTER SA -> 's' */ 1100 + { 0x39, 0x68 }, /* DEVANAGARI LETTER HA -> 'h' */ 1101 + { 0x3C, 0x27 }, /* DEVANAGARI SIGN NUKTA -> ''' */ 1102 + { 0x3D, 0x27 }, /* DEVANAGARI SIGN AVAGRAHA -> ''' */ 1103 + { 0x3F, 0x69 }, /* DEVANAGARI VOWEL SIGN I -> 'i' */ 1104 + { 0x41, 0x75 }, /* DEVANAGARI VOWEL SIGN U -> 'u' */ 1105 + { 0x43, 0x52 }, /* DEVANAGARI VOWEL SIGN VOCALIC R -> 'R' */ 1106 + { 0x46, 0x65 }, /* DEVANAGARI VOWEL SIGN SHORT E -> 'e' */ 1107 + { 0x47, 0x65 }, /* DEVANAGARI VOWEL SIGN E -> 'e' */ 1108 + { 0x4A, 0x6F }, /* DEVANAGARI VOWEL SIGN SHORT O -> 'o' */ 1109 + { 0x4B, 0x6F }, /* DEVANAGARI VOWEL SIGN O -> 'o' */ 1110 + { 0x51, 0x27 }, /* DEVANAGARI STRESS SIGN UDATTA -> ''' */ 1111 + { 0x52, 0x27 }, /* DEVANAGARI STRESS SIGN ANUDATTA -> ''' */ 1112 + { 0x53, 0x60 }, /* DEVANAGARI GRAVE ACCENT -> '`' */ 1113 + { 0x54, 0x27 }, /* DEVANAGARI ACUTE ACCENT -> ''' */ 1114 + { 0x58, 0x71 }, /* DEVANAGARI LETTER QA -> 'q' */ 1115 + { 0x5B, 0x7A }, /* DEVANAGARI LETTER ZA -> 'z' */ 1116 + { 0x5E, 0x66 }, /* DEVANAGARI LETTER FA -> 'f' */ 1117 + { 0x62, 0x4C }, /* DEVANAGARI VOWEL SIGN VOCALIC L -> 'L' */ 1118 + { 0x66, 0x30 }, /* DEVANAGARI DIGIT ZERO -> '0' */ 1119 + { 0x67, 0x31 }, /* DEVANAGARI DIGIT ONE -> '1' */ 1120 + { 0x68, 0x32 }, /* DEVANAGARI DIGIT TWO -> '2' */ 1121 + { 0x69, 0x33 }, /* DEVANAGARI DIGIT THREE -> '3' */ 1122 + { 0x6A, 0x34 }, /* DEVANAGARI DIGIT FOUR -> '4' */ 1123 + { 0x6B, 0x35 }, /* DEVANAGARI DIGIT FIVE -> '5' */ 1124 + { 0x6C, 0x36 }, /* DEVANAGARI DIGIT SIX -> '6' */ 1125 + { 0x6D, 0x37 }, /* DEVANAGARI DIGIT SEVEN -> '7' */ 1126 + { 0x6E, 0x38 }, /* DEVANAGARI DIGIT EIGHT -> '8' */ 1127 + { 0x6F, 0x39 }, /* DEVANAGARI DIGIT NINE -> '9' */ 1128 + { 0x70, 0x2E }, /* DEVANAGARI ABBREVIATION SIGN -> '.' */ 1129 + { 0x81, 0x4E }, /* BENGALI SIGN CANDRABINDU -> 'N' */ 1130 + { 0x82, 0x4E }, /* BENGALI SIGN ANUSVARA -> 'N' */ 1131 + { 0x83, 0x48 }, /* BENGALI SIGN VISARGA -> 'H' */ 1132 + { 0x85, 0x61 }, /* BENGALI LETTER A -> 'a' */ 1133 + { 0x87, 0x69 }, /* BENGALI LETTER I -> 'i' */ 1134 + { 0x89, 0x75 }, /* BENGALI LETTER U -> 'u' */ 1135 + { 0x8B, 0x52 }, /* BENGALI LETTER VOCALIC R -> 'R' */ 1136 + { 0x8F, 0x65 }, /* BENGALI LETTER E -> 'e' */ 1137 + { 0x93, 0x6F }, /* BENGALI LETTER O -> 'o' */ 1138 + { 0x95, 0x6B }, /* BENGALI LETTER KA -> 'k' */ 1139 + { 0x97, 0x67 }, /* BENGALI LETTER GA -> 'g' */ 1140 + { 0x9A, 0x63 }, /* BENGALI LETTER CA -> 'c' */ 1141 + { 0x9C, 0x6A }, /* BENGALI LETTER JA -> 'j' */ 1142 + { 0xA4, 0x74 }, /* BENGALI LETTER TA -> 't' */ 1143 + { 0xA6, 0x64 }, /* BENGALI LETTER DA -> 'd' */ 1144 + { 0xA8, 0x6E }, /* BENGALI LETTER NA -> 'n' */ 1145 + { 0xAA, 0x70 }, /* BENGALI LETTER PA -> 'p' */ 1146 + { 0xAC, 0x62 }, /* BENGALI LETTER BA -> 'b' */ 1147 + { 0xAE, 0x6D }, /* BENGALI LETTER MA -> 'm' */ 1148 + { 0xAF, 0x79 }, /* BENGALI LETTER YA -> 'y' */ 1149 + { 0xB0, 0x72 }, /* BENGALI LETTER RA -> 'r' */ 1150 + { 0xB2, 0x6C }, /* BENGALI LETTER LA -> 'l' */ 1151 + { 0xB8, 0x73 }, /* BENGALI LETTER SA -> 's' */ 1152 + { 0xB9, 0x68 }, /* BENGALI LETTER HA -> 'h' */ 1153 + { 0xBC, 0x27 }, /* BENGALI SIGN NUKTA -> ''' */ 1154 + { 0xBF, 0x69 }, /* BENGALI VOWEL SIGN I -> 'i' */ 1155 + { 0xC1, 0x75 }, /* BENGALI VOWEL SIGN U -> 'u' */ 1156 + { 0xC3, 0x52 }, /* BENGALI VOWEL SIGN VOCALIC R -> 'R' */ 1157 + { 0xC7, 0x65 }, /* BENGALI VOWEL SIGN E -> 'e' */ 1158 + { 0xCB, 0x6F }, /* BENGALI VOWEL SIGN O -> 'o' */ 1159 + { 0xD7, 0x2B }, /* BENGALI AU LENGTH MARK -> '+' */ 1160 + { 0xE2, 0x4C }, /* BENGALI VOWEL SIGN VOCALIC L -> 'L' */ 1161 + { 0xE6, 0x30 }, /* BENGALI DIGIT ZERO -> '0' */ 1162 + { 0xE7, 0x31 }, /* BENGALI DIGIT ONE -> '1' */ 1163 + { 0xE8, 0x32 }, /* BENGALI DIGIT TWO -> '2' */ 1164 + { 0xE9, 0x33 }, /* BENGALI DIGIT THREE -> '3' */ 1165 + { 0xEA, 0x34 }, /* BENGALI DIGIT FOUR -> '4' */ 1166 + { 0xEB, 0x35 }, /* BENGALI DIGIT FIVE -> '5' */ 1167 + { 0xEC, 0x36 }, /* BENGALI DIGIT SIX -> '6' */ 1168 + { 0xED, 0x37 }, /* BENGALI DIGIT SEVEN -> '7' */ 1169 + { 0xEE, 0x38 }, /* BENGALI DIGIT EIGHT -> '8' */ 1170 + { 0xEF, 0x39 }, /* BENGALI DIGIT NINE -> '9' */ 1171 + /* Entries for page 0x0A */ 1172 + { 0x02, 0x4E }, /* GURMUKHI SIGN BINDI -> 'N' */ 1173 + { 0x05, 0x61 }, /* GURMUKHI LETTER A -> 'a' */ 1174 + { 0x07, 0x69 }, /* GURMUKHI LETTER I -> 'i' */ 1175 + { 0x09, 0x75 }, /* GURMUKHI LETTER U -> 'u' */ 1176 + { 0x15, 0x6B }, /* GURMUKHI LETTER KA -> 'k' */ 1177 + { 0x17, 0x67 }, /* GURMUKHI LETTER GA -> 'g' */ 1178 + { 0x1A, 0x63 }, /* GURMUKHI LETTER CA -> 'c' */ 1179 + { 0x1C, 0x6A }, /* GURMUKHI LETTER JA -> 'j' */ 1180 + { 0x24, 0x74 }, /* GURMUKHI LETTER TA -> 't' */ 1181 + { 0x26, 0x64 }, /* GURMUKHI LETTER DA -> 'd' */ 1182 + { 0x28, 0x6E }, /* GURMUKHI LETTER NA -> 'n' */ 1183 + { 0x2A, 0x70 }, /* GURMUKHI LETTER PA -> 'p' */ 1184 + { 0x2C, 0x62 }, /* GURMUKHI LETTER BA -> 'b' */ 1185 + { 0x2E, 0x6D }, /* GURMUKHI LETTER MA -> 'm' */ 1186 + { 0x2F, 0x79 }, /* GURMUKHI LETTER YA -> 'y' */ 1187 + { 0x30, 0x72 }, /* GURMUKHI LETTER RA -> 'r' */ 1188 + { 0x32, 0x6C }, /* GURMUKHI LETTER LA -> 'l' */ 1189 + { 0x35, 0x76 }, /* GURMUKHI LETTER VA -> 'v' */ 1190 + { 0x38, 0x73 }, /* GURMUKHI LETTER SA -> 's' */ 1191 + { 0x39, 0x68 }, /* GURMUKHI LETTER HA -> 'h' */ 1192 + { 0x3C, 0x27 }, /* GURMUKHI SIGN NUKTA -> ''' */ 1193 + { 0x3F, 0x69 }, /* GURMUKHI VOWEL SIGN I -> 'i' */ 1194 + { 0x41, 0x75 }, /* GURMUKHI VOWEL SIGN U -> 'u' */ 1195 + { 0x5B, 0x7A }, /* GURMUKHI LETTER ZA -> 'z' */ 1196 + { 0x5E, 0x66 }, /* GURMUKHI LETTER FA -> 'f' */ 1197 + { 0x66, 0x30 }, /* GURMUKHI DIGIT ZERO -> '0' */ 1198 + { 0x67, 0x31 }, /* GURMUKHI DIGIT ONE -> '1' */ 1199 + { 0x68, 0x32 }, /* GURMUKHI DIGIT TWO -> '2' */ 1200 + { 0x69, 0x33 }, /* GURMUKHI DIGIT THREE -> '3' */ 1201 + { 0x6A, 0x34 }, /* GURMUKHI DIGIT FOUR -> '4' */ 1202 + { 0x6B, 0x35 }, /* GURMUKHI DIGIT FIVE -> '5' */ 1203 + { 0x6C, 0x36 }, /* GURMUKHI DIGIT SIX -> '6' */ 1204 + { 0x6D, 0x37 }, /* GURMUKHI DIGIT SEVEN -> '7' */ 1205 + { 0x6E, 0x38 }, /* GURMUKHI DIGIT EIGHT -> '8' */ 1206 + { 0x6F, 0x39 }, /* GURMUKHI DIGIT NINE -> '9' */ 1207 + { 0x70, 0x4E }, /* GURMUKHI TIPPI -> 'N' */ 1208 + { 0x71, 0x48 }, /* GURMUKHI ADDAK -> 'H' */ 1209 + { 0x81, 0x4E }, /* GUJARATI SIGN CANDRABINDU -> 'N' */ 1210 + { 0x82, 0x4E }, /* GUJARATI SIGN ANUSVARA -> 'N' */ 1211 + { 0x83, 0x48 }, /* GUJARATI SIGN VISARGA -> 'H' */ 1212 + { 0x85, 0x61 }, /* GUJARATI LETTER A -> 'a' */ 1213 + { 0x87, 0x69 }, /* GUJARATI LETTER I -> 'i' */ 1214 + { 0x89, 0x75 }, /* GUJARATI LETTER U -> 'u' */ 1215 + { 0x8B, 0x52 }, /* GUJARATI LETTER VOCALIC R -> 'R' */ 1216 + { 0x8F, 0x65 }, /* GUJARATI LETTER E -> 'e' */ 1217 + { 0x93, 0x6F }, /* GUJARATI LETTER O -> 'o' */ 1218 + { 0x95, 0x6B }, /* GUJARATI LETTER KA -> 'k' */ 1219 + { 0x97, 0x67 }, /* GUJARATI LETTER GA -> 'g' */ 1220 + { 0x9A, 0x63 }, /* GUJARATI LETTER CA -> 'c' */ 1221 + { 0x9C, 0x6A }, /* GUJARATI LETTER JA -> 'j' */ 1222 + { 0xA4, 0x74 }, /* GUJARATI LETTER TA -> 't' */ 1223 + { 0xA6, 0x64 }, /* GUJARATI LETTER DA -> 'd' */ 1224 + { 0xA8, 0x6E }, /* GUJARATI LETTER NA -> 'n' */ 1225 + { 0xAA, 0x70 }, /* GUJARATI LETTER PA -> 'p' */ 1226 + { 0xAC, 0x62 }, /* GUJARATI LETTER BA -> 'b' */ 1227 + { 0xAE, 0x6D }, /* GUJARATI LETTER MA -> 'm' */ 1228 + { 0xB0, 0x72 }, /* GUJARATI LETTER RA -> 'r' */ 1229 + { 0xB2, 0x6C }, /* GUJARATI LETTER LA -> 'l' */ 1230 + { 0xB5, 0x76 }, /* GUJARATI LETTER VA -> 'v' */ 1231 + { 0xB8, 0x73 }, /* GUJARATI LETTER SA -> 's' */ 1232 + { 0xB9, 0x68 }, /* GUJARATI LETTER HA -> 'h' */ 1233 + { 0xBC, 0x27 }, /* GUJARATI SIGN NUKTA -> ''' */ 1234 + { 0xBD, 0x27 }, /* GUJARATI SIGN AVAGRAHA -> ''' */ 1235 + { 0xBF, 0x69 }, /* GUJARATI VOWEL SIGN I -> 'i' */ 1236 + { 0xC1, 0x75 }, /* GUJARATI VOWEL SIGN U -> 'u' */ 1237 + { 0xC3, 0x52 }, /* GUJARATI VOWEL SIGN VOCALIC R -> 'R' */ 1238 + { 0xC7, 0x65 }, /* GUJARATI VOWEL SIGN E -> 'e' */ 1239 + { 0xCB, 0x6F }, /* GUJARATI VOWEL SIGN O -> 'o' */ 1240 + { 0xE6, 0x30 }, /* GUJARATI DIGIT ZERO -> '0' */ 1241 + { 0xE7, 0x31 }, /* GUJARATI DIGIT ONE -> '1' */ 1242 + { 0xE8, 0x32 }, /* GUJARATI DIGIT TWO -> '2' */ 1243 + { 0xE9, 0x33 }, /* GUJARATI DIGIT THREE -> '3' */ 1244 + { 0xEA, 0x34 }, /* GUJARATI DIGIT FOUR -> '4' */ 1245 + { 0xEB, 0x35 }, /* GUJARATI DIGIT FIVE -> '5' */ 1246 + { 0xEC, 0x36 }, /* GUJARATI DIGIT SIX -> '6' */ 1247 + { 0xED, 0x37 }, /* GUJARATI DIGIT SEVEN -> '7' */ 1248 + { 0xEE, 0x38 }, /* GUJARATI DIGIT EIGHT -> '8' */ 1249 + { 0xEF, 0x39 }, /* GUJARATI DIGIT NINE -> '9' */ 1250 + /* Entries for page 0x0B */ 1251 + { 0x01, 0x4E }, /* ORIYA SIGN CANDRABINDU -> 'N' */ 1252 + { 0x02, 0x4E }, /* ORIYA SIGN ANUSVARA -> 'N' */ 1253 + { 0x03, 0x48 }, /* ORIYA SIGN VISARGA -> 'H' */ 1254 + { 0x05, 0x61 }, /* ORIYA LETTER A -> 'a' */ 1255 + { 0x07, 0x69 }, /* ORIYA LETTER I -> 'i' */ 1256 + { 0x09, 0x75 }, /* ORIYA LETTER U -> 'u' */ 1257 + { 0x0B, 0x52 }, /* ORIYA LETTER VOCALIC R -> 'R' */ 1258 + { 0x0C, 0x4C }, /* ORIYA LETTER VOCALIC L -> 'L' */ 1259 + { 0x0F, 0x65 }, /* ORIYA LETTER E -> 'e' */ 1260 + { 0x13, 0x6F }, /* ORIYA LETTER O -> 'o' */ 1261 + { 0x15, 0x6B }, /* ORIYA LETTER KA -> 'k' */ 1262 + { 0x17, 0x67 }, /* ORIYA LETTER GA -> 'g' */ 1263 + { 0x1A, 0x63 }, /* ORIYA LETTER CA -> 'c' */ 1264 + { 0x1C, 0x6A }, /* ORIYA LETTER JA -> 'j' */ 1265 + { 0x24, 0x74 }, /* ORIYA LETTER TA -> 't' */ 1266 + { 0x26, 0x64 }, /* ORIYA LETTER DA -> 'd' */ 1267 + { 0x28, 0x6E }, /* ORIYA LETTER NA -> 'n' */ 1268 + { 0x2A, 0x70 }, /* ORIYA LETTER PA -> 'p' */ 1269 + { 0x2C, 0x62 }, /* ORIYA LETTER BA -> 'b' */ 1270 + { 0x2E, 0x6D }, /* ORIYA LETTER MA -> 'm' */ 1271 + { 0x2F, 0x79 }, /* ORIYA LETTER YA -> 'y' */ 1272 + { 0x30, 0x72 }, /* ORIYA LETTER RA -> 'r' */ 1273 + { 0x32, 0x6C }, /* ORIYA LETTER LA -> 'l' */ 1274 + { 0x38, 0x73 }, /* ORIYA LETTER SA -> 's' */ 1275 + { 0x39, 0x68 }, /* ORIYA LETTER HA -> 'h' */ 1276 + { 0x3C, 0x27 }, /* ORIYA SIGN NUKTA -> ''' */ 1277 + { 0x3D, 0x27 }, /* ORIYA SIGN AVAGRAHA -> ''' */ 1278 + { 0x3F, 0x69 }, /* ORIYA VOWEL SIGN I -> 'i' */ 1279 + { 0x41, 0x75 }, /* ORIYA VOWEL SIGN U -> 'u' */ 1280 + { 0x43, 0x52 }, /* ORIYA VOWEL SIGN VOCALIC R -> 'R' */ 1281 + { 0x47, 0x65 }, /* ORIYA VOWEL SIGN E -> 'e' */ 1282 + { 0x4B, 0x6F }, /* ORIYA VOWEL SIGN O -> 'o' */ 1283 + { 0x56, 0x2B }, /* ORIYA AI LENGTH MARK -> '+' */ 1284 + { 0x57, 0x2B }, /* ORIYA AU LENGTH MARK -> '+' */ 1285 + { 0x66, 0x30 }, /* ORIYA DIGIT ZERO -> '0' */ 1286 + { 0x67, 0x31 }, /* ORIYA DIGIT ONE -> '1' */ 1287 + { 0x68, 0x32 }, /* ORIYA DIGIT TWO -> '2' */ 1288 + { 0x69, 0x33 }, /* ORIYA DIGIT THREE -> '3' */ 1289 + { 0x6A, 0x34 }, /* ORIYA DIGIT FOUR -> '4' */ 1290 + { 0x6B, 0x35 }, /* ORIYA DIGIT FIVE -> '5' */ 1291 + { 0x6C, 0x36 }, /* ORIYA DIGIT SIX -> '6' */ 1292 + { 0x6D, 0x37 }, /* ORIYA DIGIT SEVEN -> '7' */ 1293 + { 0x6E, 0x38 }, /* ORIYA DIGIT EIGHT -> '8' */ 1294 + { 0x6F, 0x39 }, /* ORIYA DIGIT NINE -> '9' */ 1295 + { 0x82, 0x4E }, /* TAMIL SIGN ANUSVARA -> 'N' */ 1296 + { 0x83, 0x48 }, /* TAMIL SIGN VISARGA -> 'H' */ 1297 + { 0x85, 0x61 }, /* TAMIL LETTER A -> 'a' */ 1298 + { 0x87, 0x69 }, /* TAMIL LETTER I -> 'i' */ 1299 + { 0x89, 0x75 }, /* TAMIL LETTER U -> 'u' */ 1300 + { 0x8E, 0x65 }, /* TAMIL LETTER E -> 'e' */ 1301 + { 0x92, 0x6F }, /* TAMIL LETTER O -> 'o' */ 1302 + { 0x95, 0x6B }, /* TAMIL LETTER KA -> 'k' */ 1303 + { 0x9A, 0x63 }, /* TAMIL LETTER CA -> 'c' */ 1304 + { 0x9C, 0x6A }, /* TAMIL LETTER JA -> 'j' */ 1305 + { 0xA4, 0x74 }, /* TAMIL LETTER TA -> 't' */ 1306 + { 0xA8, 0x6E }, /* TAMIL LETTER NA -> 'n' */ 1307 + { 0xAA, 0x70 }, /* TAMIL LETTER PA -> 'p' */ 1308 + { 0xAE, 0x6D }, /* TAMIL LETTER MA -> 'm' */ 1309 + { 0xAF, 0x79 }, /* TAMIL LETTER YA -> 'y' */ 1310 + { 0xB0, 0x72 }, /* TAMIL LETTER RA -> 'r' */ 1311 + { 0xB2, 0x6C }, /* TAMIL LETTER LA -> 'l' */ 1312 + { 0xB5, 0x76 }, /* TAMIL LETTER VA -> 'v' */ 1313 + { 0xB8, 0x73 }, /* TAMIL LETTER SA -> 's' */ 1314 + { 0xB9, 0x68 }, /* TAMIL LETTER HA -> 'h' */ 1315 + { 0xBF, 0x69 }, /* TAMIL VOWEL SIGN I -> 'i' */ 1316 + { 0xC1, 0x75 }, /* TAMIL VOWEL SIGN U -> 'u' */ 1317 + { 0xC6, 0x65 }, /* TAMIL VOWEL SIGN E -> 'e' */ 1318 + { 0xCA, 0x6F }, /* TAMIL VOWEL SIGN O -> 'o' */ 1319 + { 0xD7, 0x2B }, /* TAMIL AU LENGTH MARK -> '+' */ 1320 + { 0xE6, 0x30 }, /* TAMIL DIGIT ZERO -> '0' */ 1321 + { 0xE7, 0x31 }, /* TAMIL DIGIT ONE -> '1' */ 1322 + { 0xE8, 0x32 }, /* TAMIL DIGIT TWO -> '2' */ 1323 + { 0xE9, 0x33 }, /* TAMIL DIGIT THREE -> '3' */ 1324 + { 0xEA, 0x34 }, /* TAMIL DIGIT FOUR -> '4' */ 1325 + { 0xEB, 0x35 }, /* TAMIL DIGIT FIVE -> '5' */ 1326 + { 0xEC, 0x36 }, /* TAMIL DIGIT SIX -> '6' */ 1327 + { 0xED, 0x37 }, /* TAMIL DIGIT SEVEN -> '7' */ 1328 + { 0xEE, 0x38 }, /* TAMIL DIGIT EIGHT -> '8' */ 1329 + { 0xEF, 0x39 }, /* TAMIL DIGIT NINE -> '9' */ 1330 + /* Entries for page 0x0C */ 1331 + { 0x01, 0x4E }, /* TELUGU SIGN CANDRABINDU -> 'N' */ 1332 + { 0x02, 0x4E }, /* TELUGU SIGN ANUSVARA -> 'N' */ 1333 + { 0x03, 0x48 }, /* TELUGU SIGN VISARGA -> 'H' */ 1334 + { 0x05, 0x61 }, /* TELUGU LETTER A -> 'a' */ 1335 + { 0x07, 0x69 }, /* TELUGU LETTER I -> 'i' */ 1336 + { 0x09, 0x75 }, /* TELUGU LETTER U -> 'u' */ 1337 + { 0x0B, 0x52 }, /* TELUGU LETTER VOCALIC R -> 'R' */ 1338 + { 0x0C, 0x4C }, /* TELUGU LETTER VOCALIC L -> 'L' */ 1339 + { 0x0E, 0x65 }, /* TELUGU LETTER E -> 'e' */ 1340 + { 0x12, 0x6F }, /* TELUGU LETTER O -> 'o' */ 1341 + { 0x15, 0x6B }, /* TELUGU LETTER KA -> 'k' */ 1342 + { 0x17, 0x67 }, /* TELUGU LETTER GA -> 'g' */ 1343 + { 0x1A, 0x63 }, /* TELUGU LETTER CA -> 'c' */ 1344 + { 0x1C, 0x6A }, /* TELUGU LETTER JA -> 'j' */ 1345 + { 0x24, 0x74 }, /* TELUGU LETTER TA -> 't' */ 1346 + { 0x26, 0x64 }, /* TELUGU LETTER DA -> 'd' */ 1347 + { 0x28, 0x6E }, /* TELUGU LETTER NA -> 'n' */ 1348 + { 0x2A, 0x70 }, /* TELUGU LETTER PA -> 'p' */ 1349 + { 0x2C, 0x62 }, /* TELUGU LETTER BA -> 'b' */ 1350 + { 0x2E, 0x6D }, /* TELUGU LETTER MA -> 'm' */ 1351 + { 0x2F, 0x79 }, /* TELUGU LETTER YA -> 'y' */ 1352 + { 0x30, 0x72 }, /* TELUGU LETTER RA -> 'r' */ 1353 + { 0x32, 0x6C }, /* TELUGU LETTER LA -> 'l' */ 1354 + { 0x35, 0x76 }, /* TELUGU LETTER VA -> 'v' */ 1355 + { 0x38, 0x73 }, /* TELUGU LETTER SA -> 's' */ 1356 + { 0x39, 0x68 }, /* TELUGU LETTER HA -> 'h' */ 1357 + { 0x3F, 0x69 }, /* TELUGU VOWEL SIGN I -> 'i' */ 1358 + { 0x41, 0x75 }, /* TELUGU VOWEL SIGN U -> 'u' */ 1359 + { 0x43, 0x52 }, /* TELUGU VOWEL SIGN VOCALIC R -> 'R' */ 1360 + { 0x46, 0x65 }, /* TELUGU VOWEL SIGN E -> 'e' */ 1361 + { 0x4A, 0x6F }, /* TELUGU VOWEL SIGN O -> 'o' */ 1362 + { 0x55, 0x2B }, /* TELUGU LENGTH MARK -> '+' */ 1363 + { 0x56, 0x2B }, /* TELUGU AI LENGTH MARK -> '+' */ 1364 + { 0x66, 0x30 }, /* TELUGU DIGIT ZERO -> '0' */ 1365 + { 0x67, 0x31 }, /* TELUGU DIGIT ONE -> '1' */ 1366 + { 0x68, 0x32 }, /* TELUGU DIGIT TWO -> '2' */ 1367 + { 0x69, 0x33 }, /* TELUGU DIGIT THREE -> '3' */ 1368 + { 0x6A, 0x34 }, /* TELUGU DIGIT FOUR -> '4' */ 1369 + { 0x6B, 0x35 }, /* TELUGU DIGIT FIVE -> '5' */ 1370 + { 0x6C, 0x36 }, /* TELUGU DIGIT SIX -> '6' */ 1371 + { 0x6D, 0x37 }, /* TELUGU DIGIT SEVEN -> '7' */ 1372 + { 0x6E, 0x38 }, /* TELUGU DIGIT EIGHT -> '8' */ 1373 + { 0x6F, 0x39 }, /* TELUGU DIGIT NINE -> '9' */ 1374 + { 0x82, 0x4E }, /* KANNADA SIGN ANUSVARA -> 'N' */ 1375 + { 0x83, 0x48 }, /* KANNADA SIGN VISARGA -> 'H' */ 1376 + { 0x85, 0x61 }, /* KANNADA LETTER A -> 'a' */ 1377 + { 0x87, 0x69 }, /* KANNADA LETTER I -> 'i' */ 1378 + { 0x89, 0x75 }, /* KANNADA LETTER U -> 'u' */ 1379 + { 0x8B, 0x52 }, /* KANNADA LETTER VOCALIC R -> 'R' */ 1380 + { 0x8C, 0x4C }, /* KANNADA LETTER VOCALIC L -> 'L' */ 1381 + { 0x8E, 0x65 }, /* KANNADA LETTER E -> 'e' */ 1382 + { 0x92, 0x6F }, /* KANNADA LETTER O -> 'o' */ 1383 + { 0x95, 0x6B }, /* KANNADA LETTER KA -> 'k' */ 1384 + { 0x97, 0x67 }, /* KANNADA LETTER GA -> 'g' */ 1385 + { 0x9A, 0x63 }, /* KANNADA LETTER CA -> 'c' */ 1386 + { 0x9C, 0x6A }, /* KANNADA LETTER JA -> 'j' */ 1387 + { 0xA4, 0x74 }, /* KANNADA LETTER TA -> 't' */ 1388 + { 0xA6, 0x64 }, /* KANNADA LETTER DA -> 'd' */ 1389 + { 0xA8, 0x6E }, /* KANNADA LETTER NA -> 'n' */ 1390 + { 0xAA, 0x70 }, /* KANNADA LETTER PA -> 'p' */ 1391 + { 0xAC, 0x62 }, /* KANNADA LETTER BA -> 'b' */ 1392 + { 0xAE, 0x6D }, /* KANNADA LETTER MA -> 'm' */ 1393 + { 0xAF, 0x79 }, /* KANNADA LETTER YA -> 'y' */ 1394 + { 0xB0, 0x72 }, /* KANNADA LETTER RA -> 'r' */ 1395 + { 0xB2, 0x6C }, /* KANNADA LETTER LA -> 'l' */ 1396 + { 0xB5, 0x76 }, /* KANNADA LETTER VA -> 'v' */ 1397 + { 0xB8, 0x73 }, /* KANNADA LETTER SA -> 's' */ 1398 + { 0xB9, 0x68 }, /* KANNADA LETTER HA -> 'h' */ 1399 + { 0xBF, 0x69 }, /* KANNADA VOWEL SIGN I -> 'i' */ 1400 + { 0xC1, 0x75 }, /* KANNADA VOWEL SIGN U -> 'u' */ 1401 + { 0xC3, 0x52 }, /* KANNADA VOWEL SIGN VOCALIC R -> 'R' */ 1402 + { 0xC6, 0x65 }, /* KANNADA VOWEL SIGN E -> 'e' */ 1403 + { 0xCA, 0x6F }, /* KANNADA VOWEL SIGN O -> 'o' */ 1404 + { 0xD5, 0x2B }, /* KANNADA LENGTH MARK -> '+' */ 1405 + { 0xD6, 0x2B }, /* KANNADA AI LENGTH MARK -> '+' */ 1406 + { 0xE6, 0x30 }, /* KANNADA DIGIT ZERO -> '0' */ 1407 + { 0xE7, 0x31 }, /* KANNADA DIGIT ONE -> '1' */ 1408 + { 0xE8, 0x32 }, /* KANNADA DIGIT TWO -> '2' */ 1409 + { 0xE9, 0x33 }, /* KANNADA DIGIT THREE -> '3' */ 1410 + { 0xEA, 0x34 }, /* KANNADA DIGIT FOUR -> '4' */ 1411 + { 0xEB, 0x35 }, /* KANNADA DIGIT FIVE -> '5' */ 1412 + { 0xEC, 0x36 }, /* KANNADA DIGIT SIX -> '6' */ 1413 + { 0xED, 0x37 }, /* KANNADA DIGIT SEVEN -> '7' */ 1414 + { 0xEE, 0x38 }, /* KANNADA DIGIT EIGHT -> '8' */ 1415 + { 0xEF, 0x39 }, /* KANNADA DIGIT NINE -> '9' */ 1416 + /* Entries for page 0x0D */ 1417 + { 0x02, 0x4E }, /* MALAYALAM SIGN ANUSVARA -> 'N' */ 1418 + { 0x03, 0x48 }, /* MALAYALAM SIGN VISARGA -> 'H' */ 1419 + { 0x05, 0x61 }, /* MALAYALAM LETTER A -> 'a' */ 1420 + { 0x07, 0x69 }, /* MALAYALAM LETTER I -> 'i' */ 1421 + { 0x09, 0x75 }, /* MALAYALAM LETTER U -> 'u' */ 1422 + { 0x0B, 0x52 }, /* MALAYALAM LETTER VOCALIC R -> 'R' */ 1423 + { 0x0C, 0x4C }, /* MALAYALAM LETTER VOCALIC L -> 'L' */ 1424 + { 0x0E, 0x65 }, /* MALAYALAM LETTER E -> 'e' */ 1425 + { 0x12, 0x6F }, /* MALAYALAM LETTER O -> 'o' */ 1426 + { 0x15, 0x6B }, /* MALAYALAM LETTER KA -> 'k' */ 1427 + { 0x17, 0x67 }, /* MALAYALAM LETTER GA -> 'g' */ 1428 + { 0x1A, 0x63 }, /* MALAYALAM LETTER CA -> 'c' */ 1429 + { 0x1C, 0x6A }, /* MALAYALAM LETTER JA -> 'j' */ 1430 + { 0x24, 0x74 }, /* MALAYALAM LETTER TA -> 't' */ 1431 + { 0x26, 0x64 }, /* MALAYALAM LETTER DA -> 'd' */ 1432 + { 0x28, 0x6E }, /* MALAYALAM LETTER NA -> 'n' */ 1433 + { 0x2A, 0x70 }, /* MALAYALAM LETTER PA -> 'p' */ 1434 + { 0x2C, 0x62 }, /* MALAYALAM LETTER BA -> 'b' */ 1435 + { 0x2E, 0x6D }, /* MALAYALAM LETTER MA -> 'm' */ 1436 + { 0x2F, 0x79 }, /* MALAYALAM LETTER YA -> 'y' */ 1437 + { 0x30, 0x72 }, /* MALAYALAM LETTER RA -> 'r' */ 1438 + { 0x32, 0x6C }, /* MALAYALAM LETTER LA -> 'l' */ 1439 + { 0x35, 0x76 }, /* MALAYALAM LETTER VA -> 'v' */ 1440 + { 0x38, 0x73 }, /* MALAYALAM LETTER SA -> 's' */ 1441 + { 0x39, 0x68 }, /* MALAYALAM LETTER HA -> 'h' */ 1442 + { 0x3F, 0x69 }, /* MALAYALAM VOWEL SIGN I -> 'i' */ 1443 + { 0x41, 0x75 }, /* MALAYALAM VOWEL SIGN U -> 'u' */ 1444 + { 0x43, 0x52 }, /* MALAYALAM VOWEL SIGN VOCALIC R -> 'R' */ 1445 + { 0x46, 0x65 }, /* MALAYALAM VOWEL SIGN E -> 'e' */ 1446 + { 0x4A, 0x6F }, /* MALAYALAM VOWEL SIGN O -> 'o' */ 1447 + { 0x57, 0x2B }, /* MALAYALAM AU LENGTH MARK -> '+' */ 1448 + { 0x66, 0x30 }, /* MALAYALAM DIGIT ZERO -> '0' */ 1449 + { 0x67, 0x31 }, /* MALAYALAM DIGIT ONE -> '1' */ 1450 + { 0x68, 0x32 }, /* MALAYALAM DIGIT TWO -> '2' */ 1451 + { 0x69, 0x33 }, /* MALAYALAM DIGIT THREE -> '3' */ 1452 + { 0x6A, 0x34 }, /* MALAYALAM DIGIT FOUR -> '4' */ 1453 + { 0x6B, 0x35 }, /* MALAYALAM DIGIT FIVE -> '5' */ 1454 + { 0x6C, 0x36 }, /* MALAYALAM DIGIT SIX -> '6' */ 1455 + { 0x6D, 0x37 }, /* MALAYALAM DIGIT SEVEN -> '7' */ 1456 + { 0x6E, 0x38 }, /* MALAYALAM DIGIT EIGHT -> '8' */ 1457 + { 0x6F, 0x39 }, /* MALAYALAM DIGIT NINE -> '9' */ 1458 + { 0x82, 0x4E }, /* SINHALA SIGN ANUSVARAYA -> 'N' */ 1459 + { 0x83, 0x48 }, /* SINHALA SIGN VISARGAYA -> 'H' */ 1460 + { 0x85, 0x61 }, /* SINHALA LETTER AYANNA -> 'a' */ 1461 + { 0x89, 0x69 }, /* SINHALA LETTER IYANNA -> 'i' */ 1462 + { 0x8B, 0x75 }, /* SINHALA LETTER UYANNA -> 'u' */ 1463 + { 0x8D, 0x52 }, /* SINHALA LETTER IRUYANNA -> 'R' */ 1464 + { 0x8F, 0x4C }, /* SINHALA LETTER ILUYANNA -> 'L' */ 1465 + { 0x91, 0x65 }, /* SINHALA LETTER EYANNA -> 'e' */ 1466 + { 0x94, 0x6F }, /* SINHALA LETTER OYANNA -> 'o' */ 1467 + { 0x9A, 0x6B }, /* SINHALA LETTER ALPAPRAANA KAYANNA -> 'k' */ 1468 + { 0x9C, 0x67 }, /* SINHALA LETTER ALPAPRAANA GAYANNA -> 'g' */ 1469 + { 0xA0, 0x63 }, /* SINHALA LETTER ALPAPRAANA CAYANNA -> 'c' */ 1470 + { 0xA2, 0x6A }, /* SINHALA LETTER ALPAPRAANA JAYANNA -> 'j' */ 1471 + { 0xAD, 0x74 }, /* SINHALA LETTER ALPAPRAANA TAYANNA -> 't' */ 1472 + { 0xAF, 0x64 }, /* SINHALA LETTER ALPAPRAANA DAYANNA -> 'd' */ 1473 + { 0xB1, 0x6E }, /* SINHALA LETTER DANTAJA NAYANNA -> 'n' */ 1474 + { 0xB4, 0x70 }, /* SINHALA LETTER ALPAPRAANA PAYANNA -> 'p' */ 1475 + { 0xB6, 0x62 }, /* SINHALA LETTER ALPAPRAANA BAYANNA -> 'b' */ 1476 + { 0xB8, 0x6D }, /* SINHALA LETTER MAYANNA -> 'm' */ 1477 + { 0xBA, 0x79 }, /* SINHALA LETTER YAYANNA -> 'y' */ 1478 + { 0xBB, 0x72 }, /* SINHALA LETTER RAYANNA -> 'r' */ 1479 + { 0xBD, 0x6C }, /* SINHALA LETTER DANTAJA LAYANNA -> 'l' */ 1480 + { 0xC0, 0x76 }, /* SINHALA LETTER VAYANNA -> 'v' */ 1481 + { 0xC3, 0x73 }, /* SINHALA LETTER DANTAJA SAYANNA -> 's' */ 1482 + { 0xC4, 0x68 }, /* SINHALA LETTER HAYANNA -> 'h' */ 1483 + { 0xC6, 0x66 }, /* SINHALA LETTER FAYANNA -> 'f' */ 1484 + { 0xD2, 0x69 }, /* SINHALA VOWEL SIGN KETTI IS-PILLA -> 'i' */ 1485 + { 0xD4, 0x75 }, /* SINHALA VOWEL SIGN KETTI PAA-PILLA -> 'u' */ 1486 + { 0xD8, 0x52 }, /* SINHALA VOWEL SIGN GAETTA-PILLA -> 'R' */ 1487 + { 0xD9, 0x65 }, /* SINHALA VOWEL SIGN KOMBUVA -> 'e' */ 1488 + { 0xDC, 0x6F }, /* SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA -> 'o' */ 1489 + { 0xDF, 0x4C }, /* SINHALA VOWEL SIGN GAYANUKITTA -> 'L' */ 1490 + /* Entries for page 0x0E */ 1491 + { 0x01, 0x6B }, /* THAI CHARACTER KO KAI -> 'k' */ 1492 + { 0x0D, 0x79 }, /* THAI CHARACTER YO YING -> 'y' */ 1493 + { 0x0E, 0x64 }, /* THAI CHARACTER DO CHADA -> 'd' */ 1494 + { 0x0F, 0x74 }, /* THAI CHARACTER TO PATAK -> 't' */ 1495 + { 0x13, 0x6E }, /* THAI CHARACTER NO NEN -> 'n' */ 1496 + { 0x14, 0x64 }, /* THAI CHARACTER DO DEK -> 'd' */ 1497 + { 0x15, 0x74 }, /* THAI CHARACTER TO TAO -> 't' */ 1498 + { 0x19, 0x6E }, /* THAI CHARACTER NO NU -> 'n' */ 1499 + { 0x1A, 0x62 }, /* THAI CHARACTER BO BAIMAI -> 'b' */ 1500 + { 0x1B, 0x70 }, /* THAI CHARACTER PO PLA -> 'p' */ 1501 + { 0x1D, 0x66 }, /* THAI CHARACTER FO FA -> 'f' */ 1502 + { 0x1F, 0x66 }, /* THAI CHARACTER FO FAN -> 'f' */ 1503 + { 0x21, 0x6D }, /* THAI CHARACTER MO MA -> 'm' */ 1504 + { 0x22, 0x79 }, /* THAI CHARACTER YO YAK -> 'y' */ 1505 + { 0x23, 0x72 }, /* THAI CHARACTER RO RUA -> 'r' */ 1506 + { 0x24, 0x52 }, /* THAI CHARACTER RU -> 'R' */ 1507 + { 0x25, 0x6C }, /* THAI CHARACTER LO LING -> 'l' */ 1508 + { 0x26, 0x4C }, /* THAI CHARACTER LU -> 'L' */ 1509 + { 0x27, 0x77 }, /* THAI CHARACTER WO WAEN -> 'w' */ 1510 + { 0x28, 0x00 }, /* THAI CHARACTER SO SALA -> ... */ 1511 + { 0x2A, 0x73 }, /* THAI CHARACTER SO SUA -> 's' */ 1512 + { 0x2B, 0x68 }, /* THAI CHARACTER HO HIP -> 'h' */ 1513 + { 0x2C, 0x6C }, /* THAI CHARACTER LO CHULA -> 'l' */ 1514 + { 0x2D, 0x60 }, /* THAI CHARACTER O ANG -> '`' */ 1515 + { 0x2E, 0x68 }, /* THAI CHARACTER HO NOKHUK -> 'h' */ 1516 + { 0x2F, 0x7E }, /* THAI CHARACTER PAIYANNOI -> '~' */ 1517 + { 0x30, 0x61 }, /* THAI CHARACTER SARA A -> 'a' */ 1518 + { 0x31, 0x61 }, /* THAI CHARACTER MAI HAN-AKAT -> 'a' */ 1519 + { 0x34, 0x69 }, /* THAI CHARACTER SARA I -> 'i' */ 1520 + { 0x38, 0x75 }, /* THAI CHARACTER SARA U -> 'u' */ 1521 + { 0x3A, 0x27 }, /* THAI CHARACTER PHINTHU -> ''' */ 1522 + { 0x40, 0x65 }, /* THAI CHARACTER SARA E -> 'e' */ 1523 + { 0x42, 0x6F }, /* THAI CHARACTER SARA O -> 'o' */ 1524 + { 0x46, 0x2B }, /* THAI CHARACTER MAIYAMOK -> '+' */ 1525 + { 0x4D, 0x4D }, /* THAI CHARACTER NIKHAHIT -> 'M' */ 1526 + { 0x50, 0x30 }, /* THAI DIGIT ZERO -> '0' */ 1527 + { 0x51, 0x31 }, /* THAI DIGIT ONE -> '1' */ 1528 + { 0x52, 0x32 }, /* THAI DIGIT TWO -> '2' */ 1529 + { 0x53, 0x33 }, /* THAI DIGIT THREE -> '3' */ 1530 + { 0x54, 0x34 }, /* THAI DIGIT FOUR -> '4' */ 1531 + { 0x55, 0x35 }, /* THAI DIGIT FIVE -> '5' */ 1532 + { 0x56, 0x36 }, /* THAI DIGIT SIX -> '6' */ 1533 + { 0x57, 0x37 }, /* THAI DIGIT SEVEN -> '7' */ 1534 + { 0x58, 0x38 }, /* THAI DIGIT EIGHT -> '8' */ 1535 + { 0x59, 0x39 }, /* THAI DIGIT NINE -> '9' */ 1536 + { 0x81, 0x6B }, /* LAO LETTER KO -> 'k' */ 1537 + { 0x8A, 0x73 }, /* LAO LETTER SO TAM -> 's' */ 1538 + { 0x94, 0x64 }, /* LAO LETTER DO -> 'd' */ 1539 + { 0x95, 0x68 }, /* LAO LETTER TO -> 'h' */ 1540 + { 0x99, 0x6E }, /* LAO LETTER NO -> 'n' */ 1541 + { 0x9A, 0x62 }, /* LAO LETTER BO -> 'b' */ 1542 + { 0x9B, 0x70 }, /* LAO LETTER PO -> 'p' */ 1543 + { 0x9D, 0x66 }, /* LAO LETTER FO TAM -> 'f' */ 1544 + { 0x9F, 0x66 }, /* LAO LETTER FO SUNG -> 'f' */ 1545 + { 0xA1, 0x6D }, /* LAO LETTER MO -> 'm' */ 1546 + { 0xA2, 0x79 }, /* LAO LETTER YO -> 'y' */ 1547 + { 0xA3, 0x72 }, /* LAO LETTER LO LING -> 'r' */ 1548 + { 0xA5, 0x6C }, /* LAO LETTER LO LOOT -> 'l' */ 1549 + { 0xA7, 0x77 }, /* LAO LETTER WO -> 'w' */ 1550 + { 0xAA, 0x73 }, /* LAO LETTER SO SUNG -> 's' */ 1551 + { 0xAB, 0x68 }, /* LAO LETTER HO SUNG -> 'h' */ 1552 + { 0xAD, 0x60 }, /* LAO LETTER O -> '`' */ 1553 + { 0xAF, 0x7E }, /* LAO ELLIPSIS -> '~' */ 1554 + { 0xB0, 0x61 }, /* LAO VOWEL SIGN A -> 'a' */ 1555 + { 0xB4, 0x69 }, /* LAO VOWEL SIGN I -> 'i' */ 1556 + { 0xB6, 0x79 }, /* LAO VOWEL SIGN Y -> 'y' */ 1557 + { 0xB8, 0x75 }, /* LAO VOWEL SIGN U -> 'u' */ 1558 + { 0xBB, 0x6F }, /* LAO VOWEL SIGN MAI KON -> 'o' */ 1559 + { 0xBC, 0x6C }, /* LAO SEMIVOWEL SIGN LO -> 'l' */ 1560 + { 0xC0, 0x65 }, /* LAO VOWEL SIGN E -> 'e' */ 1561 + { 0xC2, 0x6F }, /* LAO VOWEL SIGN O -> 'o' */ 1562 + { 0xC6, 0x2B }, /* LAO KO LA -> '+' */ 1563 + { 0xCD, 0x4D }, /* LAO NIGGAHITA -> 'M' */ 1564 + { 0xD0, 0x30 }, /* LAO DIGIT ZERO -> '0' */ 1565 + { 0xD1, 0x31 }, /* LAO DIGIT ONE -> '1' */ 1566 + { 0xD2, 0x32 }, /* LAO DIGIT TWO -> '2' */ 1567 + { 0xD3, 0x33 }, /* LAO DIGIT THREE -> '3' */ 1568 + { 0xD4, 0x34 }, /* LAO DIGIT FOUR -> '4' */ 1569 + { 0xD5, 0x35 }, /* LAO DIGIT FIVE -> '5' */ 1570 + { 0xD6, 0x36 }, /* LAO DIGIT SIX -> '6' */ 1571 + { 0xD7, 0x37 }, /* LAO DIGIT SEVEN -> '7' */ 1572 + { 0xD8, 0x38 }, /* LAO DIGIT EIGHT -> '8' */ 1573 + { 0xD9, 0x39 }, /* LAO DIGIT NINE -> '9' */ 1574 + /* Entries for page 0x0F */ 1575 + { 0x0B, 0x2D }, /* TIBETAN MARK INTERSYLLABIC TSHEG -> '-' */ 1576 + { 0x20, 0x30 }, /* TIBETAN DIGIT ZERO -> '0' */ 1577 + { 0x21, 0x31 }, /* TIBETAN DIGIT ONE -> '1' */ 1578 + { 0x22, 0x32 }, /* TIBETAN DIGIT TWO -> '2' */ 1579 + { 0x23, 0x33 }, /* TIBETAN DIGIT THREE -> '3' */ 1580 + { 0x24, 0x34 }, /* TIBETAN DIGIT FOUR -> '4' */ 1581 + { 0x25, 0x35 }, /* TIBETAN DIGIT FIVE -> '5' */ 1582 + { 0x26, 0x36 }, /* TIBETAN DIGIT SIX -> '6' */ 1583 + { 0x27, 0x37 }, /* TIBETAN DIGIT SEVEN -> '7' */ 1584 + { 0x28, 0x38 }, /* TIBETAN DIGIT EIGHT -> '8' */ 1585 + { 0x29, 0x39 }, /* TIBETAN DIGIT NINE -> '9' */ 1586 + { 0x34, 0x2B }, /* TIBETAN MARK BSDUS RTAGS -> '+' */ 1587 + { 0x35, 0x2A }, /* TIBETAN MARK NGAS BZUNG NYI ZLA -> '*' */ 1588 + { 0x36, 0x5E }, /* TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN -> '^' */ 1589 + { 0x37, 0x5F }, /* TIBETAN MARK NGAS BZUNG SGOR RTAGS -> '_' */ 1590 + { 0x39, 0x7E }, /* TIBETAN MARK TSA -PHRU -> '~' */ 1591 + { 0x3B, 0x5D }, /* TIBETAN MARK GUG RTAGS GYAS -> ']' */ 1592 + { 0x40, 0x6B }, /* TIBETAN LETTER KA -> 'k' */ 1593 + { 0x42, 0x67 }, /* TIBETAN LETTER GA -> 'g' */ 1594 + { 0x45, 0x63 }, /* TIBETAN LETTER CA -> 'c' */ 1595 + { 0x47, 0x6A }, /* TIBETAN LETTER JA -> 'j' */ 1596 + { 0x4F, 0x74 }, /* TIBETAN LETTER TA -> 't' */ 1597 + { 0x51, 0x64 }, /* TIBETAN LETTER DA -> 'd' */ 1598 + { 0x53, 0x6E }, /* TIBETAN LETTER NA -> 'n' */ 1599 + { 0x54, 0x70 }, /* TIBETAN LETTER PA -> 'p' */ 1600 + { 0x56, 0x62 }, /* TIBETAN LETTER BA -> 'b' */ 1601 + { 0x58, 0x6D }, /* TIBETAN LETTER MA -> 'm' */ 1602 + { 0x5D, 0x77 }, /* TIBETAN LETTER WA -> 'w' */ 1603 + { 0x5F, 0x7A }, /* TIBETAN LETTER ZA -> 'z' */ 1604 + { 0x60, 0x27 }, /* TIBETAN LETTER -A -> ''' */ 1605 + { 0x61, 0x79 }, /* TIBETAN LETTER YA -> 'y' */ 1606 + { 0x62, 0x72 }, /* TIBETAN LETTER RA -> 'r' */ 1607 + { 0x63, 0x6C }, /* TIBETAN LETTER LA -> 'l' */ 1608 + { 0x66, 0x73 }, /* TIBETAN LETTER SA -> 's' */ 1609 + { 0x67, 0x68 }, /* TIBETAN LETTER HA -> 'h' */ 1610 + { 0x68, 0x61 }, /* TIBETAN LETTER A -> 'a' */ 1611 + { 0x6A, 0x72 }, /* TIBETAN LETTER FIXED-FORM RA -> 'r' */ 1612 + { 0x72, 0x69 }, /* TIBETAN VOWEL SIGN I -> 'i' */ 1613 + { 0x74, 0x75 }, /* TIBETAN VOWEL SIGN U -> 'u' */ 1614 + { 0x76, 0x52 }, /* TIBETAN VOWEL SIGN VOCALIC R -> 'R' */ 1615 + { 0x78, 0x4C }, /* TIBETAN VOWEL SIGN VOCALIC L -> 'L' */ 1616 + { 0x7A, 0x65 }, /* TIBETAN VOWEL SIGN E -> 'e' */ 1617 + { 0x7C, 0x6F }, /* TIBETAN VOWEL SIGN O -> 'o' */ 1618 + { 0x7E, 0x4D }, /* TIBETAN SIGN RJES SU NGA RO -> 'M' */ 1619 + { 0x7F, 0x48 }, /* TIBETAN SIGN RNAM BCAD -> 'H' */ 1620 + { 0x80, 0x69 }, /* TIBETAN VOWEL SIGN REVERSED I -> 'i' */ 1621 + { 0x90, 0x6B }, /* TIBETAN SUBJOINED LETTER KA -> 'k' */ 1622 + { 0x92, 0x67 }, /* TIBETAN SUBJOINED LETTER GA -> 'g' */ 1623 + { 0x95, 0x63 }, /* TIBETAN SUBJOINED LETTER CA -> 'c' */ 1624 + { 0x97, 0x6A }, /* TIBETAN SUBJOINED LETTER JA -> 'j' */ 1625 + { 0x9F, 0x74 }, /* TIBETAN SUBJOINED LETTER TA -> 't' */ 1626 + { 0xA1, 0x64 }, /* TIBETAN SUBJOINED LETTER DA -> 'd' */ 1627 + { 0xA3, 0x6E }, /* TIBETAN SUBJOINED LETTER NA -> 'n' */ 1628 + { 0xA4, 0x70 }, /* TIBETAN SUBJOINED LETTER PA -> 'p' */ 1629 + { 0xA6, 0x62 }, /* TIBETAN SUBJOINED LETTER BA -> 'b' */ 1630 + { 0xA8, 0x6D }, /* TIBETAN SUBJOINED LETTER MA -> 'm' */ 1631 + { 0xAD, 0x77 }, /* TIBETAN SUBJOINED LETTER WA -> 'w' */ 1632 + { 0xAF, 0x7A }, /* TIBETAN SUBJOINED LETTER ZA -> 'z' */ 1633 + { 0xB0, 0x27 }, /* TIBETAN SUBJOINED LETTER -A -> ''' */ 1634 + { 0xB1, 0x79 }, /* TIBETAN SUBJOINED LETTER YA -> 'y' */ 1635 + { 0xB2, 0x72 }, /* TIBETAN SUBJOINED LETTER RA -> 'r' */ 1636 + { 0xB3, 0x6C }, /* TIBETAN SUBJOINED LETTER LA -> 'l' */ 1637 + { 0xB6, 0x73 }, /* TIBETAN SUBJOINED LETTER SA -> 's' */ 1638 + { 0xB7, 0x68 }, /* TIBETAN SUBJOINED LETTER HA -> 'h' */ 1639 + { 0xB8, 0x61 }, /* TIBETAN SUBJOINED LETTER A -> 'a' */ 1640 + { 0xBA, 0x77 }, /* TIBETAN SUBJOINED LETTER FIXED-FORM WA -> 'w' */ 1641 + { 0xBB, 0x79 }, /* TIBETAN SUBJOINED LETTER FIXED-FORM YA -> 'y' */ 1642 + { 0xBC, 0x72 }, /* TIBETAN SUBJOINED LETTER FIXED-FORM RA -> 'r' */ 1643 + { 0xBE, 0x58 }, /* TIBETAN KU RU KHA -> 'X' */ 1644 + /* Entries for page 0x10 */ 1645 + { 0x00, 0x6B }, /* MYANMAR LETTER KA -> 'k' */ 1646 + { 0x02, 0x67 }, /* MYANMAR LETTER GA -> 'g' */ 1647 + { 0x05, 0x63 }, /* MYANMAR LETTER CA -> 'c' */ 1648 + { 0x07, 0x6A }, /* MYANMAR LETTER JA -> 'j' */ 1649 + { 0x12, 0x64 }, /* MYANMAR LETTER DA -> 'd' */ 1650 + { 0x14, 0x6E }, /* MYANMAR LETTER NA -> 'n' */ 1651 + { 0x15, 0x70 }, /* MYANMAR LETTER PA -> 'p' */ 1652 + { 0x17, 0x62 }, /* MYANMAR LETTER BA -> 'b' */ 1653 + { 0x19, 0x6D }, /* MYANMAR LETTER MA -> 'm' */ 1654 + { 0x1A, 0x79 }, /* MYANMAR LETTER YA -> 'y' */ 1655 + { 0x1B, 0x72 }, /* MYANMAR LETTER RA -> 'r' */ 1656 + { 0x1C, 0x6C }, /* MYANMAR LETTER LA -> 'l' */ 1657 + { 0x1D, 0x77 }, /* MYANMAR LETTER WA -> 'w' */ 1658 + { 0x1E, 0x73 }, /* MYANMAR LETTER SA -> 's' */ 1659 + { 0x1F, 0x68 }, /* MYANMAR LETTER HA -> 'h' */ 1660 + { 0x21, 0x61 }, /* MYANMAR LETTER A -> 'a' */ 1661 + { 0x23, 0x69 }, /* MYANMAR LETTER I -> 'i' */ 1662 + { 0x25, 0x75 }, /* MYANMAR LETTER U -> 'u' */ 1663 + { 0x27, 0x65 }, /* MYANMAR LETTER E -> 'e' */ 1664 + { 0x29, 0x6F }, /* MYANMAR LETTER O -> 'o' */ 1665 + { 0x2D, 0x69 }, /* MYANMAR VOWEL SIGN I -> 'i' */ 1666 + { 0x2F, 0x75 }, /* MYANMAR VOWEL SIGN U -> 'u' */ 1667 + { 0x31, 0x65 }, /* MYANMAR VOWEL SIGN E -> 'e' */ 1668 + { 0x36, 0x4E }, /* MYANMAR SIGN ANUSVARA -> 'N' */ 1669 + { 0x37, 0x27 }, /* MYANMAR SIGN DOT BELOW -> ''' */ 1670 + { 0x38, 0x3A }, /* MYANMAR SIGN VISARGA -> ':' */ 1671 + { 0x40, 0x30 }, /* MYANMAR DIGIT ZERO -> '0' */ 1672 + { 0x41, 0x31 }, /* MYANMAR DIGIT ONE -> '1' */ 1673 + { 0x42, 0x32 }, /* MYANMAR DIGIT TWO -> '2' */ 1674 + { 0x43, 0x33 }, /* MYANMAR DIGIT THREE -> '3' */ 1675 + { 0x44, 0x34 }, /* MYANMAR DIGIT FOUR -> '4' */ 1676 + { 0x45, 0x35 }, /* MYANMAR DIGIT FIVE -> '5' */ 1677 + { 0x46, 0x36 }, /* MYANMAR DIGIT SIX -> '6' */ 1678 + { 0x47, 0x37 }, /* MYANMAR DIGIT SEVEN -> '7' */ 1679 + { 0x48, 0x38 }, /* MYANMAR DIGIT EIGHT -> '8' */ 1680 + { 0x49, 0x39 }, /* MYANMAR DIGIT NINE -> '9' */ 1681 + { 0x52, 0x52 }, /* MYANMAR LETTER VOCALIC R -> 'R' */ 1682 + { 0x54, 0x4C }, /* MYANMAR LETTER VOCALIC L -> 'L' */ 1683 + { 0x56, 0x52 }, /* MYANMAR VOWEL SIGN VOCALIC R -> 'R' */ 1684 + { 0x58, 0x4C }, /* MYANMAR VOWEL SIGN VOCALIC L -> 'L' */ 1685 + { 0xA0, 0x41 }, /* GEORGIAN CAPITAL LETTER AN -> 'A' */ 1686 + { 0xA1, 0x42 }, /* GEORGIAN CAPITAL LETTER BAN -> 'B' */ 1687 + { 0xA2, 0x47 }, /* GEORGIAN CAPITAL LETTER GAN -> 'G' */ 1688 + { 0xA3, 0x44 }, /* GEORGIAN CAPITAL LETTER DON -> 'D' */ 1689 + { 0xA4, 0x45 }, /* GEORGIAN CAPITAL LETTER EN -> 'E' */ 1690 + { 0xA5, 0x56 }, /* GEORGIAN CAPITAL LETTER VIN -> 'V' */ 1691 + { 0xA6, 0x5A }, /* GEORGIAN CAPITAL LETTER ZEN -> 'Z' */ 1692 + { 0xA8, 0x49 }, /* GEORGIAN CAPITAL LETTER IN -> 'I' */ 1693 + { 0xA9, 0x4B }, /* GEORGIAN CAPITAL LETTER KAN -> 'K' */ 1694 + { 0xAA, 0x4C }, /* GEORGIAN CAPITAL LETTER LAS -> 'L' */ 1695 + { 0xAB, 0x4D }, /* GEORGIAN CAPITAL LETTER MAN -> 'M' */ 1696 + { 0xAC, 0x4E }, /* GEORGIAN CAPITAL LETTER NAR -> 'N' */ 1697 + { 0xAD, 0x4F }, /* GEORGIAN CAPITAL LETTER ON -> 'O' */ 1698 + { 0xAE, 0x50 }, /* GEORGIAN CAPITAL LETTER PAR -> 'P' */ 1699 + { 0xB0, 0x52 }, /* GEORGIAN CAPITAL LETTER RAE -> 'R' */ 1700 + { 0xB1, 0x53 }, /* GEORGIAN CAPITAL LETTER SAN -> 'S' */ 1701 + { 0xB2, 0x54 }, /* GEORGIAN CAPITAL LETTER TAR -> 'T' */ 1702 + { 0xB3, 0x55 }, /* GEORGIAN CAPITAL LETTER UN -> 'U' */ 1703 + { 0xB7, 0x51 }, /* GEORGIAN CAPITAL LETTER QAR -> 'Q' */ 1704 + { 0xBC, 0x43 }, /* GEORGIAN CAPITAL LETTER CIL -> 'C' */ 1705 + { 0xBE, 0x58 }, /* GEORGIAN CAPITAL LETTER XAN -> 'X' */ 1706 + { 0xBF, 0x4A }, /* GEORGIAN CAPITAL LETTER JHAN -> 'J' */ 1707 + { 0xC0, 0x48 }, /* GEORGIAN CAPITAL LETTER HAE -> 'H' */ 1708 + { 0xC1, 0x45 }, /* GEORGIAN CAPITAL LETTER HE -> 'E' */ 1709 + { 0xC2, 0x59 }, /* GEORGIAN CAPITAL LETTER HIE -> 'Y' */ 1710 + { 0xC3, 0x57 }, /* GEORGIAN CAPITAL LETTER WE -> 'W' */ 1711 + { 0xD0, 0x61 }, /* GEORGIAN LETTER AN -> 'a' */ 1712 + { 0xD1, 0x62 }, /* GEORGIAN LETTER BAN -> 'b' */ 1713 + { 0xD2, 0x67 }, /* GEORGIAN LETTER GAN -> 'g' */ 1714 + { 0xD3, 0x64 }, /* GEORGIAN LETTER DON -> 'd' */ 1715 + { 0xD4, 0x65 }, /* GEORGIAN LETTER EN -> 'e' */ 1716 + { 0xD5, 0x76 }, /* GEORGIAN LETTER VIN -> 'v' */ 1717 + { 0xD6, 0x7A }, /* GEORGIAN LETTER ZEN -> 'z' */ 1718 + { 0xD8, 0x69 }, /* GEORGIAN LETTER IN -> 'i' */ 1719 + { 0xD9, 0x6B }, /* GEORGIAN LETTER KAN -> 'k' */ 1720 + { 0xDA, 0x6C }, /* GEORGIAN LETTER LAS -> 'l' */ 1721 + { 0xDB, 0x6D }, /* GEORGIAN LETTER MAN -> 'm' */ 1722 + { 0xDC, 0x6E }, /* GEORGIAN LETTER NAR -> 'n' */ 1723 + { 0xDD, 0x6F }, /* GEORGIAN LETTER ON -> 'o' */ 1724 + { 0xDE, 0x70 }, /* GEORGIAN LETTER PAR -> 'p' */ 1725 + { 0xE0, 0x72 }, /* GEORGIAN LETTER RAE -> 'r' */ 1726 + { 0xE1, 0x73 }, /* GEORGIAN LETTER SAN -> 's' */ 1727 + { 0xE2, 0x74 }, /* GEORGIAN LETTER TAR -> 't' */ 1728 + { 0xE3, 0x75 }, /* GEORGIAN LETTER UN -> 'u' */ 1729 + { 0xE7, 0x71 }, /* GEORGIAN LETTER QAR -> 'q' */ 1730 + { 0xEC, 0x63 }, /* GEORGIAN LETTER CIL -> 'c' */ 1731 + { 0xEE, 0x78 }, /* GEORGIAN LETTER XAN -> 'x' */ 1732 + { 0xEF, 0x6A }, /* GEORGIAN LETTER JHAN -> 'j' */ 1733 + { 0xF0, 0x68 }, /* GEORGIAN LETTER HAE -> 'h' */ 1734 + { 0xF1, 0x65 }, /* GEORGIAN LETTER HE -> 'e' */ 1735 + { 0xF2, 0x79 }, /* GEORGIAN LETTER HIE -> 'y' */ 1736 + { 0xF3, 0x77 }, /* GEORGIAN LETTER WE -> 'w' */ 1737 + { 0xF6, 0x66 }, /* GEORGIAN LETTER FI -> 'f' */ 1738 + /* Entries for page 0x11 */ 1739 + { 0x00, 0x67 }, /* HANGUL CHOSEONG KIYEOK -> 'g' */ 1740 + { 0x02, 0x6E }, /* HANGUL CHOSEONG NIEUN -> 'n' */ 1741 + { 0x03, 0x64 }, /* HANGUL CHOSEONG TIKEUT -> 'd' */ 1742 + { 0x05, 0x72 }, /* HANGUL CHOSEONG RIEUL -> 'r' */ 1743 + { 0x06, 0x6D }, /* HANGUL CHOSEONG MIEUM -> 'm' */ 1744 + { 0x07, 0x62 }, /* HANGUL CHOSEONG PIEUP -> 'b' */ 1745 + { 0x09, 0x73 }, /* HANGUL CHOSEONG SIOS -> 's' */ 1746 + { 0x0C, 0x6A }, /* HANGUL CHOSEONG CIEUC -> 'j' */ 1747 + { 0x0E, 0x63 }, /* HANGUL CHOSEONG CHIEUCH -> 'c' */ 1748 + { 0x0F, 0x6B }, /* HANGUL CHOSEONG KHIEUKH -> 'k' */ 1749 + { 0x10, 0x74 }, /* HANGUL CHOSEONG THIEUTH -> 't' */ 1750 + { 0x11, 0x70 }, /* HANGUL CHOSEONG PHIEUPH -> 'p' */ 1751 + { 0x12, 0x68 }, /* HANGUL CHOSEONG HIEUH -> 'h' */ 1752 + { 0x35, 0x73 }, /* HANGUL CHOSEONG SIOS-IEUNG -> 's' */ 1753 + { 0x40, 0x5A }, /* HANGUL CHOSEONG PANSIOS -> 'Z' */ 1754 + { 0x41, 0x67 }, /* HANGUL CHOSEONG IEUNG-KIYEOK -> 'g' */ 1755 + { 0x42, 0x64 }, /* HANGUL CHOSEONG IEUNG-TIKEUT -> 'd' */ 1756 + { 0x43, 0x6D }, /* HANGUL CHOSEONG IEUNG-MIEUM -> 'm' */ 1757 + { 0x44, 0x62 }, /* HANGUL CHOSEONG IEUNG-PIEUP -> 'b' */ 1758 + { 0x45, 0x73 }, /* HANGUL CHOSEONG IEUNG-SIOS -> 's' */ 1759 + { 0x46, 0x5A }, /* HANGUL CHOSEONG IEUNG-PANSIOS -> 'Z' */ 1760 + { 0x48, 0x6A }, /* HANGUL CHOSEONG IEUNG-CIEUC -> 'j' */ 1761 + { 0x49, 0x63 }, /* HANGUL CHOSEONG IEUNG-CHIEUCH -> 'c' */ 1762 + { 0x4A, 0x74 }, /* HANGUL CHOSEONG IEUNG-THIEUTH -> 't' */ 1763 + { 0x4B, 0x70 }, /* HANGUL CHOSEONG IEUNG-PHIEUPH -> 'p' */ 1764 + { 0x4C, 0x4E }, /* HANGUL CHOSEONG YESIEUNG -> 'N' */ 1765 + { 0x4D, 0x6A }, /* HANGUL CHOSEONG CIEUC-IEUNG -> 'j' */ 1766 + { 0x59, 0x51 }, /* HANGUL CHOSEONG YEORINHIEUH -> 'Q' */ 1767 + { 0x61, 0x61 }, /* HANGUL JUNGSEONG A -> 'a' */ 1768 + { 0x66, 0x65 }, /* HANGUL JUNGSEONG E -> 'e' */ 1769 + { 0x69, 0x6F }, /* HANGUL JUNGSEONG O -> 'o' */ 1770 + { 0x6E, 0x75 }, /* HANGUL JUNGSEONG U -> 'u' */ 1771 + { 0x75, 0x69 }, /* HANGUL JUNGSEONG I -> 'i' */ 1772 + { 0x9E, 0x55 }, /* HANGUL JUNGSEONG ARAEA -> 'U' */ 1773 + { 0xA8, 0x67 }, /* HANGUL JONGSEONG KIYEOK -> 'g' */ 1774 + { 0xAB, 0x6E }, /* HANGUL JONGSEONG NIEUN -> 'n' */ 1775 + { 0xAE, 0x64 }, /* HANGUL JONGSEONG TIKEUT -> 'd' */ 1776 + { 0xAF, 0x6C }, /* HANGUL JONGSEONG RIEUL -> 'l' */ 1777 + { 0xB7, 0x6D }, /* HANGUL JONGSEONG MIEUM -> 'm' */ 1778 + { 0xB8, 0x62 }, /* HANGUL JONGSEONG PIEUP -> 'b' */ 1779 + { 0xBA, 0x73 }, /* HANGUL JONGSEONG SIOS -> 's' */ 1780 + { 0xBD, 0x6A }, /* HANGUL JONGSEONG CIEUC -> 'j' */ 1781 + { 0xBE, 0x63 }, /* HANGUL JONGSEONG CHIEUCH -> 'c' */ 1782 + { 0xBF, 0x6B }, /* HANGUL JONGSEONG KHIEUKH -> 'k' */ 1783 + { 0xC0, 0x74 }, /* HANGUL JONGSEONG THIEUTH -> 't' */ 1784 + { 0xC1, 0x70 }, /* HANGUL JONGSEONG PHIEUPH -> 'p' */ 1785 + { 0xC2, 0x68 }, /* HANGUL JONGSEONG HIEUH -> 'h' */ 1786 + { 0xEB, 0x5A }, /* HANGUL JONGSEONG PANSIOS -> 'Z' */ 1787 + { 0xEC, 0x67 }, /* HANGUL JONGSEONG IEUNG-KIYEOK -> 'g' */ 1788 + { 0xF0, 0x4E }, /* HANGUL JONGSEONG YESIEUNG -> 'N' */ 1789 + { 0xF9, 0x51 }, /* HANGUL JONGSEONG YEORINHIEUH -> 'Q' */ 1790 + /* Entries for page 0x13 */ 1791 + { 0x61, 0x20 }, /* ETHIOPIC WORDSPACE -> ' ' */ 1792 + { 0x62, 0x2E }, /* ETHIOPIC FULL STOP -> '.' */ 1793 + { 0x63, 0x2C }, /* ETHIOPIC COMMA -> ',' */ 1794 + { 0x64, 0x3B }, /* ETHIOPIC SEMICOLON -> ';' */ 1795 + { 0x65, 0x3A }, /* ETHIOPIC COLON -> ':' */ 1796 + { 0x67, 0x3F }, /* ETHIOPIC QUESTION MARK -> '?' */ 1797 + { 0x69, 0x31 }, /* ETHIOPIC DIGIT ONE -> '1' */ 1798 + { 0x6A, 0x32 }, /* ETHIOPIC DIGIT TWO -> '2' */ 1799 + { 0x6B, 0x33 }, /* ETHIOPIC DIGIT THREE -> '3' */ 1800 + { 0x6C, 0x34 }, /* ETHIOPIC DIGIT FOUR -> '4' */ 1801 + { 0x6D, 0x35 }, /* ETHIOPIC DIGIT FIVE -> '5' */ 1802 + { 0x6E, 0x36 }, /* ETHIOPIC DIGIT SIX -> '6' */ 1803 + { 0x6F, 0x37 }, /* ETHIOPIC DIGIT SEVEN -> '7' */ 1804 + { 0x70, 0x38 }, /* ETHIOPIC DIGIT EIGHT -> '8' */ 1805 + { 0x71, 0x39 }, /* ETHIOPIC DIGIT NINE -> '9' */ 1806 + { 0xA0, 0x61 }, /* CHEROKEE LETTER A -> 'a' */ 1807 + { 0xA1, 0x65 }, /* CHEROKEE LETTER E -> 'e' */ 1808 + { 0xA2, 0x69 }, /* CHEROKEE LETTER I -> 'i' */ 1809 + { 0xA3, 0x6F }, /* CHEROKEE LETTER O -> 'o' */ 1810 + { 0xA4, 0x75 }, /* CHEROKEE LETTER U -> 'u' */ 1811 + { 0xA5, 0x76 }, /* CHEROKEE LETTER V -> 'v' */ 1812 + { 0xCD, 0x73 }, /* CHEROKEE LETTER S -> 's' */ 1813 + /* Entries for page 0x14 */ 1814 + { 0x01, 0x65 }, /* CANADIAN SYLLABICS E -> 'e' */ 1815 + { 0x03, 0x69 }, /* CANADIAN SYLLABICS I -> 'i' */ 1816 + { 0x05, 0x6F }, /* CANADIAN SYLLABICS O -> 'o' */ 1817 + { 0x09, 0x69 }, /* CANADIAN SYLLABICS CARRIER I -> 'i' */ 1818 + { 0x0A, 0x61 }, /* CANADIAN SYLLABICS A -> 'a' */ 1819 + { 0x1D, 0x77 }, /* CANADIAN SYLLABICS Y-CREE W -> 'w' */ 1820 + { 0x1E, 0x27 }, /* CANADIAN SYLLABICS GLOTTAL STOP -> ''' */ 1821 + { 0x1F, 0x74 }, /* CANADIAN SYLLABICS FINAL ACUTE -> 't' */ 1822 + { 0x20, 0x6B }, /* CANADIAN SYLLABICS FINAL GRAVE -> 'k' */ 1823 + { 0x22, 0x73 }, /* CANADIAN SYLLABICS FINAL TOP HALF RING -> 's' */ 1824 + { 0x23, 0x6E }, /* CANADIAN SYLLABICS FINAL RIGHT HALF RING -> 'n' */ 1825 + { 0x24, 0x77 }, /* CANADIAN SYLLABICS FINAL RING -> 'w' */ 1826 + { 0x25, 0x6E }, /* CANADIAN SYLLABICS FINAL DOUBLE ACUTE -> 'n' */ 1827 + { 0x27, 0x77 }, /* CANADIAN SYLLABICS FINAL MIDDLE DOT -> 'w' */ 1828 + { 0x28, 0x63 }, /* CANADIAN SYLLABICS FINAL SHORT HORIZONTAL STROKE -> 'c' */ 1829 + { 0x29, 0x3F }, /* CANADIAN SYLLABICS FINAL PLUS -> '?' */ 1830 + { 0x2A, 0x6C }, /* CANADIAN SYLLABICS FINAL DOWN TACK -> 'l' */ 1831 + { 0x49, 0x70 }, /* CANADIAN SYLLABICS P -> 'p' */ 1832 + { 0x4A, 0x70 }, /* CANADIAN SYLLABICS WEST-CREE P -> 'p' */ 1833 + { 0x4B, 0x68 }, /* CANADIAN SYLLABICS CARRIER H -> 'h' */ 1834 + { 0x66, 0x74 }, /* CANADIAN SYLLABICS T -> 't' */ 1835 + { 0x83, 0x6B }, /* CANADIAN SYLLABICS K -> 'k' */ 1836 + { 0xA1, 0x63 }, /* CANADIAN SYLLABICS C -> 'c' */ 1837 + { 0xBB, 0x6D }, /* CANADIAN SYLLABICS M -> 'm' */ 1838 + { 0xBC, 0x6D }, /* CANADIAN SYLLABICS WEST-CREE M -> 'm' */ 1839 + { 0xBE, 0x6D }, /* CANADIAN SYLLABICS ATHAPASCAN M -> 'm' */ 1840 + { 0xBF, 0x6D }, /* CANADIAN SYLLABICS SAYISI M -> 'm' */ 1841 + { 0xD0, 0x6E }, /* CANADIAN SYLLABICS N -> 'n' */ 1842 + { 0xEA, 0x00 }, /* CANADIAN SYLLABICS L -> ... */ 1843 + { 0xEC, 0x6C }, /* CANADIAN SYLLABICS MEDIAL L -> 'l' */ 1844 + /* Entries for page 0x15 */ 1845 + { 0x05, 0x73 }, /* CANADIAN SYLLABICS S -> 's' */ 1846 + { 0x06, 0x73 }, /* CANADIAN SYLLABICS ATHAPASCAN S -> 's' */ 1847 + { 0x08, 0x73 }, /* CANADIAN SYLLABICS BLACKFOOT S -> 's' */ 1848 + { 0x3E, 0x00 }, /* CANADIAN SYLLABICS Y -> ... */ 1849 + { 0x40, 0x79 }, /* CANADIAN SYLLABICS WEST-CREE Y -> 'y' */ 1850 + { 0x50, 0x00 }, /* CANADIAN SYLLABICS R -> ... */ 1851 + { 0x52, 0x72 }, /* CANADIAN SYLLABICS MEDIAL R -> 'r' */ 1852 + { 0x5D, 0x66 }, /* CANADIAN SYLLABICS F -> 'f' */ 1853 + { 0x7B, 0x68 }, /* CANADIAN SYLLABICS NUNAVIK H -> 'h' */ 1854 + { 0x7C, 0x68 }, /* CANADIAN SYLLABICS NUNAVUT H -> 'h' */ 1855 + { 0x85, 0x71 }, /* CANADIAN SYLLABICS Q -> 'q' */ 1856 + { 0xAF, 0x62 }, /* CANADIAN SYLLABICS AIVILIK B -> 'b' */ 1857 + { 0xB0, 0x65 }, /* CANADIAN SYLLABICS BLACKFOOT E -> 'e' */ 1858 + { 0xB1, 0x69 }, /* CANADIAN SYLLABICS BLACKFOOT I -> 'i' */ 1859 + { 0xB2, 0x6F }, /* CANADIAN SYLLABICS BLACKFOOT O -> 'o' */ 1860 + { 0xB3, 0x61 }, /* CANADIAN SYLLABICS BLACKFOOT A -> 'a' */ 1861 + { 0xEE, 0x70 }, /* CANADIAN SYLLABICS CARRIER P -> 'p' */ 1862 + /* Entries for page 0x16 */ 1863 + { 0x46, 0x7A }, /* CANADIAN SYLLABICS CARRIER Z -> 'z' */ 1864 + { 0x47, 0x7A }, /* CANADIAN SYLLABICS CARRIER INITIAL Z -> 'z' */ 1865 + { 0x6D, 0x58 }, /* CANADIAN SYLLABICS CHI SIGN -> 'X' */ 1866 + { 0x6E, 0x2E }, /* CANADIAN SYLLABICS FULL STOP -> '.' */ 1867 + { 0x80, 0x20 }, /* OGHAM SPACE MARK -> ' ' */ 1868 + { 0x81, 0x62 }, /* OGHAM LETTER BEITH -> 'b' */ 1869 + { 0x82, 0x6C }, /* OGHAM LETTER LUIS -> 'l' */ 1870 + { 0x83, 0x66 }, /* OGHAM LETTER FEARN -> 'f' */ 1871 + { 0x84, 0x73 }, /* OGHAM LETTER SAIL -> 's' */ 1872 + { 0x85, 0x6E }, /* OGHAM LETTER NION -> 'n' */ 1873 + { 0x86, 0x68 }, /* OGHAM LETTER UATH -> 'h' */ 1874 + { 0x87, 0x64 }, /* OGHAM LETTER DAIR -> 'd' */ 1875 + { 0x88, 0x74 }, /* OGHAM LETTER TINNE -> 't' */ 1876 + { 0x89, 0x63 }, /* OGHAM LETTER COLL -> 'c' */ 1877 + { 0x8A, 0x71 }, /* OGHAM LETTER CEIRT -> 'q' */ 1878 + { 0x8B, 0x6D }, /* OGHAM LETTER MUIN -> 'm' */ 1879 + { 0x8C, 0x67 }, /* OGHAM LETTER GORT -> 'g' */ 1880 + { 0x8E, 0x7A }, /* OGHAM LETTER STRAIF -> 'z' */ 1881 + { 0x8F, 0x72 }, /* OGHAM LETTER RUIS -> 'r' */ 1882 + { 0x90, 0x61 }, /* OGHAM LETTER AILM -> 'a' */ 1883 + { 0x91, 0x6F }, /* OGHAM LETTER ONN -> 'o' */ 1884 + { 0x92, 0x75 }, /* OGHAM LETTER UR -> 'u' */ 1885 + { 0x93, 0x65 }, /* OGHAM LETTER EADHADH -> 'e' */ 1886 + { 0x94, 0x69 }, /* OGHAM LETTER IODHADH -> 'i' */ 1887 + { 0x98, 0x70 }, /* OGHAM LETTER IFIN -> 'p' */ 1888 + { 0x99, 0x78 }, /* OGHAM LETTER EAMHANCHOLL -> 'x' */ 1889 + { 0x9A, 0x70 }, /* OGHAM LETTER PEITH -> 'p' */ 1890 + { 0x9B, 0x3C }, /* OGHAM FEATHER MARK -> '<' */ 1891 + { 0x9C, 0x3E }, /* OGHAM REVERSED FEATHER MARK -> '>' */ 1892 + { 0xA0, 0x66 }, /* RUNIC LETTER FEHU FEOH FE F -> 'f' */ 1893 + { 0xA1, 0x76 }, /* RUNIC LETTER V -> 'v' */ 1894 + { 0xA2, 0x75 }, /* RUNIC LETTER URUZ UR U -> 'u' */ 1895 + { 0xA4, 0x79 }, /* RUNIC LETTER Y -> 'y' */ 1896 + { 0xA5, 0x77 }, /* RUNIC LETTER W -> 'w' */ 1897 + { 0xA8, 0x61 }, /* RUNIC LETTER ANSUZ A -> 'a' */ 1898 + { 0xA9, 0x6F }, /* RUNIC LETTER OS O -> 'o' */ 1899 + { 0xAC, 0x00 }, /* RUNIC LETTER LONG-BRANCH-OSS O -> ... */ 1900 + { 0xAE, 0x6F }, /* RUNIC LETTER O -> 'o' */ 1901 + { 0xB1, 0x72 }, /* RUNIC LETTER RAIDO RAD REID R -> 'r' */ 1902 + { 0xB2, 0x6B }, /* RUNIC LETTER KAUNA -> 'k' */ 1903 + { 0xB3, 0x63 }, /* RUNIC LETTER CEN -> 'c' */ 1904 + { 0xB4, 0x6B }, /* RUNIC LETTER KAUN K -> 'k' */ 1905 + { 0xB5, 0x67 }, /* RUNIC LETTER G -> 'g' */ 1906 + { 0xB7, 0x67 }, /* RUNIC LETTER GEBO GYFU G -> 'g' */ 1907 + { 0xB8, 0x67 }, /* RUNIC LETTER GAR -> 'g' */ 1908 + { 0xB9, 0x77 }, /* RUNIC LETTER WUNJO WYNN W -> 'w' */ 1909 + { 0xBA, 0x00 }, /* RUNIC LETTER HAGLAZ H -> ... */ 1910 + { 0xBD, 0x68 }, /* RUNIC LETTER SHORT-TWIG-HAGALL H -> 'h' */ 1911 + { 0xBE, 0x00 }, /* RUNIC LETTER NAUDIZ NYD NAUD N -> ... */ 1912 + { 0xC0, 0x6E }, /* RUNIC LETTER DOTTED-N -> 'n' */ 1913 + { 0xC1, 0x69 }, /* RUNIC LETTER ISAZ IS ISS I -> 'i' */ 1914 + { 0xC2, 0x65 }, /* RUNIC LETTER E -> 'e' */ 1915 + { 0xC3, 0x6A }, /* RUNIC LETTER JERAN J -> 'j' */ 1916 + { 0xC4, 0x67 }, /* RUNIC LETTER GER -> 'g' */ 1917 + { 0xC6, 0x61 }, /* RUNIC LETTER SHORT-TWIG-AR A -> 'a' */ 1918 + { 0xC8, 0x70 }, /* RUNIC LETTER PERTHO PEORTH P -> 'p' */ 1919 + { 0xC9, 0x7A }, /* RUNIC LETTER ALGIZ EOLHX -> 'z' */ 1920 + { 0xCA, 0x00 }, /* RUNIC LETTER SOWILO S -> ... */ 1921 + { 0xCC, 0x73 }, /* RUNIC LETTER SHORT-TWIG-SOL S -> 's' */ 1922 + { 0xCD, 0x63 }, /* RUNIC LETTER C -> 'c' */ 1923 + { 0xCE, 0x7A }, /* RUNIC LETTER Z -> 'z' */ 1924 + { 0xCF, 0x74 }, /* RUNIC LETTER TIWAZ TIR TYR T -> 't' */ 1925 + { 0xD0, 0x74 }, /* RUNIC LETTER SHORT-TWIG-TYR T -> 't' */ 1926 + { 0xD1, 0x64 }, /* RUNIC LETTER D -> 'd' */ 1927 + { 0xD2, 0x62 }, /* RUNIC LETTER BERKANAN BEORC BJARKAN B -> 'b' */ 1928 + { 0xD3, 0x62 }, /* RUNIC LETTER SHORT-TWIG-BJARKAN B -> 'b' */ 1929 + { 0xD4, 0x70 }, /* RUNIC LETTER DOTTED-P -> 'p' */ 1930 + { 0xD5, 0x70 }, /* RUNIC LETTER OPEN-P -> 'p' */ 1931 + { 0xD6, 0x65 }, /* RUNIC LETTER EHWAZ EH E -> 'e' */ 1932 + { 0xD7, 0x00 }, /* RUNIC LETTER MANNAZ MAN M -> ... */ 1933 + { 0xD9, 0x6D }, /* RUNIC LETTER SHORT-TWIG-MADR M -> 'm' */ 1934 + { 0xDA, 0x6C }, /* RUNIC LETTER LAUKAZ LAGU LOGR L -> 'l' */ 1935 + { 0xDB, 0x6C }, /* RUNIC LETTER DOTTED-L -> 'l' */ 1936 + { 0xDE, 0x64 }, /* RUNIC LETTER DAGAZ DAEG D -> 'd' */ 1937 + { 0xDF, 0x6F }, /* RUNIC LETTER OTHALAN ETHEL O -> 'o' */ 1938 + { 0xE5, 0x73 }, /* RUNIC LETTER STAN -> 's' */ 1939 + { 0xE9, 0x71 }, /* RUNIC LETTER Q -> 'q' */ 1940 + { 0xEA, 0x78 }, /* RUNIC LETTER X -> 'x' */ 1941 + { 0xEB, 0x2E }, /* RUNIC SINGLE PUNCTUATION -> '.' */ 1942 + { 0xEC, 0x3A }, /* RUNIC MULTIPLE PUNCTUATION -> ':' */ 1943 + { 0xED, 0x2B }, /* RUNIC CROSS PUNCTUATION -> '+' */ 1944 + /* Entries for page 0x17 */ 1945 + { 0x80, 0x6B }, /* KHMER LETTER KA -> 'k' */ 1946 + { 0x82, 0x67 }, /* KHMER LETTER KO -> 'g' */ 1947 + { 0x85, 0x63 }, /* KHMER LETTER CA -> 'c' */ 1948 + { 0x87, 0x6A }, /* KHMER LETTER CO -> 'j' */ 1949 + { 0x8A, 0x74 }, /* KHMER LETTER DA -> 't' */ 1950 + { 0x8C, 0x64 }, /* KHMER LETTER DO -> 'd' */ 1951 + { 0x8F, 0x74 }, /* KHMER LETTER TA -> 't' */ 1952 + { 0x91, 0x64 }, /* KHMER LETTER TO -> 'd' */ 1953 + { 0x93, 0x6E }, /* KHMER LETTER NO -> 'n' */ 1954 + { 0x94, 0x70 }, /* KHMER LETTER BA -> 'p' */ 1955 + { 0x96, 0x62 }, /* KHMER LETTER PO -> 'b' */ 1956 + { 0x98, 0x6D }, /* KHMER LETTER MO -> 'm' */ 1957 + { 0x99, 0x79 }, /* KHMER LETTER YO -> 'y' */ 1958 + { 0x9A, 0x72 }, /* KHMER LETTER RO -> 'r' */ 1959 + { 0x9B, 0x6C }, /* KHMER LETTER LO -> 'l' */ 1960 + { 0x9C, 0x76 }, /* KHMER LETTER VO -> 'v' */ 1961 + { 0x9F, 0x73 }, /* KHMER LETTER SA -> 's' */ 1962 + { 0xA0, 0x68 }, /* KHMER LETTER HA -> 'h' */ 1963 + { 0xA1, 0x6C }, /* KHMER LETTER LA -> 'l' */ 1964 + { 0xA2, 0x71 }, /* KHMER LETTER QA -> 'q' */ 1965 + { 0xA3, 0x61 }, /* KHMER INDEPENDENT VOWEL QAQ -> 'a' */ 1966 + { 0xA5, 0x69 }, /* KHMER INDEPENDENT VOWEL QI -> 'i' */ 1967 + { 0xA7, 0x75 }, /* KHMER INDEPENDENT VOWEL QU -> 'u' */ 1968 + { 0xAF, 0x65 }, /* KHMER INDEPENDENT VOWEL QE -> 'e' */ 1969 + { 0xB4, 0x61 }, /* KHMER VOWEL INHERENT AQ -> 'a' */ 1970 + { 0xB7, 0x69 }, /* KHMER VOWEL SIGN I -> 'i' */ 1971 + { 0xB9, 0x79 }, /* KHMER VOWEL SIGN Y -> 'y' */ 1972 + { 0xBB, 0x75 }, /* KHMER VOWEL SIGN U -> 'u' */ 1973 + { 0xC1, 0x65 }, /* KHMER VOWEL SIGN E -> 'e' */ 1974 + { 0xC6, 0x4D }, /* KHMER SIGN NIKAHIT -> 'M' */ 1975 + { 0xC7, 0x48 }, /* KHMER SIGN REAHMUK -> 'H' */ 1976 + { 0xCC, 0x72 }, /* KHMER SIGN ROBAT -> 'r' */ 1977 + { 0xCE, 0x21 }, /* KHMER SIGN KAKABAT -> '!' */ 1978 + { 0xD4, 0x2E }, /* KHMER SIGN KHAN -> '.' */ 1979 + { 0xD6, 0x3A }, /* KHMER SIGN CAMNUC PII KUUH -> ':' */ 1980 + { 0xD7, 0x2B }, /* KHMER SIGN LEK TOO -> '+' */ 1981 + { 0xDC, 0x27 }, /* KHMER SIGN AVAKRAHASANYA -> ''' */ 1982 + { 0xE0, 0x30 }, /* KHMER DIGIT ZERO -> '0' */ 1983 + { 0xE1, 0x31 }, /* KHMER DIGIT ONE -> '1' */ 1984 + { 0xE2, 0x32 }, /* KHMER DIGIT TWO -> '2' */ 1985 + { 0xE3, 0x33 }, /* KHMER DIGIT THREE -> '3' */ 1986 + { 0xE4, 0x34 }, /* KHMER DIGIT FOUR -> '4' */ 1987 + { 0xE5, 0x35 }, /* KHMER DIGIT FIVE -> '5' */ 1988 + { 0xE6, 0x36 }, /* KHMER DIGIT SIX -> '6' */ 1989 + { 0xE7, 0x37 }, /* KHMER DIGIT SEVEN -> '7' */ 1990 + { 0xE8, 0x38 }, /* KHMER DIGIT EIGHT -> '8' */ 1991 + { 0xE9, 0x39 }, /* KHMER DIGIT NINE -> '9' */ 1992 + /* Entries for page 0x18 */ 1993 + { 0x07, 0x2D }, /* MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER -> '-' */ 1994 + { 0x10, 0x30 }, /* MONGOLIAN DIGIT ZERO -> '0' */ 1995 + { 0x11, 0x31 }, /* MONGOLIAN DIGIT ONE -> '1' */ 1996 + { 0x12, 0x32 }, /* MONGOLIAN DIGIT TWO -> '2' */ 1997 + { 0x13, 0x33 }, /* MONGOLIAN DIGIT THREE -> '3' */ 1998 + { 0x14, 0x34 }, /* MONGOLIAN DIGIT FOUR -> '4' */ 1999 + { 0x15, 0x35 }, /* MONGOLIAN DIGIT FIVE -> '5' */ 2000 + { 0x16, 0x36 }, /* MONGOLIAN DIGIT SIX -> '6' */ 2001 + { 0x17, 0x37 }, /* MONGOLIAN DIGIT SEVEN -> '7' */ 2002 + { 0x18, 0x38 }, /* MONGOLIAN DIGIT EIGHT -> '8' */ 2003 + { 0x19, 0x39 }, /* MONGOLIAN DIGIT NINE -> '9' */ 2004 + { 0x20, 0x61 }, /* MONGOLIAN LETTER A -> 'a' */ 2005 + { 0x21, 0x65 }, /* MONGOLIAN LETTER E -> 'e' */ 2006 + { 0x22, 0x69 }, /* MONGOLIAN LETTER I -> 'i' */ 2007 + { 0x23, 0x6F }, /* MONGOLIAN LETTER O -> 'o' */ 2008 + { 0x24, 0x75 }, /* MONGOLIAN LETTER U -> 'u' */ 2009 + { 0x25, 0x4F }, /* MONGOLIAN LETTER OE -> 'O' */ 2010 + { 0x26, 0x55 }, /* MONGOLIAN LETTER UE -> 'U' */ 2011 + { 0x28, 0x6E }, /* MONGOLIAN LETTER NA -> 'n' */ 2012 + { 0x2A, 0x62 }, /* MONGOLIAN LETTER BA -> 'b' */ 2013 + { 0x2B, 0x70 }, /* MONGOLIAN LETTER PA -> 'p' */ 2014 + { 0x2C, 0x71 }, /* MONGOLIAN LETTER QA -> 'q' */ 2015 + { 0x2D, 0x67 }, /* MONGOLIAN LETTER GA -> 'g' */ 2016 + { 0x2E, 0x6D }, /* MONGOLIAN LETTER MA -> 'm' */ 2017 + { 0x2F, 0x6C }, /* MONGOLIAN LETTER LA -> 'l' */ 2018 + { 0x30, 0x73 }, /* MONGOLIAN LETTER SA -> 's' */ 2019 + { 0x32, 0x74 }, /* MONGOLIAN LETTER TA -> 't' */ 2020 + { 0x33, 0x64 }, /* MONGOLIAN LETTER DA -> 'd' */ 2021 + { 0x35, 0x6A }, /* MONGOLIAN LETTER JA -> 'j' */ 2022 + { 0x36, 0x79 }, /* MONGOLIAN LETTER YA -> 'y' */ 2023 + { 0x37, 0x72 }, /* MONGOLIAN LETTER RA -> 'r' */ 2024 + { 0x38, 0x77 }, /* MONGOLIAN LETTER WA -> 'w' */ 2025 + { 0x39, 0x66 }, /* MONGOLIAN LETTER FA -> 'f' */ 2026 + { 0x3A, 0x6B }, /* MONGOLIAN LETTER KA -> 'k' */ 2027 + { 0x3D, 0x7A }, /* MONGOLIAN LETTER ZA -> 'z' */ 2028 + { 0x3E, 0x68 }, /* MONGOLIAN LETTER HAA -> 'h' */ 2029 + { 0x43, 0x2D }, /* MONGOLIAN LETTER TODO LONG VOWEL SIGN -> '-' */ 2030 + { 0x44, 0x65 }, /* MONGOLIAN LETTER TODO E -> 'e' */ 2031 + { 0x45, 0x69 }, /* MONGOLIAN LETTER TODO I -> 'i' */ 2032 + { 0x46, 0x6F }, /* MONGOLIAN LETTER TODO O -> 'o' */ 2033 + { 0x47, 0x75 }, /* MONGOLIAN LETTER TODO U -> 'u' */ 2034 + { 0x48, 0x4F }, /* MONGOLIAN LETTER TODO OE -> 'O' */ 2035 + { 0x49, 0x55 }, /* MONGOLIAN LETTER TODO UE -> 'U' */ 2036 + { 0x4B, 0x62 }, /* MONGOLIAN LETTER TODO BA -> 'b' */ 2037 + { 0x4C, 0x70 }, /* MONGOLIAN LETTER TODO PA -> 'p' */ 2038 + { 0x4D, 0x71 }, /* MONGOLIAN LETTER TODO QA -> 'q' */ 2039 + { 0x4E, 0x67 }, /* MONGOLIAN LETTER TODO GA -> 'g' */ 2040 + { 0x4F, 0x6D }, /* MONGOLIAN LETTER TODO MA -> 'm' */ 2041 + { 0x50, 0x74 }, /* MONGOLIAN LETTER TODO TA -> 't' */ 2042 + { 0x51, 0x64 }, /* MONGOLIAN LETTER TODO DA -> 'd' */ 2043 + { 0x53, 0x6A }, /* MONGOLIAN LETTER TODO JA -> 'j' */ 2044 + { 0x55, 0x79 }, /* MONGOLIAN LETTER TODO YA -> 'y' */ 2045 + { 0x56, 0x77 }, /* MONGOLIAN LETTER TODO WA -> 'w' */ 2046 + { 0x57, 0x6B }, /* MONGOLIAN LETTER TODO KA -> 'k' */ 2047 + { 0x58, 0x67 }, /* MONGOLIAN LETTER TODO GAA -> 'g' */ 2048 + { 0x59, 0x68 }, /* MONGOLIAN LETTER TODO HAA -> 'h' */ 2049 + { 0x5D, 0x65 }, /* MONGOLIAN LETTER SIBE E -> 'e' */ 2050 + { 0x5E, 0x69 }, /* MONGOLIAN LETTER SIBE I -> 'i' */ 2051 + { 0x60, 0x55 }, /* MONGOLIAN LETTER SIBE UE -> 'U' */ 2052 + { 0x61, 0x75 }, /* MONGOLIAN LETTER SIBE U -> 'u' */ 2053 + { 0x63, 0x6B }, /* MONGOLIAN LETTER SIBE KA -> 'k' */ 2054 + { 0x64, 0x67 }, /* MONGOLIAN LETTER SIBE GA -> 'g' */ 2055 + { 0x65, 0x68 }, /* MONGOLIAN LETTER SIBE HA -> 'h' */ 2056 + { 0x66, 0x70 }, /* MONGOLIAN LETTER SIBE PA -> 'p' */ 2057 + { 0x68, 0x74 }, /* MONGOLIAN LETTER SIBE TA -> 't' */ 2058 + { 0x69, 0x64 }, /* MONGOLIAN LETTER SIBE DA -> 'd' */ 2059 + { 0x6A, 0x6A }, /* MONGOLIAN LETTER SIBE JA -> 'j' */ 2060 + { 0x6B, 0x66 }, /* MONGOLIAN LETTER SIBE FA -> 'f' */ 2061 + { 0x6C, 0x67 }, /* MONGOLIAN LETTER SIBE GAA -> 'g' */ 2062 + { 0x6D, 0x68 }, /* MONGOLIAN LETTER SIBE HAA -> 'h' */ 2063 + { 0x6F, 0x7A }, /* MONGOLIAN LETTER SIBE ZA -> 'z' */ 2064 + { 0x70, 0x72 }, /* MONGOLIAN LETTER SIBE RAA -> 'r' */ 2065 + { 0x73, 0x69 }, /* MONGOLIAN LETTER MANCHU I -> 'i' */ 2066 + { 0x74, 0x6B }, /* MONGOLIAN LETTER MANCHU KA -> 'k' */ 2067 + { 0x75, 0x72 }, /* MONGOLIAN LETTER MANCHU RA -> 'r' */ 2068 + { 0x76, 0x66 }, /* MONGOLIAN LETTER MANCHU FA -> 'f' */ 2069 + { 0x81, 0x48 }, /* MONGOLIAN LETTER ALI GALI VISARGA ONE -> 'H' */ 2070 + { 0x82, 0x58 }, /* MONGOLIAN LETTER ALI GALI DAMARU -> 'X' */ 2071 + { 0x83, 0x57 }, /* MONGOLIAN LETTER ALI GALI UBADAMA -> 'W' */ 2072 + { 0x84, 0x4D }, /* MONGOLIAN LETTER ALI GALI INVERTED UBADAMA -> 'M' */ 2073 + { 0x87, 0x61 }, /* MONGOLIAN LETTER ALI GALI A -> 'a' */ 2074 + { 0x88, 0x69 }, /* MONGOLIAN LETTER ALI GALI I -> 'i' */ 2075 + { 0x89, 0x6B }, /* MONGOLIAN LETTER ALI GALI KA -> 'k' */ 2076 + { 0x8B, 0x63 }, /* MONGOLIAN LETTER ALI GALI CA -> 'c' */ 2077 + { 0x90, 0x74 }, /* MONGOLIAN LETTER ALI GALI TA -> 't' */ 2078 + { 0x91, 0x64 }, /* MONGOLIAN LETTER ALI GALI DA -> 'd' */ 2079 + { 0x92, 0x70 }, /* MONGOLIAN LETTER ALI GALI PA -> 'p' */ 2080 + { 0x96, 0x7A }, /* MONGOLIAN LETTER ALI GALI ZA -> 'z' */ 2081 + { 0x97, 0x61 }, /* MONGOLIAN LETTER ALI GALI AH -> 'a' */ 2082 + { 0x98, 0x74 }, /* MONGOLIAN LETTER TODO ALI GALI TA -> 't' */ 2083 + { 0x9C, 0x63 }, /* MONGOLIAN LETTER MANCHU ALI GALI CA -> 'c' */ 2084 + { 0xA0, 0x74 }, /* MONGOLIAN LETTER MANCHU ALI GALI TA -> 't' */ 2085 + { 0xA5, 0x7A }, /* MONGOLIAN LETTER MANCHU ALI GALI ZA -> 'z' */ 2086 + { 0xA6, 0x75 }, /* MONGOLIAN LETTER ALI GALI HALF U -> 'u' */ 2087 + { 0xA7, 0x79 }, /* MONGOLIAN LETTER ALI GALI HALF YA -> 'y' */ 2088 + { 0xA9, 0x27 }, /* MONGOLIAN LETTER ALI GALI DAGALGA -> ''' */ 2089 + /* Entries for page 0x1D */ 2090 + { 0x00, 0x41 }, /* LATIN LETTER SMALL CAPITAL A -> 'A' */ 2091 + { 0x03, 0x42 }, /* LATIN LETTER SMALL CAPITAL BARRED B -> 'B' */ 2092 + { 0x04, 0x43 }, /* LATIN LETTER SMALL CAPITAL C -> 'C' */ 2093 + { 0x05, 0x44 }, /* LATIN LETTER SMALL CAPITAL D -> 'D' */ 2094 + { 0x06, 0x44 }, /* LATIN LETTER SMALL CAPITAL ETH -> 'D' */ 2095 + { 0x07, 0x45 }, /* LATIN LETTER SMALL CAPITAL E -> 'E' */ 2096 + { 0x08, 0x65 }, /* LATIN SMALL LETTER TURNED OPEN E -> 'e' */ 2097 + { 0x09, 0x69 }, /* LATIN SMALL LETTER TURNED I -> 'i' */ 2098 + { 0x0A, 0x4A }, /* LATIN LETTER SMALL CAPITAL J -> 'J' */ 2099 + { 0x0B, 0x4B }, /* LATIN LETTER SMALL CAPITAL K -> 'K' */ 2100 + { 0x0C, 0x4C }, /* LATIN LETTER SMALL CAPITAL L WITH STROKE -> 'L' */ 2101 + { 0x0D, 0x4D }, /* LATIN LETTER SMALL CAPITAL M -> 'M' */ 2102 + { 0x0E, 0x4E }, /* LATIN LETTER SMALL CAPITAL REVERSED N -> 'N' */ 2103 + { 0x0F, 0x4F }, /* LATIN LETTER SMALL CAPITAL O -> 'O' */ 2104 + { 0x11, 0x4F }, /* LATIN SMALL LETTER SIDEWAYS O -> 'O' */ 2105 + { 0x13, 0x4F }, /* LATIN SMALL LETTER SIDEWAYS O WITH STROKE -> 'O' */ 2106 + { 0x18, 0x50 }, /* LATIN LETTER SMALL CAPITAL P -> 'P' */ 2107 + { 0x19, 0x52 }, /* LATIN LETTER SMALL CAPITAL REVERSED R -> 'R' */ 2108 + { 0x1A, 0x52 }, /* LATIN LETTER SMALL CAPITAL TURNED R -> 'R' */ 2109 + { 0x1B, 0x54 }, /* LATIN LETTER SMALL CAPITAL T -> 'T' */ 2110 + { 0x1C, 0x55 }, /* LATIN LETTER SMALL CAPITAL U -> 'U' */ 2111 + { 0x1D, 0x75 }, /* LATIN SMALL LETTER SIDEWAYS U -> 'u' */ 2112 + { 0x1E, 0x75 }, /* LATIN SMALL LETTER SIDEWAYS DIAERESIZED U -> 'u' */ 2113 + { 0x1F, 0x6D }, /* LATIN SMALL LETTER SIDEWAYS TURNED M -> 'm' */ 2114 + { 0x20, 0x56 }, /* LATIN LETTER SMALL CAPITAL V -> 'V' */ 2115 + { 0x21, 0x57 }, /* LATIN LETTER SMALL CAPITAL W -> 'W' */ 2116 + { 0x22, 0x5A }, /* LATIN LETTER SMALL CAPITAL Z -> 'Z' */ 2117 + { 0x2C, 0x41 }, /* MODIFIER LETTER CAPITAL A -> 'A' */ 2118 + { 0x2E, 0x42 }, /* MODIFIER LETTER CAPITAL B -> 'B' */ 2119 + { 0x2F, 0x42 }, /* MODIFIER LETTER CAPITAL BARRED B -> 'B' */ 2120 + { 0x30, 0x44 }, /* MODIFIER LETTER CAPITAL D -> 'D' */ 2121 + { 0x31, 0x45 }, /* MODIFIER LETTER CAPITAL E -> 'E' */ 2122 + { 0x32, 0x45 }, /* MODIFIER LETTER CAPITAL REVERSED E -> 'E' */ 2123 + { 0x33, 0x47 }, /* MODIFIER LETTER CAPITAL G -> 'G' */ 2124 + { 0x34, 0x48 }, /* MODIFIER LETTER CAPITAL H -> 'H' */ 2125 + { 0x35, 0x49 }, /* MODIFIER LETTER CAPITAL I -> 'I' */ 2126 + { 0x36, 0x4A }, /* MODIFIER LETTER CAPITAL J -> 'J' */ 2127 + { 0x37, 0x4B }, /* MODIFIER LETTER CAPITAL K -> 'K' */ 2128 + { 0x38, 0x4C }, /* MODIFIER LETTER CAPITAL L -> 'L' */ 2129 + { 0x39, 0x4D }, /* MODIFIER LETTER CAPITAL M -> 'M' */ 2130 + { 0x3A, 0x4E }, /* MODIFIER LETTER CAPITAL N -> 'N' */ 2131 + { 0x3B, 0x4E }, /* MODIFIER LETTER CAPITAL REVERSED N -> 'N' */ 2132 + { 0x3C, 0x4F }, /* MODIFIER LETTER CAPITAL O -> 'O' */ 2133 + { 0x3E, 0x50 }, /* MODIFIER LETTER CAPITAL P -> 'P' */ 2134 + { 0x3F, 0x52 }, /* MODIFIER LETTER CAPITAL R -> 'R' */ 2135 + { 0x40, 0x54 }, /* MODIFIER LETTER CAPITAL T -> 'T' */ 2136 + { 0x41, 0x55 }, /* MODIFIER LETTER CAPITAL U -> 'U' */ 2137 + { 0x42, 0x57 }, /* MODIFIER LETTER CAPITAL W -> 'W' */ 2138 + { 0x43, 0x00 }, /* MODIFIER LETTER SMALL A -> ... */ 2139 + { 0x45, 0x61 }, /* MODIFIER LETTER SMALL ALPHA -> 'a' */ 2140 + { 0x47, 0x62 }, /* MODIFIER LETTER SMALL B -> 'b' */ 2141 + { 0x48, 0x64 }, /* MODIFIER LETTER SMALL D -> 'd' */ 2142 + { 0x49, 0x65 }, /* MODIFIER LETTER SMALL E -> 'e' */ 2143 + { 0x4B, 0x65 }, /* MODIFIER LETTER SMALL OPEN E -> 'e' */ 2144 + { 0x4C, 0x65 }, /* MODIFIER LETTER SMALL TURNED OPEN E -> 'e' */ 2145 + { 0x4D, 0x67 }, /* MODIFIER LETTER SMALL G -> 'g' */ 2146 + { 0x4E, 0x69 }, /* MODIFIER LETTER SMALL TURNED I -> 'i' */ 2147 + { 0x4F, 0x6B }, /* MODIFIER LETTER SMALL K -> 'k' */ 2148 + { 0x50, 0x6D }, /* MODIFIER LETTER SMALL M -> 'm' */ 2149 + { 0x52, 0x6F }, /* MODIFIER LETTER SMALL O -> 'o' */ 2150 + { 0x56, 0x70 }, /* MODIFIER LETTER SMALL P -> 'p' */ 2151 + { 0x57, 0x74 }, /* MODIFIER LETTER SMALL T -> 't' */ 2152 + { 0x58, 0x75 }, /* MODIFIER LETTER SMALL U -> 'u' */ 2153 + { 0x59, 0x75 }, /* MODIFIER LETTER SMALL SIDEWAYS U -> 'u' */ 2154 + { 0x5A, 0x6D }, /* MODIFIER LETTER SMALL TURNED M -> 'm' */ 2155 + { 0x5B, 0x76 }, /* MODIFIER LETTER SMALL V -> 'v' */ 2156 + { 0x5D, 0x62 }, /* MODIFIER LETTER SMALL BETA -> 'b' */ 2157 + { 0x5E, 0x67 }, /* MODIFIER LETTER SMALL GREEK GAMMA -> 'g' */ 2158 + { 0x5F, 0x64 }, /* MODIFIER LETTER SMALL DELTA -> 'd' */ 2159 + { 0x60, 0x66 }, /* MODIFIER LETTER SMALL GREEK PHI -> 'f' */ 2160 + { 0x62, 0x69 }, /* LATIN SUBSCRIPT SMALL LETTER I -> 'i' */ 2161 + { 0x63, 0x72 }, /* LATIN SUBSCRIPT SMALL LETTER R -> 'r' */ 2162 + { 0x64, 0x75 }, /* LATIN SUBSCRIPT SMALL LETTER U -> 'u' */ 2163 + { 0x65, 0x76 }, /* LATIN SUBSCRIPT SMALL LETTER V -> 'v' */ 2164 + { 0x66, 0x62 }, /* GREEK SUBSCRIPT SMALL LETTER BETA -> 'b' */ 2165 + { 0x67, 0x67 }, /* GREEK SUBSCRIPT SMALL LETTER GAMMA -> 'g' */ 2166 + { 0x68, 0x72 }, /* GREEK SUBSCRIPT SMALL LETTER RHO -> 'r' */ 2167 + { 0x69, 0x66 }, /* GREEK SUBSCRIPT SMALL LETTER PHI -> 'f' */ 2168 + { 0x6C, 0x62 }, /* LATIN SMALL LETTER B WITH MIDDLE TILDE -> 'b' */ 2169 + { 0x6D, 0x64 }, /* LATIN SMALL LETTER D WITH MIDDLE TILDE -> 'd' */ 2170 + { 0x6E, 0x66 }, /* LATIN SMALL LETTER F WITH MIDDLE TILDE -> 'f' */ 2171 + { 0x6F, 0x6D }, /* LATIN SMALL LETTER M WITH MIDDLE TILDE -> 'm' */ 2172 + { 0x70, 0x6E }, /* LATIN SMALL LETTER N WITH MIDDLE TILDE -> 'n' */ 2173 + { 0x71, 0x70 }, /* LATIN SMALL LETTER P WITH MIDDLE TILDE -> 'p' */ 2174 + { 0x72, 0x72 }, /* LATIN SMALL LETTER R WITH MIDDLE TILDE -> 'r' */ 2175 + { 0x73, 0x72 }, /* LATIN SMALL LETTER R WITH FISHHOOK AND MIDDLE TILDE -> 'r' */ 2176 + { 0x74, 0x73 }, /* LATIN SMALL LETTER S WITH MIDDLE TILDE -> 's' */ 2177 + { 0x75, 0x74 }, /* LATIN SMALL LETTER T WITH MIDDLE TILDE -> 't' */ 2178 + { 0x76, 0x7A }, /* LATIN SMALL LETTER Z WITH MIDDLE TILDE -> 'z' */ 2179 + { 0x77, 0x67 }, /* LATIN SMALL LETTER TURNED G -> 'g' */ 2180 + { 0x7D, 0x70 }, /* LATIN SMALL LETTER P WITH STROKE -> 'p' */ 2181 + { 0x80, 0x62 }, /* LATIN SMALL LETTER B WITH PALATAL HOOK -> 'b' */ 2182 + { 0x81, 0x64 }, /* LATIN SMALL LETTER D WITH PALATAL HOOK -> 'd' */ 2183 + { 0x82, 0x66 }, /* LATIN SMALL LETTER F WITH PALATAL HOOK -> 'f' */ 2184 + { 0x83, 0x67 }, /* LATIN SMALL LETTER G WITH PALATAL HOOK -> 'g' */ 2185 + { 0x84, 0x6B }, /* LATIN SMALL LETTER K WITH PALATAL HOOK -> 'k' */ 2186 + { 0x85, 0x6C }, /* LATIN SMALL LETTER L WITH PALATAL HOOK -> 'l' */ 2187 + { 0x86, 0x6D }, /* LATIN SMALL LETTER M WITH PALATAL HOOK -> 'm' */ 2188 + { 0x87, 0x6E }, /* LATIN SMALL LETTER N WITH PALATAL HOOK -> 'n' */ 2189 + { 0x88, 0x70 }, /* LATIN SMALL LETTER P WITH PALATAL HOOK -> 'p' */ 2190 + { 0x89, 0x72 }, /* LATIN SMALL LETTER R WITH PALATAL HOOK -> 'r' */ 2191 + { 0x8A, 0x73 }, /* LATIN SMALL LETTER S WITH PALATAL HOOK -> 's' */ 2192 + { 0x8C, 0x76 }, /* LATIN SMALL LETTER V WITH PALATAL HOOK -> 'v' */ 2193 + { 0x8D, 0x78 }, /* LATIN SMALL LETTER X WITH PALATAL HOOK -> 'x' */ 2194 + { 0x8E, 0x7A }, /* LATIN SMALL LETTER Z WITH PALATAL HOOK -> 'z' */ 2195 + /* Entries for page 0x1E */ 2196 + { 0x00, 0x41 }, /* LATIN CAPITAL LETTER A WITH RING BELOW -> 'A' */ 2197 + { 0x01, 0x61 }, /* LATIN SMALL LETTER A WITH RING BELOW -> 'a' */ 2198 + { 0x02, 0x42 }, /* LATIN CAPITAL LETTER B WITH DOT ABOVE -> 'B' */ 2199 + { 0x03, 0x62 }, /* LATIN SMALL LETTER B WITH DOT ABOVE -> 'b' */ 2200 + { 0x04, 0x42 }, /* LATIN CAPITAL LETTER B WITH DOT BELOW -> 'B' */ 2201 + { 0x05, 0x62 }, /* LATIN SMALL LETTER B WITH DOT BELOW -> 'b' */ 2202 + { 0x06, 0x42 }, /* LATIN CAPITAL LETTER B WITH LINE BELOW -> 'B' */ 2203 + { 0x07, 0x62 }, /* LATIN SMALL LETTER B WITH LINE BELOW -> 'b' */ 2204 + { 0x08, 0x43 }, /* LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE -> 'C' */ 2205 + { 0x09, 0x63 }, /* LATIN SMALL LETTER C WITH CEDILLA AND ACUTE -> 'c' */ 2206 + { 0x0A, 0x44 }, /* LATIN CAPITAL LETTER D WITH DOT ABOVE -> 'D' */ 2207 + { 0x0B, 0x64 }, /* LATIN SMALL LETTER D WITH DOT ABOVE -> 'd' */ 2208 + { 0x0C, 0x44 }, /* LATIN CAPITAL LETTER D WITH DOT BELOW -> 'D' */ 2209 + { 0x0D, 0x64 }, /* LATIN SMALL LETTER D WITH DOT BELOW -> 'd' */ 2210 + { 0x0E, 0x44 }, /* LATIN CAPITAL LETTER D WITH LINE BELOW -> 'D' */ 2211 + { 0x0F, 0x64 }, /* LATIN SMALL LETTER D WITH LINE BELOW -> 'd' */ 2212 + { 0x10, 0x44 }, /* LATIN CAPITAL LETTER D WITH CEDILLA -> 'D' */ 2213 + { 0x11, 0x64 }, /* LATIN SMALL LETTER D WITH CEDILLA -> 'd' */ 2214 + { 0x12, 0x44 }, /* LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW -> 'D' */ 2215 + { 0x13, 0x64 }, /* LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW -> 'd' */ 2216 + { 0x14, 0x45 }, /* LATIN CAPITAL LETTER E WITH MACRON AND GRAVE -> 'E' */ 2217 + { 0x15, 0x65 }, /* LATIN SMALL LETTER E WITH MACRON AND GRAVE -> 'e' */ 2218 + { 0x16, 0x45 }, /* LATIN CAPITAL LETTER E WITH MACRON AND ACUTE -> 'E' */ 2219 + { 0x17, 0x65 }, /* LATIN SMALL LETTER E WITH MACRON AND ACUTE -> 'e' */ 2220 + { 0x18, 0x45 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW -> 'E' */ 2221 + { 0x19, 0x65 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW -> 'e' */ 2222 + { 0x1A, 0x45 }, /* LATIN CAPITAL LETTER E WITH TILDE BELOW -> 'E' */ 2223 + { 0x1B, 0x65 }, /* LATIN SMALL LETTER E WITH TILDE BELOW -> 'e' */ 2224 + { 0x1C, 0x45 }, /* LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE -> 'E' */ 2225 + { 0x1D, 0x65 }, /* LATIN SMALL LETTER E WITH CEDILLA AND BREVE -> 'e' */ 2226 + { 0x1E, 0x46 }, /* LATIN CAPITAL LETTER F WITH DOT ABOVE -> 'F' */ 2227 + { 0x1F, 0x66 }, /* LATIN SMALL LETTER F WITH DOT ABOVE -> 'f' */ 2228 + { 0x20, 0x47 }, /* LATIN CAPITAL LETTER G WITH MACRON -> 'G' */ 2229 + { 0x21, 0x67 }, /* LATIN SMALL LETTER G WITH MACRON -> 'g' */ 2230 + { 0x22, 0x48 }, /* LATIN CAPITAL LETTER H WITH DOT ABOVE -> 'H' */ 2231 + { 0x23, 0x68 }, /* LATIN SMALL LETTER H WITH DOT ABOVE -> 'h' */ 2232 + { 0x24, 0x48 }, /* LATIN CAPITAL LETTER H WITH DOT BELOW -> 'H' */ 2233 + { 0x25, 0x68 }, /* LATIN SMALL LETTER H WITH DOT BELOW -> 'h' */ 2234 + { 0x26, 0x48 }, /* LATIN CAPITAL LETTER H WITH DIAERESIS -> 'H' */ 2235 + { 0x27, 0x68 }, /* LATIN SMALL LETTER H WITH DIAERESIS -> 'h' */ 2236 + { 0x28, 0x48 }, /* LATIN CAPITAL LETTER H WITH CEDILLA -> 'H' */ 2237 + { 0x29, 0x68 }, /* LATIN SMALL LETTER H WITH CEDILLA -> 'h' */ 2238 + { 0x2A, 0x48 }, /* LATIN CAPITAL LETTER H WITH BREVE BELOW -> 'H' */ 2239 + { 0x2B, 0x68 }, /* LATIN SMALL LETTER H WITH BREVE BELOW -> 'h' */ 2240 + { 0x2C, 0x49 }, /* LATIN CAPITAL LETTER I WITH TILDE BELOW -> 'I' */ 2241 + { 0x2D, 0x69 }, /* LATIN SMALL LETTER I WITH TILDE BELOW -> 'i' */ 2242 + { 0x2E, 0x49 }, /* LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE -> 'I' */ 2243 + { 0x2F, 0x69 }, /* LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE -> 'i' */ 2244 + { 0x30, 0x4B }, /* LATIN CAPITAL LETTER K WITH ACUTE -> 'K' */ 2245 + { 0x31, 0x6B }, /* LATIN SMALL LETTER K WITH ACUTE -> 'k' */ 2246 + { 0x32, 0x4B }, /* LATIN CAPITAL LETTER K WITH DOT BELOW -> 'K' */ 2247 + { 0x33, 0x6B }, /* LATIN SMALL LETTER K WITH DOT BELOW -> 'k' */ 2248 + { 0x34, 0x4B }, /* LATIN CAPITAL LETTER K WITH LINE BELOW -> 'K' */ 2249 + { 0x35, 0x6B }, /* LATIN SMALL LETTER K WITH LINE BELOW -> 'k' */ 2250 + { 0x36, 0x4C }, /* LATIN CAPITAL LETTER L WITH DOT BELOW -> 'L' */ 2251 + { 0x37, 0x6C }, /* LATIN SMALL LETTER L WITH DOT BELOW -> 'l' */ 2252 + { 0x38, 0x4C }, /* LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON -> 'L' */ 2253 + { 0x39, 0x6C }, /* LATIN SMALL LETTER L WITH DOT BELOW AND MACRON -> 'l' */ 2254 + { 0x3A, 0x4C }, /* LATIN CAPITAL LETTER L WITH LINE BELOW -> 'L' */ 2255 + { 0x3B, 0x6C }, /* LATIN SMALL LETTER L WITH LINE BELOW -> 'l' */ 2256 + { 0x3C, 0x4C }, /* LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW -> 'L' */ 2257 + { 0x3D, 0x6C }, /* LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW -> 'l' */ 2258 + { 0x3E, 0x4D }, /* LATIN CAPITAL LETTER M WITH ACUTE -> 'M' */ 2259 + { 0x3F, 0x6D }, /* LATIN SMALL LETTER M WITH ACUTE -> 'm' */ 2260 + { 0x40, 0x4D }, /* LATIN CAPITAL LETTER M WITH DOT ABOVE -> 'M' */ 2261 + { 0x41, 0x6D }, /* LATIN SMALL LETTER M WITH DOT ABOVE -> 'm' */ 2262 + { 0x42, 0x4D }, /* LATIN CAPITAL LETTER M WITH DOT BELOW -> 'M' */ 2263 + { 0x43, 0x6D }, /* LATIN SMALL LETTER M WITH DOT BELOW -> 'm' */ 2264 + { 0x44, 0x4E }, /* LATIN CAPITAL LETTER N WITH DOT ABOVE -> 'N' */ 2265 + { 0x45, 0x6E }, /* LATIN SMALL LETTER N WITH DOT ABOVE -> 'n' */ 2266 + { 0x46, 0x4E }, /* LATIN CAPITAL LETTER N WITH DOT BELOW -> 'N' */ 2267 + { 0x47, 0x6E }, /* LATIN SMALL LETTER N WITH DOT BELOW -> 'n' */ 2268 + { 0x48, 0x4E }, /* LATIN CAPITAL LETTER N WITH LINE BELOW -> 'N' */ 2269 + { 0x49, 0x6E }, /* LATIN SMALL LETTER N WITH LINE BELOW -> 'n' */ 2270 + { 0x4A, 0x4E }, /* LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW -> 'N' */ 2271 + { 0x4B, 0x6E }, /* LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW -> 'n' */ 2272 + { 0x4C, 0x4F }, /* LATIN CAPITAL LETTER O WITH TILDE AND ACUTE -> 'O' */ 2273 + { 0x4D, 0x6F }, /* LATIN SMALL LETTER O WITH TILDE AND ACUTE -> 'o' */ 2274 + { 0x4E, 0x4F }, /* LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS -> 'O' */ 2275 + { 0x4F, 0x6F }, /* LATIN SMALL LETTER O WITH TILDE AND DIAERESIS -> 'o' */ 2276 + { 0x50, 0x4F }, /* LATIN CAPITAL LETTER O WITH MACRON AND GRAVE -> 'O' */ 2277 + { 0x51, 0x6F }, /* LATIN SMALL LETTER O WITH MACRON AND GRAVE -> 'o' */ 2278 + { 0x52, 0x4F }, /* LATIN CAPITAL LETTER O WITH MACRON AND ACUTE -> 'O' */ 2279 + { 0x53, 0x6F }, /* LATIN SMALL LETTER O WITH MACRON AND ACUTE -> 'o' */ 2280 + { 0x54, 0x50 }, /* LATIN CAPITAL LETTER P WITH ACUTE -> 'P' */ 2281 + { 0x55, 0x70 }, /* LATIN SMALL LETTER P WITH ACUTE -> 'p' */ 2282 + { 0x56, 0x50 }, /* LATIN CAPITAL LETTER P WITH DOT ABOVE -> 'P' */ 2283 + { 0x57, 0x70 }, /* LATIN SMALL LETTER P WITH DOT ABOVE -> 'p' */ 2284 + { 0x58, 0x52 }, /* LATIN CAPITAL LETTER R WITH DOT ABOVE -> 'R' */ 2285 + { 0x59, 0x72 }, /* LATIN SMALL LETTER R WITH DOT ABOVE -> 'r' */ 2286 + { 0x5A, 0x52 }, /* LATIN CAPITAL LETTER R WITH DOT BELOW -> 'R' */ 2287 + { 0x5B, 0x72 }, /* LATIN SMALL LETTER R WITH DOT BELOW -> 'r' */ 2288 + { 0x5C, 0x52 }, /* LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON -> 'R' */ 2289 + { 0x5D, 0x72 }, /* LATIN SMALL LETTER R WITH DOT BELOW AND MACRON -> 'r' */ 2290 + { 0x5E, 0x52 }, /* LATIN CAPITAL LETTER R WITH LINE BELOW -> 'R' */ 2291 + { 0x5F, 0x72 }, /* LATIN SMALL LETTER R WITH LINE BELOW -> 'r' */ 2292 + { 0x60, 0x53 }, /* LATIN CAPITAL LETTER S WITH DOT ABOVE -> 'S' */ 2293 + { 0x61, 0x73 }, /* LATIN SMALL LETTER S WITH DOT ABOVE -> 's' */ 2294 + { 0x62, 0x53 }, /* LATIN CAPITAL LETTER S WITH DOT BELOW -> 'S' */ 2295 + { 0x63, 0x73 }, /* LATIN SMALL LETTER S WITH DOT BELOW -> 's' */ 2296 + { 0x64, 0x53 }, /* LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE -> 'S' */ 2297 + { 0x65, 0x73 }, /* LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE -> 's' */ 2298 + { 0x66, 0x53 }, /* LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE -> 'S' */ 2299 + { 0x67, 0x73 }, /* LATIN SMALL LETTER S WITH CARON AND DOT ABOVE -> 's' */ 2300 + { 0x68, 0x53 }, /* LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE -> 'S' */ 2301 + { 0x69, 0x73 }, /* LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE -> 's' */ 2302 + { 0x6A, 0x54 }, /* LATIN CAPITAL LETTER T WITH DOT ABOVE -> 'T' */ 2303 + { 0x6B, 0x74 }, /* LATIN SMALL LETTER T WITH DOT ABOVE -> 't' */ 2304 + { 0x6C, 0x54 }, /* LATIN CAPITAL LETTER T WITH DOT BELOW -> 'T' */ 2305 + { 0x6D, 0x74 }, /* LATIN SMALL LETTER T WITH DOT BELOW -> 't' */ 2306 + { 0x6E, 0x54 }, /* LATIN CAPITAL LETTER T WITH LINE BELOW -> 'T' */ 2307 + { 0x6F, 0x74 }, /* LATIN SMALL LETTER T WITH LINE BELOW -> 't' */ 2308 + { 0x70, 0x54 }, /* LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW -> 'T' */ 2309 + { 0x71, 0x74 }, /* LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW -> 't' */ 2310 + { 0x72, 0x55 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS BELOW -> 'U' */ 2311 + { 0x73, 0x75 }, /* LATIN SMALL LETTER U WITH DIAERESIS BELOW -> 'u' */ 2312 + { 0x74, 0x55 }, /* LATIN CAPITAL LETTER U WITH TILDE BELOW -> 'U' */ 2313 + { 0x75, 0x75 }, /* LATIN SMALL LETTER U WITH TILDE BELOW -> 'u' */ 2314 + { 0x76, 0x55 }, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW -> 'U' */ 2315 + { 0x77, 0x75 }, /* LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW -> 'u' */ 2316 + { 0x78, 0x55 }, /* LATIN CAPITAL LETTER U WITH TILDE AND ACUTE -> 'U' */ 2317 + { 0x79, 0x75 }, /* LATIN SMALL LETTER U WITH TILDE AND ACUTE -> 'u' */ 2318 + { 0x7A, 0x55 }, /* LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS -> 'U' */ 2319 + { 0x7B, 0x75 }, /* LATIN SMALL LETTER U WITH MACRON AND DIAERESIS -> 'u' */ 2320 + { 0x7C, 0x56 }, /* LATIN CAPITAL LETTER V WITH TILDE -> 'V' */ 2321 + { 0x7D, 0x76 }, /* LATIN SMALL LETTER V WITH TILDE -> 'v' */ 2322 + { 0x7E, 0x56 }, /* LATIN CAPITAL LETTER V WITH DOT BELOW -> 'V' */ 2323 + { 0x7F, 0x76 }, /* LATIN SMALL LETTER V WITH DOT BELOW -> 'v' */ 2324 + { 0x80, 0x57 }, /* LATIN CAPITAL LETTER W WITH GRAVE -> 'W' */ 2325 + { 0x81, 0x77 }, /* LATIN SMALL LETTER W WITH GRAVE -> 'w' */ 2326 + { 0x82, 0x57 }, /* LATIN CAPITAL LETTER W WITH ACUTE -> 'W' */ 2327 + { 0x83, 0x77 }, /* LATIN SMALL LETTER W WITH ACUTE -> 'w' */ 2328 + { 0x84, 0x57 }, /* LATIN CAPITAL LETTER W WITH DIAERESIS -> 'W' */ 2329 + { 0x85, 0x77 }, /* LATIN SMALL LETTER W WITH DIAERESIS -> 'w' */ 2330 + { 0x86, 0x57 }, /* LATIN CAPITAL LETTER W WITH DOT ABOVE -> 'W' */ 2331 + { 0x87, 0x77 }, /* LATIN SMALL LETTER W WITH DOT ABOVE -> 'w' */ 2332 + { 0x88, 0x57 }, /* LATIN CAPITAL LETTER W WITH DOT BELOW -> 'W' */ 2333 + { 0x89, 0x77 }, /* LATIN SMALL LETTER W WITH DOT BELOW -> 'w' */ 2334 + { 0x8A, 0x58 }, /* LATIN CAPITAL LETTER X WITH DOT ABOVE -> 'X' */ 2335 + { 0x8B, 0x78 }, /* LATIN SMALL LETTER X WITH DOT ABOVE -> 'x' */ 2336 + { 0x8C, 0x58 }, /* LATIN CAPITAL LETTER X WITH DIAERESIS -> 'X' */ 2337 + { 0x8D, 0x78 }, /* LATIN SMALL LETTER X WITH DIAERESIS -> 'x' */ 2338 + { 0x8E, 0x59 }, /* LATIN CAPITAL LETTER Y WITH DOT ABOVE -> 'Y' */ 2339 + { 0x8F, 0x79 }, /* LATIN SMALL LETTER Y WITH DOT ABOVE -> 'y' */ 2340 + { 0x90, 0x5A }, /* LATIN CAPITAL LETTER Z WITH CIRCUMFLEX -> 'Z' */ 2341 + { 0x91, 0x7A }, /* LATIN SMALL LETTER Z WITH CIRCUMFLEX -> 'z' */ 2342 + { 0x92, 0x5A }, /* LATIN CAPITAL LETTER Z WITH DOT BELOW -> 'Z' */ 2343 + { 0x93, 0x7A }, /* LATIN SMALL LETTER Z WITH DOT BELOW -> 'z' */ 2344 + { 0x94, 0x5A }, /* LATIN CAPITAL LETTER Z WITH LINE BELOW -> 'Z' */ 2345 + { 0x95, 0x7A }, /* LATIN SMALL LETTER Z WITH LINE BELOW -> 'z' */ 2346 + { 0x96, 0x68 }, /* LATIN SMALL LETTER H WITH LINE BELOW -> 'h' */ 2347 + { 0x97, 0x74 }, /* LATIN SMALL LETTER T WITH DIAERESIS -> 't' */ 2348 + { 0x98, 0x77 }, /* LATIN SMALL LETTER W WITH RING ABOVE -> 'w' */ 2349 + { 0x99, 0x79 }, /* LATIN SMALL LETTER Y WITH RING ABOVE -> 'y' */ 2350 + { 0x9A, 0x61 }, /* LATIN SMALL LETTER A WITH RIGHT HALF RING -> 'a' */ 2351 + { 0x9B, 0x53 }, /* LATIN SMALL LETTER LONG S WITH DOT ABOVE -> 'S' */ 2352 + { 0xA0, 0x41 }, /* LATIN CAPITAL LETTER A WITH DOT BELOW -> 'A' */ 2353 + { 0xA1, 0x61 }, /* LATIN SMALL LETTER A WITH DOT BELOW -> 'a' */ 2354 + { 0xA2, 0x41 }, /* LATIN CAPITAL LETTER A WITH HOOK ABOVE -> 'A' */ 2355 + { 0xA3, 0x61 }, /* LATIN SMALL LETTER A WITH HOOK ABOVE -> 'a' */ 2356 + { 0xA4, 0x41 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE -> 'A' */ 2357 + { 0xA5, 0x61 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE -> 'a' */ 2358 + { 0xA6, 0x41 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE -> 'A' */ 2359 + { 0xA7, 0x61 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE -> 'a' */ 2360 + { 0xA8, 0x41 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE -> 'A' */ 2361 + { 0xA9, 0x61 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE -> 'a' */ 2362 + { 0xAA, 0x41 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE -> 'A' */ 2363 + { 0xAB, 0x61 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE -> 'a' */ 2364 + { 0xAC, 0x41 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW -> 'A' */ 2365 + { 0xAD, 0x61 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW -> 'a' */ 2366 + { 0xAE, 0x41 }, /* LATIN CAPITAL LETTER A WITH BREVE AND ACUTE -> 'A' */ 2367 + { 0xAF, 0x61 }, /* LATIN SMALL LETTER A WITH BREVE AND ACUTE -> 'a' */ 2368 + { 0xB0, 0x41 }, /* LATIN CAPITAL LETTER A WITH BREVE AND GRAVE -> 'A' */ 2369 + { 0xB1, 0x61 }, /* LATIN SMALL LETTER A WITH BREVE AND GRAVE -> 'a' */ 2370 + { 0xB2, 0x41 }, /* LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE -> 'A' */ 2371 + { 0xB3, 0x61 }, /* LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE -> 'a' */ 2372 + { 0xB4, 0x41 }, /* LATIN CAPITAL LETTER A WITH BREVE AND TILDE -> 'A' */ 2373 + { 0xB5, 0x61 }, /* LATIN SMALL LETTER A WITH BREVE AND TILDE -> 'a' */ 2374 + { 0xB6, 0x41 }, /* LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW -> 'A' */ 2375 + { 0xB7, 0x61 }, /* LATIN SMALL LETTER A WITH BREVE AND DOT BELOW -> 'a' */ 2376 + { 0xB8, 0x45 }, /* LATIN CAPITAL LETTER E WITH DOT BELOW -> 'E' */ 2377 + { 0xB9, 0x65 }, /* LATIN SMALL LETTER E WITH DOT BELOW -> 'e' */ 2378 + { 0xBA, 0x45 }, /* LATIN CAPITAL LETTER E WITH HOOK ABOVE -> 'E' */ 2379 + { 0xBB, 0x65 }, /* LATIN SMALL LETTER E WITH HOOK ABOVE -> 'e' */ 2380 + { 0xBC, 0x45 }, /* LATIN CAPITAL LETTER E WITH TILDE -> 'E' */ 2381 + { 0xBD, 0x65 }, /* LATIN SMALL LETTER E WITH TILDE -> 'e' */ 2382 + { 0xBE, 0x45 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE -> 'E' */ 2383 + { 0xBF, 0x65 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE -> 'e' */ 2384 + { 0xC0, 0x45 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE -> 'E' */ 2385 + { 0xC1, 0x65 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE -> 'e' */ 2386 + { 0xC2, 0x45 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE -> 'E' */ 2387 + { 0xC3, 0x65 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE -> 'e' */ 2388 + { 0xC4, 0x45 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE -> 'E' */ 2389 + { 0xC5, 0x65 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE -> 'e' */ 2390 + { 0xC6, 0x45 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW -> 'E' */ 2391 + { 0xC7, 0x65 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW -> 'e' */ 2392 + { 0xC8, 0x49 }, /* LATIN CAPITAL LETTER I WITH HOOK ABOVE -> 'I' */ 2393 + { 0xC9, 0x69 }, /* LATIN SMALL LETTER I WITH HOOK ABOVE -> 'i' */ 2394 + { 0xCA, 0x49 }, /* LATIN CAPITAL LETTER I WITH DOT BELOW -> 'I' */ 2395 + { 0xCB, 0x69 }, /* LATIN SMALL LETTER I WITH DOT BELOW -> 'i' */ 2396 + { 0xCC, 0x4F }, /* LATIN CAPITAL LETTER O WITH DOT BELOW -> 'O' */ 2397 + { 0xCD, 0x6F }, /* LATIN SMALL LETTER O WITH DOT BELOW -> 'o' */ 2398 + { 0xCE, 0x4F }, /* LATIN CAPITAL LETTER O WITH HOOK ABOVE -> 'O' */ 2399 + { 0xCF, 0x6F }, /* LATIN SMALL LETTER O WITH HOOK ABOVE -> 'o' */ 2400 + { 0xD0, 0x4F }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE -> 'O' */ 2401 + { 0xD1, 0x6F }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE -> 'o' */ 2402 + { 0xD2, 0x4F }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE -> 'O' */ 2403 + { 0xD3, 0x6F }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE -> 'o' */ 2404 + { 0xD4, 0x4F }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE -> 'O' */ 2405 + { 0xD5, 0x6F }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE -> 'o' */ 2406 + { 0xD6, 0x4F }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE -> 'O' */ 2407 + { 0xD7, 0x6F }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE -> 'o' */ 2408 + { 0xD8, 0x4F }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW -> 'O' */ 2409 + { 0xD9, 0x6F }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW -> 'o' */ 2410 + { 0xDA, 0x4F }, /* LATIN CAPITAL LETTER O WITH HORN AND ACUTE -> 'O' */ 2411 + { 0xDB, 0x6F }, /* LATIN SMALL LETTER O WITH HORN AND ACUTE -> 'o' */ 2412 + { 0xDC, 0x4F }, /* LATIN CAPITAL LETTER O WITH HORN AND GRAVE -> 'O' */ 2413 + { 0xDD, 0x6F }, /* LATIN SMALL LETTER O WITH HORN AND GRAVE -> 'o' */ 2414 + { 0xDE, 0x4F }, /* LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE -> 'O' */ 2415 + { 0xDF, 0x6F }, /* LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE -> 'o' */ 2416 + { 0xE0, 0x4F }, /* LATIN CAPITAL LETTER O WITH HORN AND TILDE -> 'O' */ 2417 + { 0xE1, 0x6F }, /* LATIN SMALL LETTER O WITH HORN AND TILDE -> 'o' */ 2418 + { 0xE2, 0x4F }, /* LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW -> 'O' */ 2419 + { 0xE3, 0x6F }, /* LATIN SMALL LETTER O WITH HORN AND DOT BELOW -> 'o' */ 2420 + { 0xE4, 0x55 }, /* LATIN CAPITAL LETTER U WITH DOT BELOW -> 'U' */ 2421 + { 0xE5, 0x75 }, /* LATIN SMALL LETTER U WITH DOT BELOW -> 'u' */ 2422 + { 0xE6, 0x55 }, /* LATIN CAPITAL LETTER U WITH HOOK ABOVE -> 'U' */ 2423 + { 0xE7, 0x75 }, /* LATIN SMALL LETTER U WITH HOOK ABOVE -> 'u' */ 2424 + { 0xE8, 0x55 }, /* LATIN CAPITAL LETTER U WITH HORN AND ACUTE -> 'U' */ 2425 + { 0xE9, 0x75 }, /* LATIN SMALL LETTER U WITH HORN AND ACUTE -> 'u' */ 2426 + { 0xEA, 0x55 }, /* LATIN CAPITAL LETTER U WITH HORN AND GRAVE -> 'U' */ 2427 + { 0xEB, 0x75 }, /* LATIN SMALL LETTER U WITH HORN AND GRAVE -> 'u' */ 2428 + { 0xEC, 0x55 }, /* LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE -> 'U' */ 2429 + { 0xED, 0x75 }, /* LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE -> 'u' */ 2430 + { 0xEE, 0x55 }, /* LATIN CAPITAL LETTER U WITH HORN AND TILDE -> 'U' */ 2431 + { 0xEF, 0x75 }, /* LATIN SMALL LETTER U WITH HORN AND TILDE -> 'u' */ 2432 + { 0xF0, 0x55 }, /* LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW -> 'U' */ 2433 + { 0xF1, 0x75 }, /* LATIN SMALL LETTER U WITH HORN AND DOT BELOW -> 'u' */ 2434 + { 0xF2, 0x59 }, /* LATIN CAPITAL LETTER Y WITH GRAVE -> 'Y' */ 2435 + { 0xF3, 0x79 }, /* LATIN SMALL LETTER Y WITH GRAVE -> 'y' */ 2436 + { 0xF4, 0x59 }, /* LATIN CAPITAL LETTER Y WITH DOT BELOW -> 'Y' */ 2437 + { 0xF5, 0x79 }, /* LATIN SMALL LETTER Y WITH DOT BELOW -> 'y' */ 2438 + { 0xF6, 0x59 }, /* LATIN CAPITAL LETTER Y WITH HOOK ABOVE -> 'Y' */ 2439 + { 0xF7, 0x79 }, /* LATIN SMALL LETTER Y WITH HOOK ABOVE -> 'y' */ 2440 + { 0xF8, 0x59 }, /* LATIN CAPITAL LETTER Y WITH TILDE -> 'Y' */ 2441 + { 0xF9, 0x79 }, /* LATIN SMALL LETTER Y WITH TILDE -> 'y' */ 2442 + /* Entries for page 0x1F */ 2443 + { 0x00, 0x00 }, /* GREEK SMALL LETTER ALPHA WITH PSILI -> ... */ 2444 + { 0x07, 0x61 }, /* GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI -> 'a' */ 2445 + { 0x08, 0x00 }, /* GREEK CAPITAL LETTER ALPHA WITH PSILI -> ... */ 2446 + { 0x0F, 0x41 }, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI -> 'A' */ 2447 + { 0x10, 0x00 }, /* GREEK SMALL LETTER EPSILON WITH PSILI -> ... */ 2448 + { 0x15, 0x65 }, /* GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA -> 'e' */ 2449 + { 0x18, 0x00 }, /* GREEK CAPITAL LETTER EPSILON WITH PSILI -> ... */ 2450 + { 0x1D, 0x45 }, /* GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA -> 'E' */ 2451 + { 0x20, 0x00 }, /* GREEK SMALL LETTER ETA WITH PSILI -> ... */ 2452 + { 0x27, 0x65 }, /* GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI -> 'e' */ 2453 + { 0x28, 0x00 }, /* GREEK CAPITAL LETTER ETA WITH PSILI -> ... */ 2454 + { 0x2F, 0x45 }, /* GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI -> 'E' */ 2455 + { 0x30, 0x00 }, /* GREEK SMALL LETTER IOTA WITH PSILI -> ... */ 2456 + { 0x37, 0x69 }, /* GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI -> 'i' */ 2457 + { 0x38, 0x00 }, /* GREEK CAPITAL LETTER IOTA WITH PSILI -> ... */ 2458 + { 0x3F, 0x49 }, /* GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI -> 'I' */ 2459 + { 0x40, 0x00 }, /* GREEK SMALL LETTER OMICRON WITH PSILI -> ... */ 2460 + { 0x45, 0x6F }, /* GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA -> 'o' */ 2461 + { 0x48, 0x00 }, /* GREEK CAPITAL LETTER OMICRON WITH PSILI -> ... */ 2462 + { 0x4D, 0x4F }, /* GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA -> 'O' */ 2463 + { 0x50, 0x00 }, /* GREEK SMALL LETTER UPSILON WITH PSILI -> ... */ 2464 + { 0x57, 0x75 }, /* GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI -> 'u' */ 2465 + { 0x59, 0x55 }, /* GREEK CAPITAL LETTER UPSILON WITH DASIA -> 'U' */ 2466 + { 0x5B, 0x55 }, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA -> 'U' */ 2467 + { 0x5D, 0x55 }, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA -> 'U' */ 2468 + { 0x5F, 0x55 }, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI -> 'U' */ 2469 + { 0x60, 0x00 }, /* GREEK SMALL LETTER OMEGA WITH PSILI -> ... */ 2470 + { 0x67, 0x6F }, /* GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI -> 'o' */ 2471 + { 0x68, 0x00 }, /* GREEK CAPITAL LETTER OMEGA WITH PSILI -> ... */ 2472 + { 0x6F, 0x4F }, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI -> 'O' */ 2473 + { 0x70, 0x61 }, /* GREEK SMALL LETTER ALPHA WITH VARIA -> 'a' */ 2474 + { 0x71, 0x61 }, /* GREEK SMALL LETTER ALPHA WITH OXIA -> 'a' */ 2475 + { 0x72, 0x00 }, /* GREEK SMALL LETTER EPSILON WITH VARIA -> ... */ 2476 + { 0x75, 0x65 }, /* GREEK SMALL LETTER ETA WITH OXIA -> 'e' */ 2477 + { 0x76, 0x69 }, /* GREEK SMALL LETTER IOTA WITH VARIA -> 'i' */ 2478 + { 0x77, 0x69 }, /* GREEK SMALL LETTER IOTA WITH OXIA -> 'i' */ 2479 + { 0x78, 0x6F }, /* GREEK SMALL LETTER OMICRON WITH VARIA -> 'o' */ 2480 + { 0x79, 0x6F }, /* GREEK SMALL LETTER OMICRON WITH OXIA -> 'o' */ 2481 + { 0x7A, 0x75 }, /* GREEK SMALL LETTER UPSILON WITH VARIA -> 'u' */ 2482 + { 0x7B, 0x75 }, /* GREEK SMALL LETTER UPSILON WITH OXIA -> 'u' */ 2483 + { 0x7C, 0x6F }, /* GREEK SMALL LETTER OMEGA WITH VARIA -> 'o' */ 2484 + { 0x7D, 0x6F }, /* GREEK SMALL LETTER OMEGA WITH OXIA -> 'o' */ 2485 + { 0x80, 0x00 }, /* GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI -> ... */ 2486 + { 0x87, 0x61 }, /* GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI -> 'a' */ 2487 + { 0x88, 0x00 }, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI -> ... */ 2488 + { 0x8F, 0x41 }, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI -> 'A' */ 2489 + { 0x90, 0x00 }, /* GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI -> ... */ 2490 + { 0x97, 0x65 }, /* GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI -> 'e' */ 2491 + { 0x98, 0x00 }, /* GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI -> ... */ 2492 + { 0x9F, 0x45 }, /* GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI -> 'E' */ 2493 + { 0xA0, 0x00 }, /* GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI -> ... */ 2494 + { 0xA7, 0x6F }, /* GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI -> 'o' */ 2495 + { 0xA8, 0x00 }, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI -> ... */ 2496 + { 0xAF, 0x4F }, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI -> 'O' */ 2497 + { 0xB0, 0x00 }, /* GREEK SMALL LETTER ALPHA WITH VRACHY -> ... */ 2498 + { 0xB4, 0x61 }, /* GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI -> 'a' */ 2499 + { 0xB6, 0x61 }, /* GREEK SMALL LETTER ALPHA WITH PERISPOMENI -> 'a' */ 2500 + { 0xB7, 0x61 }, /* GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI -> 'a' */ 2501 + { 0xB8, 0x00 }, /* GREEK CAPITAL LETTER ALPHA WITH VRACHY -> ... */ 2502 + { 0xBC, 0x41 }, /* GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI -> 'A' */ 2503 + { 0xBD, 0x27 }, /* GREEK KORONIS -> ''' */ 2504 + { 0xBE, 0x69 }, /* GREEK PROSGEGRAMMENI -> 'i' */ 2505 + { 0xBF, 0x27 }, /* GREEK PSILI -> ''' */ 2506 + { 0xC0, 0x7E }, /* GREEK PERISPOMENI -> '~' */ 2507 + { 0xC2, 0x00 }, /* GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI -> ... */ 2508 + { 0xC4, 0x65 }, /* GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI -> 'e' */ 2509 + { 0xC6, 0x65 }, /* GREEK SMALL LETTER ETA WITH PERISPOMENI -> 'e' */ 2510 + { 0xC7, 0x65 }, /* GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI -> 'e' */ 2511 + { 0xC8, 0x00 }, /* GREEK CAPITAL LETTER EPSILON WITH VARIA -> ... */ 2512 + { 0xCC, 0x45 }, /* GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI -> 'E' */ 2513 + { 0xD0, 0x00 }, /* GREEK SMALL LETTER IOTA WITH VRACHY -> ... */ 2514 + { 0xD3, 0x69 }, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA -> 'i' */ 2515 + { 0xD6, 0x69 }, /* GREEK SMALL LETTER IOTA WITH PERISPOMENI -> 'i' */ 2516 + { 0xD7, 0x69 }, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI -> 'i' */ 2517 + { 0xD8, 0x00 }, /* GREEK CAPITAL LETTER IOTA WITH VRACHY -> ... */ 2518 + { 0xDB, 0x49 }, /* GREEK CAPITAL LETTER IOTA WITH OXIA -> 'I' */ 2519 + { 0xE0, 0x00 }, /* GREEK SMALL LETTER UPSILON WITH VRACHY -> ... */ 2520 + { 0xE3, 0x75 }, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA -> 'u' */ 2521 + { 0xE4, 0x52 }, /* GREEK SMALL LETTER RHO WITH PSILI -> 'R' */ 2522 + { 0xE5, 0x52 }, /* GREEK SMALL LETTER RHO WITH DASIA -> 'R' */ 2523 + { 0xE6, 0x75 }, /* GREEK SMALL LETTER UPSILON WITH PERISPOMENI -> 'u' */ 2524 + { 0xE7, 0x75 }, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI -> 'u' */ 2525 + { 0xE8, 0x00 }, /* GREEK CAPITAL LETTER UPSILON WITH VRACHY -> ... */ 2526 + { 0xEB, 0x55 }, /* GREEK CAPITAL LETTER UPSILON WITH OXIA -> 'U' */ 2527 + { 0xEC, 0x52 }, /* GREEK CAPITAL LETTER RHO WITH DASIA -> 'R' */ 2528 + { 0xEF, 0x60 }, /* GREEK VARIA -> '`' */ 2529 + { 0xF2, 0x00 }, /* GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI -> ... */ 2530 + { 0xF4, 0x6F }, /* GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI -> 'o' */ 2531 + { 0xF6, 0x6F }, /* GREEK SMALL LETTER OMEGA WITH PERISPOMENI -> 'o' */ 2532 + { 0xF7, 0x6F }, /* GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI -> 'o' */ 2533 + { 0xF8, 0x00 }, /* GREEK CAPITAL LETTER OMICRON WITH VARIA -> ... */ 2534 + { 0xFC, 0x4F }, /* GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI -> 'O' */ 2535 + { 0xFD, 0x27 }, /* GREEK OXIA -> ''' */ 2536 + { 0xFE, 0x60 }, /* GREEK DASIA -> '`' */ 2537 + /* Entries for page 0x20 */ 2538 + { 0x00, 0x00 }, /* EN QUAD -> ... */ 2539 + { 0x0B, 0x20 }, /* ZERO WIDTH SPACE -> ' ' */ 2540 + { 0x10, 0x00 }, /* HYPHEN -> ... */ 2541 + { 0x15, 0x2D }, /* HORIZONTAL BAR -> '-' */ 2542 + { 0x17, 0x5F }, /* DOUBLE LOW LINE -> '_' */ 2543 + { 0x18, 0x27 }, /* LEFT SINGLE QUOTATION MARK -> ''' */ 2544 + { 0x19, 0x27 }, /* RIGHT SINGLE QUOTATION MARK -> ''' */ 2545 + { 0x1A, 0x2C }, /* SINGLE LOW-9 QUOTATION MARK -> ',' */ 2546 + { 0x1B, 0x27 }, /* SINGLE HIGH-REVERSED-9 QUOTATION MARK -> ''' */ 2547 + { 0x1C, 0x00 }, /* LEFT DOUBLE QUOTATION MARK -> ... */ 2548 + { 0x1F, 0x22 }, /* DOUBLE HIGH-REVERSED-9 QUOTATION MARK -> '"' */ 2549 + { 0x20, 0x2B }, /* DAGGER -> '+' */ 2550 + { 0x22, 0x2A }, /* BULLET -> '*' */ 2551 + { 0x23, 0x3E }, /* TRIANGULAR BULLET -> '>' */ 2552 + { 0x24, 0x2E }, /* ONE DOT LEADER -> '.' */ 2553 + { 0x26, 0x2E }, /* HORIZONTAL ELLIPSIS -> '.' */ 2554 + { 0x27, 0x2E }, /* HYPHENATION POINT -> '.' */ 2555 + { 0x2F, 0x20 }, /* NARROW NO-BREAK SPACE -> ' ' */ 2556 + { 0x32, 0x27 }, /* PRIME -> ''' */ 2557 + { 0x33, 0x22 }, /* DOUBLE PRIME -> '"' */ 2558 + { 0x35, 0x60 }, /* REVERSED PRIME -> '`' */ 2559 + { 0x38, 0x5E }, /* CARET -> '^' */ 2560 + { 0x39, 0x3C }, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK -> '<' */ 2561 + { 0x3A, 0x3E }, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK -> '>' */ 2562 + { 0x3B, 0x2A }, /* REFERENCE MARK -> '*' */ 2563 + { 0x3C, 0x21 }, /* DOUBLE EXCLAMATION MARK -> '!' */ 2564 + { 0x3D, 0x3F }, /* INTERROBANG -> '?' */ 2565 + { 0x3E, 0x2D }, /* OVERLINE -> '-' */ 2566 + { 0x3F, 0x5F }, /* UNDERTIE -> '_' */ 2567 + { 0x40, 0x2D }, /* CHARACTER TIE -> '-' */ 2568 + { 0x41, 0x5E }, /* CARET INSERTION POINT -> '^' */ 2569 + { 0x42, 0x2A }, /* ASTERISM -> '*' */ 2570 + { 0x43, 0x2D }, /* HYPHEN BULLET -> '-' */ 2571 + { 0x44, 0x2F }, /* FRACTION SLASH -> '/' */ 2572 + { 0x47, 0x3F }, /* DOUBLE QUESTION MARK -> '?' */ 2573 + { 0x48, 0x3F }, /* QUESTION EXCLAMATION MARK -> '?' */ 2574 + { 0x49, 0x21 }, /* EXCLAMATION QUESTION MARK -> '!' */ 2575 + { 0x4A, 0x26 }, /* TIRONIAN SIGN ET -> '&' */ 2576 + { 0x4B, 0x50 }, /* REVERSED PILCROW SIGN -> 'P' */ 2577 + { 0x4C, 0x3C }, /* BLACK LEFTWARDS BULLET -> '<' */ 2578 + { 0x4D, 0x3E }, /* BLACK RIGHTWARDS BULLET -> '>' */ 2579 + { 0x4E, 0x2A }, /* LOW ASTERISK -> '*' */ 2580 + { 0x4F, 0x3B }, /* REVERSED SEMICOLON -> ';' */ 2581 + { 0x51, 0x2A }, /* TWO ASTERISKS ALIGNED VERTICALLY -> '*' */ 2582 + { 0x52, 0x2D }, /* COMMERCIAL MINUS SIGN -> '-' */ 2583 + { 0x53, 0x7E }, /* SWUNG DASH -> '~' */ 2584 + { 0x55, 0x2A }, /* FLOWER PUNCTUATION MARK -> '*' */ 2585 + { 0x5B, 0x3A }, /* FOUR DOT MARK -> ':' */ 2586 + { 0x5F, 0x20 }, /* MEDIUM MATHEMATICAL SPACE -> ' ' */ 2587 + { 0x70, 0x30 }, /* SUPERSCRIPT ZERO -> '0' */ 2588 + { 0x71, 0x69 }, /* SUPERSCRIPT LATIN SMALL LETTER I -> 'i' */ 2589 + { 0x74, 0x34 }, /* SUPERSCRIPT FOUR -> '4' */ 2590 + { 0x75, 0x35 }, /* SUPERSCRIPT FIVE -> '5' */ 2591 + { 0x76, 0x36 }, /* SUPERSCRIPT SIX -> '6' */ 2592 + { 0x77, 0x37 }, /* SUPERSCRIPT SEVEN -> '7' */ 2593 + { 0x78, 0x38 }, /* SUPERSCRIPT EIGHT -> '8' */ 2594 + { 0x79, 0x39 }, /* SUPERSCRIPT NINE -> '9' */ 2595 + { 0x7A, 0x2B }, /* SUPERSCRIPT PLUS SIGN -> '+' */ 2596 + { 0x7B, 0x2D }, /* SUPERSCRIPT MINUS -> '-' */ 2597 + { 0x7C, 0x3D }, /* SUPERSCRIPT EQUALS SIGN -> '=' */ 2598 + { 0x7D, 0x28 }, /* SUPERSCRIPT LEFT PARENTHESIS -> '(' */ 2599 + { 0x7E, 0x29 }, /* SUPERSCRIPT RIGHT PARENTHESIS -> ')' */ 2600 + { 0x7F, 0x6E }, /* SUPERSCRIPT LATIN SMALL LETTER N -> 'n' */ 2601 + { 0x80, 0x30 }, /* SUBSCRIPT ZERO -> '0' */ 2602 + { 0x81, 0x31 }, /* SUBSCRIPT ONE -> '1' */ 2603 + { 0x82, 0x32 }, /* SUBSCRIPT TWO -> '2' */ 2604 + { 0x83, 0x33 }, /* SUBSCRIPT THREE -> '3' */ 2605 + { 0x84, 0x34 }, /* SUBSCRIPT FOUR -> '4' */ 2606 + { 0x85, 0x35 }, /* SUBSCRIPT FIVE -> '5' */ 2607 + { 0x86, 0x36 }, /* SUBSCRIPT SIX -> '6' */ 2608 + { 0x87, 0x37 }, /* SUBSCRIPT SEVEN -> '7' */ 2609 + { 0x88, 0x38 }, /* SUBSCRIPT EIGHT -> '8' */ 2610 + { 0x89, 0x39 }, /* SUBSCRIPT NINE -> '9' */ 2611 + { 0x8A, 0x2B }, /* SUBSCRIPT PLUS SIGN -> '+' */ 2612 + { 0x8B, 0x2D }, /* SUBSCRIPT MINUS -> '-' */ 2613 + { 0x8C, 0x3D }, /* SUBSCRIPT EQUALS SIGN -> '=' */ 2614 + { 0x8D, 0x28 }, /* SUBSCRIPT LEFT PARENTHESIS -> '(' */ 2615 + { 0x8E, 0x29 }, /* SUBSCRIPT RIGHT PARENTHESIS -> ')' */ 2616 + { 0x90, 0x61 }, /* LATIN SUBSCRIPT SMALL LETTER A -> 'a' */ 2617 + { 0x91, 0x65 }, /* LATIN SUBSCRIPT SMALL LETTER E -> 'e' */ 2618 + { 0x92, 0x6F }, /* LATIN SUBSCRIPT SMALL LETTER O -> 'o' */ 2619 + { 0x93, 0x78 }, /* LATIN SUBSCRIPT SMALL LETTER X -> 'x' */ 2620 + { 0x95, 0x68 }, /* LATIN SUBSCRIPT SMALL LETTER H -> 'h' */ 2621 + { 0x96, 0x6B }, /* LATIN SUBSCRIPT SMALL LETTER K -> 'k' */ 2622 + { 0x97, 0x6C }, /* LATIN SUBSCRIPT SMALL LETTER L -> 'l' */ 2623 + { 0x98, 0x6D }, /* LATIN SUBSCRIPT SMALL LETTER M -> 'm' */ 2624 + { 0x99, 0x6E }, /* LATIN SUBSCRIPT SMALL LETTER N -> 'n' */ 2625 + { 0x9A, 0x70 }, /* LATIN SUBSCRIPT SMALL LETTER P -> 'p' */ 2626 + { 0x9B, 0x73 }, /* LATIN SUBSCRIPT SMALL LETTER S -> 's' */ 2627 + { 0x9C, 0x74 }, /* LATIN SUBSCRIPT SMALL LETTER T -> 't' */ 2628 + { 0xA4, 0x4C }, /* LIRA SIGN -> 'L' */ 2629 + { 0xA6, 0x4E }, /* NAIRA SIGN -> 'N' */ 2630 + { 0xA9, 0x57 }, /* WON SIGN -> 'W' */ 2631 + { 0xAB, 0x44 }, /* DONG SIGN -> 'D' */ 2632 + { 0xAC, 0x45 }, /* EURO SIGN -> 'E' */ 2633 + { 0xAD, 0x4B }, /* KIP SIGN -> 'K' */ 2634 + { 0xAE, 0x54 }, /* TUGRIK SIGN -> 'T' */ 2635 + { 0xB1, 0x50 }, /* PESO SIGN -> 'P' */ 2636 + { 0xB2, 0x47 }, /* GUARANI SIGN -> 'G' */ 2637 + { 0xB3, 0x41 }, /* AUSTRAL SIGN -> 'A' */ 2638 + { 0xB6, 0x4C }, /* LIVRE TOURNOIS SIGN -> 'L' */ 2639 + { 0xB8, 0x54 }, /* TENGE SIGN -> 'T' */ 2640 + { 0xBA, 0x4C }, /* TURKISH LIRA SIGN -> 'L' */ 2641 + { 0xBB, 0x4D }, /* NORDIC MARK SIGN -> 'M' */ 2642 + { 0xBC, 0x6D }, /* MANAT SIGN -> 'm' */ 2643 + { 0xBD, 0x52 }, /* RUBLE SIGN -> 'R' */ 2644 + { 0xBE, 0x6C }, /* LARI SIGN -> 'l' */ 2645 + /* Entries for page 0x21 */ 2646 + { 0x02, 0x43 }, /* DOUBLE-STRUCK CAPITAL C -> 'C' */ 2647 + { 0x03, 0x43 }, /* DEGREE CELSIUS -> 'C' */ 2648 + { 0x09, 0x46 }, /* DEGREE FAHRENHEIT -> 'F' */ 2649 + { 0x0A, 0x67 }, /* SCRIPT SMALL G -> 'g' */ 2650 + { 0x0B, 0x00 }, /* SCRIPT CAPITAL H -> ... */ 2651 + { 0x0D, 0x48 }, /* DOUBLE-STRUCK CAPITAL H -> 'H' */ 2652 + { 0x0E, 0x68 }, /* PLANCK CONSTANT -> 'h' */ 2653 + { 0x10, 0x49 }, /* SCRIPT CAPITAL I -> 'I' */ 2654 + { 0x11, 0x49 }, /* BLACK-LETTER CAPITAL I -> 'I' */ 2655 + { 0x12, 0x4C }, /* SCRIPT CAPITAL L -> 'L' */ 2656 + { 0x13, 0x6C }, /* SCRIPT SMALL L -> 'l' */ 2657 + { 0x15, 0x4E }, /* DOUBLE-STRUCK CAPITAL N -> 'N' */ 2658 + { 0x19, 0x50 }, /* DOUBLE-STRUCK CAPITAL P -> 'P' */ 2659 + { 0x1A, 0x51 }, /* DOUBLE-STRUCK CAPITAL Q -> 'Q' */ 2660 + { 0x1B, 0x00 }, /* SCRIPT CAPITAL R -> ... */ 2661 + { 0x1D, 0x52 }, /* DOUBLE-STRUCK CAPITAL R -> 'R' */ 2662 + { 0x22, 0x54 }, /* TRADE MARK SIGN -> 'T' */ 2663 + { 0x24, 0x5A }, /* DOUBLE-STRUCK CAPITAL Z -> 'Z' */ 2664 + { 0x28, 0x5A }, /* BLACK-LETTER CAPITAL Z -> 'Z' */ 2665 + { 0x2A, 0x4B }, /* KELVIN SIGN -> 'K' */ 2666 + { 0x2B, 0x41 }, /* ANGSTROM SIGN -> 'A' */ 2667 + { 0x2C, 0x42 }, /* SCRIPT CAPITAL B -> 'B' */ 2668 + { 0x2D, 0x43 }, /* BLACK-LETTER CAPITAL C -> 'C' */ 2669 + { 0x2E, 0x65 }, /* ESTIMATED SYMBOL -> 'e' */ 2670 + { 0x2F, 0x65 }, /* SCRIPT SMALL E -> 'e' */ 2671 + { 0x30, 0x45 }, /* SCRIPT CAPITAL E -> 'E' */ 2672 + { 0x31, 0x46 }, /* SCRIPT CAPITAL F -> 'F' */ 2673 + { 0x32, 0x46 }, /* TURNED CAPITAL F -> 'F' */ 2674 + { 0x33, 0x4D }, /* SCRIPT CAPITAL M -> 'M' */ 2675 + { 0x34, 0x6F }, /* SCRIPT SMALL O -> 'o' */ 2676 + { 0x39, 0x69 }, /* INFORMATION SOURCE -> 'i' */ 2677 + { 0x45, 0x44 }, /* DOUBLE-STRUCK ITALIC CAPITAL D -> 'D' */ 2678 + { 0x46, 0x64 }, /* DOUBLE-STRUCK ITALIC SMALL D -> 'd' */ 2679 + { 0x47, 0x65 }, /* DOUBLE-STRUCK ITALIC SMALL E -> 'e' */ 2680 + { 0x48, 0x69 }, /* DOUBLE-STRUCK ITALIC SMALL I -> 'i' */ 2681 + { 0x49, 0x6A }, /* DOUBLE-STRUCK ITALIC SMALL J -> 'j' */ 2682 + { 0x4E, 0x46 }, /* TURNED SMALL F -> 'F' */ 2683 + { 0x60, 0x49 }, /* ROMAN NUMERAL ONE -> 'I' */ 2684 + { 0x64, 0x56 }, /* ROMAN NUMERAL FIVE -> 'V' */ 2685 + { 0x69, 0x58 }, /* ROMAN NUMERAL TEN -> 'X' */ 2686 + { 0x6C, 0x4C }, /* ROMAN NUMERAL FIFTY -> 'L' */ 2687 + { 0x6D, 0x43 }, /* ROMAN NUMERAL ONE HUNDRED -> 'C' */ 2688 + { 0x6E, 0x44 }, /* ROMAN NUMERAL FIVE HUNDRED -> 'D' */ 2689 + { 0x6F, 0x4D }, /* ROMAN NUMERAL ONE THOUSAND -> 'M' */ 2690 + { 0x70, 0x69 }, /* SMALL ROMAN NUMERAL ONE -> 'i' */ 2691 + { 0x74, 0x76 }, /* SMALL ROMAN NUMERAL FIVE -> 'v' */ 2692 + { 0x79, 0x78 }, /* SMALL ROMAN NUMERAL TEN -> 'x' */ 2693 + { 0x7C, 0x6C }, /* SMALL ROMAN NUMERAL FIFTY -> 'l' */ 2694 + { 0x7D, 0x63 }, /* SMALL ROMAN NUMERAL ONE HUNDRED -> 'c' */ 2695 + { 0x7E, 0x64 }, /* SMALL ROMAN NUMERAL FIVE HUNDRED -> 'd' */ 2696 + { 0x7F, 0x6D }, /* SMALL ROMAN NUMERAL ONE THOUSAND -> 'm' */ 2697 + { 0x83, 0x29 }, /* ROMAN NUMERAL REVERSED ONE HUNDRED -> ')' */ 2698 + { 0x90, 0x3C }, /* LEFTWARDS ARROW -> '<' */ 2699 + { 0x91, 0x5E }, /* UPWARDS ARROW -> '^' */ 2700 + { 0x92, 0x3E }, /* RIGHTWARDS ARROW -> '>' */ 2701 + { 0x93, 0x76 }, /* DOWNWARDS ARROW -> 'v' */ 2702 + { 0x94, 0x2D }, /* LEFT RIGHT ARROW -> '-' */ 2703 + { 0x95, 0x7C }, /* UP DOWN ARROW -> '|' */ 2704 + { 0x96, 0x5C }, /* NORTH WEST ARROW -> '\' */ 2705 + { 0x97, 0x2F }, /* NORTH EAST ARROW -> '/' */ 2706 + { 0x98, 0x5C }, /* SOUTH EAST ARROW -> '\' */ 2707 + { 0x99, 0x2F }, /* SOUTH WEST ARROW -> '/' */ 2708 + { 0x9A, 0x21 }, /* LEFTWARDS ARROW WITH STROKE -> '!' */ 2709 + { 0x9B, 0x21 }, /* RIGHTWARDS ARROW WITH STROKE -> '!' */ 2710 + { 0x9C, 0x7E }, /* LEFTWARDS WAVE ARROW -> '~' */ 2711 + { 0x9D, 0x7E }, /* RIGHTWARDS WAVE ARROW -> '~' */ 2712 + { 0x9E, 0x2D }, /* LEFTWARDS TWO HEADED ARROW -> '-' */ 2713 + { 0x9F, 0x7C }, /* UPWARDS TWO HEADED ARROW -> '|' */ 2714 + { 0xA0, 0x2D }, /* RIGHTWARDS TWO HEADED ARROW -> '-' */ 2715 + { 0xA1, 0x7C }, /* DOWNWARDS TWO HEADED ARROW -> '|' */ 2716 + { 0xA2, 0x00 }, /* LEFTWARDS ARROW WITH TAIL -> ... */ 2717 + { 0xA4, 0x2D }, /* LEFTWARDS ARROW FROM BAR -> '-' */ 2718 + { 0xA5, 0x7C }, /* UPWARDS ARROW FROM BAR -> '|' */ 2719 + { 0xA6, 0x2D }, /* RIGHTWARDS ARROW FROM BAR -> '-' */ 2720 + { 0xA7, 0x7C }, /* DOWNWARDS ARROW FROM BAR -> '|' */ 2721 + { 0xA8, 0x7C }, /* UP DOWN ARROW WITH BASE -> '|' */ 2722 + { 0xA9, 0x00 }, /* LEFTWARDS ARROW WITH HOOK -> ... */ 2723 + { 0xAD, 0x2D }, /* LEFT RIGHT WAVE ARROW -> '-' */ 2724 + { 0xAE, 0x21 }, /* LEFT RIGHT ARROW WITH STROKE -> '!' */ 2725 + { 0xAF, 0x00 }, /* DOWNWARDS ZIGZAG ARROW -> ... */ 2726 + { 0xB5, 0x7C }, /* DOWNWARDS ARROW WITH CORNER LEFTWARDS -> '|' */ 2727 + { 0xB6, 0x5E }, /* ANTICLOCKWISE TOP SEMICIRCLE ARROW -> '^' */ 2728 + { 0xB7, 0x56 }, /* CLOCKWISE TOP SEMICIRCLE ARROW -> 'V' */ 2729 + { 0xB8, 0x5C }, /* NORTH WEST ARROW TO LONG BAR -> '\' */ 2730 + { 0xB9, 0x3D }, /* LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR -> '=' */ 2731 + { 0xBA, 0x56 }, /* ANTICLOCKWISE OPEN CIRCLE ARROW -> 'V' */ 2732 + { 0xBB, 0x5E }, /* CLOCKWISE OPEN CIRCLE ARROW -> '^' */ 2733 + { 0xBC, 0x2D }, /* LEFTWARDS HARPOON WITH BARB UPWARDS -> '-' */ 2734 + { 0xBD, 0x2D }, /* LEFTWARDS HARPOON WITH BARB DOWNWARDS -> '-' */ 2735 + { 0xBE, 0x7C }, /* UPWARDS HARPOON WITH BARB RIGHTWARDS -> '|' */ 2736 + { 0xBF, 0x7C }, /* UPWARDS HARPOON WITH BARB LEFTWARDS -> '|' */ 2737 + { 0xC0, 0x2D }, /* RIGHTWARDS HARPOON WITH BARB UPWARDS -> '-' */ 2738 + { 0xC1, 0x2D }, /* RIGHTWARDS HARPOON WITH BARB DOWNWARDS -> '-' */ 2739 + { 0xC2, 0x7C }, /* DOWNWARDS HARPOON WITH BARB RIGHTWARDS -> '|' */ 2740 + { 0xC3, 0x7C }, /* DOWNWARDS HARPOON WITH BARB LEFTWARDS -> '|' */ 2741 + { 0xC4, 0x3D }, /* RIGHTWARDS ARROW OVER LEFTWARDS ARROW -> '=' */ 2742 + { 0xC5, 0x7C }, /* UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW -> '|' */ 2743 + { 0xC6, 0x3D }, /* LEFTWARDS ARROW OVER RIGHTWARDS ARROW -> '=' */ 2744 + { 0xC7, 0x3D }, /* LEFTWARDS PAIRED ARROWS -> '=' */ 2745 + { 0xC8, 0x7C }, /* UPWARDS PAIRED ARROWS -> '|' */ 2746 + { 0xC9, 0x3D }, /* RIGHTWARDS PAIRED ARROWS -> '=' */ 2747 + { 0xCA, 0x7C }, /* DOWNWARDS PAIRED ARROWS -> '|' */ 2748 + { 0xCB, 0x3D }, /* LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON -> '=' */ 2749 + { 0xCC, 0x3D }, /* RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON -> '=' */ 2750 + { 0xCD, 0x00 }, /* LEFTWARDS DOUBLE ARROW WITH STROKE -> ... */ 2751 + { 0xCF, 0x21 }, /* RIGHTWARDS DOUBLE ARROW WITH STROKE -> '!' */ 2752 + { 0xD0, 0x3C }, /* LEFTWARDS DOUBLE ARROW -> '<' */ 2753 + { 0xD1, 0x5E }, /* UPWARDS DOUBLE ARROW -> '^' */ 2754 + { 0xD2, 0x3E }, /* RIGHTWARDS DOUBLE ARROW -> '>' */ 2755 + { 0xD3, 0x76 }, /* DOWNWARDS DOUBLE ARROW -> 'v' */ 2756 + { 0xD4, 0x3D }, /* LEFT RIGHT DOUBLE ARROW -> '=' */ 2757 + { 0xD5, 0x7C }, /* UP DOWN DOUBLE ARROW -> '|' */ 2758 + { 0xD6, 0x5C }, /* NORTH WEST DOUBLE ARROW -> '\' */ 2759 + { 0xD7, 0x2F }, /* NORTH EAST DOUBLE ARROW -> '/' */ 2760 + { 0xD8, 0x5C }, /* SOUTH EAST DOUBLE ARROW -> '\' */ 2761 + { 0xD9, 0x2F }, /* SOUTH WEST DOUBLE ARROW -> '/' */ 2762 + { 0xDA, 0x3D }, /* LEFTWARDS TRIPLE ARROW -> '=' */ 2763 + { 0xDB, 0x3D }, /* RIGHTWARDS TRIPLE ARROW -> '=' */ 2764 + { 0xDC, 0x7E }, /* LEFTWARDS SQUIGGLE ARROW -> '~' */ 2765 + { 0xDD, 0x7E }, /* RIGHTWARDS SQUIGGLE ARROW -> '~' */ 2766 + { 0xDE, 0x7C }, /* UPWARDS ARROW WITH DOUBLE STROKE -> '|' */ 2767 + { 0xDF, 0x7C }, /* DOWNWARDS ARROW WITH DOUBLE STROKE -> '|' */ 2768 + { 0xE0, 0x2D }, /* LEFTWARDS DASHED ARROW -> '-' */ 2769 + { 0xE1, 0x7C }, /* UPWARDS DASHED ARROW -> '|' */ 2770 + { 0xE2, 0x2D }, /* RIGHTWARDS DASHED ARROW -> '-' */ 2771 + { 0xE3, 0x7C }, /* DOWNWARDS DASHED ARROW -> '|' */ 2772 + { 0xE4, 0x00 }, /* LEFTWARDS ARROW TO BAR -> ... */ 2773 + { 0xE6, 0x2D }, /* LEFTWARDS WHITE ARROW -> '-' */ 2774 + { 0xE7, 0x7C }, /* UPWARDS WHITE ARROW -> '|' */ 2775 + { 0xE8, 0x2D }, /* RIGHTWARDS WHITE ARROW -> '-' */ 2776 + { 0xE9, 0x00 }, /* DOWNWARDS WHITE ARROW -> ... */ 2777 + { 0xEF, 0x7C }, /* UPWARDS WHITE DOUBLE ARROW ON PEDESTAL -> '|' */ 2778 + { 0xF0, 0x2D }, /* RIGHTWARDS WHITE ARROW FROM WALL -> '-' */ 2779 + { 0xF1, 0x5C }, /* NORTH WEST ARROW TO CORNER -> '\' */ 2780 + { 0xF2, 0x5C }, /* SOUTH EAST ARROW TO CORNER -> '\' */ 2781 + { 0xF3, 0x7C }, /* UP DOWN WHITE ARROW -> '|' */ 2782 + /* Entries for page 0x22 */ 2783 + { 0x04, 0x21 }, /* THERE DOES NOT EXIST -> '!' */ 2784 + { 0x09, 0x21 }, /* NOT AN ELEMENT OF -> '!' */ 2785 + { 0x0C, 0x21 }, /* DOES NOT CONTAIN AS MEMBER -> '!' */ 2786 + { 0x12, 0x2D }, /* MINUS SIGN -> '-' */ 2787 + { 0x15, 0x2F }, /* DIVISION SLASH -> '/' */ 2788 + { 0x16, 0x5C }, /* SET MINUS -> '\' */ 2789 + { 0x17, 0x2A }, /* ASTERISK OPERATOR -> '*' */ 2790 + { 0x18, 0x6F }, /* RING OPERATOR -> 'o' */ 2791 + { 0x19, 0x2E }, /* BULLET OPERATOR -> '.' */ 2792 + { 0x23, 0x7C }, /* DIVIDES -> '|' */ 2793 + { 0x24, 0x21 }, /* DOES NOT DIVIDE -> '!' */ 2794 + { 0x26, 0x21 }, /* NOT PARALLEL TO -> '!' */ 2795 + { 0x36, 0x3A }, /* RATIO -> ':' */ 2796 + { 0x3C, 0x7E }, /* TILDE OPERATOR -> '~' */ 2797 + { 0x41, 0x23 }, /* NOT TILDE -> '#' */ 2798 + { 0x44, 0x23 }, /* NOT ASYMPTOTICALLY EQUAL TO -> '#' */ 2799 + { 0x49, 0x23 }, /* NOT ALMOST EQUAL TO -> '#' */ 2800 + { 0x60, 0x23 }, /* NOT EQUAL TO -> '#' */ 2801 + { 0x62, 0x23 }, /* NOT IDENTICAL TO -> '#' */ 2802 + { 0x64, 0x3C }, /* LESS-THAN OR EQUAL TO -> '<' */ 2803 + { 0x65, 0x3E }, /* GREATER-THAN OR EQUAL TO -> '>' */ 2804 + { 0x68, 0x23 }, /* LESS-THAN BUT NOT EQUAL TO -> '#' */ 2805 + { 0x69, 0x23 }, /* GREATER-THAN BUT NOT EQUAL TO -> '#' */ 2806 + { 0x6D, 0x23 }, /* NOT EQUIVALENT TO -> '#' */ 2807 + { 0x6E, 0x21 }, /* NOT LESS-THAN -> '!' */ 2808 + { 0x6F, 0x21 }, /* NOT GREATER-THAN -> '!' */ 2809 + { 0x80, 0x21 }, /* DOES NOT PRECEDE -> '!' */ 2810 + { 0x81, 0x21 }, /* DOES NOT SUCCEED -> '!' */ 2811 + { 0x84, 0x21 }, /* NOT A SUBSET OF -> '!' */ 2812 + { 0x85, 0x21 }, /* NOT A SUPERSET OF -> '!' */ 2813 + { 0x8A, 0x23 }, /* SUBSET OF WITH NOT EQUAL TO -> '#' */ 2814 + { 0x8B, 0x23 }, /* SUPERSET OF WITH NOT EQUAL TO -> '#' */ 2815 + { 0x9B, 0x2A }, /* CIRCLED ASTERISK OPERATOR -> '*' */ 2816 + { 0xC6, 0x2A }, /* STAR OPERATOR -> '*' */ 2817 + /* Entries for page 0x23 */ 2818 + { 0x03, 0x5E }, /* UP ARROWHEAD -> '^' */ 2819 + { 0x29, 0x3C }, /* LEFT-POINTING ANGLE BRACKET -> '<' */ 2820 + { 0x5F, 0x2A }, /* APL FUNCTIONAL SYMBOL CIRCLE STAR -> '*' */ 2821 + { 0x63, 0x2A }, /* APL FUNCTIONAL SYMBOL STAR DIAERESIS -> '*' */ 2822 + /* Entries for page 0x24 */ 2823 + { 0x60, 0x31 }, /* CIRCLED DIGIT ONE -> '1' */ 2824 + { 0x61, 0x32 }, /* CIRCLED DIGIT TWO -> '2' */ 2825 + { 0x62, 0x33 }, /* CIRCLED DIGIT THREE -> '3' */ 2826 + { 0x63, 0x34 }, /* CIRCLED DIGIT FOUR -> '4' */ 2827 + { 0x64, 0x35 }, /* CIRCLED DIGIT FIVE -> '5' */ 2828 + { 0x65, 0x36 }, /* CIRCLED DIGIT SIX -> '6' */ 2829 + { 0x66, 0x37 }, /* CIRCLED DIGIT SEVEN -> '7' */ 2830 + { 0x67, 0x38 }, /* CIRCLED DIGIT EIGHT -> '8' */ 2831 + { 0x68, 0x39 }, /* CIRCLED DIGIT NINE -> '9' */ 2832 + { 0xB6, 0x41 }, /* CIRCLED LATIN CAPITAL LETTER A -> 'A' */ 2833 + { 0xB7, 0x42 }, /* CIRCLED LATIN CAPITAL LETTER B -> 'B' */ 2834 + { 0xB8, 0x43 }, /* CIRCLED LATIN CAPITAL LETTER C -> 'C' */ 2835 + { 0xB9, 0x44 }, /* CIRCLED LATIN CAPITAL LETTER D -> 'D' */ 2836 + { 0xBA, 0x45 }, /* CIRCLED LATIN CAPITAL LETTER E -> 'E' */ 2837 + { 0xBB, 0x46 }, /* CIRCLED LATIN CAPITAL LETTER F -> 'F' */ 2838 + { 0xBC, 0x47 }, /* CIRCLED LATIN CAPITAL LETTER G -> 'G' */ 2839 + { 0xBD, 0x48 }, /* CIRCLED LATIN CAPITAL LETTER H -> 'H' */ 2840 + { 0xBE, 0x49 }, /* CIRCLED LATIN CAPITAL LETTER I -> 'I' */ 2841 + { 0xBF, 0x4A }, /* CIRCLED LATIN CAPITAL LETTER J -> 'J' */ 2842 + { 0xC0, 0x4B }, /* CIRCLED LATIN CAPITAL LETTER K -> 'K' */ 2843 + { 0xC1, 0x4C }, /* CIRCLED LATIN CAPITAL LETTER L -> 'L' */ 2844 + { 0xC2, 0x4D }, /* CIRCLED LATIN CAPITAL LETTER M -> 'M' */ 2845 + { 0xC3, 0x4E }, /* CIRCLED LATIN CAPITAL LETTER N -> 'N' */ 2846 + { 0xC4, 0x4F }, /* CIRCLED LATIN CAPITAL LETTER O -> 'O' */ 2847 + { 0xC5, 0x50 }, /* CIRCLED LATIN CAPITAL LETTER P -> 'P' */ 2848 + { 0xC6, 0x51 }, /* CIRCLED LATIN CAPITAL LETTER Q -> 'Q' */ 2849 + { 0xC7, 0x52 }, /* CIRCLED LATIN CAPITAL LETTER R -> 'R' */ 2850 + { 0xC8, 0x53 }, /* CIRCLED LATIN CAPITAL LETTER S -> 'S' */ 2851 + { 0xC9, 0x54 }, /* CIRCLED LATIN CAPITAL LETTER T -> 'T' */ 2852 + { 0xCA, 0x55 }, /* CIRCLED LATIN CAPITAL LETTER U -> 'U' */ 2853 + { 0xCB, 0x56 }, /* CIRCLED LATIN CAPITAL LETTER V -> 'V' */ 2854 + { 0xCC, 0x57 }, /* CIRCLED LATIN CAPITAL LETTER W -> 'W' */ 2855 + { 0xCD, 0x58 }, /* CIRCLED LATIN CAPITAL LETTER X -> 'X' */ 2856 + { 0xCE, 0x59 }, /* CIRCLED LATIN CAPITAL LETTER Y -> 'Y' */ 2857 + { 0xCF, 0x5A }, /* CIRCLED LATIN CAPITAL LETTER Z -> 'Z' */ 2858 + { 0xD0, 0x61 }, /* CIRCLED LATIN SMALL LETTER A -> 'a' */ 2859 + { 0xD1, 0x62 }, /* CIRCLED LATIN SMALL LETTER B -> 'b' */ 2860 + { 0xD2, 0x63 }, /* CIRCLED LATIN SMALL LETTER C -> 'c' */ 2861 + { 0xD3, 0x64 }, /* CIRCLED LATIN SMALL LETTER D -> 'd' */ 2862 + { 0xD4, 0x65 }, /* CIRCLED LATIN SMALL LETTER E -> 'e' */ 2863 + { 0xD5, 0x66 }, /* CIRCLED LATIN SMALL LETTER F -> 'f' */ 2864 + { 0xD6, 0x67 }, /* CIRCLED LATIN SMALL LETTER G -> 'g' */ 2865 + { 0xD7, 0x68 }, /* CIRCLED LATIN SMALL LETTER H -> 'h' */ 2866 + { 0xD8, 0x69 }, /* CIRCLED LATIN SMALL LETTER I -> 'i' */ 2867 + { 0xD9, 0x6A }, /* CIRCLED LATIN SMALL LETTER J -> 'j' */ 2868 + { 0xDA, 0x6B }, /* CIRCLED LATIN SMALL LETTER K -> 'k' */ 2869 + { 0xDB, 0x6C }, /* CIRCLED LATIN SMALL LETTER L -> 'l' */ 2870 + { 0xDC, 0x6D }, /* CIRCLED LATIN SMALL LETTER M -> 'm' */ 2871 + { 0xDD, 0x6E }, /* CIRCLED LATIN SMALL LETTER N -> 'n' */ 2872 + { 0xDE, 0x6F }, /* CIRCLED LATIN SMALL LETTER O -> 'o' */ 2873 + { 0xDF, 0x70 }, /* CIRCLED LATIN SMALL LETTER P -> 'p' */ 2874 + { 0xE0, 0x71 }, /* CIRCLED LATIN SMALL LETTER Q -> 'q' */ 2875 + { 0xE1, 0x72 }, /* CIRCLED LATIN SMALL LETTER R -> 'r' */ 2876 + { 0xE2, 0x73 }, /* CIRCLED LATIN SMALL LETTER S -> 's' */ 2877 + { 0xE3, 0x74 }, /* CIRCLED LATIN SMALL LETTER T -> 't' */ 2878 + { 0xE4, 0x75 }, /* CIRCLED LATIN SMALL LETTER U -> 'u' */ 2879 + { 0xE5, 0x76 }, /* CIRCLED LATIN SMALL LETTER V -> 'v' */ 2880 + { 0xE6, 0x77 }, /* CIRCLED LATIN SMALL LETTER W -> 'w' */ 2881 + { 0xE7, 0x78 }, /* CIRCLED LATIN SMALL LETTER X -> 'x' */ 2882 + { 0xE8, 0x79 }, /* CIRCLED LATIN SMALL LETTER Y -> 'y' */ 2883 + { 0xE9, 0x7A }, /* CIRCLED LATIN SMALL LETTER Z -> 'z' */ 2884 + { 0xEA, 0x30 }, /* CIRCLED DIGIT ZERO -> '0' */ 2885 + { 0xF5, 0x31 }, /* DOUBLE CIRCLED DIGIT ONE -> '1' */ 2886 + { 0xF6, 0x32 }, /* DOUBLE CIRCLED DIGIT TWO -> '2' */ 2887 + { 0xF7, 0x33 }, /* DOUBLE CIRCLED DIGIT THREE -> '3' */ 2888 + { 0xF8, 0x34 }, /* DOUBLE CIRCLED DIGIT FOUR -> '4' */ 2889 + { 0xF9, 0x35 }, /* DOUBLE CIRCLED DIGIT FIVE -> '5' */ 2890 + { 0xFA, 0x36 }, /* DOUBLE CIRCLED DIGIT SIX -> '6' */ 2891 + { 0xFB, 0x37 }, /* DOUBLE CIRCLED DIGIT SEVEN -> '7' */ 2892 + { 0xFC, 0x38 }, /* DOUBLE CIRCLED DIGIT EIGHT -> '8' */ 2893 + { 0xFD, 0x39 }, /* DOUBLE CIRCLED DIGIT NINE -> '9' */ 2894 + { 0xFF, 0x30 }, /* NEGATIVE CIRCLED DIGIT ZERO -> '0' */ 2895 + /* Entries for page 0x25 */ 2896 + { 0x00, 0x2D }, /* BOX DRAWINGS LIGHT HORIZONTAL -> '-' */ 2897 + { 0x01, 0x2D }, /* BOX DRAWINGS HEAVY HORIZONTAL -> '-' */ 2898 + { 0x02, 0x7C }, /* BOX DRAWINGS LIGHT VERTICAL -> '|' */ 2899 + { 0x03, 0x7C }, /* BOX DRAWINGS HEAVY VERTICAL -> '|' */ 2900 + { 0x04, 0x2D }, /* BOX DRAWINGS LIGHT TRIPLE DASH HORIZONTAL -> '-' */ 2901 + { 0x05, 0x2D }, /* BOX DRAWINGS HEAVY TRIPLE DASH HORIZONTAL -> '-' */ 2902 + { 0x06, 0x7C }, /* BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL -> '|' */ 2903 + { 0x07, 0x7C }, /* BOX DRAWINGS HEAVY TRIPLE DASH VERTICAL -> '|' */ 2904 + { 0x08, 0x2D }, /* BOX DRAWINGS LIGHT QUADRUPLE DASH HORIZONTAL -> '-' */ 2905 + { 0x09, 0x2D }, /* BOX DRAWINGS HEAVY QUADRUPLE DASH HORIZONTAL -> '-' */ 2906 + { 0x0A, 0x7C }, /* BOX DRAWINGS LIGHT QUADRUPLE DASH VERTICAL -> '|' */ 2907 + { 0x0B, 0x7C }, /* BOX DRAWINGS HEAVY QUADRUPLE DASH VERTICAL -> '|' */ 2908 + { 0x0C, 0x00 }, /* BOX DRAWINGS LIGHT DOWN AND RIGHT -> ... */ 2909 + { 0x4B, 0x2B }, /* BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL -> '+' */ 2910 + { 0x4C, 0x2D }, /* BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL -> '-' */ 2911 + { 0x4D, 0x2D }, /* BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL -> '-' */ 2912 + { 0x4E, 0x7C }, /* BOX DRAWINGS LIGHT DOUBLE DASH VERTICAL -> '|' */ 2913 + { 0x4F, 0x7C }, /* BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL -> '|' */ 2914 + { 0x50, 0x2D }, /* BOX DRAWINGS DOUBLE HORIZONTAL -> '-' */ 2915 + { 0x51, 0x7C }, /* BOX DRAWINGS DOUBLE VERTICAL -> '|' */ 2916 + { 0x52, 0x00 }, /* BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE -> ... */ 2917 + { 0x70, 0x2B }, /* BOX DRAWINGS LIGHT ARC UP AND RIGHT -> '+' */ 2918 + { 0x71, 0x2F }, /* BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT -> '/' */ 2919 + { 0x72, 0x5C }, /* BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT -> '\' */ 2920 + { 0x73, 0x58 }, /* BOX DRAWINGS LIGHT DIAGONAL CROSS -> 'X' */ 2921 + { 0x74, 0x2D }, /* BOX DRAWINGS LIGHT LEFT -> '-' */ 2922 + { 0x75, 0x7C }, /* BOX DRAWINGS LIGHT UP -> '|' */ 2923 + { 0x76, 0x2D }, /* BOX DRAWINGS LIGHT RIGHT -> '-' */ 2924 + { 0x77, 0x7C }, /* BOX DRAWINGS LIGHT DOWN -> '|' */ 2925 + { 0x78, 0x2D }, /* BOX DRAWINGS HEAVY LEFT -> '-' */ 2926 + { 0x79, 0x7C }, /* BOX DRAWINGS HEAVY UP -> '|' */ 2927 + { 0x7A, 0x2D }, /* BOX DRAWINGS HEAVY RIGHT -> '-' */ 2928 + { 0x7B, 0x7C }, /* BOX DRAWINGS HEAVY DOWN -> '|' */ 2929 + { 0x7C, 0x2D }, /* BOX DRAWINGS LIGHT LEFT AND HEAVY RIGHT -> '-' */ 2930 + { 0x7D, 0x7C }, /* BOX DRAWINGS LIGHT UP AND HEAVY DOWN -> '|' */ 2931 + { 0x7E, 0x2D }, /* BOX DRAWINGS HEAVY LEFT AND LIGHT RIGHT -> '-' */ 2932 + { 0x7F, 0x7C }, /* BOX DRAWINGS HEAVY UP AND LIGHT DOWN -> '|' */ 2933 + { 0x80, 0x00 }, /* UPPER HALF BLOCK -> ... */ 2934 + { 0x93, 0x23 }, /* DARK SHADE -> '#' */ 2935 + { 0x94, 0x2D }, /* UPPER ONE EIGHTH BLOCK -> '-' */ 2936 + { 0x95, 0x7C }, /* RIGHT ONE EIGHTH BLOCK -> '|' */ 2937 + { 0x96, 0x00 }, /* QUADRANT LOWER LEFT -> ... */ 2938 + { 0xB1, 0x23 }, /* WHITE PARALLELOGRAM -> '#' */ 2939 + { 0xB2, 0x00 }, /* BLACK UP-POINTING TRIANGLE -> ... */ 2940 + { 0xB5, 0x5E }, /* WHITE UP-POINTING SMALL TRIANGLE -> '^' */ 2941 + { 0xB6, 0x00 }, /* BLACK RIGHT-POINTING TRIANGLE -> ... */ 2942 + { 0xBB, 0x3E }, /* WHITE RIGHT-POINTING POINTER -> '>' */ 2943 + { 0xBC, 0x00 }, /* BLACK DOWN-POINTING TRIANGLE -> ... */ 2944 + { 0xBF, 0x56 }, /* WHITE DOWN-POINTING SMALL TRIANGLE -> 'V' */ 2945 + { 0xC0, 0x00 }, /* BLACK LEFT-POINTING TRIANGLE -> ... */ 2946 + { 0xC5, 0x3C }, /* WHITE LEFT-POINTING POINTER -> '<' */ 2947 + { 0xC6, 0x00 }, /* BLACK DIAMOND -> ... */ 2948 + { 0xE6, 0x2A }, /* WHITE BULLET -> '*' */ 2949 + { 0xE7, 0x00 }, /* SQUARE WITH LEFT HALF BLACK -> ... */ 2950 + { 0xEB, 0x23 }, /* WHITE SQUARE WITH VERTICAL BISECTING LINE -> '#' */ 2951 + { 0xEC, 0x00 }, /* WHITE UP-POINTING TRIANGLE WITH DOT -> ... */ 2952 + { 0xEE, 0x5E }, /* UP-POINTING TRIANGLE WITH RIGHT HALF BLACK -> '^' */ 2953 + { 0xEF, 0x4F }, /* LARGE CIRCLE -> 'O' */ 2954 + { 0xF0, 0x00 }, /* WHITE SQUARE WITH UPPER LEFT QUADRANT -> ... */ 2955 + { 0xF7, 0x23 }, /* WHITE CIRCLE WITH UPPER RIGHT QUADRANT -> '#' */ 2956 + /* Entries for page 0x26 */ 2957 + { 0x05, 0x2A }, /* BLACK STAR -> '*' */ 2958 + { 0x06, 0x2A }, /* WHITE STAR -> '*' */ 2959 + { 0x2A, 0x2A }, /* STAR AND CRESCENT -> '*' */ 2960 + { 0x6F, 0x23 }, /* MUSIC SHARP SIGN -> '#' */ 2961 + { 0x98, 0x2A }, /* FLOWER -> '*' */ 2962 + { 0x9D, 0x2A }, /* OUTLINED WHITE STAR -> '*' */ 2963 + /* Entries for page 0x27 */ 2964 + { 0x13, 0x76 }, /* CHECK MARK -> 'v' */ 2965 + { 0x14, 0x56 }, /* HEAVY CHECK MARK -> 'V' */ 2966 + { 0x15, 0x78 }, /* MULTIPLICATION X -> 'x' */ 2967 + { 0x16, 0x58 }, /* HEAVY MULTIPLICATION X -> 'X' */ 2968 + { 0x17, 0x78 }, /* BALLOT X -> 'x' */ 2969 + { 0x18, 0x58 }, /* HEAVY BALLOT X -> 'X' */ 2970 + { 0x21, 0x00 }, /* STAR OF DAVID -> ... */ 2971 + { 0x46, 0x2A }, /* HEAVY CHEVRON SNOWFLAKE -> '*' */ 2972 + { 0x49, 0x00 }, /* BALLOON-SPOKED ASTERISK -> ... */ 2973 + { 0x4B, 0x2A }, /* HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK -> '*' */ 2974 + { 0x58, 0x7C }, /* LIGHT VERTICAL BAR -> '|' */ 2975 + { 0x5C, 0x27 }, /* HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT -> ''' */ 2976 + { 0x5D, 0x22 }, /* HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT -> '"' */ 2977 + { 0x5E, 0x22 }, /* HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT -> '"' */ 2978 + { 0x5F, 0x2C }, /* HEAVY LOW SINGLE COMMA QUOTATION MARK ORNAMENT -> ',' */ 2979 + { 0x62, 0x21 }, /* HEAVY EXCLAMATION MARK ORNAMENT -> '!' */ 2980 + { 0xE6, 0x5B }, /* MATHEMATICAL LEFT WHITE SQUARE BRACKET -> '[' */ 2981 + { 0xE8, 0x3C }, /* MATHEMATICAL LEFT ANGLE BRACKET -> '<' */ 2982 + /* Entries for page 0x28 */ 2983 + { 0x00, 0x20 }, /* BRAILLE PATTERN BLANK -> ' ' */ 2984 + { 0x01, 0x61 }, /* BRAILLE PATTERN DOTS-1 -> 'a' */ 2985 + { 0x02, 0x31 }, /* BRAILLE PATTERN DOTS-2 -> '1' */ 2986 + { 0x03, 0x62 }, /* BRAILLE PATTERN DOTS-12 -> 'b' */ 2987 + { 0x04, 0x27 }, /* BRAILLE PATTERN DOTS-3 -> ''' */ 2988 + { 0x05, 0x6B }, /* BRAILLE PATTERN DOTS-13 -> 'k' */ 2989 + { 0x06, 0x32 }, /* BRAILLE PATTERN DOTS-23 -> '2' */ 2990 + { 0x07, 0x6C }, /* BRAILLE PATTERN DOTS-123 -> 'l' */ 2991 + { 0x08, 0x40 }, /* BRAILLE PATTERN DOTS-4 -> '@' */ 2992 + { 0x09, 0x63 }, /* BRAILLE PATTERN DOTS-14 -> 'c' */ 2993 + { 0x0A, 0x69 }, /* BRAILLE PATTERN DOTS-24 -> 'i' */ 2994 + { 0x0B, 0x66 }, /* BRAILLE PATTERN DOTS-124 -> 'f' */ 2995 + { 0x0C, 0x2F }, /* BRAILLE PATTERN DOTS-34 -> '/' */ 2996 + { 0x0D, 0x6D }, /* BRAILLE PATTERN DOTS-134 -> 'm' */ 2997 + { 0x0E, 0x73 }, /* BRAILLE PATTERN DOTS-234 -> 's' */ 2998 + { 0x0F, 0x70 }, /* BRAILLE PATTERN DOTS-1234 -> 'p' */ 2999 + { 0x10, 0x22 }, /* BRAILLE PATTERN DOTS-5 -> '"' */ 3000 + { 0x11, 0x65 }, /* BRAILLE PATTERN DOTS-15 -> 'e' */ 3001 + { 0x12, 0x33 }, /* BRAILLE PATTERN DOTS-25 -> '3' */ 3002 + { 0x13, 0x68 }, /* BRAILLE PATTERN DOTS-125 -> 'h' */ 3003 + { 0x14, 0x39 }, /* BRAILLE PATTERN DOTS-35 -> '9' */ 3004 + { 0x15, 0x6F }, /* BRAILLE PATTERN DOTS-135 -> 'o' */ 3005 + { 0x16, 0x36 }, /* BRAILLE PATTERN DOTS-235 -> '6' */ 3006 + { 0x17, 0x72 }, /* BRAILLE PATTERN DOTS-1235 -> 'r' */ 3007 + { 0x18, 0x5E }, /* BRAILLE PATTERN DOTS-45 -> '^' */ 3008 + { 0x19, 0x64 }, /* BRAILLE PATTERN DOTS-145 -> 'd' */ 3009 + { 0x1A, 0x6A }, /* BRAILLE PATTERN DOTS-245 -> 'j' */ 3010 + { 0x1B, 0x67 }, /* BRAILLE PATTERN DOTS-1245 -> 'g' */ 3011 + { 0x1C, 0x3E }, /* BRAILLE PATTERN DOTS-345 -> '>' */ 3012 + { 0x1D, 0x6E }, /* BRAILLE PATTERN DOTS-1345 -> 'n' */ 3013 + { 0x1E, 0x74 }, /* BRAILLE PATTERN DOTS-2345 -> 't' */ 3014 + { 0x1F, 0x71 }, /* BRAILLE PATTERN DOTS-12345 -> 'q' */ 3015 + { 0x20, 0x2C }, /* BRAILLE PATTERN DOTS-6 -> ',' */ 3016 + { 0x21, 0x2A }, /* BRAILLE PATTERN DOTS-16 -> '*' */ 3017 + { 0x22, 0x35 }, /* BRAILLE PATTERN DOTS-26 -> '5' */ 3018 + { 0x23, 0x3C }, /* BRAILLE PATTERN DOTS-126 -> '<' */ 3019 + { 0x24, 0x2D }, /* BRAILLE PATTERN DOTS-36 -> '-' */ 3020 + { 0x25, 0x75 }, /* BRAILLE PATTERN DOTS-136 -> 'u' */ 3021 + { 0x26, 0x38 }, /* BRAILLE PATTERN DOTS-236 -> '8' */ 3022 + { 0x27, 0x76 }, /* BRAILLE PATTERN DOTS-1236 -> 'v' */ 3023 + { 0x28, 0x2E }, /* BRAILLE PATTERN DOTS-46 -> '.' */ 3024 + { 0x29, 0x25 }, /* BRAILLE PATTERN DOTS-146 -> '%' */ 3025 + { 0x2A, 0x5B }, /* BRAILLE PATTERN DOTS-246 -> '[' */ 3026 + { 0x2B, 0x24 }, /* BRAILLE PATTERN DOTS-1246 -> '$' */ 3027 + { 0x2C, 0x2B }, /* BRAILLE PATTERN DOTS-346 -> '+' */ 3028 + { 0x2D, 0x78 }, /* BRAILLE PATTERN DOTS-1346 -> 'x' */ 3029 + { 0x2E, 0x21 }, /* BRAILLE PATTERN DOTS-2346 -> '!' */ 3030 + { 0x2F, 0x26 }, /* BRAILLE PATTERN DOTS-12346 -> '&' */ 3031 + { 0x30, 0x3B }, /* BRAILLE PATTERN DOTS-56 -> ';' */ 3032 + { 0x31, 0x3A }, /* BRAILLE PATTERN DOTS-156 -> ':' */ 3033 + { 0x32, 0x34 }, /* BRAILLE PATTERN DOTS-256 -> '4' */ 3034 + { 0x33, 0x5C }, /* BRAILLE PATTERN DOTS-1256 -> '\' */ 3035 + { 0x34, 0x30 }, /* BRAILLE PATTERN DOTS-356 -> '0' */ 3036 + { 0x35, 0x7A }, /* BRAILLE PATTERN DOTS-1356 -> 'z' */ 3037 + { 0x36, 0x37 }, /* BRAILLE PATTERN DOTS-2356 -> '7' */ 3038 + { 0x37, 0x28 }, /* BRAILLE PATTERN DOTS-12356 -> '(' */ 3039 + { 0x38, 0x5F }, /* BRAILLE PATTERN DOTS-456 -> '_' */ 3040 + { 0x39, 0x3F }, /* BRAILLE PATTERN DOTS-1456 -> '?' */ 3041 + { 0x3A, 0x77 }, /* BRAILLE PATTERN DOTS-2456 -> 'w' */ 3042 + { 0x3B, 0x5D }, /* BRAILLE PATTERN DOTS-12456 -> ']' */ 3043 + { 0x3C, 0x23 }, /* BRAILLE PATTERN DOTS-3456 -> '#' */ 3044 + { 0x3D, 0x79 }, /* BRAILLE PATTERN DOTS-13456 -> 'y' */ 3045 + { 0x3E, 0x29 }, /* BRAILLE PATTERN DOTS-23456 -> ')' */ 3046 + { 0x3F, 0x3D }, /* BRAILLE PATTERN DOTS-123456 -> '=' */ 3047 + /* Entries for page 0x29 */ 3048 + { 0x83, 0x7B }, /* LEFT WHITE CURLY BRACKET -> '{' */ 3049 + /* Entries for page 0x2C */ 3050 + { 0x60, 0x4C }, /* LATIN CAPITAL LETTER L WITH DOUBLE BAR -> 'L' */ 3051 + { 0x61, 0x6C }, /* LATIN SMALL LETTER L WITH DOUBLE BAR -> 'l' */ 3052 + { 0x62, 0x4C }, /* LATIN CAPITAL LETTER L WITH MIDDLE TILDE -> 'L' */ 3053 + { 0x63, 0x50 }, /* LATIN CAPITAL LETTER P WITH STROKE -> 'P' */ 3054 + { 0x64, 0x52 }, /* LATIN CAPITAL LETTER R WITH TAIL -> 'R' */ 3055 + { 0x65, 0x61 }, /* LATIN SMALL LETTER A WITH STROKE -> 'a' */ 3056 + { 0x66, 0x74 }, /* LATIN SMALL LETTER T WITH DIAGONAL STROKE -> 't' */ 3057 + { 0x67, 0x48 }, /* LATIN CAPITAL LETTER H WITH DESCENDER -> 'H' */ 3058 + { 0x68, 0x68 }, /* LATIN SMALL LETTER H WITH DESCENDER -> 'h' */ 3059 + { 0x69, 0x4B }, /* LATIN CAPITAL LETTER K WITH DESCENDER -> 'K' */ 3060 + { 0x6A, 0x6B }, /* LATIN SMALL LETTER K WITH DESCENDER -> 'k' */ 3061 + { 0x6B, 0x5A }, /* LATIN CAPITAL LETTER Z WITH DESCENDER -> 'Z' */ 3062 + { 0x6C, 0x7A }, /* LATIN SMALL LETTER Z WITH DESCENDER -> 'z' */ 3063 + { 0x6E, 0x4D }, /* LATIN CAPITAL LETTER M WITH HOOK -> 'M' */ 3064 + { 0x6F, 0x41 }, /* LATIN CAPITAL LETTER TURNED A -> 'A' */ 3065 + /* Entries for page 0x2E */ 3066 + { 0x00, 0x72 }, /* RIGHT ANGLE SUBSTITUTION MARKER -> 'r' */ 3067 + { 0x06, 0x54 }, /* RAISED INTERPOLATION MARKER -> 'T' */ 3068 + { 0x09, 0x73 }, /* LEFT TRANSPOSITION BRACKET -> 's' */ 3069 + { 0x0C, 0x5C }, /* LEFT RAISED OMISSION BRACKET -> '\' */ 3070 + { 0x0D, 0x2F }, /* RIGHT RAISED OMISSION BRACKET -> '/' */ 3071 + { 0x12, 0x3E }, /* HYPODIASTOLE -> '>' */ 3072 + { 0x13, 0x25 }, /* DOTTED OBELOS -> '%' */ 3073 + { 0x16, 0x3E }, /* DOTTED RIGHT-POINTING ANGLE -> '>' */ 3074 + { 0x17, 0x3D }, /* DOUBLE OBLIQUE HYPHEN -> '=' */ 3075 + { 0x19, 0x2F }, /* PALM BRANCH -> '/' */ 3076 + { 0x1A, 0x2D }, /* HYPHEN WITH DIAERESIS -> '-' */ 3077 + { 0x1B, 0x7E }, /* TILDE WITH RING ABOVE -> '~' */ 3078 + { 0x1C, 0x5C }, /* LEFT LOW PARAPHRASE BRACKET -> '\' */ 3079 + { 0x1D, 0x2F }, /* RIGHT LOW PARAPHRASE BRACKET -> '/' */ 3080 + { 0x1E, 0x7E }, /* TILDE WITH DOT ABOVE -> '~' */ 3081 + { 0x1F, 0x7E }, /* TILDE WITH DOT BELOW -> '~' */ 3082 + { 0x2E, 0x3F }, /* REVERSED QUESTION MARK -> '?' */ 3083 + { 0x2F, 0x27 }, /* VERTICAL TILDE -> ''' */ 3084 + { 0x30, 0x6F }, /* RING POINT -> 'o' */ 3085 + { 0x31, 0x2E }, /* WORD SEPARATOR MIDDLE DOT -> '.' */ 3086 + { 0x32, 0x2C }, /* TURNED COMMA -> ',' */ 3087 + { 0x33, 0x2E }, /* RAISED DOT -> '.' */ 3088 + { 0x34, 0x2C }, /* RAISED COMMA -> ',' */ 3089 + { 0x35, 0x3B }, /* TURNED SEMICOLON -> ';' */ 3090 + { 0x3C, 0x78 }, /* STENOGRAPHIC FULL STOP -> 'x' */ 3091 + { 0x3D, 0x7C }, /* VERTICAL SIX DOTS -> '|' */ 3092 + { 0x40, 0x3D }, /* DOUBLE HYPHEN -> '=' */ 3093 + { 0x41, 0x2C }, /* REVERSED COMMA -> ',' */ 3094 + { 0x42, 0x22 }, /* DOUBLE LOW-REVERSED-9 QUOTATION MARK -> '"' */ 3095 + /* Entries for page 0x30 */ 3096 + { 0x00, 0x20 }, /* IDEOGRAPHIC SPACE -> ' ' */ 3097 + { 0x03, 0x22 }, /* DITTO MARK -> '"' */ 3098 + { 0x05, 0x22 }, /* IDEOGRAPHIC ITERATION MARK -> '"' */ 3099 + { 0x06, 0x2F }, /* IDEOGRAPHIC CLOSING MARK -> '/' */ 3100 + { 0x07, 0x30 }, /* IDEOGRAPHIC NUMBER ZERO -> '0' */ 3101 + { 0x08, 0x3C }, /* LEFT ANGLE BRACKET -> '<' */ 3102 + { 0x0C, 0x5B }, /* LEFT CORNER BRACKET -> '[' */ 3103 + { 0x0E, 0x7B }, /* LEFT WHITE CORNER BRACKET -> '{' */ 3104 + { 0x12, 0x40 }, /* POSTAL MARK -> '@' */ 3105 + { 0x14, 0x5B }, /* LEFT TORTOISE SHELL BRACKET -> '[' */ 3106 + { 0x20, 0x40 }, /* POSTAL MARK FACE -> '@' */ 3107 + { 0x21, 0x31 }, /* HANGZHOU NUMERAL ONE -> '1' */ 3108 + { 0x22, 0x32 }, /* HANGZHOU NUMERAL TWO -> '2' */ 3109 + { 0x23, 0x33 }, /* HANGZHOU NUMERAL THREE -> '3' */ 3110 + { 0x24, 0x34 }, /* HANGZHOU NUMERAL FOUR -> '4' */ 3111 + { 0x25, 0x35 }, /* HANGZHOU NUMERAL FIVE -> '5' */ 3112 + { 0x26, 0x36 }, /* HANGZHOU NUMERAL SIX -> '6' */ 3113 + { 0x27, 0x37 }, /* HANGZHOU NUMERAL SEVEN -> '7' */ 3114 + { 0x28, 0x38 }, /* HANGZHOU NUMERAL EIGHT -> '8' */ 3115 + { 0x29, 0x39 }, /* HANGZHOU NUMERAL NINE -> '9' */ 3116 + { 0x30, 0x7E }, /* WAVY DASH -> '~' */ 3117 + { 0x31, 0x00 }, /* VERTICAL KANA REPEAT MARK -> ... */ 3118 + { 0x34, 0x2B }, /* VERTICAL KANA REPEAT WITH VOICED SOUND MARK UPPER HALF -> '+' */ 3119 + { 0x36, 0x40 }, /* CIRCLED POSTAL MARK -> '@' */ 3120 + { 0x41, 0x61 }, /* HIRAGANA LETTER SMALL A -> 'a' */ 3121 + { 0x42, 0x61 }, /* HIRAGANA LETTER A -> 'a' */ 3122 + { 0x43, 0x69 }, /* HIRAGANA LETTER SMALL I -> 'i' */ 3123 + { 0x44, 0x69 }, /* HIRAGANA LETTER I -> 'i' */ 3124 + { 0x45, 0x75 }, /* HIRAGANA LETTER SMALL U -> 'u' */ 3125 + { 0x46, 0x75 }, /* HIRAGANA LETTER U -> 'u' */ 3126 + { 0x47, 0x65 }, /* HIRAGANA LETTER SMALL E -> 'e' */ 3127 + { 0x48, 0x65 }, /* HIRAGANA LETTER E -> 'e' */ 3128 + { 0x49, 0x6F }, /* HIRAGANA LETTER SMALL O -> 'o' */ 3129 + { 0x4A, 0x6F }, /* HIRAGANA LETTER O -> 'o' */ 3130 + { 0x93, 0x6E }, /* HIRAGANA LETTER N -> 'n' */ 3131 + { 0x9D, 0x22 }, /* HIRAGANA ITERATION MARK -> '"' */ 3132 + { 0x9E, 0x22 }, /* HIRAGANA VOICED ITERATION MARK -> '"' */ 3133 + { 0xA0, 0x3D }, /* KATAKANA-HIRAGANA DOUBLE HYPHEN -> '=' */ 3134 + { 0xA1, 0x61 }, /* KATAKANA LETTER SMALL A -> 'a' */ 3135 + { 0xA2, 0x61 }, /* KATAKANA LETTER A -> 'a' */ 3136 + { 0xA3, 0x69 }, /* KATAKANA LETTER SMALL I -> 'i' */ 3137 + { 0xA4, 0x69 }, /* KATAKANA LETTER I -> 'i' */ 3138 + { 0xA5, 0x75 }, /* KATAKANA LETTER SMALL U -> 'u' */ 3139 + { 0xA6, 0x75 }, /* KATAKANA LETTER U -> 'u' */ 3140 + { 0xA7, 0x65 }, /* KATAKANA LETTER SMALL E -> 'e' */ 3141 + { 0xA8, 0x65 }, /* KATAKANA LETTER E -> 'e' */ 3142 + { 0xA9, 0x6F }, /* KATAKANA LETTER SMALL O -> 'o' */ 3143 + { 0xAA, 0x6F }, /* KATAKANA LETTER O -> 'o' */ 3144 + { 0xF3, 0x6E }, /* KATAKANA LETTER N -> 'n' */ 3145 + { 0xFB, 0x2A }, /* KATAKANA MIDDLE DOT -> '*' */ 3146 + { 0xFC, 0x2D }, /* KATAKANA-HIRAGANA PROLONGED SOUND MARK -> '-' */ 3147 + { 0xFD, 0x22 }, /* KATAKANA ITERATION MARK -> '"' */ 3148 + { 0xFE, 0x22 }, /* KATAKANA VOICED ITERATION MARK -> '"' */ 3149 + /* Entries for page 0x31 */ 3150 + { 0x05, 0x42 }, /* BOPOMOFO LETTER B -> 'B' */ 3151 + { 0x06, 0x50 }, /* BOPOMOFO LETTER P -> 'P' */ 3152 + { 0x07, 0x4D }, /* BOPOMOFO LETTER M -> 'M' */ 3153 + { 0x08, 0x46 }, /* BOPOMOFO LETTER F -> 'F' */ 3154 + { 0x09, 0x44 }, /* BOPOMOFO LETTER D -> 'D' */ 3155 + { 0x0A, 0x54 }, /* BOPOMOFO LETTER T -> 'T' */ 3156 + { 0x0B, 0x4E }, /* BOPOMOFO LETTER N -> 'N' */ 3157 + { 0x0C, 0x4C }, /* BOPOMOFO LETTER L -> 'L' */ 3158 + { 0x0D, 0x47 }, /* BOPOMOFO LETTER G -> 'G' */ 3159 + { 0x0E, 0x4B }, /* BOPOMOFO LETTER K -> 'K' */ 3160 + { 0x0F, 0x48 }, /* BOPOMOFO LETTER H -> 'H' */ 3161 + { 0x10, 0x4A }, /* BOPOMOFO LETTER J -> 'J' */ 3162 + { 0x11, 0x51 }, /* BOPOMOFO LETTER Q -> 'Q' */ 3163 + { 0x12, 0x58 }, /* BOPOMOFO LETTER X -> 'X' */ 3164 + { 0x16, 0x52 }, /* BOPOMOFO LETTER R -> 'R' */ 3165 + { 0x17, 0x5A }, /* BOPOMOFO LETTER Z -> 'Z' */ 3166 + { 0x18, 0x43 }, /* BOPOMOFO LETTER C -> 'C' */ 3167 + { 0x19, 0x53 }, /* BOPOMOFO LETTER S -> 'S' */ 3168 + { 0x1A, 0x41 }, /* BOPOMOFO LETTER A -> 'A' */ 3169 + { 0x1B, 0x4F }, /* BOPOMOFO LETTER O -> 'O' */ 3170 + { 0x1C, 0x45 }, /* BOPOMOFO LETTER E -> 'E' */ 3171 + { 0x27, 0x49 }, /* BOPOMOFO LETTER I -> 'I' */ 3172 + { 0x28, 0x55 }, /* BOPOMOFO LETTER U -> 'U' */ 3173 + { 0x2A, 0x56 }, /* BOPOMOFO LETTER V -> 'V' */ 3174 + { 0x31, 0x67 }, /* HANGUL LETTER KIYEOK -> 'g' */ 3175 + { 0x34, 0x6E }, /* HANGUL LETTER NIEUN -> 'n' */ 3176 + { 0x37, 0x64 }, /* HANGUL LETTER TIKEUT -> 'd' */ 3177 + { 0x39, 0x72 }, /* HANGUL LETTER RIEUL -> 'r' */ 3178 + { 0x41, 0x6D }, /* HANGUL LETTER MIEUM -> 'm' */ 3179 + { 0x42, 0x62 }, /* HANGUL LETTER PIEUP -> 'b' */ 3180 + { 0x45, 0x73 }, /* HANGUL LETTER SIOS -> 's' */ 3181 + { 0x48, 0x6A }, /* HANGUL LETTER CIEUC -> 'j' */ 3182 + { 0x4A, 0x63 }, /* HANGUL LETTER CHIEUCH -> 'c' */ 3183 + { 0x4B, 0x6B }, /* HANGUL LETTER KHIEUKH -> 'k' */ 3184 + { 0x4C, 0x74 }, /* HANGUL LETTER THIEUTH -> 't' */ 3185 + { 0x4D, 0x70 }, /* HANGUL LETTER PHIEUPH -> 'p' */ 3186 + { 0x4E, 0x68 }, /* HANGUL LETTER HIEUH -> 'h' */ 3187 + { 0x4F, 0x61 }, /* HANGUL LETTER A -> 'a' */ 3188 + { 0x54, 0x65 }, /* HANGUL LETTER E -> 'e' */ 3189 + { 0x57, 0x6F }, /* HANGUL LETTER O -> 'o' */ 3190 + { 0x5C, 0x75 }, /* HANGUL LETTER U -> 'u' */ 3191 + { 0x63, 0x69 }, /* HANGUL LETTER I -> 'i' */ 3192 + { 0x7F, 0x5A }, /* HANGUL LETTER PANSIOS -> 'Z' */ 3193 + { 0x81, 0x4E }, /* HANGUL LETTER YESIEUNG -> 'N' */ 3194 + { 0x86, 0x51 }, /* HANGUL LETTER YEORINHIEUH -> 'Q' */ 3195 + { 0x8D, 0x55 }, /* HANGUL LETTER ARAEA -> 'U' */ 3196 + { 0xB4, 0x50 }, /* BOPOMOFO FINAL LETTER P -> 'P' */ 3197 + { 0xB5, 0x54 }, /* BOPOMOFO FINAL LETTER T -> 'T' */ 3198 + { 0xB6, 0x4B }, /* BOPOMOFO FINAL LETTER K -> 'K' */ 3199 + { 0xB7, 0x48 }, /* BOPOMOFO FINAL LETTER H -> 'H' */ 3200 + /* Entries for page 0x32 */ 3201 + { 0xD0, 0x61 }, /* CIRCLED KATAKANA A -> 'a' */ 3202 + { 0xD1, 0x69 }, /* CIRCLED KATAKANA I -> 'i' */ 3203 + { 0xD2, 0x75 }, /* CIRCLED KATAKANA U -> 'u' */ 3204 + { 0xD3, 0x75 }, /* CIRCLED KATAKANA E -> 'u' */ 3205 + { 0xD4, 0x6F }, /* CIRCLED KATAKANA O -> 'o' */ 3206 + /* Entries for page 0xA0 */ 3207 + { 0x02, 0x69 }, /* YI SYLLABLE I -> 'i' */ 3208 + { 0x0A, 0x61 }, /* YI SYLLABLE A -> 'a' */ 3209 + { 0x11, 0x6F }, /* YI SYLLABLE O -> 'o' */ 3210 + { 0x14, 0x65 }, /* YI SYLLABLE E -> 'e' */ 3211 + /* Entries for page 0xC5 */ 3212 + { 0x44, 0x61 }, /* HANGUL SYLLABLE A -> 'a' */ 3213 + { 0xD0, 0x65 }, /* HANGUL SYLLABLE E -> 'e' */ 3214 + /* Entries for page 0xC6 */ 3215 + { 0x24, 0x6F }, /* HANGUL SYLLABLE O -> 'o' */ 3216 + { 0xB0, 0x75 }, /* HANGUL SYLLABLE U -> 'u' */ 3217 + /* Entries for page 0xC7 */ 3218 + { 0x74, 0x69 }, /* HANGUL SYLLABLE I -> 'i' */ 3219 + /* Entries for page 0xFB */ 3220 + { 0x1D, 0x69 }, /* HEBREW LETTER YOD WITH HIRIQ -> 'i' */ 3221 + { 0x20, 0x60 }, /* HEBREW LETTER ALTERNATIVE AYIN -> '`' */ 3222 + { 0x21, 0x41 }, /* HEBREW LETTER WIDE ALEF -> 'A' */ 3223 + { 0x22, 0x64 }, /* HEBREW LETTER WIDE DALET -> 'd' */ 3224 + { 0x23, 0x68 }, /* HEBREW LETTER WIDE HE -> 'h' */ 3225 + { 0x25, 0x6C }, /* HEBREW LETTER WIDE LAMED -> 'l' */ 3226 + { 0x26, 0x6D }, /* HEBREW LETTER WIDE FINAL MEM -> 'm' */ 3227 + { 0x27, 0x72 }, /* HEBREW LETTER WIDE RESH -> 'r' */ 3228 + { 0x28, 0x74 }, /* HEBREW LETTER WIDE TAV -> 't' */ 3229 + { 0x29, 0x2B }, /* HEBREW LETTER ALTERNATIVE PLUS SIGN -> '+' */ 3230 + { 0x2B, 0x53 }, /* HEBREW LETTER SHIN WITH SIN DOT -> 'S' */ 3231 + { 0x2D, 0x53 }, /* HEBREW LETTER SHIN WITH DAGESH AND SIN DOT -> 'S' */ 3232 + { 0x2E, 0x61 }, /* HEBREW LETTER ALEF WITH PATAH -> 'a' */ 3233 + { 0x2F, 0x61 }, /* HEBREW LETTER ALEF WITH QAMATS -> 'a' */ 3234 + { 0x30, 0x41 }, /* HEBREW LETTER ALEF WITH MAPIQ -> 'A' */ 3235 + { 0x31, 0x62 }, /* HEBREW LETTER BET WITH DAGESH -> 'b' */ 3236 + { 0x32, 0x67 }, /* HEBREW LETTER GIMEL WITH DAGESH -> 'g' */ 3237 + { 0x33, 0x64 }, /* HEBREW LETTER DALET WITH DAGESH -> 'd' */ 3238 + { 0x34, 0x68 }, /* HEBREW LETTER HE WITH MAPIQ -> 'h' */ 3239 + { 0x35, 0x76 }, /* HEBREW LETTER VAV WITH DAGESH -> 'v' */ 3240 + { 0x36, 0x7A }, /* HEBREW LETTER ZAYIN WITH DAGESH -> 'z' */ 3241 + { 0x38, 0x74 }, /* HEBREW LETTER TET WITH DAGESH -> 't' */ 3242 + { 0x39, 0x79 }, /* HEBREW LETTER YOD WITH DAGESH -> 'y' */ 3243 + { 0x3C, 0x6C }, /* HEBREW LETTER LAMED WITH DAGESH -> 'l' */ 3244 + { 0x3E, 0x6D }, /* HEBREW LETTER MEM WITH DAGESH -> 'm' */ 3245 + { 0x40, 0x6E }, /* HEBREW LETTER NUN WITH DAGESH -> 'n' */ 3246 + { 0x41, 0x73 }, /* HEBREW LETTER SAMEKH WITH DAGESH -> 's' */ 3247 + { 0x43, 0x70 }, /* HEBREW LETTER FINAL PE WITH DAGESH -> 'p' */ 3248 + { 0x44, 0x70 }, /* HEBREW LETTER PE WITH DAGESH -> 'p' */ 3249 + { 0x47, 0x6B }, /* HEBREW LETTER QOF WITH DAGESH -> 'k' */ 3250 + { 0x48, 0x72 }, /* HEBREW LETTER RESH WITH DAGESH -> 'r' */ 3251 + { 0x4A, 0x74 }, /* HEBREW LETTER TAV WITH DAGESH -> 't' */ 3252 + { 0x4B, 0x6F }, /* HEBREW LETTER VAV WITH HOLAM -> 'o' */ 3253 + { 0x4C, 0x76 }, /* HEBREW LETTER BET WITH RAFE -> 'v' */ 3254 + { 0x4E, 0x66 }, /* HEBREW LETTER PE WITH RAFE -> 'f' */ 3255 + /* Entries for page 0xFE */ 3256 + { 0x23, 0x7E }, /* COMBINING DOUBLE TILDE RIGHT HALF -> '~' */ 3257 + { 0x32, 0x2D }, /* PRESENTATION FORM FOR VERTICAL EN DASH -> '-' */ 3258 + { 0x33, 0x5F }, /* PRESENTATION FORM FOR VERTICAL LOW LINE -> '_' */ 3259 + { 0x34, 0x5F }, /* PRESENTATION FORM FOR VERTICAL WAVY LOW LINE -> '_' */ 3260 + { 0x35, 0x28 }, /* PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS -> '(' */ 3261 + { 0x37, 0x7B }, /* PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET -> '{' */ 3262 + { 0x39, 0x5B }, /* PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET -> '[' */ 3263 + { 0x3F, 0x3C }, /* PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET -> '<' */ 3264 + { 0x41, 0x5B }, /* PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET -> '[' */ 3265 + { 0x43, 0x7B }, /* PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET -> '{' */ 3266 + { 0x44, 0x7D }, /* PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET -> '}' */ 3267 + { 0x50, 0x2C }, /* SMALL COMMA -> ',' */ 3268 + { 0x51, 0x2C }, /* SMALL IDEOGRAPHIC COMMA -> ',' */ 3269 + { 0x52, 0x2E }, /* SMALL FULL STOP -> '.' */ 3270 + { 0x54, 0x3B }, /* SMALL SEMICOLON -> ';' */ 3271 + { 0x55, 0x3A }, /* SMALL COLON -> ':' */ 3272 + { 0x56, 0x3F }, /* SMALL QUESTION MARK -> '?' */ 3273 + { 0x57, 0x21 }, /* SMALL EXCLAMATION MARK -> '!' */ 3274 + { 0x58, 0x2D }, /* SMALL EM DASH -> '-' */ 3275 + { 0x59, 0x28 }, /* SMALL LEFT PARENTHESIS -> '(' */ 3276 + { 0x5A, 0x29 }, /* SMALL RIGHT PARENTHESIS -> ')' */ 3277 + { 0x5B, 0x7B }, /* SMALL LEFT CURLY BRACKET -> '{' */ 3278 + { 0x5C, 0x7D }, /* SMALL RIGHT CURLY BRACKET -> '}' */ 3279 + { 0x5D, 0x7B }, /* SMALL LEFT TORTOISE SHELL BRACKET -> '{' */ 3280 + { 0x5E, 0x7D }, /* SMALL RIGHT TORTOISE SHELL BRACKET -> '}' */ 3281 + { 0x5F, 0x23 }, /* SMALL NUMBER SIGN -> '#' */ 3282 + { 0x60, 0x26 }, /* SMALL AMPERSAND -> '&' */ 3283 + { 0x61, 0x2A }, /* SMALL ASTERISK -> '*' */ 3284 + { 0x62, 0x2B }, /* SMALL PLUS SIGN -> '+' */ 3285 + { 0x63, 0x2D }, /* SMALL HYPHEN-MINUS -> '-' */ 3286 + { 0x64, 0x3C }, /* SMALL LESS-THAN SIGN -> '<' */ 3287 + { 0x65, 0x3E }, /* SMALL GREATER-THAN SIGN -> '>' */ 3288 + { 0x66, 0x3D }, /* SMALL EQUALS SIGN -> '=' */ 3289 + { 0x68, 0x5C }, /* SMALL REVERSE SOLIDUS -> '\' */ 3290 + { 0x69, 0x24 }, /* SMALL DOLLAR SIGN -> '$' */ 3291 + { 0x6A, 0x25 }, /* SMALL PERCENT SIGN -> '%' */ 3292 + { 0x6B, 0x40 }, /* SMALL COMMERCIAL AT -> '@' */ 3293 + /* Entries for page 0xFF */ 3294 + { 0x61, 0x2E }, /* HALFWIDTH IDEOGRAPHIC FULL STOP -> '.' */ 3295 + { 0x62, 0x5B }, /* HALFWIDTH LEFT CORNER BRACKET -> '[' */ 3296 + { 0x63, 0x5D }, /* HALFWIDTH RIGHT CORNER BRACKET -> ']' */ 3297 + { 0x64, 0x2C }, /* HALFWIDTH IDEOGRAPHIC COMMA -> ',' */ 3298 + { 0x65, 0x2A }, /* HALFWIDTH KATAKANA MIDDLE DOT -> '*' */ 3299 + { 0x67, 0x61 }, /* HALFWIDTH KATAKANA LETTER SMALL A -> 'a' */ 3300 + { 0x68, 0x69 }, /* HALFWIDTH KATAKANA LETTER SMALL I -> 'i' */ 3301 + { 0x69, 0x75 }, /* HALFWIDTH KATAKANA LETTER SMALL U -> 'u' */ 3302 + { 0x6A, 0x65 }, /* HALFWIDTH KATAKANA LETTER SMALL E -> 'e' */ 3303 + { 0x6B, 0x6F }, /* HALFWIDTH KATAKANA LETTER SMALL O -> 'o' */ 3304 + { 0x70, 0x2B }, /* HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK -> '+' */ 3305 + { 0x71, 0x61 }, /* HALFWIDTH KATAKANA LETTER A -> 'a' */ 3306 + { 0x72, 0x69 }, /* HALFWIDTH KATAKANA LETTER I -> 'i' */ 3307 + { 0x73, 0x75 }, /* HALFWIDTH KATAKANA LETTER U -> 'u' */ 3308 + { 0x74, 0x65 }, /* HALFWIDTH KATAKANA LETTER E -> 'e' */ 3309 + { 0x75, 0x6F }, /* HALFWIDTH KATAKANA LETTER O -> 'o' */ 3310 + { 0x9D, 0x6E }, /* HALFWIDTH KATAKANA LETTER N -> 'n' */ 3311 + { 0x9E, 0x3A }, /* HALFWIDTH KATAKANA VOICED SOUND MARK -> ':' */ 3312 + { 0x9F, 0x3B }, /* HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK -> ';' */ 3313 + { 0xA1, 0x67 }, /* HALFWIDTH HANGUL LETTER KIYEOK -> 'g' */ 3314 + { 0xA4, 0x6E }, /* HALFWIDTH HANGUL LETTER NIEUN -> 'n' */ 3315 + { 0xA7, 0x64 }, /* HALFWIDTH HANGUL LETTER TIKEUT -> 'd' */ 3316 + { 0xA9, 0x72 }, /* HALFWIDTH HANGUL LETTER RIEUL -> 'r' */ 3317 + { 0xB1, 0x6D }, /* HALFWIDTH HANGUL LETTER MIEUM -> 'm' */ 3318 + { 0xB2, 0x62 }, /* HALFWIDTH HANGUL LETTER PIEUP -> 'b' */ 3319 + { 0xB5, 0x73 }, /* HALFWIDTH HANGUL LETTER SIOS -> 's' */ 3320 + { 0xB8, 0x6A }, /* HALFWIDTH HANGUL LETTER CIEUC -> 'j' */ 3321 + { 0xBA, 0x63 }, /* HALFWIDTH HANGUL LETTER CHIEUCH -> 'c' */ 3322 + { 0xBB, 0x6B }, /* HALFWIDTH HANGUL LETTER KHIEUKH -> 'k' */ 3323 + { 0xBC, 0x74 }, /* HALFWIDTH HANGUL LETTER THIEUTH -> 't' */ 3324 + { 0xBD, 0x70 }, /* HALFWIDTH HANGUL LETTER PHIEUPH -> 'p' */ 3325 + { 0xBE, 0x68 }, /* HALFWIDTH HANGUL LETTER HIEUH -> 'h' */ 3326 + { 0xC2, 0x61 }, /* HALFWIDTH HANGUL LETTER A -> 'a' */ 3327 + { 0xC7, 0x65 }, /* HALFWIDTH HANGUL LETTER E -> 'e' */ 3328 + { 0xCC, 0x6F }, /* HALFWIDTH HANGUL LETTER O -> 'o' */ 3329 + { 0xD3, 0x75 }, /* HALFWIDTH HANGUL LETTER U -> 'u' */ 3330 + { 0xDC, 0x69 }, /* HALFWIDTH HANGUL LETTER I -> 'i' */ 3331 + { 0xE2, 0x21 }, /* FULLWIDTH NOT SIGN -> '!' */ 3332 + { 0xE3, 0x2D }, /* FULLWIDTH MACRON -> '-' */ 3333 + { 0xE4, 0x7C }, /* FULLWIDTH BROKEN BAR -> '|' */ 3334 + { 0xE8, 0x7C }, /* HALFWIDTH FORMS LIGHT VERTICAL -> '|' */ 3335 + { 0xE9, 0x3C }, /* HALFWIDTH LEFTWARDS ARROW -> '<' */ 3336 + { 0xEA, 0x5E }, /* HALFWIDTH UPWARDS ARROW -> '^' */ 3337 + { 0xEB, 0x3E }, /* HALFWIDTH RIGHTWARDS ARROW -> '>' */ 3338 + { 0xEC, 0x76 }, /* HALFWIDTH DOWNWARDS ARROW -> 'v' */ 3339 + { 0xED, 0x23 }, /* HALFWIDTH BLACK SQUARE -> '#' */ 3340 + { 0xEE, 0x4F }, /* HALFWIDTH WHITE CIRCLE -> 'O' */ 3341 + { 0xF9, 0x7B }, /* INTERLINEAR ANNOTATION ANCHOR -> '{' */ 3342 + { 0xFA, 0x7C }, /* INTERLINEAR ANNOTATION SEPARATOR -> '|' */ 3343 + { 0xFB, 0x7D }, /* INTERLINEAR ANNOTATION TERMINATOR -> '}' */ 3344 + }; 3345 + 3346 + #define UCS_PAGE_ENTRY_RANGE_MARKER 0
+102
drivers/tty/vt/ucs_recompose_table.h_shipped
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * ucs_recompose_table.h - Unicode character recomposition 4 + * 5 + * Auto-generated by gen_ucs_recompose_table.py 6 + * 7 + * Unicode Version: 16.0.0 8 + * 9 + * This file contains a table with most commonly used Latin, Greek, and 10 + * Cyrillic recomposition pairs only (71 entries). To generate a table with 11 + * all possible recomposition pairs from the Unicode BMP (1000 entries) 12 + * instead, run: 13 + * 14 + * python gen_ucs_recompose_table.py --full 15 + */ 16 + 17 + /* 18 + * Table of most commonly used Latin, Greek, and Cyrillic recomposition pairs only 19 + * Sorted by base character and then combining mark for binary search 20 + */ 21 + static const struct ucs_recomposition ucs_recomposition_table[] = { 22 + { 0x0041, 0x0300, 0x00C0 }, /* LATIN CAPITAL LETTER A + COMBINING GRAVE ACCENT = LATIN CAPITAL LETTER A WITH GRAVE */ 23 + { 0x0041, 0x0301, 0x00C1 }, /* LATIN CAPITAL LETTER A + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER A WITH ACUTE */ 24 + { 0x0041, 0x0302, 0x00C2 }, /* LATIN CAPITAL LETTER A + COMBINING CIRCUMFLEX ACCENT = LATIN CAPITAL LETTER A WITH CIRCUMFLEX */ 25 + { 0x0041, 0x0303, 0x00C3 }, /* LATIN CAPITAL LETTER A + COMBINING TILDE = LATIN CAPITAL LETTER A WITH TILDE */ 26 + { 0x0041, 0x0308, 0x00C4 }, /* LATIN CAPITAL LETTER A + COMBINING DIAERESIS = LATIN CAPITAL LETTER A WITH DIAERESIS */ 27 + { 0x0041, 0x030A, 0x00C5 }, /* LATIN CAPITAL LETTER A + COMBINING RING ABOVE = LATIN CAPITAL LETTER A WITH RING ABOVE */ 28 + { 0x0043, 0x0327, 0x00C7 }, /* LATIN CAPITAL LETTER C + COMBINING CEDILLA = LATIN CAPITAL LETTER C WITH CEDILLA */ 29 + { 0x0045, 0x0300, 0x00C8 }, /* LATIN CAPITAL LETTER E + COMBINING GRAVE ACCENT = LATIN CAPITAL LETTER E WITH GRAVE */ 30 + { 0x0045, 0x0301, 0x00C9 }, /* LATIN CAPITAL LETTER E + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER E WITH ACUTE */ 31 + { 0x0045, 0x0302, 0x00CA }, /* LATIN CAPITAL LETTER E + COMBINING CIRCUMFLEX ACCENT = LATIN CAPITAL LETTER E WITH CIRCUMFLEX */ 32 + { 0x0045, 0x0308, 0x00CB }, /* LATIN CAPITAL LETTER E + COMBINING DIAERESIS = LATIN CAPITAL LETTER E WITH DIAERESIS */ 33 + { 0x0049, 0x0300, 0x00CC }, /* LATIN CAPITAL LETTER I + COMBINING GRAVE ACCENT = LATIN CAPITAL LETTER I WITH GRAVE */ 34 + { 0x0049, 0x0301, 0x00CD }, /* LATIN CAPITAL LETTER I + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER I WITH ACUTE */ 35 + { 0x0049, 0x0302, 0x00CE }, /* LATIN CAPITAL LETTER I + COMBINING CIRCUMFLEX ACCENT = LATIN CAPITAL LETTER I WITH CIRCUMFLEX */ 36 + { 0x0049, 0x0308, 0x00CF }, /* LATIN CAPITAL LETTER I + COMBINING DIAERESIS = LATIN CAPITAL LETTER I WITH DIAERESIS */ 37 + { 0x004E, 0x0303, 0x00D1 }, /* LATIN CAPITAL LETTER N + COMBINING TILDE = LATIN CAPITAL LETTER N WITH TILDE */ 38 + { 0x004F, 0x0300, 0x00D2 }, /* LATIN CAPITAL LETTER O + COMBINING GRAVE ACCENT = LATIN CAPITAL LETTER O WITH GRAVE */ 39 + { 0x004F, 0x0301, 0x00D3 }, /* LATIN CAPITAL LETTER O + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER O WITH ACUTE */ 40 + { 0x004F, 0x0302, 0x00D4 }, /* LATIN CAPITAL LETTER O + COMBINING CIRCUMFLEX ACCENT = LATIN CAPITAL LETTER O WITH CIRCUMFLEX */ 41 + { 0x004F, 0x0303, 0x00D5 }, /* LATIN CAPITAL LETTER O + COMBINING TILDE = LATIN CAPITAL LETTER O WITH TILDE */ 42 + { 0x004F, 0x0308, 0x00D6 }, /* LATIN CAPITAL LETTER O + COMBINING DIAERESIS = LATIN CAPITAL LETTER O WITH DIAERESIS */ 43 + { 0x0055, 0x0300, 0x00D9 }, /* LATIN CAPITAL LETTER U + COMBINING GRAVE ACCENT = LATIN CAPITAL LETTER U WITH GRAVE */ 44 + { 0x0055, 0x0301, 0x00DA }, /* LATIN CAPITAL LETTER U + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER U WITH ACUTE */ 45 + { 0x0055, 0x0302, 0x00DB }, /* LATIN CAPITAL LETTER U + COMBINING CIRCUMFLEX ACCENT = LATIN CAPITAL LETTER U WITH CIRCUMFLEX */ 46 + { 0x0055, 0x0308, 0x00DC }, /* LATIN CAPITAL LETTER U + COMBINING DIAERESIS = LATIN CAPITAL LETTER U WITH DIAERESIS */ 47 + { 0x0059, 0x0301, 0x00DD }, /* LATIN CAPITAL LETTER Y + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER Y WITH ACUTE */ 48 + { 0x0061, 0x0300, 0x00E0 }, /* LATIN SMALL LETTER A + COMBINING GRAVE ACCENT = LATIN SMALL LETTER A WITH GRAVE */ 49 + { 0x0061, 0x0301, 0x00E1 }, /* LATIN SMALL LETTER A + COMBINING ACUTE ACCENT = LATIN SMALL LETTER A WITH ACUTE */ 50 + { 0x0061, 0x0302, 0x00E2 }, /* LATIN SMALL LETTER A + COMBINING CIRCUMFLEX ACCENT = LATIN SMALL LETTER A WITH CIRCUMFLEX */ 51 + { 0x0061, 0x0303, 0x00E3 }, /* LATIN SMALL LETTER A + COMBINING TILDE = LATIN SMALL LETTER A WITH TILDE */ 52 + { 0x0061, 0x0308, 0x00E4 }, /* LATIN SMALL LETTER A + COMBINING DIAERESIS = LATIN SMALL LETTER A WITH DIAERESIS */ 53 + { 0x0061, 0x030A, 0x00E5 }, /* LATIN SMALL LETTER A + COMBINING RING ABOVE = LATIN SMALL LETTER A WITH RING ABOVE */ 54 + { 0x0063, 0x0327, 0x00E7 }, /* LATIN SMALL LETTER C + COMBINING CEDILLA = LATIN SMALL LETTER C WITH CEDILLA */ 55 + { 0x0065, 0x0300, 0x00E8 }, /* LATIN SMALL LETTER E + COMBINING GRAVE ACCENT = LATIN SMALL LETTER E WITH GRAVE */ 56 + { 0x0065, 0x0301, 0x00E9 }, /* LATIN SMALL LETTER E + COMBINING ACUTE ACCENT = LATIN SMALL LETTER E WITH ACUTE */ 57 + { 0x0065, 0x0302, 0x00EA }, /* LATIN SMALL LETTER E + COMBINING CIRCUMFLEX ACCENT = LATIN SMALL LETTER E WITH CIRCUMFLEX */ 58 + { 0x0065, 0x0308, 0x00EB }, /* LATIN SMALL LETTER E + COMBINING DIAERESIS = LATIN SMALL LETTER E WITH DIAERESIS */ 59 + { 0x0069, 0x0300, 0x00EC }, /* LATIN SMALL LETTER I + COMBINING GRAVE ACCENT = LATIN SMALL LETTER I WITH GRAVE */ 60 + { 0x0069, 0x0301, 0x00ED }, /* LATIN SMALL LETTER I + COMBINING ACUTE ACCENT = LATIN SMALL LETTER I WITH ACUTE */ 61 + { 0x0069, 0x0302, 0x00EE }, /* LATIN SMALL LETTER I + COMBINING CIRCUMFLEX ACCENT = LATIN SMALL LETTER I WITH CIRCUMFLEX */ 62 + { 0x0069, 0x0308, 0x00EF }, /* LATIN SMALL LETTER I + COMBINING DIAERESIS = LATIN SMALL LETTER I WITH DIAERESIS */ 63 + { 0x006E, 0x0303, 0x00F1 }, /* LATIN SMALL LETTER N + COMBINING TILDE = LATIN SMALL LETTER N WITH TILDE */ 64 + { 0x006F, 0x0300, 0x00F2 }, /* LATIN SMALL LETTER O + COMBINING GRAVE ACCENT = LATIN SMALL LETTER O WITH GRAVE */ 65 + { 0x006F, 0x0301, 0x00F3 }, /* LATIN SMALL LETTER O + COMBINING ACUTE ACCENT = LATIN SMALL LETTER O WITH ACUTE */ 66 + { 0x006F, 0x0302, 0x00F4 }, /* LATIN SMALL LETTER O + COMBINING CIRCUMFLEX ACCENT = LATIN SMALL LETTER O WITH CIRCUMFLEX */ 67 + { 0x006F, 0x0303, 0x00F5 }, /* LATIN SMALL LETTER O + COMBINING TILDE = LATIN SMALL LETTER O WITH TILDE */ 68 + { 0x006F, 0x0308, 0x00F6 }, /* LATIN SMALL LETTER O + COMBINING DIAERESIS = LATIN SMALL LETTER O WITH DIAERESIS */ 69 + { 0x0075, 0x0300, 0x00F9 }, /* LATIN SMALL LETTER U + COMBINING GRAVE ACCENT = LATIN SMALL LETTER U WITH GRAVE */ 70 + { 0x0075, 0x0301, 0x00FA }, /* LATIN SMALL LETTER U + COMBINING ACUTE ACCENT = LATIN SMALL LETTER U WITH ACUTE */ 71 + { 0x0075, 0x0302, 0x00FB }, /* LATIN SMALL LETTER U + COMBINING CIRCUMFLEX ACCENT = LATIN SMALL LETTER U WITH CIRCUMFLEX */ 72 + { 0x0075, 0x0308, 0x00FC }, /* LATIN SMALL LETTER U + COMBINING DIAERESIS = LATIN SMALL LETTER U WITH DIAERESIS */ 73 + { 0x0079, 0x0301, 0x00FD }, /* LATIN SMALL LETTER Y + COMBINING ACUTE ACCENT = LATIN SMALL LETTER Y WITH ACUTE */ 74 + { 0x0079, 0x0308, 0x00FF }, /* LATIN SMALL LETTER Y + COMBINING DIAERESIS = LATIN SMALL LETTER Y WITH DIAERESIS */ 75 + { 0x0391, 0x0301, 0x0386 }, /* GREEK CAPITAL LETTER ALPHA + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER ALPHA WITH TONOS */ 76 + { 0x0395, 0x0301, 0x0388 }, /* GREEK CAPITAL LETTER EPSILON + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER EPSILON WITH TONOS */ 77 + { 0x0397, 0x0301, 0x0389 }, /* GREEK CAPITAL LETTER ETA + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER ETA WITH TONOS */ 78 + { 0x0399, 0x0301, 0x038A }, /* GREEK CAPITAL LETTER IOTA + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER IOTA WITH TONOS */ 79 + { 0x039F, 0x0301, 0x038C }, /* GREEK CAPITAL LETTER OMICRON + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER OMICRON WITH TONOS */ 80 + { 0x03A5, 0x0301, 0x038E }, /* GREEK CAPITAL LETTER UPSILON + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER UPSILON WITH TONOS */ 81 + { 0x03A9, 0x0301, 0x038F }, /* GREEK CAPITAL LETTER OMEGA + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER OMEGA WITH TONOS */ 82 + { 0x03B1, 0x0301, 0x03AC }, /* GREEK SMALL LETTER ALPHA + COMBINING ACUTE ACCENT = GREEK SMALL LETTER ALPHA WITH TONOS */ 83 + { 0x03B5, 0x0301, 0x03AD }, /* GREEK SMALL LETTER EPSILON + COMBINING ACUTE ACCENT = GREEK SMALL LETTER EPSILON WITH TONOS */ 84 + { 0x03B7, 0x0301, 0x03AE }, /* GREEK SMALL LETTER ETA + COMBINING ACUTE ACCENT = GREEK SMALL LETTER ETA WITH TONOS */ 85 + { 0x03B9, 0x0301, 0x03AF }, /* GREEK SMALL LETTER IOTA + COMBINING ACUTE ACCENT = GREEK SMALL LETTER IOTA WITH TONOS */ 86 + { 0x03BF, 0x0301, 0x03CC }, /* GREEK SMALL LETTER OMICRON + COMBINING ACUTE ACCENT = GREEK SMALL LETTER OMICRON WITH TONOS */ 87 + { 0x03C5, 0x0301, 0x03CD }, /* GREEK SMALL LETTER UPSILON + COMBINING ACUTE ACCENT = GREEK SMALL LETTER UPSILON WITH TONOS */ 88 + { 0x03C9, 0x0301, 0x03CE }, /* GREEK SMALL LETTER OMEGA + COMBINING ACUTE ACCENT = GREEK SMALL LETTER OMEGA WITH TONOS */ 89 + { 0x0418, 0x0306, 0x0419 }, /* CYRILLIC CAPITAL LETTER I + COMBINING BREVE = CYRILLIC CAPITAL LETTER SHORT I */ 90 + { 0x0423, 0x0306, 0x040E }, /* CYRILLIC CAPITAL LETTER U + COMBINING BREVE = CYRILLIC CAPITAL LETTER SHORT U */ 91 + { 0x0438, 0x0306, 0x0439 }, /* CYRILLIC SMALL LETTER I + COMBINING BREVE = CYRILLIC SMALL LETTER SHORT I */ 92 + { 0x0443, 0x0306, 0x045E }, /* CYRILLIC SMALL LETTER U + COMBINING BREVE = CYRILLIC SMALL LETTER SHORT U */ 93 + }; 94 + 95 + /* 96 + * Boundary values for quick rejection 97 + * These are calculated by analyzing the table during generation 98 + */ 99 + #define UCS_RECOMPOSE_MIN_BASE 0x0041 100 + #define UCS_RECOMPOSE_MAX_BASE 0x0443 101 + #define UCS_RECOMPOSE_MIN_MARK 0x0300 102 + #define UCS_RECOMPOSE_MAX_MARK 0x0327
+453
drivers/tty/vt/ucs_width_table.h_shipped
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * ucs_width_table.h - Unicode character width 4 + * 5 + * Auto-generated by gen_ucs_width_table.py 6 + * 7 + * Unicode Version: 16.0.0 8 + */ 9 + 10 + /* Zero-width character ranges (BMP - Basic Multilingual Plane, U+0000 to U+FFFF) */ 11 + static const struct ucs_interval16 ucs_zero_width_bmp_ranges[] = { 12 + { 0x00AD, 0x00AD }, /* SOFT HYPHEN */ 13 + { 0x0300, 0x036F }, /* COMBINING GRAVE ACCENT - COMBINING LATIN SMALL LETTER X */ 14 + { 0x0483, 0x0489 }, /* COMBINING CYRILLIC TITLO - COMBINING CYRILLIC MILLIONS SIGN */ 15 + { 0x0591, 0x05BD }, /* HEBREW ACCENT ETNAHTA - HEBREW POINT METEG */ 16 + { 0x05BF, 0x05BF }, /* HEBREW POINT RAFE */ 17 + { 0x05C1, 0x05C2 }, /* HEBREW POINT SHIN DOT - HEBREW POINT SIN DOT */ 18 + { 0x05C4, 0x05C5 }, /* HEBREW MARK UPPER DOT - HEBREW MARK LOWER DOT */ 19 + { 0x05C7, 0x05C7 }, /* HEBREW POINT QAMATS QATAN */ 20 + { 0x0600, 0x0605 }, /* ARABIC NUMBER SIGN - ARABIC NUMBER MARK ABOVE */ 21 + { 0x0610, 0x061A }, /* ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM - ARABIC SMALL KASRA */ 22 + { 0x061C, 0x061C }, /* ARABIC LETTER MARK */ 23 + { 0x064B, 0x065F }, /* ARABIC FATHATAN - ARABIC WAVY HAMZA BELOW */ 24 + { 0x0670, 0x0670 }, /* ARABIC LETTER SUPERSCRIPT ALEF */ 25 + { 0x06D6, 0x06DD }, /* ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA - ARABIC END OF AYAH */ 26 + { 0x06DF, 0x06E4 }, /* ARABIC SMALL HIGH ROUNDED ZERO - ARABIC SMALL HIGH MADDA */ 27 + { 0x06E7, 0x06E8 }, /* ARABIC SMALL HIGH YEH - ARABIC SMALL HIGH NOON */ 28 + { 0x06EA, 0x06ED }, /* ARABIC EMPTY CENTRE LOW STOP - ARABIC SMALL LOW MEEM */ 29 + { 0x070F, 0x070F }, /* SYRIAC ABBREVIATION MARK */ 30 + { 0x0711, 0x0711 }, /* SYRIAC LETTER SUPERSCRIPT ALAPH */ 31 + { 0x0730, 0x074A }, /* SYRIAC PTHAHA ABOVE - SYRIAC BARREKH */ 32 + { 0x07A6, 0x07B0 }, /* THAANA ABAFILI - THAANA SUKUN */ 33 + { 0x07EB, 0x07F3 }, /* NKO COMBINING SHORT HIGH TONE - NKO COMBINING DOUBLE DOT ABOVE */ 34 + { 0x07FD, 0x07FD }, /* NKO DANTAYALAN */ 35 + { 0x0816, 0x0819 }, /* SAMARITAN MARK IN - SAMARITAN MARK DAGESH */ 36 + { 0x081B, 0x0823 }, /* SAMARITAN MARK EPENTHETIC YUT - SAMARITAN VOWEL SIGN A */ 37 + { 0x0825, 0x0827 }, /* SAMARITAN VOWEL SIGN SHORT A - SAMARITAN VOWEL SIGN U */ 38 + { 0x0829, 0x082D }, /* SAMARITAN VOWEL SIGN LONG I - SAMARITAN MARK NEQUDAA */ 39 + { 0x0859, 0x085B }, /* MANDAIC AFFRICATION MARK - MANDAIC GEMINATION MARK */ 40 + { 0x0890, 0x0891 }, /* ARABIC POUND MARK ABOVE - ARABIC PIASTRE MARK ABOVE */ 41 + { 0x0897, 0x089F }, /* ARABIC PEPET - ARABIC HALF MADDA OVER MADDA */ 42 + { 0x08CA, 0x0903 }, /* ARABIC SMALL HIGH FARSI YEH - DEVANAGARI SIGN VISARGA */ 43 + { 0x093A, 0x093C }, /* DEVANAGARI VOWEL SIGN OE - DEVANAGARI SIGN NUKTA */ 44 + { 0x093E, 0x094F }, /* DEVANAGARI VOWEL SIGN AA - DEVANAGARI VOWEL SIGN AW */ 45 + { 0x0951, 0x0957 }, /* DEVANAGARI STRESS SIGN UDATTA - DEVANAGARI VOWEL SIGN UUE */ 46 + { 0x0962, 0x0963 }, /* DEVANAGARI VOWEL SIGN VOCALIC L - DEVANAGARI VOWEL SIGN VOCALIC LL */ 47 + { 0x0981, 0x0983 }, /* BENGALI SIGN CANDRABINDU - BENGALI SIGN VISARGA */ 48 + { 0x09BC, 0x09BC }, /* BENGALI SIGN NUKTA */ 49 + { 0x09BE, 0x09C4 }, /* BENGALI VOWEL SIGN AA - BENGALI VOWEL SIGN VOCALIC RR */ 50 + { 0x09C7, 0x09C8 }, /* BENGALI VOWEL SIGN E - BENGALI VOWEL SIGN AI */ 51 + { 0x09CB, 0x09CD }, /* BENGALI VOWEL SIGN O - BENGALI SIGN VIRAMA */ 52 + { 0x09D7, 0x09D7 }, /* BENGALI AU LENGTH MARK */ 53 + { 0x09E2, 0x09E3 }, /* BENGALI VOWEL SIGN VOCALIC L - BENGALI VOWEL SIGN VOCALIC LL */ 54 + { 0x09FE, 0x09FE }, /* BENGALI SANDHI MARK */ 55 + { 0x0A01, 0x0A03 }, /* GURMUKHI SIGN ADAK BINDI - GURMUKHI SIGN VISARGA */ 56 + { 0x0A3C, 0x0A3C }, /* GURMUKHI SIGN NUKTA */ 57 + { 0x0A3E, 0x0A42 }, /* GURMUKHI VOWEL SIGN AA - GURMUKHI VOWEL SIGN UU */ 58 + { 0x0A47, 0x0A48 }, /* GURMUKHI VOWEL SIGN EE - GURMUKHI VOWEL SIGN AI */ 59 + { 0x0A4B, 0x0A4D }, /* GURMUKHI VOWEL SIGN OO - GURMUKHI SIGN VIRAMA */ 60 + { 0x0A51, 0x0A51 }, /* GURMUKHI SIGN UDAAT */ 61 + { 0x0A70, 0x0A71 }, /* GURMUKHI TIPPI - GURMUKHI ADDAK */ 62 + { 0x0A75, 0x0A75 }, /* GURMUKHI SIGN YAKASH */ 63 + { 0x0A81, 0x0A83 }, /* GUJARATI SIGN CANDRABINDU - GUJARATI SIGN VISARGA */ 64 + { 0x0ABC, 0x0ABC }, /* GUJARATI SIGN NUKTA */ 65 + { 0x0ABE, 0x0AC5 }, /* GUJARATI VOWEL SIGN AA - GUJARATI VOWEL SIGN CANDRA E */ 66 + { 0x0AC7, 0x0AC9 }, /* GUJARATI VOWEL SIGN E - GUJARATI VOWEL SIGN CANDRA O */ 67 + { 0x0ACB, 0x0ACD }, /* GUJARATI VOWEL SIGN O - GUJARATI SIGN VIRAMA */ 68 + { 0x0AE2, 0x0AE3 }, /* GUJARATI VOWEL SIGN VOCALIC L - GUJARATI VOWEL SIGN VOCALIC LL */ 69 + { 0x0AFA, 0x0AFF }, /* GUJARATI SIGN SUKUN - GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE */ 70 + { 0x0B01, 0x0B03 }, /* ORIYA SIGN CANDRABINDU - ORIYA SIGN VISARGA */ 71 + { 0x0B3C, 0x0B3C }, /* ORIYA SIGN NUKTA */ 72 + { 0x0B3E, 0x0B44 }, /* ORIYA VOWEL SIGN AA - ORIYA VOWEL SIGN VOCALIC RR */ 73 + { 0x0B47, 0x0B48 }, /* ORIYA VOWEL SIGN E - ORIYA VOWEL SIGN AI */ 74 + { 0x0B4B, 0x0B4D }, /* ORIYA VOWEL SIGN O - ORIYA SIGN VIRAMA */ 75 + { 0x0B55, 0x0B57 }, /* ORIYA SIGN OVERLINE - ORIYA AU LENGTH MARK */ 76 + { 0x0B62, 0x0B63 }, /* ORIYA VOWEL SIGN VOCALIC L - ORIYA VOWEL SIGN VOCALIC LL */ 77 + { 0x0B82, 0x0B82 }, /* TAMIL SIGN ANUSVARA */ 78 + { 0x0BBE, 0x0BC2 }, /* TAMIL VOWEL SIGN AA - TAMIL VOWEL SIGN UU */ 79 + { 0x0BC6, 0x0BC8 }, /* TAMIL VOWEL SIGN E - TAMIL VOWEL SIGN AI */ 80 + { 0x0BCA, 0x0BCD }, /* TAMIL VOWEL SIGN O - TAMIL SIGN VIRAMA */ 81 + { 0x0BD7, 0x0BD7 }, /* TAMIL AU LENGTH MARK */ 82 + { 0x0C00, 0x0C04 }, /* TELUGU SIGN COMBINING CANDRABINDU ABOVE - TELUGU SIGN COMBINING ANUSVARA ABOVE */ 83 + { 0x0C3C, 0x0C3C }, /* TELUGU SIGN NUKTA */ 84 + { 0x0C3E, 0x0C44 }, /* TELUGU VOWEL SIGN AA - TELUGU VOWEL SIGN VOCALIC RR */ 85 + { 0x0C46, 0x0C48 }, /* TELUGU VOWEL SIGN E - TELUGU VOWEL SIGN AI */ 86 + { 0x0C4A, 0x0C4D }, /* TELUGU VOWEL SIGN O - TELUGU SIGN VIRAMA */ 87 + { 0x0C55, 0x0C56 }, /* TELUGU LENGTH MARK - TELUGU AI LENGTH MARK */ 88 + { 0x0C62, 0x0C63 }, /* TELUGU VOWEL SIGN VOCALIC L - TELUGU VOWEL SIGN VOCALIC LL */ 89 + { 0x0C81, 0x0C83 }, /* KANNADA SIGN CANDRABINDU - KANNADA SIGN VISARGA */ 90 + { 0x0CBC, 0x0CBC }, /* KANNADA SIGN NUKTA */ 91 + { 0x0CBE, 0x0CC4 }, /* KANNADA VOWEL SIGN AA - KANNADA VOWEL SIGN VOCALIC RR */ 92 + { 0x0CC6, 0x0CC8 }, /* KANNADA VOWEL SIGN E - KANNADA VOWEL SIGN AI */ 93 + { 0x0CCA, 0x0CCD }, /* KANNADA VOWEL SIGN O - KANNADA SIGN VIRAMA */ 94 + { 0x0CD5, 0x0CD6 }, /* KANNADA LENGTH MARK - KANNADA AI LENGTH MARK */ 95 + { 0x0CE2, 0x0CE3 }, /* KANNADA VOWEL SIGN VOCALIC L - KANNADA VOWEL SIGN VOCALIC LL */ 96 + { 0x0CF3, 0x0CF3 }, /* KANNADA SIGN COMBINING ANUSVARA ABOVE RIGHT */ 97 + { 0x0D00, 0x0D03 }, /* MALAYALAM SIGN COMBINING ANUSVARA ABOVE - MALAYALAM SIGN VISARGA */ 98 + { 0x0D3B, 0x0D3C }, /* MALAYALAM SIGN VERTICAL BAR VIRAMA - MALAYALAM SIGN CIRCULAR VIRAMA */ 99 + { 0x0D3E, 0x0D44 }, /* MALAYALAM VOWEL SIGN AA - MALAYALAM VOWEL SIGN VOCALIC RR */ 100 + { 0x0D46, 0x0D48 }, /* MALAYALAM VOWEL SIGN E - MALAYALAM VOWEL SIGN AI */ 101 + { 0x0D4A, 0x0D4D }, /* MALAYALAM VOWEL SIGN O - MALAYALAM SIGN VIRAMA */ 102 + { 0x0D57, 0x0D57 }, /* MALAYALAM AU LENGTH MARK */ 103 + { 0x0D62, 0x0D63 }, /* MALAYALAM VOWEL SIGN VOCALIC L - MALAYALAM VOWEL SIGN VOCALIC LL */ 104 + { 0x0D81, 0x0D83 }, /* SINHALA SIGN CANDRABINDU - SINHALA SIGN VISARGAYA */ 105 + { 0x0DCA, 0x0DCA }, /* SINHALA SIGN AL-LAKUNA */ 106 + { 0x0DCF, 0x0DD4 }, /* SINHALA VOWEL SIGN AELA-PILLA - SINHALA VOWEL SIGN KETTI PAA-PILLA */ 107 + { 0x0DD6, 0x0DD6 }, /* SINHALA VOWEL SIGN DIGA PAA-PILLA */ 108 + { 0x0DD8, 0x0DDF }, /* SINHALA VOWEL SIGN GAETTA-PILLA - SINHALA VOWEL SIGN GAYANUKITTA */ 109 + { 0x0DF2, 0x0DF3 }, /* SINHALA VOWEL SIGN DIGA GAETTA-PILLA - SINHALA VOWEL SIGN DIGA GAYANUKITTA */ 110 + { 0x0E31, 0x0E31 }, /* THAI CHARACTER MAI HAN-AKAT */ 111 + { 0x0E34, 0x0E3A }, /* THAI CHARACTER SARA I - THAI CHARACTER PHINTHU */ 112 + { 0x0E47, 0x0E4E }, /* THAI CHARACTER MAITAIKHU - THAI CHARACTER YAMAKKAN */ 113 + { 0x0EB1, 0x0EB1 }, /* LAO VOWEL SIGN MAI KAN */ 114 + { 0x0EB4, 0x0EBC }, /* LAO VOWEL SIGN I - LAO SEMIVOWEL SIGN LO */ 115 + { 0x0EC8, 0x0ECE }, /* LAO TONE MAI EK - LAO YAMAKKAN */ 116 + { 0x0F18, 0x0F19 }, /* TIBETAN ASTROLOGICAL SIGN -KHYUD PA - TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS */ 117 + { 0x0F35, 0x0F35 }, /* TIBETAN MARK NGAS BZUNG NYI ZLA */ 118 + { 0x0F37, 0x0F37 }, /* TIBETAN MARK NGAS BZUNG SGOR RTAGS */ 119 + { 0x0F39, 0x0F39 }, /* TIBETAN MARK TSA -PHRU */ 120 + { 0x0F3E, 0x0F3F }, /* TIBETAN SIGN YAR TSHES - TIBETAN SIGN MAR TSHES */ 121 + { 0x0F71, 0x0F84 }, /* TIBETAN VOWEL SIGN AA - TIBETAN MARK HALANTA */ 122 + { 0x0F86, 0x0F87 }, /* TIBETAN SIGN LCI RTAGS - TIBETAN SIGN YANG RTAGS */ 123 + { 0x0F8D, 0x0F97 }, /* TIBETAN SUBJOINED SIGN LCE TSA CAN - TIBETAN SUBJOINED LETTER JA */ 124 + { 0x0F99, 0x0FBC }, /* TIBETAN SUBJOINED LETTER NYA - TIBETAN SUBJOINED LETTER FIXED-FORM RA */ 125 + { 0x0FC6, 0x0FC6 }, /* TIBETAN SYMBOL PADMA GDAN */ 126 + { 0x102B, 0x103E }, /* MYANMAR VOWEL SIGN TALL AA - MYANMAR CONSONANT SIGN MEDIAL HA */ 127 + { 0x1056, 0x1059 }, /* MYANMAR VOWEL SIGN VOCALIC R - MYANMAR VOWEL SIGN VOCALIC LL */ 128 + { 0x105E, 0x1060 }, /* MYANMAR CONSONANT SIGN MON MEDIAL NA - MYANMAR CONSONANT SIGN MON MEDIAL LA */ 129 + { 0x1062, 0x1064 }, /* MYANMAR VOWEL SIGN SGAW KAREN EU - MYANMAR TONE MARK SGAW KAREN KE PHO */ 130 + { 0x1067, 0x106D }, /* MYANMAR VOWEL SIGN WESTERN PWO KAREN EU - MYANMAR SIGN WESTERN PWO KAREN TONE-5 */ 131 + { 0x1071, 0x1074 }, /* MYANMAR VOWEL SIGN GEBA KAREN I - MYANMAR VOWEL SIGN KAYAH EE */ 132 + { 0x1082, 0x108D }, /* MYANMAR CONSONANT SIGN SHAN MEDIAL WA - MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE */ 133 + { 0x108F, 0x108F }, /* MYANMAR SIGN RUMAI PALAUNG TONE-5 */ 134 + { 0x109A, 0x109D }, /* MYANMAR SIGN KHAMTI TONE-1 - MYANMAR VOWEL SIGN AITON AI */ 135 + { 0x135D, 0x135F }, /* ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK - ETHIOPIC COMBINING GEMINATION MARK */ 136 + { 0x1712, 0x1715 }, /* TAGALOG VOWEL SIGN I - TAGALOG SIGN PAMUDPOD */ 137 + { 0x1732, 0x1734 }, /* HANUNOO VOWEL SIGN I - HANUNOO SIGN PAMUDPOD */ 138 + { 0x1752, 0x1753 }, /* BUHID VOWEL SIGN I - BUHID VOWEL SIGN U */ 139 + { 0x1772, 0x1773 }, /* TAGBANWA VOWEL SIGN I - TAGBANWA VOWEL SIGN U */ 140 + { 0x17B4, 0x17D3 }, /* KHMER VOWEL INHERENT AQ - KHMER SIGN BATHAMASAT */ 141 + { 0x17DD, 0x17DD }, /* KHMER SIGN ATTHACAN */ 142 + { 0x180B, 0x180F }, /* MONGOLIAN FREE VARIATION SELECTOR ONE - MONGOLIAN FREE VARIATION SELECTOR FOUR */ 143 + { 0x1885, 0x1886 }, /* MONGOLIAN LETTER ALI GALI BALUDA - MONGOLIAN LETTER ALI GALI THREE BALUDA */ 144 + { 0x18A9, 0x18A9 }, /* MONGOLIAN LETTER ALI GALI DAGALGA */ 145 + { 0x1920, 0x192B }, /* LIMBU VOWEL SIGN A - LIMBU SUBJOINED LETTER WA */ 146 + { 0x1930, 0x193B }, /* LIMBU SMALL LETTER KA - LIMBU SIGN SA-I */ 147 + { 0x1A17, 0x1A1B }, /* BUGINESE VOWEL SIGN I - BUGINESE VOWEL SIGN AE */ 148 + { 0x1A55, 0x1A5E }, /* TAI THAM CONSONANT SIGN MEDIAL RA - TAI THAM CONSONANT SIGN SA */ 149 + { 0x1A60, 0x1A7C }, /* TAI THAM SIGN SAKOT - TAI THAM SIGN KHUEN-LUE KARAN */ 150 + { 0x1A7F, 0x1A7F }, /* TAI THAM COMBINING CRYPTOGRAMMIC DOT */ 151 + { 0x1AB0, 0x1ACE }, /* COMBINING DOUBLED CIRCUMFLEX ACCENT - COMBINING LATIN SMALL LETTER INSULAR T */ 152 + { 0x1B00, 0x1B04 }, /* BALINESE SIGN ULU RICEM - BALINESE SIGN BISAH */ 153 + { 0x1B34, 0x1B44 }, /* BALINESE SIGN REREKAN - BALINESE ADEG ADEG */ 154 + { 0x1B6B, 0x1B73 }, /* BALINESE MUSICAL SYMBOL COMBINING TEGEH - BALINESE MUSICAL SYMBOL COMBINING GONG */ 155 + { 0x1B80, 0x1B82 }, /* SUNDANESE SIGN PANYECEK - SUNDANESE SIGN PANGWISAD */ 156 + { 0x1BA1, 0x1BAD }, /* SUNDANESE CONSONANT SIGN PAMINGKAL - SUNDANESE CONSONANT SIGN PASANGAN WA */ 157 + { 0x1BE6, 0x1BF3 }, /* BATAK SIGN TOMPI - BATAK PANONGONAN */ 158 + { 0x1C24, 0x1C37 }, /* LEPCHA SUBJOINED LETTER YA - LEPCHA SIGN NUKTA */ 159 + { 0x1CD0, 0x1CD2 }, /* VEDIC TONE KARSHANA - VEDIC TONE PRENKHA */ 160 + { 0x1CD4, 0x1CE8 }, /* VEDIC SIGN YAJURVEDIC MIDLINE SVARITA - VEDIC SIGN VISARGA ANUDATTA WITH TAIL */ 161 + { 0x1CED, 0x1CED }, /* VEDIC SIGN TIRYAK */ 162 + { 0x1CF4, 0x1CF4 }, /* VEDIC TONE CANDRA ABOVE */ 163 + { 0x1CF7, 0x1CF9 }, /* VEDIC SIGN ATIKRAMA - VEDIC TONE DOUBLE RING ABOVE */ 164 + { 0x1DC0, 0x1DFF }, /* COMBINING DOTTED GRAVE ACCENT - COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW */ 165 + { 0x200B, 0x200F }, /* ZERO WIDTH SPACE - RIGHT-TO-LEFT MARK */ 166 + { 0x202A, 0x202E }, /* LEFT-TO-RIGHT EMBEDDING - RIGHT-TO-LEFT OVERRIDE */ 167 + { 0x2060, 0x2064 }, /* WORD JOINER - INVISIBLE PLUS */ 168 + { 0x2066, 0x206F }, /* LEFT-TO-RIGHT ISOLATE - NOMINAL DIGIT SHAPES */ 169 + { 0x20D0, 0x20F0 }, /* COMBINING LEFT HARPOON ABOVE - COMBINING ASTERISK ABOVE */ 170 + { 0x2640, 0x2640 }, /* FEMALE SIGN */ 171 + { 0x2642, 0x2642 }, /* MALE SIGN */ 172 + { 0x26A7, 0x26A7 }, /* MALE WITH STROKE AND MALE AND FEMALE SIGN */ 173 + { 0x2CEF, 0x2CF1 }, /* COPTIC COMBINING NI ABOVE - COPTIC COMBINING SPIRITUS LENIS */ 174 + { 0x2D7F, 0x2D7F }, /* TIFINAGH CONSONANT JOINER */ 175 + { 0x2DE0, 0x2DFF }, /* COMBINING CYRILLIC LETTER BE - COMBINING CYRILLIC LETTER IOTIFIED BIG YUS */ 176 + { 0x302A, 0x302F }, /* IDEOGRAPHIC LEVEL TONE MARK - HANGUL DOUBLE DOT TONE MARK */ 177 + { 0x3099, 0x309A }, /* COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK - COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */ 178 + { 0xA66F, 0xA672 }, /* COMBINING CYRILLIC VZMET - COMBINING CYRILLIC THOUSAND MILLIONS SIGN */ 179 + { 0xA674, 0xA67D }, /* COMBINING CYRILLIC LETTER UKRAINIAN IE - COMBINING CYRILLIC PAYEROK */ 180 + { 0xA69E, 0xA69F }, /* COMBINING CYRILLIC LETTER EF - COMBINING CYRILLIC LETTER IOTIFIED E */ 181 + { 0xA6F0, 0xA6F1 }, /* BAMUM COMBINING MARK KOQNDON - BAMUM COMBINING MARK TUKWENTIS */ 182 + { 0xA802, 0xA802 }, /* SYLOTI NAGRI SIGN DVISVARA */ 183 + { 0xA806, 0xA806 }, /* SYLOTI NAGRI SIGN HASANTA */ 184 + { 0xA80B, 0xA80B }, /* SYLOTI NAGRI SIGN ANUSVARA */ 185 + { 0xA823, 0xA827 }, /* SYLOTI NAGRI VOWEL SIGN A - SYLOTI NAGRI VOWEL SIGN OO */ 186 + { 0xA82C, 0xA82C }, /* SYLOTI NAGRI SIGN ALTERNATE HASANTA */ 187 + { 0xA880, 0xA881 }, /* SAURASHTRA SIGN ANUSVARA - SAURASHTRA SIGN VISARGA */ 188 + { 0xA8B4, 0xA8C5 }, /* SAURASHTRA CONSONANT SIGN HAARU - SAURASHTRA SIGN CANDRABINDU */ 189 + { 0xA8E0, 0xA8F1 }, /* COMBINING DEVANAGARI DIGIT ZERO - COMBINING DEVANAGARI SIGN AVAGRAHA */ 190 + { 0xA8FF, 0xA8FF }, /* DEVANAGARI VOWEL SIGN AY */ 191 + { 0xA926, 0xA92D }, /* KAYAH LI VOWEL UE - KAYAH LI TONE CALYA PLOPHU */ 192 + { 0xA947, 0xA953 }, /* REJANG VOWEL SIGN I - REJANG VIRAMA */ 193 + { 0xA980, 0xA983 }, /* JAVANESE SIGN PANYANGGA - JAVANESE SIGN WIGNYAN */ 194 + { 0xA9B3, 0xA9C0 }, /* JAVANESE SIGN CECAK TELU - JAVANESE PANGKON */ 195 + { 0xA9E5, 0xA9E5 }, /* MYANMAR SIGN SHAN SAW */ 196 + { 0xAA29, 0xAA36 }, /* CHAM VOWEL SIGN AA - CHAM CONSONANT SIGN WA */ 197 + { 0xAA43, 0xAA43 }, /* CHAM CONSONANT SIGN FINAL NG */ 198 + { 0xAA4C, 0xAA4D }, /* CHAM CONSONANT SIGN FINAL M - CHAM CONSONANT SIGN FINAL H */ 199 + { 0xAA7B, 0xAA7D }, /* MYANMAR SIGN PAO KAREN TONE - MYANMAR SIGN TAI LAING TONE-5 */ 200 + { 0xAAB0, 0xAAB0 }, /* TAI VIET MAI KANG */ 201 + { 0xAAB2, 0xAAB4 }, /* TAI VIET VOWEL I - TAI VIET VOWEL U */ 202 + { 0xAAB7, 0xAAB8 }, /* TAI VIET MAI KHIT - TAI VIET VOWEL IA */ 203 + { 0xAABE, 0xAABF }, /* TAI VIET VOWEL AM - TAI VIET TONE MAI EK */ 204 + { 0xAAC1, 0xAAC1 }, /* TAI VIET TONE MAI THO */ 205 + { 0xAAEB, 0xAAEF }, /* MEETEI MAYEK VOWEL SIGN II - MEETEI MAYEK VOWEL SIGN AAU */ 206 + { 0xAAF5, 0xAAF6 }, /* MEETEI MAYEK VOWEL SIGN VISARGA - MEETEI MAYEK VIRAMA */ 207 + { 0xABE3, 0xABEA }, /* MEETEI MAYEK VOWEL SIGN ONAP - MEETEI MAYEK VOWEL SIGN NUNG */ 208 + { 0xABEC, 0xABED }, /* MEETEI MAYEK LUM IYEK - MEETEI MAYEK APUN IYEK */ 209 + { 0xFB1E, 0xFB1E }, /* HEBREW POINT JUDEO-SPANISH VARIKA */ 210 + { 0xFE00, 0xFE0F }, /* VARIATION SELECTOR-1 - VARIATION SELECTOR-16 */ 211 + { 0xFE20, 0xFE2F }, /* COMBINING LIGATURE LEFT HALF - COMBINING CYRILLIC TITLO RIGHT HALF */ 212 + { 0xFEFF, 0xFEFF }, /* ZERO WIDTH NO-BREAK SPACE */ 213 + { 0xFFF9, 0xFFFB }, /* INTERLINEAR ANNOTATION ANCHOR - INTERLINEAR ANNOTATION TERMINATOR */ 214 + }; 215 + 216 + /* Zero-width character ranges (non-BMP, U+10000 and above) */ 217 + static const struct ucs_interval32 ucs_zero_width_non_bmp_ranges[] = { 218 + { 0x101FD, 0x101FD }, /* PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE */ 219 + { 0x102E0, 0x102E0 }, /* COPTIC EPACT THOUSANDS MARK */ 220 + { 0x10376, 0x1037A }, /* COMBINING OLD PERMIC LETTER AN - COMBINING OLD PERMIC LETTER SII */ 221 + { 0x10A01, 0x10A03 }, /* KHAROSHTHI VOWEL SIGN I - KHAROSHTHI VOWEL SIGN VOCALIC R */ 222 + { 0x10A05, 0x10A06 }, /* KHAROSHTHI VOWEL SIGN E - KHAROSHTHI VOWEL SIGN O */ 223 + { 0x10A0C, 0x10A0F }, /* KHAROSHTHI VOWEL LENGTH MARK - KHAROSHTHI SIGN VISARGA */ 224 + { 0x10A38, 0x10A3A }, /* KHAROSHTHI SIGN BAR ABOVE - KHAROSHTHI SIGN DOT BELOW */ 225 + { 0x10A3F, 0x10A3F }, /* KHAROSHTHI VIRAMA */ 226 + { 0x10AE5, 0x10AE6 }, /* MANICHAEAN ABBREVIATION MARK ABOVE - MANICHAEAN ABBREVIATION MARK BELOW */ 227 + { 0x10D24, 0x10D27 }, /* HANIFI ROHINGYA SIGN HARBAHAY - HANIFI ROHINGYA SIGN TASSI */ 228 + { 0x10D69, 0x10D6D }, /* GARAY VOWEL SIGN E - GARAY CONSONANT NASALIZATION MARK */ 229 + { 0x10EAB, 0x10EAC }, /* YEZIDI COMBINING HAMZA MARK - YEZIDI COMBINING MADDA MARK */ 230 + { 0x10EFC, 0x10EFF }, /* ARABIC COMBINING ALEF OVERLAY - ARABIC SMALL LOW WORD MADDA */ 231 + { 0x10F46, 0x10F50 }, /* SOGDIAN COMBINING DOT BELOW - SOGDIAN COMBINING STROKE BELOW */ 232 + { 0x10F82, 0x10F85 }, /* OLD UYGHUR COMBINING DOT ABOVE - OLD UYGHUR COMBINING TWO DOTS BELOW */ 233 + { 0x11000, 0x11002 }, /* BRAHMI SIGN CANDRABINDU - BRAHMI SIGN VISARGA */ 234 + { 0x11038, 0x11046 }, /* BRAHMI VOWEL SIGN AA - BRAHMI VIRAMA */ 235 + { 0x11070, 0x11070 }, /* BRAHMI SIGN OLD TAMIL VIRAMA */ 236 + { 0x11073, 0x11074 }, /* BRAHMI VOWEL SIGN OLD TAMIL SHORT E - BRAHMI VOWEL SIGN OLD TAMIL SHORT O */ 237 + { 0x1107F, 0x11082 }, /* BRAHMI NUMBER JOINER - KAITHI SIGN VISARGA */ 238 + { 0x110B0, 0x110BA }, /* KAITHI VOWEL SIGN AA - KAITHI SIGN NUKTA */ 239 + { 0x110BD, 0x110BD }, /* KAITHI NUMBER SIGN */ 240 + { 0x110C2, 0x110C2 }, /* KAITHI VOWEL SIGN VOCALIC R */ 241 + { 0x110CD, 0x110CD }, /* KAITHI NUMBER SIGN ABOVE */ 242 + { 0x11100, 0x11102 }, /* CHAKMA SIGN CANDRABINDU - CHAKMA SIGN VISARGA */ 243 + { 0x11127, 0x11134 }, /* CHAKMA VOWEL SIGN A - CHAKMA MAAYYAA */ 244 + { 0x11145, 0x11146 }, /* CHAKMA VOWEL SIGN AA - CHAKMA VOWEL SIGN EI */ 245 + { 0x11173, 0x11173 }, /* MAHAJANI SIGN NUKTA */ 246 + { 0x11180, 0x11182 }, /* SHARADA SIGN CANDRABINDU - SHARADA SIGN VISARGA */ 247 + { 0x111B3, 0x111C0 }, /* SHARADA VOWEL SIGN AA - SHARADA SIGN VIRAMA */ 248 + { 0x111C9, 0x111CC }, /* SHARADA SANDHI MARK - SHARADA EXTRA SHORT VOWEL MARK */ 249 + { 0x111CE, 0x111CF }, /* SHARADA VOWEL SIGN PRISHTHAMATRA E - SHARADA SIGN INVERTED CANDRABINDU */ 250 + { 0x1122C, 0x11237 }, /* KHOJKI VOWEL SIGN AA - KHOJKI SIGN SHADDA */ 251 + { 0x1123E, 0x1123E }, /* KHOJKI SIGN SUKUN */ 252 + { 0x11241, 0x11241 }, /* KHOJKI VOWEL SIGN VOCALIC R */ 253 + { 0x112DF, 0x112EA }, /* KHUDAWADI SIGN ANUSVARA - KHUDAWADI SIGN VIRAMA */ 254 + { 0x11300, 0x11303 }, /* GRANTHA SIGN COMBINING ANUSVARA ABOVE - GRANTHA SIGN VISARGA */ 255 + { 0x1133B, 0x1133C }, /* COMBINING BINDU BELOW - GRANTHA SIGN NUKTA */ 256 + { 0x1133E, 0x11344 }, /* GRANTHA VOWEL SIGN AA - GRANTHA VOWEL SIGN VOCALIC RR */ 257 + { 0x11347, 0x11348 }, /* GRANTHA VOWEL SIGN EE - GRANTHA VOWEL SIGN AI */ 258 + { 0x1134B, 0x1134D }, /* GRANTHA VOWEL SIGN OO - GRANTHA SIGN VIRAMA */ 259 + { 0x11357, 0x11357 }, /* GRANTHA AU LENGTH MARK */ 260 + { 0x11362, 0x11363 }, /* GRANTHA VOWEL SIGN VOCALIC L - GRANTHA VOWEL SIGN VOCALIC LL */ 261 + { 0x11366, 0x1136C }, /* COMBINING GRANTHA DIGIT ZERO - COMBINING GRANTHA DIGIT SIX */ 262 + { 0x11370, 0x11374 }, /* COMBINING GRANTHA LETTER A - COMBINING GRANTHA LETTER PA */ 263 + { 0x113B8, 0x113C0 }, /* TULU-TIGALARI VOWEL SIGN AA - TULU-TIGALARI VOWEL SIGN VOCALIC LL */ 264 + { 0x113C2, 0x113C2 }, /* TULU-TIGALARI VOWEL SIGN EE */ 265 + { 0x113C5, 0x113C5 }, /* TULU-TIGALARI VOWEL SIGN AI */ 266 + { 0x113C7, 0x113CA }, /* TULU-TIGALARI VOWEL SIGN OO - TULU-TIGALARI SIGN CANDRA ANUNASIKA */ 267 + { 0x113CC, 0x113D0 }, /* TULU-TIGALARI SIGN ANUSVARA - TULU-TIGALARI CONJOINER */ 268 + { 0x113D2, 0x113D2 }, /* TULU-TIGALARI GEMINATION MARK */ 269 + { 0x113E1, 0x113E2 }, /* TULU-TIGALARI VEDIC TONE SVARITA - TULU-TIGALARI VEDIC TONE ANUDATTA */ 270 + { 0x11435, 0x11446 }, /* NEWA VOWEL SIGN AA - NEWA SIGN NUKTA */ 271 + { 0x1145E, 0x1145E }, /* NEWA SANDHI MARK */ 272 + { 0x114B0, 0x114C3 }, /* TIRHUTA VOWEL SIGN AA - TIRHUTA SIGN NUKTA */ 273 + { 0x115AF, 0x115B5 }, /* SIDDHAM VOWEL SIGN AA - SIDDHAM VOWEL SIGN VOCALIC RR */ 274 + { 0x115B8, 0x115C0 }, /* SIDDHAM VOWEL SIGN E - SIDDHAM SIGN NUKTA */ 275 + { 0x115DC, 0x115DD }, /* SIDDHAM VOWEL SIGN ALTERNATE U - SIDDHAM VOWEL SIGN ALTERNATE UU */ 276 + { 0x11630, 0x11640 }, /* MODI VOWEL SIGN AA - MODI SIGN ARDHACANDRA */ 277 + { 0x116AB, 0x116B7 }, /* TAKRI SIGN ANUSVARA - TAKRI SIGN NUKTA */ 278 + { 0x1171D, 0x1172B }, /* AHOM CONSONANT SIGN MEDIAL LA - AHOM SIGN KILLER */ 279 + { 0x1182C, 0x1183A }, /* DOGRA VOWEL SIGN AA - DOGRA SIGN NUKTA */ 280 + { 0x11930, 0x11935 }, /* DIVES AKURU VOWEL SIGN AA - DIVES AKURU VOWEL SIGN E */ 281 + { 0x11937, 0x11938 }, /* DIVES AKURU VOWEL SIGN AI - DIVES AKURU VOWEL SIGN O */ 282 + { 0x1193B, 0x1193E }, /* DIVES AKURU SIGN ANUSVARA - DIVES AKURU VIRAMA */ 283 + { 0x11940, 0x11940 }, /* DIVES AKURU MEDIAL YA */ 284 + { 0x11942, 0x11943 }, /* DIVES AKURU MEDIAL RA - DIVES AKURU SIGN NUKTA */ 285 + { 0x119D1, 0x119D7 }, /* NANDINAGARI VOWEL SIGN AA - NANDINAGARI VOWEL SIGN VOCALIC RR */ 286 + { 0x119DA, 0x119E0 }, /* NANDINAGARI VOWEL SIGN E - NANDINAGARI SIGN VIRAMA */ 287 + { 0x119E4, 0x119E4 }, /* NANDINAGARI VOWEL SIGN PRISHTHAMATRA E */ 288 + { 0x11A01, 0x11A0A }, /* ZANABAZAR SQUARE VOWEL SIGN I - ZANABAZAR SQUARE VOWEL LENGTH MARK */ 289 + { 0x11A33, 0x11A39 }, /* ZANABAZAR SQUARE FINAL CONSONANT MARK - ZANABAZAR SQUARE SIGN VISARGA */ 290 + { 0x11A3B, 0x11A3E }, /* ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA - ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA */ 291 + { 0x11A47, 0x11A47 }, /* ZANABAZAR SQUARE SUBJOINER */ 292 + { 0x11A51, 0x11A5B }, /* SOYOMBO VOWEL SIGN I - SOYOMBO VOWEL LENGTH MARK */ 293 + { 0x11A8A, 0x11A99 }, /* SOYOMBO FINAL CONSONANT SIGN G - SOYOMBO SUBJOINER */ 294 + { 0x11C2F, 0x11C36 }, /* BHAIKSUKI VOWEL SIGN AA - BHAIKSUKI VOWEL SIGN VOCALIC L */ 295 + { 0x11C38, 0x11C3F }, /* BHAIKSUKI VOWEL SIGN E - BHAIKSUKI SIGN VIRAMA */ 296 + { 0x11C92, 0x11CA7 }, /* MARCHEN SUBJOINED LETTER KA - MARCHEN SUBJOINED LETTER ZA */ 297 + { 0x11CA9, 0x11CB6 }, /* MARCHEN SUBJOINED LETTER YA - MARCHEN SIGN CANDRABINDU */ 298 + { 0x11D31, 0x11D36 }, /* MASARAM GONDI VOWEL SIGN AA - MASARAM GONDI VOWEL SIGN VOCALIC R */ 299 + { 0x11D3A, 0x11D3A }, /* MASARAM GONDI VOWEL SIGN E */ 300 + { 0x11D3C, 0x11D3D }, /* MASARAM GONDI VOWEL SIGN AI - MASARAM GONDI VOWEL SIGN O */ 301 + { 0x11D3F, 0x11D45 }, /* MASARAM GONDI VOWEL SIGN AU - MASARAM GONDI VIRAMA */ 302 + { 0x11D47, 0x11D47 }, /* MASARAM GONDI RA-KARA */ 303 + { 0x11D8A, 0x11D8E }, /* GUNJALA GONDI VOWEL SIGN AA - GUNJALA GONDI VOWEL SIGN UU */ 304 + { 0x11D90, 0x11D91 }, /* GUNJALA GONDI VOWEL SIGN EE - GUNJALA GONDI VOWEL SIGN AI */ 305 + { 0x11D93, 0x11D97 }, /* GUNJALA GONDI VOWEL SIGN OO - GUNJALA GONDI VIRAMA */ 306 + { 0x11EF3, 0x11EF6 }, /* MAKASAR VOWEL SIGN I - MAKASAR VOWEL SIGN O */ 307 + { 0x11F00, 0x11F01 }, /* KAWI SIGN CANDRABINDU - KAWI SIGN ANUSVARA */ 308 + { 0x11F03, 0x11F03 }, /* KAWI SIGN VISARGA */ 309 + { 0x11F34, 0x11F3A }, /* KAWI VOWEL SIGN AA - KAWI VOWEL SIGN VOCALIC R */ 310 + { 0x11F3E, 0x11F42 }, /* KAWI VOWEL SIGN E - KAWI CONJOINER */ 311 + { 0x11F5A, 0x11F5A }, /* KAWI SIGN NUKTA */ 312 + { 0x13430, 0x13440 }, /* EGYPTIAN HIEROGLYPH VERTICAL JOINER - EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY */ 313 + { 0x13447, 0x13455 }, /* EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START - EGYPTIAN HIEROGLYPH MODIFIER DAMAGED */ 314 + { 0x1611E, 0x1612F }, /* GURUNG KHEMA VOWEL SIGN AA - GURUNG KHEMA SIGN THOLHOMA */ 315 + { 0x16AF0, 0x16AF4 }, /* BASSA VAH COMBINING HIGH TONE - BASSA VAH COMBINING HIGH-LOW TONE */ 316 + { 0x16B30, 0x16B36 }, /* PAHAWH HMONG MARK CIM TUB - PAHAWH HMONG MARK CIM TAUM */ 317 + { 0x16F4F, 0x16F4F }, /* MIAO SIGN CONSONANT MODIFIER BAR */ 318 + { 0x16F51, 0x16F87 }, /* MIAO SIGN ASPIRATION - MIAO VOWEL SIGN UI */ 319 + { 0x16F8F, 0x16F92 }, /* MIAO TONE RIGHT - MIAO TONE BELOW */ 320 + { 0x16FE4, 0x16FE4 }, /* KHITAN SMALL SCRIPT FILLER */ 321 + { 0x16FF0, 0x16FF1 }, /* VIETNAMESE ALTERNATE READING MARK CA - VIETNAMESE ALTERNATE READING MARK NHAY */ 322 + { 0x1BC9D, 0x1BC9E }, /* DUPLOYAN THICK LETTER SELECTOR - DUPLOYAN DOUBLE MARK */ 323 + { 0x1BCA0, 0x1BCA3 }, /* SHORTHAND FORMAT LETTER OVERLAP - SHORTHAND FORMAT UP STEP */ 324 + { 0x1CF00, 0x1CF2D }, /* ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT - ZNAMENNY COMBINING MARK KRYZH ON LEFT */ 325 + { 0x1CF30, 0x1CF46 }, /* ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO - ZNAMENNY PRIZNAK MODIFIER ROG */ 326 + { 0x1D165, 0x1D169 }, /* MUSICAL SYMBOL COMBINING STEM - MUSICAL SYMBOL COMBINING TREMOLO-3 */ 327 + { 0x1D16D, 0x1D182 }, /* MUSICAL SYMBOL COMBINING AUGMENTATION DOT - MUSICAL SYMBOL COMBINING LOURE */ 328 + { 0x1D185, 0x1D18B }, /* MUSICAL SYMBOL COMBINING DOIT - MUSICAL SYMBOL COMBINING TRIPLE TONGUE */ 329 + { 0x1D1AA, 0x1D1AD }, /* MUSICAL SYMBOL COMBINING DOWN BOW - MUSICAL SYMBOL COMBINING SNAP PIZZICATO */ 330 + { 0x1D242, 0x1D244 }, /* COMBINING GREEK MUSICAL TRISEME - COMBINING GREEK MUSICAL PENTASEME */ 331 + { 0x1DA00, 0x1DA36 }, /* SIGNWRITING HEAD RIM - SIGNWRITING AIR SUCKING IN */ 332 + { 0x1DA3B, 0x1DA6C }, /* SIGNWRITING MOUTH CLOSED NEUTRAL - SIGNWRITING EXCITEMENT */ 333 + { 0x1DA75, 0x1DA75 }, /* SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS */ 334 + { 0x1DA84, 0x1DA84 }, /* SIGNWRITING LOCATION HEAD NECK */ 335 + { 0x1DA9B, 0x1DA9F }, /* SIGNWRITING FILL MODIFIER-2 - SIGNWRITING FILL MODIFIER-6 */ 336 + { 0x1DAA1, 0x1DAAF }, /* SIGNWRITING ROTATION MODIFIER-2 - SIGNWRITING ROTATION MODIFIER-16 */ 337 + { 0x1E000, 0x1E006 }, /* COMBINING GLAGOLITIC LETTER AZU - COMBINING GLAGOLITIC LETTER ZHIVETE */ 338 + { 0x1E008, 0x1E018 }, /* COMBINING GLAGOLITIC LETTER ZEMLJA - COMBINING GLAGOLITIC LETTER HERU */ 339 + { 0x1E01B, 0x1E021 }, /* COMBINING GLAGOLITIC LETTER SHTA - COMBINING GLAGOLITIC LETTER YATI */ 340 + { 0x1E023, 0x1E024 }, /* COMBINING GLAGOLITIC LETTER YU - COMBINING GLAGOLITIC LETTER SMALL YUS */ 341 + { 0x1E026, 0x1E02A }, /* COMBINING GLAGOLITIC LETTER YO - COMBINING GLAGOLITIC LETTER FITA */ 342 + { 0x1E08F, 0x1E08F }, /* COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */ 343 + { 0x1E130, 0x1E136 }, /* NYIAKENG PUACHUE HMONG TONE-B - NYIAKENG PUACHUE HMONG TONE-D */ 344 + { 0x1E2AE, 0x1E2AE }, /* TOTO SIGN RISING TONE */ 345 + { 0x1E2EC, 0x1E2EF }, /* WANCHO TONE TUP - WANCHO TONE KOINI */ 346 + { 0x1E4EC, 0x1E4EF }, /* NAG MUNDARI SIGN MUHOR - NAG MUNDARI SIGN SUTUH */ 347 + { 0x1E5EE, 0x1E5EF }, /* OL ONAL SIGN MU - OL ONAL SIGN IKIR */ 348 + { 0x1E8D0, 0x1E8D6 }, /* MENDE KIKAKUI COMBINING NUMBER TEENS - MENDE KIKAKUI COMBINING NUMBER MILLIONS */ 349 + { 0x1E944, 0x1E94A }, /* ADLAM ALIF LENGTHENER - ADLAM NUKTA */ 350 + { 0x1F3FB, 0x1F3FF }, /* EMOJI MODIFIER FITZPATRICK TYPE-1-2 - EMOJI MODIFIER FITZPATRICK TYPE-6 */ 351 + { 0x1F9B0, 0x1F9B3 }, /* EMOJI COMPONENT RED HAIR - EMOJI COMPONENT WHITE HAIR */ 352 + { 0xE0001, 0xE0001 }, /* LANGUAGE TAG */ 353 + { 0xE0020, 0xE007F }, /* TAG SPACE - CANCEL TAG */ 354 + { 0xE0100, 0xE01EF }, /* VARIATION SELECTOR-17 - VARIATION SELECTOR-256 */ 355 + }; 356 + 357 + /* Double-width character ranges (BMP - Basic Multilingual Plane, U+0000 to U+FFFF) */ 358 + static const struct ucs_interval16 ucs_double_width_bmp_ranges[] = { 359 + { 0x1100, 0x115F }, /* HANGUL CHOSEONG KIYEOK - HANGUL CHOSEONG FILLER */ 360 + { 0x231A, 0x231B }, /* WATCH - HOURGLASS */ 361 + { 0x2329, 0x232A }, /* LEFT-POINTING ANGLE BRACKET - RIGHT-POINTING ANGLE BRACKET */ 362 + { 0x23E9, 0x23EC }, /* BLACK RIGHT-POINTING DOUBLE TRIANGLE - BLACK DOWN-POINTING DOUBLE TRIANGLE */ 363 + { 0x23F0, 0x23F0 }, /* ALARM CLOCK */ 364 + { 0x23F3, 0x23F3 }, /* HOURGLASS WITH FLOWING SAND */ 365 + { 0x25FD, 0x25FE }, /* WHITE MEDIUM SMALL SQUARE - BLACK MEDIUM SMALL SQUARE */ 366 + { 0x2614, 0x2615 }, /* UMBRELLA WITH RAIN DROPS - HOT BEVERAGE */ 367 + { 0x2630, 0x2637 }, /* TRIGRAM FOR HEAVEN - TRIGRAM FOR EARTH */ 368 + { 0x2648, 0x2653 }, /* ARIES - PISCES */ 369 + { 0x267F, 0x267F }, /* WHEELCHAIR SYMBOL */ 370 + { 0x268A, 0x268F }, /* MONOGRAM FOR YANG - DIGRAM FOR GREATER YIN */ 371 + { 0x2693, 0x2693 }, /* ANCHOR */ 372 + { 0x26A1, 0x26A1 }, /* HIGH VOLTAGE SIGN */ 373 + { 0x26AA, 0x26AB }, /* MEDIUM WHITE CIRCLE - MEDIUM BLACK CIRCLE */ 374 + { 0x26BD, 0x26BE }, /* SOCCER BALL - BASEBALL */ 375 + { 0x26C4, 0x26C5 }, /* SNOWMAN WITHOUT SNOW - SUN BEHIND CLOUD */ 376 + { 0x26CE, 0x26CE }, /* OPHIUCHUS */ 377 + { 0x26D4, 0x26D4 }, /* NO ENTRY */ 378 + { 0x26EA, 0x26EA }, /* CHURCH */ 379 + { 0x26F2, 0x26F3 }, /* FOUNTAIN - FLAG IN HOLE */ 380 + { 0x26F5, 0x26F5 }, /* SAILBOAT */ 381 + { 0x26FA, 0x26FA }, /* TENT */ 382 + { 0x26FD, 0x26FD }, /* FUEL PUMP */ 383 + { 0x2705, 0x2705 }, /* WHITE HEAVY CHECK MARK */ 384 + { 0x270A, 0x270B }, /* RAISED FIST - RAISED HAND */ 385 + { 0x2728, 0x2728 }, /* SPARKLES */ 386 + { 0x274C, 0x274C }, /* CROSS MARK */ 387 + { 0x274E, 0x274E }, /* NEGATIVE SQUARED CROSS MARK */ 388 + { 0x2753, 0x2755 }, /* BLACK QUESTION MARK ORNAMENT - WHITE EXCLAMATION MARK ORNAMENT */ 389 + { 0x2757, 0x2757 }, /* HEAVY EXCLAMATION MARK SYMBOL */ 390 + { 0x2795, 0x2797 }, /* HEAVY PLUS SIGN - HEAVY DIVISION SIGN */ 391 + { 0x27B0, 0x27B0 }, /* CURLY LOOP */ 392 + { 0x27BF, 0x27BF }, /* DOUBLE CURLY LOOP */ 393 + { 0x2B1B, 0x2B1C }, /* BLACK LARGE SQUARE - WHITE LARGE SQUARE */ 394 + { 0x2B50, 0x2B50 }, /* WHITE MEDIUM STAR */ 395 + { 0x2B55, 0x2B55 }, /* HEAVY LARGE CIRCLE */ 396 + { 0x2E80, 0x2E99 }, /* CJK RADICAL REPEAT - CJK RADICAL RAP */ 397 + { 0x2E9B, 0x2EF3 }, /* CJK RADICAL CHOKE - CJK RADICAL C-SIMPLIFIED TURTLE */ 398 + { 0x2F00, 0x2FD5 }, /* KANGXI RADICAL ONE - KANGXI RADICAL FLUTE */ 399 + { 0x2FF0, 0x3029 }, /* IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT - HANGZHOU NUMERAL NINE */ 400 + { 0x3030, 0x303E }, /* WAVY DASH - IDEOGRAPHIC VARIATION INDICATOR */ 401 + { 0x3041, 0x3096 }, /* HIRAGANA LETTER SMALL A - HIRAGANA LETTER SMALL KE */ 402 + { 0x309B, 0x30FF }, /* KATAKANA-HIRAGANA VOICED SOUND MARK - KATAKANA DIGRAPH KOTO */ 403 + { 0x3105, 0x312F }, /* BOPOMOFO LETTER B - BOPOMOFO LETTER NN */ 404 + { 0x3131, 0x318E }, /* HANGUL LETTER KIYEOK - HANGUL LETTER ARAEAE */ 405 + { 0x3190, 0x31E5 }, /* IDEOGRAPHIC ANNOTATION LINKING MARK - CJK STROKE SZP */ 406 + { 0x31EF, 0x321E }, /* IDEOGRAPHIC DESCRIPTION CHARACTER SUBTRACTION - PARENTHESIZED KOREAN CHARACTER O HU */ 407 + { 0x3220, 0x3247 }, /* PARENTHESIZED IDEOGRAPH ONE - CIRCLED IDEOGRAPH KOTO */ 408 + { 0x3250, 0xA48C }, /* PARTNERSHIP SIGN - YI SYLLABLE YYR */ 409 + { 0xA490, 0xA4C6 }, /* YI RADICAL QOT - YI RADICAL KE */ 410 + { 0xA960, 0xA97C }, /* HANGUL CHOSEONG TIKEUT-MIEUM - HANGUL CHOSEONG SSANGYEORINHIEUH */ 411 + { 0xAC00, 0xD7A3 }, /* HANGUL SYLLABLE GA - HANGUL SYLLABLE HIH */ 412 + { 0xF900, 0xFAFF }, /* U+F900 - U+FAFF */ 413 + { 0xFE10, 0xFE19 }, /* PRESENTATION FORM FOR VERTICAL COMMA - PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS */ 414 + { 0xFE30, 0xFE52 }, /* PRESENTATION FORM FOR VERTICAL TWO DOT LEADER - SMALL FULL STOP */ 415 + { 0xFE54, 0xFE66 }, /* SMALL SEMICOLON - SMALL EQUALS SIGN */ 416 + { 0xFE68, 0xFE6B }, /* SMALL REVERSE SOLIDUS - SMALL COMMERCIAL AT */ 417 + { 0xFF01, 0xFF60 }, /* FULLWIDTH EXCLAMATION MARK - FULLWIDTH RIGHT WHITE PARENTHESIS */ 418 + { 0xFFE0, 0xFFE6 }, /* FULLWIDTH CENT SIGN - FULLWIDTH WON SIGN */ 419 + }; 420 + 421 + /* Double-width character ranges (non-BMP, U+10000 and above) */ 422 + static const struct ucs_interval32 ucs_double_width_non_bmp_ranges[] = { 423 + { 0x16FE0, 0x16FE3 }, /* TANGUT ITERATION MARK - OLD CHINESE ITERATION MARK */ 424 + { 0x17000, 0x187F7 }, /* U+17000 - U+187F7 */ 425 + { 0x18800, 0x18CD5 }, /* TANGUT COMPONENT-001 - KHITAN SMALL SCRIPT CHARACTER-18CD5 */ 426 + { 0x18CFF, 0x18D08 }, /* U+18CFF - U+18D08 */ 427 + { 0x1AFF0, 0x1AFF3 }, /* KATAKANA LETTER MINNAN TONE-2 - KATAKANA LETTER MINNAN TONE-5 */ 428 + { 0x1AFF5, 0x1AFFB }, /* KATAKANA LETTER MINNAN TONE-7 - KATAKANA LETTER MINNAN NASALIZED TONE-5 */ 429 + { 0x1AFFD, 0x1AFFE }, /* KATAKANA LETTER MINNAN NASALIZED TONE-7 - KATAKANA LETTER MINNAN NASALIZED TONE-8 */ 430 + { 0x1B000, 0x1B122 }, /* KATAKANA LETTER ARCHAIC E - KATAKANA LETTER ARCHAIC WU */ 431 + { 0x1B132, 0x1B132 }, /* HIRAGANA LETTER SMALL KO */ 432 + { 0x1B150, 0x1B152 }, /* HIRAGANA LETTER SMALL WI - HIRAGANA LETTER SMALL WO */ 433 + { 0x1B155, 0x1B155 }, /* KATAKANA LETTER SMALL KO */ 434 + { 0x1B164, 0x1B167 }, /* KATAKANA LETTER SMALL WI - KATAKANA LETTER SMALL N */ 435 + { 0x1B170, 0x1B2FB }, /* NUSHU CHARACTER-1B170 - NUSHU CHARACTER-1B2FB */ 436 + { 0x1D300, 0x1D356 }, /* MONOGRAM FOR EARTH - TETRAGRAM FOR FOSTERING */ 437 + { 0x1D360, 0x1D376 }, /* COUNTING ROD UNIT DIGIT ONE - IDEOGRAPHIC TALLY MARK FIVE */ 438 + { 0x1F000, 0x1F02F }, /* U+1F000 - U+1F02F */ 439 + { 0x1F0A0, 0x1F0FF }, /* U+1F0A0 - U+1F0FF */ 440 + { 0x1F18E, 0x1F18E }, /* NEGATIVE SQUARED AB */ 441 + { 0x1F191, 0x1F19A }, /* SQUARED CL - SQUARED VS */ 442 + { 0x1F200, 0x1F202 }, /* SQUARE HIRAGANA HOKA - SQUARED KATAKANA SA */ 443 + { 0x1F210, 0x1F23B }, /* SQUARED CJK UNIFIED IDEOGRAPH-624B - SQUARED CJK UNIFIED IDEOGRAPH-914D */ 444 + { 0x1F240, 0x1F248 }, /* TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C - TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557 */ 445 + { 0x1F250, 0x1F251 }, /* CIRCLED IDEOGRAPH ADVANTAGE - CIRCLED IDEOGRAPH ACCEPT */ 446 + { 0x1F260, 0x1F265 }, /* ROUNDED SYMBOL FOR FU - ROUNDED SYMBOL FOR CAI */ 447 + { 0x1F300, 0x1F3FA }, /* CYCLONE - AMPHORA */ 448 + { 0x1F400, 0x1F64F }, /* RAT - PERSON WITH FOLDED HANDS */ 449 + { 0x1F680, 0x1F9AF }, /* ROCKET - PROBING CANE */ 450 + { 0x1F9B4, 0x1FAFF }, /* U+1F9B4 - U+1FAFF */ 451 + { 0x20000, 0x2FFFD }, /* U+20000 - U+2FFFD */ 452 + { 0x30000, 0x3FFFD }, /* U+30000 - U+3FFFD */ 453 + };
+163 -79
drivers/tty/vt/vt.c
··· 104 104 #include <linux/uaccess.h> 105 105 #include <linux/kdb.h> 106 106 #include <linux/ctype.h> 107 - #include <linux/bsearch.h> 108 107 #include <linux/gcd.h> 109 108 110 109 #define MAX_NR_CON_DRIVER 16 ··· 441 442 juggle_array(&uni_lines[top], size, nr); 442 443 vc_uniscr_clear_lines(vc, bottom - nr, nr); 443 444 } 445 + } 446 + 447 + static u32 vc_uniscr_getc(struct vc_data *vc, int relative_pos) 448 + { 449 + int pos = vc->state.x + vc->vc_need_wrap + relative_pos; 450 + 451 + if (vc->vc_uni_lines && in_range(pos, 0, vc->vc_cols)) 452 + return vc->vc_uni_lines[vc->state.y][pos]; 453 + return 0; 444 454 } 445 455 446 456 static void vc_uniscr_copy_area(u32 **dst_lines, ··· 1870 1862 return vc_cons[fg_console].d->vc_report_mouse; 1871 1863 } 1872 1864 1865 + /* invoked via ioctl(TIOCLINUX) */ 1866 + static int get_bracketed_paste(struct tty_struct *tty) 1867 + { 1868 + struct vc_data *vc = tty->driver_data; 1869 + 1870 + return vc->vc_bracketed_paste; 1871 + } 1872 + 1873 1873 enum { 1874 1874 CSI_DEC_hl_CURSOR_KEYS = 1, /* CKM: cursor keys send ^[Ox/^[[x */ 1875 1875 CSI_DEC_hl_132_COLUMNS = 3, /* COLM: 80/132 mode switch */ ··· 1888 1872 CSI_DEC_hl_MOUSE_X10 = 9, 1889 1873 CSI_DEC_hl_SHOW_CURSOR = 25, /* TCEM */ 1890 1874 CSI_DEC_hl_MOUSE_VT200 = 1000, 1875 + CSI_DEC_hl_BRACKETED_PASTE = 2004, 1891 1876 }; 1892 1877 1893 1878 /* console_lock is held */ ··· 1940 1923 break; 1941 1924 case CSI_DEC_hl_MOUSE_VT200: 1942 1925 vc->vc_report_mouse = on_off ? 2 : 0; 1926 + break; 1927 + case CSI_DEC_hl_BRACKETED_PASTE: 1928 + vc->vc_bracketed_paste = on_off; 1943 1929 break; 1944 1930 } 1945 1931 } ··· 2169 2149 vc->state.charset = 0; 2170 2150 vc->vc_need_wrap = 0; 2171 2151 vc->vc_report_mouse = 0; 2152 + vc->vc_bracketed_paste = 0; 2172 2153 vc->vc_utf = default_utf8; 2173 2154 vc->vc_utf_count = 0; 2174 2155 ··· 2733 2712 } 2734 2713 } 2735 2714 2736 - /* is_double_width() is based on the wcwidth() implementation by 2737 - * Markus Kuhn -- 2007-05-26 (Unicode 5.0) 2738 - * Latest version: https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c 2739 - */ 2740 - struct interval { 2741 - uint32_t first; 2742 - uint32_t last; 2743 - }; 2744 - 2745 - static int ucs_cmp(const void *key, const void *elt) 2746 - { 2747 - uint32_t ucs = *(uint32_t *)key; 2748 - struct interval e = *(struct interval *) elt; 2749 - 2750 - if (ucs > e.last) 2751 - return 1; 2752 - else if (ucs < e.first) 2753 - return -1; 2754 - return 0; 2755 - } 2756 - 2757 - static int is_double_width(uint32_t ucs) 2758 - { 2759 - static const struct interval double_width[] = { 2760 - { 0x1100, 0x115F }, { 0x2329, 0x232A }, { 0x2E80, 0x303E }, 2761 - { 0x3040, 0xA4CF }, { 0xAC00, 0xD7A3 }, { 0xF900, 0xFAFF }, 2762 - { 0xFE10, 0xFE19 }, { 0xFE30, 0xFE6F }, { 0xFF00, 0xFF60 }, 2763 - { 0xFFE0, 0xFFE6 }, { 0x20000, 0x2FFFD }, { 0x30000, 0x3FFFD } 2764 - }; 2765 - if (ucs < double_width[0].first || 2766 - ucs > double_width[ARRAY_SIZE(double_width) - 1].last) 2767 - return 0; 2768 - 2769 - return bsearch(&ucs, double_width, ARRAY_SIZE(double_width), 2770 - sizeof(struct interval), ucs_cmp) != NULL; 2771 - } 2772 - 2773 2715 struct vc_draw_region { 2774 2716 unsigned long from, to; 2775 2717 int x; ··· 2801 2817 if ((c & 0xc0) == 0x80) { 2802 2818 /* Unexpected continuation byte? */ 2803 2819 if (!vc->vc_utf_count) 2804 - return 0xfffd; 2820 + goto bad_sequence; 2805 2821 2806 2822 vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f); 2807 2823 vc->vc_npar++; ··· 2813 2829 /* Reject overlong sequences */ 2814 2830 if (c <= utf8_length_changes[vc->vc_npar - 1] || 2815 2831 c > utf8_length_changes[vc->vc_npar]) 2816 - return 0xfffd; 2832 + goto bad_sequence; 2817 2833 2818 2834 return vc_sanitize_unicode(c); 2819 2835 } 2820 2836 2821 2837 /* Single ASCII byte or first byte of a sequence received */ 2822 2838 if (vc->vc_utf_count) { 2823 - /* Continuation byte expected */ 2839 + /* A continuation byte was expected */ 2824 2840 *rescan = true; 2825 2841 vc->vc_utf_count = 0; 2826 - return 0xfffd; 2842 + goto bad_sequence; 2827 2843 } 2828 2844 2829 2845 /* Nothing to do if an ASCII byte was received */ ··· 2842 2858 vc->vc_utf_count = 3; 2843 2859 vc->vc_utf_char = (c & 0x07); 2844 2860 } else { 2845 - return 0xfffd; 2861 + goto bad_sequence; 2846 2862 } 2847 2863 2848 2864 need_more_bytes: 2849 2865 return -1; 2866 + 2867 + bad_sequence: 2868 + return 0xfffd; 2850 2869 } 2851 2870 2852 2871 static int vc_translate(struct vc_data *vc, int *c, bool *rescan) ··· 2927 2940 return false; 2928 2941 } 2929 2942 2943 + static void vc_con_rewind(struct vc_data *vc) 2944 + { 2945 + if (vc->state.x && !vc->vc_need_wrap) { 2946 + vc->vc_pos -= 2; 2947 + vc->state.x--; 2948 + } 2949 + vc->vc_need_wrap = 0; 2950 + } 2951 + 2952 + #define UCS_ZWS 0x200b /* Zero Width Space */ 2953 + #define UCS_VS16 0xfe0f /* Variation Selector 16 */ 2954 + #define UCS_REPLACEMENT 0xfffd /* Replacement Character */ 2955 + 2956 + static int vc_process_ucs(struct vc_data *vc, int *c, int *tc) 2957 + { 2958 + u32 prev_c, curr_c = *c; 2959 + 2960 + if (ucs_is_double_width(curr_c)) { 2961 + /* 2962 + * The Unicode screen memory is allocated only when 2963 + * required. This is one such case as we need to remember 2964 + * which displayed characters are double-width. 2965 + */ 2966 + vc_uniscr_check(vc); 2967 + return 2; 2968 + } 2969 + 2970 + if (!ucs_is_zero_width(curr_c)) 2971 + return 1; 2972 + 2973 + /* From here curr_c is known to be zero-width. */ 2974 + 2975 + if (ucs_is_double_width(vc_uniscr_getc(vc, -2))) { 2976 + /* 2977 + * Let's merge this zero-width code point with the preceding 2978 + * double-width code point by replacing the existing 2979 + * zero-width space padding. To do so we rewind one column 2980 + * and pretend this has a width of 1. 2981 + * We give the legacy display the same initial space padding. 2982 + */ 2983 + vc_con_rewind(vc); 2984 + *tc = ' '; 2985 + return 1; 2986 + } 2987 + 2988 + /* From here the preceding character, if any, must be single-width. */ 2989 + prev_c = vc_uniscr_getc(vc, -1); 2990 + 2991 + if (curr_c == UCS_VS16 && prev_c != 0) { 2992 + /* 2993 + * VS16 (U+FE0F) is special. It typically turns the preceding 2994 + * single-width character into a double-width one. Let it 2995 + * have a width of 1 effectively making the combination with 2996 + * the preceding character double-width. 2997 + */ 2998 + *tc = ' '; 2999 + return 1; 3000 + } 3001 + 3002 + /* try recomposition */ 3003 + prev_c = ucs_recompose(prev_c, curr_c); 3004 + if (prev_c != 0) { 3005 + vc_con_rewind(vc); 3006 + *tc = *c = prev_c; 3007 + return 1; 3008 + } 3009 + 3010 + /* Otherwise zero-width code points are ignored. */ 3011 + return 0; 3012 + } 3013 + 3014 + static int vc_get_glyph(struct vc_data *vc, int tc) 3015 + { 3016 + int glyph = conv_uni_to_pc(vc, tc); 3017 + u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; 3018 + 3019 + if (!(glyph & ~charmask)) 3020 + return glyph; 3021 + 3022 + if (glyph == -1) 3023 + return -1; /* nothing to display */ 3024 + 3025 + /* Glyph not found */ 3026 + if ((!vc->vc_utf || vc->vc_disp_ctrl || tc < 128) && !(tc & ~charmask)) { 3027 + /* 3028 + * In legacy mode use the glyph we get by a 1:1 mapping. 3029 + * This would make absolutely no sense with Unicode in mind, but do this for 3030 + * ASCII characters since a font may lack Unicode mapping info and we don't 3031 + * want to end up with having question marks only. 3032 + */ 3033 + return tc; 3034 + } 3035 + 3036 + /* 3037 + * The Unicode screen memory is allocated only when required. 3038 + * This is one such case: we're about to "cheat" with the displayed 3039 + * character meaning the simple screen buffer won't hold the original 3040 + * information, whereas the Unicode screen buffer always does. 3041 + */ 3042 + vc_uniscr_check(vc); 3043 + 3044 + /* Try getting a simpler fallback character. */ 3045 + tc = ucs_get_fallback(tc); 3046 + if (tc) 3047 + return vc_get_glyph(vc, tc); 3048 + 3049 + /* Display U+FFFD (Unicode Replacement Character). */ 3050 + return conv_uni_to_pc(vc, UCS_REPLACEMENT); 3051 + } 3052 + 2930 3053 static int vc_con_write_normal(struct vc_data *vc, int tc, int c, 2931 3054 struct vc_draw_region *draw) 2932 3055 { 2933 3056 int next_c; 2934 3057 unsigned char vc_attr = vc->vc_attr; 2935 - u16 himask = vc->vc_hi_font_mask, charmask = himask ? 0x1ff : 0xff; 3058 + u16 himask = vc->vc_hi_font_mask; 2936 3059 u8 width = 1; 2937 3060 bool inverse = false; 2938 3061 2939 3062 if (vc->vc_utf && !vc->vc_disp_ctrl) { 2940 - if (is_double_width(c)) 2941 - width = 2; 3063 + width = vc_process_ucs(vc, &c, &tc); 3064 + if (!width) 3065 + goto out; 2942 3066 } 2943 3067 2944 3068 /* Now try to find out how to display it */ 2945 - tc = conv_uni_to_pc(vc, tc); 2946 - if (tc & ~charmask) { 2947 - if (tc == -1 || tc == -2) 2948 - return -1; /* nothing to display */ 3069 + tc = vc_get_glyph(vc, tc); 3070 + if (tc == -1) 3071 + return -1; /* nothing to display */ 3072 + if (tc < 0) { 3073 + inverse = true; 3074 + tc = conv_uni_to_pc(vc, '?'); 3075 + if (tc < 0) 3076 + tc = '?'; 2949 3077 2950 - /* Glyph not found */ 2951 - if ((!vc->vc_utf || vc->vc_disp_ctrl || c < 128) && 2952 - !(c & ~charmask)) { 2953 - /* 2954 - * In legacy mode use the glyph we get by a 1:1 2955 - * mapping. 2956 - * This would make absolutely no sense with Unicode in 2957 - * mind, but do this for ASCII characters since a font 2958 - * may lack Unicode mapping info and we don't want to 2959 - * end up with having question marks only. 2960 - */ 2961 - tc = c; 2962 - } else { 2963 - /* 2964 - * Display U+FFFD. If it's not found, display an inverse 2965 - * question mark. 2966 - */ 2967 - tc = conv_uni_to_pc(vc, 0xfffd); 2968 - if (tc < 0) { 2969 - inverse = true; 2970 - tc = conv_uni_to_pc(vc, '?'); 2971 - if (tc < 0) 2972 - tc = '?'; 2973 - 2974 - vc_attr = vc_invert_attr(vc); 2975 - con_flush(vc, draw); 2976 - } 2977 - } 3078 + vc_attr = vc_invert_attr(vc); 3079 + con_flush(vc, draw); 2978 3080 } 2979 3081 2980 3082 next_c = c; ··· 3104 3028 tc = conv_uni_to_pc(vc, ' '); 3105 3029 if (tc < 0) 3106 3030 tc = ' '; 3107 - next_c = ' '; 3031 + /* 3032 + * Store a zero-width space in the Unicode screen given that 3033 + * the previous code point is semantically double width. 3034 + */ 3035 + next_c = UCS_ZWS; 3108 3036 } 3037 + 3038 + out: 3109 3039 notify_write(vc, c); 3110 3040 3111 3041 if (inverse) ··· 3496 3414 break; 3497 3415 case TIOCL_BLANKEDSCREEN: 3498 3416 return console_blanked; 3417 + case TIOCL_GETBRACKETEDPASTE: 3418 + return get_bracketed_paste(tty); 3499 3419 default: 3500 3420 return -EINVAL; 3501 3421 }
+16 -2
drivers/tty/vt/vt_ioctl.c
··· 951 951 (unsigned short __user *)arg); 952 952 case VT_WAITEVENT: 953 953 return vt_event_wait_ioctl((struct vt_event __user *)arg); 954 + 955 + case VT_GETCONSIZECSRPOS: 956 + { 957 + struct vt_consizecsrpos concsr; 958 + 959 + console_lock(); 960 + concsr.con_cols = vc->vc_cols; 961 + concsr.con_rows = vc->vc_rows; 962 + concsr.csr_col = vc->state.x; 963 + concsr.csr_row = vc->state.y; 964 + console_unlock(); 965 + if (copy_to_user(up, &concsr, sizeof(concsr))) 966 + return -EFAULT; 967 + return 0; 968 + } 969 + 954 970 default: 955 971 return -ENOIOCTLCMD; 956 972 } ··· 1119 1103 case VT_WAITACTIVE: 1120 1104 case VT_RELDISP: 1121 1105 case VT_DISALLOCATE: 1122 - case VT_RESIZE: 1123 - case VT_RESIZEX: 1124 1106 return vt_ioctl(tty, cmd, arg); 1125 1107 1126 1108 /*
+1
include/linux/console_struct.h
··· 145 145 unsigned int vc_need_wrap : 1; 146 146 unsigned int vc_can_do_color : 1; 147 147 unsigned int vc_report_mouse : 2; 148 + unsigned int vc_bracketed_paste : 1; 148 149 unsigned char vc_utf : 1; /* Unicode UTF-8 encoding */ 149 150 unsigned char vc_utf_count; 150 151 int vc_utf_char;
+24
include/linux/consolemap.h
··· 28 28 u32 conv_8bit_to_uni(unsigned char c); 29 29 int conv_uni_to_8bit(u32 uni); 30 30 void console_map_init(void); 31 + bool ucs_is_double_width(uint32_t cp); 32 + bool ucs_is_zero_width(uint32_t cp); 33 + u32 ucs_recompose(u32 base, u32 mark); 34 + u32 ucs_get_fallback(u32 cp); 31 35 #else 32 36 static inline u16 inverse_translate(const struct vc_data *conp, u16 glyph, 33 37 bool use_unicode) ··· 61 57 } 62 58 63 59 static inline void console_map_init(void) { } 60 + 61 + static inline bool ucs_is_double_width(uint32_t cp) 62 + { 63 + return false; 64 + } 65 + 66 + static inline bool ucs_is_zero_width(uint32_t cp) 67 + { 68 + return false; 69 + } 70 + 71 + static inline u32 ucs_recompose(u32 base, u32 mark) 72 + { 73 + return 0; 74 + } 75 + 76 + static inline u32 ucs_get_fallback(u32 cp) 77 + { 78 + return 0; 79 + } 64 80 #endif /* CONFIG_CONSOLE_TRANSLATIONS */ 65 81 66 82 #endif /* __LINUX_CONSOLEMAP_H__ */
+16 -14
include/linux/serial_core.h
··· 427 427 typedef u64 __bitwise upf_t; 428 428 typedef unsigned int __bitwise upstat_t; 429 429 430 + enum uart_iotype { 431 + UPIO_UNKNOWN = -1, 432 + UPIO_PORT = SERIAL_IO_PORT, /* 8b I/O port access */ 433 + UPIO_HUB6 = SERIAL_IO_HUB6, /* Hub6 ISA card */ 434 + UPIO_MEM = SERIAL_IO_MEM, /* driver-specific */ 435 + UPIO_MEM32 = SERIAL_IO_MEM32, /* 32b little endian */ 436 + UPIO_AU = SERIAL_IO_AU, /* Au1x00 and RT288x type IO */ 437 + UPIO_TSI = SERIAL_IO_TSI, /* Tsi108/109 type IO */ 438 + UPIO_MEM32BE = SERIAL_IO_MEM32BE, /* 32b big endian */ 439 + UPIO_MEM16 = SERIAL_IO_MEM16, /* 16b little endian */ 440 + }; 441 + 430 442 struct uart_port { 431 443 spinlock_t lock; /* port lock */ 432 444 unsigned long iobase; /* in/out[bwl] */ ··· 481 469 unsigned char x_char; /* xon/xoff char */ 482 470 unsigned char regshift; /* reg offset shift */ 483 471 484 - unsigned char iotype; /* io access style */ 485 - 486 - #define UPIO_UNKNOWN ((unsigned char)~0U) /* UCHAR_MAX */ 487 - #define UPIO_PORT (SERIAL_IO_PORT) /* 8b I/O port access */ 488 - #define UPIO_HUB6 (SERIAL_IO_HUB6) /* Hub6 ISA card */ 489 - #define UPIO_MEM (SERIAL_IO_MEM) /* driver-specific */ 490 - #define UPIO_MEM32 (SERIAL_IO_MEM32) /* 32b little endian */ 491 - #define UPIO_AU (SERIAL_IO_AU) /* Au1x00 and RT288x type IO */ 492 - #define UPIO_TSI (SERIAL_IO_TSI) /* Tsi108/109 type IO */ 493 - #define UPIO_MEM32BE (SERIAL_IO_MEM32BE) /* 32b big endian */ 494 - #define UPIO_MEM16 (SERIAL_IO_MEM16) /* 16b little endian */ 495 - 496 472 unsigned char quirks; /* internal quirks */ 497 473 498 474 /* internal quirks must be updated while holding port mutex */ 499 475 #define UPQ_NO_TXEN_TEST BIT(0) 476 + 477 + enum uart_iotype iotype; /* io access style */ 500 478 501 479 unsigned int read_status_mask; /* driver specific */ 502 480 unsigned int ignore_status_mask; /* driver specific */ ··· 1103 1101 1104 1102 struct uart_port *uart_get_console(struct uart_port *ports, int nr, 1105 1103 struct console *c); 1106 - int uart_parse_earlycon(char *p, unsigned char *iotype, resource_size_t *addr, 1107 - char **options); 1104 + int uart_parse_earlycon(char *p, enum uart_iotype *iotype, 1105 + resource_size_t *addr, char **options); 1108 1106 void uart_parse_options(const char *options, int *baud, int *parity, int *bits, 1109 1107 int *flow); 1110 1108 int uart_set_options(struct uart_port *port, struct console *co, int baud,
-3
include/linux/tty_port.h
··· 147 147 struct tty_driver *driver, unsigned index, 148 148 struct device *device, void *drvdata, 149 149 const struct attribute_group **attr_grp); 150 - struct device *tty_port_register_device_serdev(struct tty_port *port, 151 - struct tty_driver *driver, unsigned index, 152 - struct device *host, struct device *parent); 153 150 struct device *tty_port_register_device_attr_serdev(struct tty_port *port, 154 151 struct tty_driver *driver, unsigned index, 155 152 struct device *host, struct device *parent, void *drvdata,
+1
include/uapi/linux/tiocl.h
··· 36 36 #define TIOCL_BLANKSCREEN 14 /* keep screen blank even if a key is pressed */ 37 37 #define TIOCL_BLANKEDSCREEN 15 /* return which vt was blanked */ 38 38 #define TIOCL_GETKMSGREDIRECT 17 /* get the vt the kernel messages are restricted to */ 39 + #define TIOCL_GETBRACKETEDPASTE 18 /* get whether paste may be bracketed */ 39 40 40 41 #endif /* _LINUX_TIOCL_H */
+11
include/uapi/linux/vt.h
··· 2 2 #ifndef _UAPI_LINUX_VT_H 3 3 #define _UAPI_LINUX_VT_H 4 4 5 + #include <linux/ioctl.h> 6 + #include <linux/types.h> 5 7 6 8 /* 7 9 * These constants are also useful for user-level apps (e.g., VC ··· 85 83 }; 86 84 87 85 #define VT_SETACTIVATE 0x560F /* Activate and set the mode of a console */ 86 + 87 + /* get console size and cursor position */ 88 + struct vt_consizecsrpos { 89 + __u16 con_rows; /* number of console rows */ 90 + __u16 con_cols; /* number of console columns */ 91 + __u16 csr_row; /* current cursor's row */ 92 + __u16 csr_col; /* current cursor's column */ 93 + }; 94 + #define VT_GETCONSIZECSRPOS _IOR('V', 0x10, struct vt_consizecsrpos) 88 95 89 96 #endif /* _UAPI_LINUX_VT_H */