livesplit_hotkey/linux/x11_impl.rs
1use std::{
2 collections::HashMap,
3 mem::MaybeUninit,
4 os::raw::{c_int, c_uint},
5 ptr, thread,
6};
7
8use mio::{unix::SourceFd, Events, Interest, Poll, Token, Waker};
9use x11_dl::xlib::{
10 AnyKey, AnyModifier, ControlMask, Display, GrabModeAsync, KeyPress, LockMask, Mod1Mask,
11 Mod2Mask, Mod3Mask, Mod4Mask, ShiftMask, XErrorEvent, XKeyEvent, Xlib, _XDisplay,
12};
13
14use super::{Error, Hook, Message};
15use crate::{KeyCode, Modifiers, Result};
16
17unsafe fn ungrab_all(xlib: &Xlib, display: *mut Display) {
18 let screencount = (xlib.XScreenCount)(display);
19 for screen in 0..screencount {
20 let rootwindow = (xlib.XRootWindow)(display, screen);
21 (xlib.XUngrabKey)(display, AnyKey, AnyModifier, rootwindow);
22 }
23}
24
25const fn mask(x: c_uint) -> u8 {
26 if x < 256 {
27 x as u8
28 } else {
29 panic!()
30 }
31}
32
33const CAPS_LOCK: u8 = mask(LockMask);
34const NUM_LOCK: u8 = mask(Mod2Mask);
35const SCROLL_LOCK: u8 = mask(Mod3Mask);
36
37// X11 has no way of ignoring additional modifiers, so we have to register every
38// single combination of them. We are mostly only interested in the lock keys,
39// because they may be in the wrong state without you actively interacting with
40// them.
41const IGNORE_MASKS: [u8; 8] = [
42 0,
43 CAPS_LOCK,
44 NUM_LOCK,
45 NUM_LOCK | CAPS_LOCK,
46 SCROLL_LOCK,
47 SCROLL_LOCK | CAPS_LOCK,
48 SCROLL_LOCK | NUM_LOCK,
49 SCROLL_LOCK | NUM_LOCK | CAPS_LOCK,
50];
51
52unsafe fn grab_key(
53 xlib: &Xlib,
54 display: *mut Display,
55 code: c_uint,
56 modifiers: Modifiers,
57 ungrab: bool,
58) {
59 let screencount = (xlib.XScreenCount)(display);
60 for screen in 0..screencount {
61 let window = (xlib.XRootWindow)(display, screen);
62
63 let mut mod_mask = 0;
64 if modifiers.contains(Modifiers::SHIFT) {
65 mod_mask |= ShiftMask;
66 }
67 if modifiers.contains(Modifiers::CONTROL) {
68 mod_mask |= ControlMask;
69 }
70 if modifiers.contains(Modifiers::ALT) {
71 mod_mask |= Mod1Mask;
72 }
73 if modifiers.contains(Modifiers::META) {
74 mod_mask |= Mod4Mask;
75 }
76
77 for ignore_mask in IGNORE_MASKS {
78 if ungrab {
79 (xlib.XUngrabKey)(
80 display,
81 code as c_int,
82 mod_mask | (ignore_mask as c_uint),
83 window,
84 );
85 } else {
86 (xlib.XGrabKey)(
87 display,
88 code as c_int,
89 mod_mask | (ignore_mask as c_uint),
90 window,
91 false as _,
92 GrabModeAsync,
93 GrabModeAsync,
94 );
95 }
96 }
97 }
98
99 // On some X11 connections it's crucial for the events to be flushed. They
100 // may otherwise stay buffered and the hotkeys don't actually work.
101 (xlib.XFlush)(display);
102}
103
104unsafe extern "C" fn handle_error(_: *mut Display, _: *mut XErrorEvent) -> c_int {
105 0
106}
107
108const fn code_for(key: KeyCode) -> Option<c_uint> {
109 match super::evdev_impl::code_for(key) {
110 Some(code) => Some(code.0 as c_uint + 8),
111 None => None,
112 }
113}
114
115const X_TOKEN: Token = Token(0);
116const PING_TOKEN: Token = Token(1);
117
118pub fn new() -> Result<Hook> {
119 unsafe {
120 let (sender, receiver) = crossbeam_channel::unbounded();
121
122 let xlib = Xlib::open().map_err(|_| Error::NoXLib)?;
123 (xlib.XSetErrorHandler)(Some(handle_error));
124
125 let display = (xlib.XOpenDisplay)(ptr::null());
126 if display.is_null() {
127 return Err(Error::OpenXServerConnection.into());
128 }
129
130 let fd = (xlib.XConnectionNumber)(display) as std::os::unix::io::RawFd;
131 let mut poll = Poll::new().map_err(|_| Error::EPoll)?;
132
133 let waker = Waker::new(poll.registry(), PING_TOKEN).map_err(|_| Error::EPoll)?;
134
135 poll.registry()
136 .register(
137 &mut SourceFd(&fd),
138 X_TOKEN,
139 Interest::READABLE | Interest::WRITABLE,
140 )
141 .map_err(|_| Error::EPoll)?;
142
143 struct XData(Xlib, *mut Display);
144 unsafe impl Send for XData {}
145 let xdata = XData(xlib, display);
146
147 let join_handle = thread::spawn(move || -> Result<()> {
148 // Force the whole XData to be moved.
149 let XData(xlib, display) = { xdata };
150
151 let mut result = Ok(());
152 let mut events = Events::with_capacity(1024);
153 let mut hotkeys = HashMap::new();
154
155 // For some reason we need to call this once for any KeyGrabs to
156 // actually do anything.
157 (xlib.XKeysymToKeycode)(display, 0);
158
159 'event_loop: loop {
160 if poll.poll(&mut events, None).is_err() {
161 result = Err(Error::EPoll);
162 break 'event_loop;
163 }
164
165 for mio_event in &events {
166 if mio_event.token() == PING_TOKEN {
167 for message in receiver.try_iter() {
168 match message {
169 Message::Register(key, callback, promise) => {
170 promise.set(if let Some(code) = code_for(key.key_code) {
171 if hotkeys.insert((code, key.modifiers), callback).is_some()
172 {
173 Err(crate::Error::AlreadyRegistered)
174 } else {
175 grab_key(&xlib, display, code, key.modifiers, false);
176 Ok(())
177 }
178 } else {
179 Ok(())
180 });
181 }
182 Message::Unregister(key, promise) => {
183 let res = if let Some(code) = code_for(key.key_code) {
184 let res = hotkeys
185 .remove(&(code, key.modifiers))
186 .map(drop)
187 .ok_or(crate::Error::NotRegistered);
188 if res.is_ok() {
189 grab_key(&xlib, display, code, key.modifiers, true);
190 }
191 res
192 } else {
193 Ok(())
194 };
195 promise.set(res);
196 }
197 Message::Resolve(key_code, promise) => {
198 promise.set(resolve(&xlib, display, key_code))
199 }
200 Message::End => {
201 break 'event_loop;
202 }
203 }
204 }
205 } else if mio_event.token() == X_TOKEN {
206 while (xlib.XPending)(display) != 0 {
207 let mut event = MaybeUninit::uninit();
208 let err_code = (xlib.XNextEvent)(display, event.as_mut_ptr());
209 if err_code == 0 {
210 let event = event.assume_init();
211 if event.get_type() == KeyPress {
212 let event: &XKeyEvent = event.as_ref();
213
214 let mut modifiers = Modifiers::empty();
215 if event.state & ShiftMask != 0 {
216 modifiers.insert(Modifiers::SHIFT);
217 }
218 if event.state & ControlMask != 0 {
219 modifiers.insert(Modifiers::CONTROL);
220 }
221 if event.state & Mod1Mask != 0 {
222 modifiers.insert(Modifiers::ALT);
223 }
224 if event.state & Mod4Mask != 0 {
225 modifiers.insert(Modifiers::META);
226 }
227
228 if let Some(callback) =
229 hotkeys.get_mut(&(event.keycode, modifiers))
230 {
231 callback();
232 }
233 }
234 }
235 }
236 }
237 }
238 }
239
240 ungrab_all(&xlib, display);
241
242 (xlib.XCloseDisplay)(display);
243
244 result.map_err(Into::into)
245 });
246
247 Ok(Hook {
248 sender,
249 waker,
250 join_handle: Some(join_handle),
251 })
252 }
253}
254
255pub(super) fn resolve(xlib: &Xlib, display: *mut _XDisplay, key_code: KeyCode) -> Option<char> {
256 let key_sym = unsafe { (xlib.XKeycodeToKeysym)(display, code_for(key_code)? as _, 0) };
257 if key_sym == 0 {
258 return None;
259 }
260 let code_point = keysym_to_utf32(key_sym as _);
261 if code_point == 0 {
262 return None;
263 }
264 char::from_u32(code_point)
265}
266
267// Based on this public domain code:
268// https://github.com/xkbcommon/libxkbcommon/blob/9af1f9f2cb3a7895f6ed7a130ffd3da1006dcc7b/src/keysym-utf.c
269fn keysym_to_utf32(keysym: u64) -> u32 {
270 const KP_SPACE: u64 = 0xff80;
271 const KP_TAB: u64 = 0xff89;
272 const KP_ENTER: u64 = 0xff8d;
273 const KP_EQUAL: u64 = 0xffbd;
274 const KP_MULTIPLY: u64 = 0xffaa;
275 const SPACE: u64 = 0x0020;
276 const BACKSPACE: u64 = 0xff08;
277 const CLEAR: u64 = 0xff0b;
278 const RETURN: u64 = 0xff0d;
279 const ESCAPE: u64 = 0xff1b;
280 const DELETE: u64 = 0xffff;
281 const KP_9: u64 = 0xffb9;
282
283 const NO_KEYSYM_UNICODE_CONVERSION: u32 = 0;
284
285 /// Offset to use when converting a Unicode code point to a keysym
286 const XKB_KEYSYM_UNICODE_OFFSET: u64 = 0x01000000;
287 /// Maximum Unicode keysym, correspoding to the maximum Unicode code point
288 const XKB_KEYSYM_UNICODE_MAX: u64 = 0x0110ffff;
289
290 // first check for Latin-1 characters (1:1 mapping)
291 if matches!(keysym, 0x0020..=0x007e | 0x00a0..=0x00ff) {
292 return keysym as u32;
293 }
294
295 // patch encoding botch
296 if keysym == KP_SPACE {
297 return (SPACE & 0x7f) as u32;
298 }
299
300 // special keysyms
301 if matches!(
302 keysym,
303 BACKSPACE..=CLEAR |
304 KP_MULTIPLY..=KP_9 |
305 RETURN | ESCAPE | DELETE | KP_TAB | KP_ENTER | KP_EQUAL
306 ) {
307 return (keysym & 0x7f) as u32;
308 }
309
310 // also check for directly encoded Unicode codepoints
311
312 // Exclude surrogates: they are invalid in UTF-32.
313 // See https://www.unicode.org/versions/Unicode15.0.0/ch03.pdf#G28875
314 // for further details.
315 if matches!(keysym, 0x0100d800..=0x0100dfff) {
316 return NO_KEYSYM_UNICODE_CONVERSION;
317 }
318
319 // In theory, this is supposed to start from 0x100100, such that the ASCII
320 // range, which is already covered by 0x00-0xff, can't be encoded in two
321 // ways. However, changing this after a couple of decades probably won't
322 // go well, so it stays as it is.
323 if matches!(keysym, XKB_KEYSYM_UNICODE_OFFSET..=XKB_KEYSYM_UNICODE_MAX) {
324 return (keysym - XKB_KEYSYM_UNICODE_OFFSET) as u32;
325 }
326
327 match keysym {
328 0x01a1 => 0x0104, // Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK
329 0x01a2 => 0x02d8, // breve ˘ BREVE
330 0x01a3 => 0x0141, // Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE
331 0x01a5 => 0x013d, // Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON
332 0x01a6 => 0x015a, // Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE
333 0x01a9 => 0x0160, // Scaron Š LATIN CAPITAL LETTER S WITH CARON
334 0x01aa => 0x015e, // Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA
335 0x01ab => 0x0164, // Tcaron Ť LATIN CAPITAL LETTER T WITH CARON
336 0x01ac => 0x0179, // Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE
337 0x01ae => 0x017d, // Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON
338 0x01af => 0x017b, // Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE
339 0x01b1 => 0x0105, // aogonek ą LATIN SMALL LETTER A WITH OGONEK
340 0x01b2 => 0x02db, // ogonek ˛ OGONEK
341 0x01b3 => 0x0142, // lstroke ł LATIN SMALL LETTER L WITH STROKE
342 0x01b5 => 0x013e, // lcaron ľ LATIN SMALL LETTER L WITH CARON
343 0x01b6 => 0x015b, // sacute ś LATIN SMALL LETTER S WITH ACUTE
344 0x01b7 => 0x02c7, // caron ˇ CARON
345 0x01b9 => 0x0161, // scaron š LATIN SMALL LETTER S WITH CARON
346 0x01ba => 0x015f, // scedilla ş LATIN SMALL LETTER S WITH CEDILLA
347 0x01bb => 0x0165, // tcaron ť LATIN SMALL LETTER T WITH CARON
348 0x01bc => 0x017a, // zacute ź LATIN SMALL LETTER Z WITH ACUTE
349 0x01bd => 0x02dd, // doubleacute ˝ DOUBLE ACUTE ACCENT
350 0x01be => 0x017e, // zcaron ž LATIN SMALL LETTER Z WITH CARON
351 0x01bf => 0x017c, // zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE
352 0x01c0 => 0x0154, // Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE
353 0x01c3 => 0x0102, // Abreve Ă LATIN CAPITAL LETTER A WITH BREVE
354 0x01c5 => 0x0139, // Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE
355 0x01c6 => 0x0106, // Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE
356 0x01c8 => 0x010c, // Ccaron Č LATIN CAPITAL LETTER C WITH CARON
357 0x01ca => 0x0118, // Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK
358 0x01cc => 0x011a, // Ecaron Ě LATIN CAPITAL LETTER E WITH CARON
359 0x01cf => 0x010e, // Dcaron Ď LATIN CAPITAL LETTER D WITH CARON
360 0x01d0 => 0x0110, // Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE
361 0x01d1 => 0x0143, // Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE
362 0x01d2 => 0x0147, // Ncaron Ň LATIN CAPITAL LETTER N WITH CARON
363 0x01d5 => 0x0150, // Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
364 0x01d8 => 0x0158, // Rcaron Ř LATIN CAPITAL LETTER R WITH CARON
365 0x01d9 => 0x016e, // Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE
366 0x01db => 0x0170, // Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
367 0x01de => 0x0162, // Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA
368 0x01e0 => 0x0155, // racute ŕ LATIN SMALL LETTER R WITH ACUTE
369 0x01e3 => 0x0103, // abreve ă LATIN SMALL LETTER A WITH BREVE
370 0x01e5 => 0x013a, // lacute ĺ LATIN SMALL LETTER L WITH ACUTE
371 0x01e6 => 0x0107, // cacute ć LATIN SMALL LETTER C WITH ACUTE
372 0x01e8 => 0x010d, // ccaron č LATIN SMALL LETTER C WITH CARON
373 0x01ea => 0x0119, // eogonek ę LATIN SMALL LETTER E WITH OGONEK
374 0x01ec => 0x011b, // ecaron ě LATIN SMALL LETTER E WITH CARON
375 0x01ef => 0x010f, // dcaron ď LATIN SMALL LETTER D WITH CARON
376 0x01f0 => 0x0111, // dstroke đ LATIN SMALL LETTER D WITH STROKE
377 0x01f1 => 0x0144, // nacute ń LATIN SMALL LETTER N WITH ACUTE
378 0x01f2 => 0x0148, // ncaron ň LATIN SMALL LETTER N WITH CARON
379 0x01f5 => 0x0151, // odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE
380 0x01f8 => 0x0159, // rcaron ř LATIN SMALL LETTER R WITH CARON
381 0x01f9 => 0x016f, // uring ů LATIN SMALL LETTER U WITH RING ABOVE
382 0x01fb => 0x0171, // udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE
383 0x01fe => 0x0163, // tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA
384 0x01ff => 0x02d9, // abovedot ˙ DOT ABOVE
385 0x02a1 => 0x0126, // Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE
386 0x02a6 => 0x0124, // Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX
387 0x02a9 => 0x0130, // Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE
388 0x02ab => 0x011e, // Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE
389 0x02ac => 0x0134, // Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX
390 0x02b1 => 0x0127, // hstroke ħ LATIN SMALL LETTER H WITH STROKE
391 0x02b6 => 0x0125, // hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX
392 0x02b9 => 0x0131, // idotless ı LATIN SMALL LETTER DOTLESS I
393 0x02bb => 0x011f, // gbreve ğ LATIN SMALL LETTER G WITH BREVE
394 0x02bc => 0x0135, // jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX
395 0x02c5 => 0x010a, // Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE
396 0x02c6 => 0x0108, // Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX
397 0x02d5 => 0x0120, // Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE
398 0x02d8 => 0x011c, // Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX
399 0x02dd => 0x016c, // Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE
400 0x02de => 0x015c, // Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX
401 0x02e5 => 0x010b, // cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE
402 0x02e6 => 0x0109, // ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX
403 0x02f5 => 0x0121, // gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE
404 0x02f8 => 0x011d, // gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX
405 0x02fd => 0x016d, // ubreve ŭ LATIN SMALL LETTER U WITH BREVE
406 0x02fe => 0x015d, // scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX
407 0x03a2 => 0x0138, // kra ĸ LATIN SMALL LETTER KRA
408 0x03a3 => 0x0156, // Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA
409 0x03a5 => 0x0128, // Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE
410 0x03a6 => 0x013b, // Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA
411 0x03aa => 0x0112, // Emacron Ē LATIN CAPITAL LETTER E WITH MACRON
412 0x03ab => 0x0122, // Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA
413 0x03ac => 0x0166, // Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE
414 0x03b3 => 0x0157, // rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA
415 0x03b5 => 0x0129, // itilde ĩ LATIN SMALL LETTER I WITH TILDE
416 0x03b6 => 0x013c, // lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA
417 0x03ba => 0x0113, // emacron ē LATIN SMALL LETTER E WITH MACRON
418 0x03bb => 0x0123, // gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA
419 0x03bc => 0x0167, // tslash ŧ LATIN SMALL LETTER T WITH STROKE
420 0x03bd => 0x014a, // ENG Ŋ LATIN CAPITAL LETTER ENG
421 0x03bf => 0x014b, // eng ŋ LATIN SMALL LETTER ENG
422 0x03c0 => 0x0100, // Amacron Ā LATIN CAPITAL LETTER A WITH MACRON
423 0x03c7 => 0x012e, // Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK
424 0x03cc => 0x0116, // Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE
425 0x03cf => 0x012a, // Imacron Ī LATIN CAPITAL LETTER I WITH MACRON
426 0x03d1 => 0x0145, // Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA
427 0x03d2 => 0x014c, // Omacron Ō LATIN CAPITAL LETTER O WITH MACRON
428 0x03d3 => 0x0136, // Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA
429 0x03d9 => 0x0172, // Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK
430 0x03dd => 0x0168, // Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE
431 0x03de => 0x016a, // Umacron Ū LATIN CAPITAL LETTER U WITH MACRON
432 0x03e0 => 0x0101, // amacron ā LATIN SMALL LETTER A WITH MACRON
433 0x03e7 => 0x012f, // iogonek į LATIN SMALL LETTER I WITH OGONEK
434 0x03ec => 0x0117, // eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE
435 0x03ef => 0x012b, // imacron ī LATIN SMALL LETTER I WITH MACRON
436 0x03f1 => 0x0146, // ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA
437 0x03f2 => 0x014d, // omacron ō LATIN SMALL LETTER O WITH MACRON
438 0x03f3 => 0x0137, // kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA
439 0x03f9 => 0x0173, // uogonek ų LATIN SMALL LETTER U WITH OGONEK
440 0x03fd => 0x0169, // utilde ũ LATIN SMALL LETTER U WITH TILDE
441 0x03fe => 0x016b, // umacron ū LATIN SMALL LETTER U WITH MACRON
442 0x047e => 0x203e, // overline ‾ OVERLINE
443 0x04a1 => 0x3002, // kana_fullstop 。 IDEOGRAPHIC FULL STOP
444 0x04a2 => 0x300c, // kana_openingbracket 「 LEFT CORNER BRACKET
445 0x04a3 => 0x300d, // kana_closingbracket 」 RIGHT CORNER BRACKET
446 0x04a4 => 0x3001, // kana_comma 、 IDEOGRAPHIC COMMA
447 0x04a5 => 0x30fb, // kana_conjunctive ・ KATAKANA MIDDLE DOT
448 0x04a6 => 0x30f2, // kana_WO ヲ KATAKANA LETTER WO
449 0x04a7 => 0x30a1, // kana_a ァ KATAKANA LETTER SMALL A
450 0x04a8 => 0x30a3, // kana_i ィ KATAKANA LETTER SMALL I
451 0x04a9 => 0x30a5, // kana_u ゥ KATAKANA LETTER SMALL U
452 0x04aa => 0x30a7, // kana_e ェ KATAKANA LETTER SMALL E
453 0x04ab => 0x30a9, // kana_o ォ KATAKANA LETTER SMALL O
454 0x04ac => 0x30e3, // kana_ya ャ KATAKANA LETTER SMALL YA
455 0x04ad => 0x30e5, // kana_yu ュ KATAKANA LETTER SMALL YU
456 0x04ae => 0x30e7, // kana_yo ョ KATAKANA LETTER SMALL YO
457 0x04af => 0x30c3, // kana_tsu ッ KATAKANA LETTER SMALL TU
458 0x04b0 => 0x30fc, // prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK
459 0x04b1 => 0x30a2, // kana_A ア KATAKANA LETTER A
460 0x04b2 => 0x30a4, // kana_I イ KATAKANA LETTER I
461 0x04b3 => 0x30a6, // kana_U ウ KATAKANA LETTER U
462 0x04b4 => 0x30a8, // kana_E エ KATAKANA LETTER E
463 0x04b5 => 0x30aa, // kana_O オ KATAKANA LETTER O
464 0x04b6 => 0x30ab, // kana_KA カ KATAKANA LETTER KA
465 0x04b7 => 0x30ad, // kana_KI キ KATAKANA LETTER KI
466 0x04b8 => 0x30af, // kana_KU ク KATAKANA LETTER KU
467 0x04b9 => 0x30b1, // kana_KE ケ KATAKANA LETTER KE
468 0x04ba => 0x30b3, // kana_KO コ KATAKANA LETTER KO
469 0x04bb => 0x30b5, // kana_SA サ KATAKANA LETTER SA
470 0x04bc => 0x30b7, // kana_SHI シ KATAKANA LETTER SI
471 0x04bd => 0x30b9, // kana_SU ス KATAKANA LETTER SU
472 0x04be => 0x30bb, // kana_SE セ KATAKANA LETTER SE
473 0x04bf => 0x30bd, // kana_SO ソ KATAKANA LETTER SO
474 0x04c0 => 0x30bf, // kana_TA タ KATAKANA LETTER TA
475 0x04c1 => 0x30c1, // kana_CHI チ KATAKANA LETTER TI
476 0x04c2 => 0x30c4, // kana_TSU ツ KATAKANA LETTER TU
477 0x04c3 => 0x30c6, // kana_TE テ KATAKANA LETTER TE
478 0x04c4 => 0x30c8, // kana_TO ト KATAKANA LETTER TO
479 0x04c5 => 0x30ca, // kana_NA ナ KATAKANA LETTER NA
480 0x04c6 => 0x30cb, // kana_NI ニ KATAKANA LETTER NI
481 0x04c7 => 0x30cc, // kana_NU ヌ KATAKANA LETTER NU
482 0x04c8 => 0x30cd, // kana_NE ネ KATAKANA LETTER NE
483 0x04c9 => 0x30ce, // kana_NO ノ KATAKANA LETTER NO
484 0x04ca => 0x30cf, // kana_HA ハ KATAKANA LETTER HA
485 0x04cb => 0x30d2, // kana_HI ヒ KATAKANA LETTER HI
486 0x04cc => 0x30d5, // kana_FU フ KATAKANA LETTER HU
487 0x04cd => 0x30d8, // kana_HE ヘ KATAKANA LETTER HE
488 0x04ce => 0x30db, // kana_HO ホ KATAKANA LETTER HO
489 0x04cf => 0x30de, // kana_MA マ KATAKANA LETTER MA
490 0x04d0 => 0x30df, // kana_MI ミ KATAKANA LETTER MI
491 0x04d1 => 0x30e0, // kana_MU ム KATAKANA LETTER MU
492 0x04d2 => 0x30e1, // kana_ME メ KATAKANA LETTER ME
493 0x04d3 => 0x30e2, // kana_MO モ KATAKANA LETTER MO
494 0x04d4 => 0x30e4, // kana_YA ヤ KATAKANA LETTER YA
495 0x04d5 => 0x30e6, // kana_YU ユ KATAKANA LETTER YU
496 0x04d6 => 0x30e8, // kana_YO ヨ KATAKANA LETTER YO
497 0x04d7 => 0x30e9, // kana_RA ラ KATAKANA LETTER RA
498 0x04d8 => 0x30ea, // kana_RI リ KATAKANA LETTER RI
499 0x04d9 => 0x30eb, // kana_RU ル KATAKANA LETTER RU
500 0x04da => 0x30ec, // kana_RE レ KATAKANA LETTER RE
501 0x04db => 0x30ed, // kana_RO ロ KATAKANA LETTER RO
502 0x04dc => 0x30ef, // kana_WA ワ KATAKANA LETTER WA
503 0x04dd => 0x30f3, // kana_N ン KATAKANA LETTER N
504 0x04de => 0x309b, // voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK
505 0x04df => 0x309c, // semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
506 0x05ac => 0x060c, // Arabic_comma ، ARABIC COMMA
507 0x05bb => 0x061b, // Arabic_semicolon ؛ ARABIC SEMICOLON
508 0x05bf => 0x061f, // Arabic_question_mark ؟ ARABIC QUESTION MARK
509 0x05c1 => 0x0621, // Arabic_hamza ء ARABIC LETTER HAMZA
510 0x05c2 => 0x0622, // Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE
511 0x05c3 => 0x0623, // Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE
512 0x05c4 => 0x0624, // Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE
513 0x05c5 => 0x0625, // Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW
514 0x05c6 => 0x0626, // Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE
515 0x05c7 => 0x0627, // Arabic_alef ا ARABIC LETTER ALEF
516 0x05c8 => 0x0628, // Arabic_beh ب ARABIC LETTER BEH
517 0x05c9 => 0x0629, // Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA
518 0x05ca => 0x062a, // Arabic_teh ت ARABIC LETTER TEH
519 0x05cb => 0x062b, // Arabic_theh ث ARABIC LETTER THEH
520 0x05cc => 0x062c, // Arabic_jeem ج ARABIC LETTER JEEM
521 0x05cd => 0x062d, // Arabic_hah ح ARABIC LETTER HAH
522 0x05ce => 0x062e, // Arabic_khah خ ARABIC LETTER KHAH
523 0x05cf => 0x062f, // Arabic_dal د ARABIC LETTER DAL
524 0x05d0 => 0x0630, // Arabic_thal ذ ARABIC LETTER THAL
525 0x05d1 => 0x0631, // Arabic_ra ر ARABIC LETTER REH
526 0x05d2 => 0x0632, // Arabic_zain ز ARABIC LETTER ZAIN
527 0x05d3 => 0x0633, // Arabic_seen س ARABIC LETTER SEEN
528 0x05d4 => 0x0634, // Arabic_sheen ش ARABIC LETTER SHEEN
529 0x05d5 => 0x0635, // Arabic_sad ص ARABIC LETTER SAD
530 0x05d6 => 0x0636, // Arabic_dad ض ARABIC LETTER DAD
531 0x05d7 => 0x0637, // Arabic_tah ط ARABIC LETTER TAH
532 0x05d8 => 0x0638, // Arabic_zah ظ ARABIC LETTER ZAH
533 0x05d9 => 0x0639, // Arabic_ain ع ARABIC LETTER AIN
534 0x05da => 0x063a, // Arabic_ghain غ ARABIC LETTER GHAIN
535 0x05e0 => 0x0640, // Arabic_tatweel ـ ARABIC TATWEEL
536 0x05e1 => 0x0641, // Arabic_feh ف ARABIC LETTER FEH
537 0x05e2 => 0x0642, // Arabic_qaf ق ARABIC LETTER QAF
538 0x05e3 => 0x0643, // Arabic_kaf ك ARABIC LETTER KAF
539 0x05e4 => 0x0644, // Arabic_lam ل ARABIC LETTER LAM
540 0x05e5 => 0x0645, // Arabic_meem م ARABIC LETTER MEEM
541 0x05e6 => 0x0646, // Arabic_noon ن ARABIC LETTER NOON
542 0x05e7 => 0x0647, // Arabic_ha ه ARABIC LETTER HEH
543 0x05e8 => 0x0648, // Arabic_waw و ARABIC LETTER WAW
544 0x05e9 => 0x0649, // Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA
545 0x05ea => 0x064a, // Arabic_yeh ي ARABIC LETTER YEH
546 0x05eb => 0x064b, // Arabic_fathatan ً ARABIC FATHATAN
547 0x05ec => 0x064c, // Arabic_dammatan ٌ ARABIC DAMMATAN
548 0x05ed => 0x064d, // Arabic_kasratan ٍ ARABIC KASRATAN
549 0x05ee => 0x064e, // Arabic_fatha َ ARABIC FATHA
550 0x05ef => 0x064f, // Arabic_damma ُ ARABIC DAMMA
551 0x05f0 => 0x0650, // Arabic_kasra ِ ARABIC KASRA
552 0x05f1 => 0x0651, // Arabic_shadda ّ ARABIC SHADDA
553 0x05f2 => 0x0652, // Arabic_sukun ْ ARABIC SUKUN
554 0x06a1 => 0x0452, // Serbian_dje ђ CYRILLIC SMALL LETTER DJE
555 0x06a2 => 0x0453, // Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE
556 0x06a3 => 0x0451, // Cyrillic_io ё CYRILLIC SMALL LETTER IO
557 0x06a4 => 0x0454, // Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE
558 0x06a5 => 0x0455, // Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE
559 0x06a6 => 0x0456, // Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
560 0x06a7 => 0x0457, // Ukrainian_yi ї CYRILLIC SMALL LETTER YI
561 0x06a8 => 0x0458, // Cyrillic_je ј CYRILLIC SMALL LETTER JE
562 0x06a9 => 0x0459, // Cyrillic_lje љ CYRILLIC SMALL LETTER LJE
563 0x06aa => 0x045a, // Cyrillic_nje њ CYRILLIC SMALL LETTER NJE
564 0x06ab => 0x045b, // Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE
565 0x06ac => 0x045c, // Macedonia_kje ќ CYRILLIC SMALL LETTER KJE
566 0x06ad => 0x0491, // Ukrainian_ghe_with_upturn ґ CYRILLIC SMALL LETTER GHE WITH UPTURN
567 0x06ae => 0x045e, // Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U
568 0x06af => 0x045f, // Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE
569 0x06b0 => 0x2116, // numerosign № NUMERO SIGN
570 0x06b1 => 0x0402, // Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE
571 0x06b2 => 0x0403, // Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE
572 0x06b3 => 0x0401, // Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO
573 0x06b4 => 0x0404, // Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE
574 0x06b5 => 0x0405, // Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE
575 0x06b6 => 0x0406, // Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
576 0x06b7 => 0x0407, // Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI
577 0x06b8 => 0x0408, // Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE
578 0x06b9 => 0x0409, // Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE
579 0x06ba => 0x040a, // Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE
580 0x06bb => 0x040b, // Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE
581 0x06bc => 0x040c, // Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE
582 0x06bd => 0x0490, // Ukrainian_GHE_WITH_UPTURN Ґ CYRILLIC CAPITAL LETTER GHE WITH UPTURN
583 0x06be => 0x040e, // Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U
584 0x06bf => 0x040f, // Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE
585 0x06c0 => 0x044e, // Cyrillic_yu ю CYRILLIC SMALL LETTER YU
586 0x06c1 => 0x0430, // Cyrillic_a а CYRILLIC SMALL LETTER A
587 0x06c2 => 0x0431, // Cyrillic_be б CYRILLIC SMALL LETTER BE
588 0x06c3 => 0x0446, // Cyrillic_tse ц CYRILLIC SMALL LETTER TSE
589 0x06c4 => 0x0434, // Cyrillic_de д CYRILLIC SMALL LETTER DE
590 0x06c5 => 0x0435, // Cyrillic_ie е CYRILLIC SMALL LETTER IE
591 0x06c6 => 0x0444, // Cyrillic_ef ф CYRILLIC SMALL LETTER EF
592 0x06c7 => 0x0433, // Cyrillic_ghe г CYRILLIC SMALL LETTER GHE
593 0x06c8 => 0x0445, // Cyrillic_ha х CYRILLIC SMALL LETTER HA
594 0x06c9 => 0x0438, // Cyrillic_i и CYRILLIC SMALL LETTER I
595 0x06ca => 0x0439, // Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I
596 0x06cb => 0x043a, // Cyrillic_ka к CYRILLIC SMALL LETTER KA
597 0x06cc => 0x043b, // Cyrillic_el л CYRILLIC SMALL LETTER EL
598 0x06cd => 0x043c, // Cyrillic_em м CYRILLIC SMALL LETTER EM
599 0x06ce => 0x043d, // Cyrillic_en н CYRILLIC SMALL LETTER EN
600 0x06cf => 0x043e, // Cyrillic_o о CYRILLIC SMALL LETTER O
601 0x06d0 => 0x043f, // Cyrillic_pe п CYRILLIC SMALL LETTER PE
602 0x06d1 => 0x044f, // Cyrillic_ya я CYRILLIC SMALL LETTER YA
603 0x06d2 => 0x0440, // Cyrillic_er р CYRILLIC SMALL LETTER ER
604 0x06d3 => 0x0441, // Cyrillic_es с CYRILLIC SMALL LETTER ES
605 0x06d4 => 0x0442, // Cyrillic_te т CYRILLIC SMALL LETTER TE
606 0x06d5 => 0x0443, // Cyrillic_u у CYRILLIC SMALL LETTER U
607 0x06d6 => 0x0436, // Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE
608 0x06d7 => 0x0432, // Cyrillic_ve в CYRILLIC SMALL LETTER VE
609 0x06d8 => 0x044c, // Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN
610 0x06d9 => 0x044b, // Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU
611 0x06da => 0x0437, // Cyrillic_ze з CYRILLIC SMALL LETTER ZE
612 0x06db => 0x0448, // Cyrillic_sha ш CYRILLIC SMALL LETTER SHA
613 0x06dc => 0x044d, // Cyrillic_e э CYRILLIC SMALL LETTER E
614 0x06dd => 0x0449, // Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA
615 0x06de => 0x0447, // Cyrillic_che ч CYRILLIC SMALL LETTER CHE
616 0x06df => 0x044a, // Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN
617 0x06e0 => 0x042e, // Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU
618 0x06e1 => 0x0410, // Cyrillic_A А CYRILLIC CAPITAL LETTER A
619 0x06e2 => 0x0411, // Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE
620 0x06e3 => 0x0426, // Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE
621 0x06e4 => 0x0414, // Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE
622 0x06e5 => 0x0415, // Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE
623 0x06e6 => 0x0424, // Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF
624 0x06e7 => 0x0413, // Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE
625 0x06e8 => 0x0425, // Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA
626 0x06e9 => 0x0418, // Cyrillic_I И CYRILLIC CAPITAL LETTER I
627 0x06ea => 0x0419, // Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I
628 0x06eb => 0x041a, // Cyrillic_KA К CYRILLIC CAPITAL LETTER KA
629 0x06ec => 0x041b, // Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL
630 0x06ed => 0x041c, // Cyrillic_EM М CYRILLIC CAPITAL LETTER EM
631 0x06ee => 0x041d, // Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN
632 0x06ef => 0x041e, // Cyrillic_O О CYRILLIC CAPITAL LETTER O
633 0x06f0 => 0x041f, // Cyrillic_PE П CYRILLIC CAPITAL LETTER PE
634 0x06f1 => 0x042f, // Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA
635 0x06f2 => 0x0420, // Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER
636 0x06f3 => 0x0421, // Cyrillic_ES С CYRILLIC CAPITAL LETTER ES
637 0x06f4 => 0x0422, // Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE
638 0x06f5 => 0x0423, // Cyrillic_U У CYRILLIC CAPITAL LETTER U
639 0x06f6 => 0x0416, // Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE
640 0x06f7 => 0x0412, // Cyrillic_VE В CYRILLIC CAPITAL LETTER VE
641 0x06f8 => 0x042c, // Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN
642 0x06f9 => 0x042b, // Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU
643 0x06fa => 0x0417, // Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE
644 0x06fb => 0x0428, // Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA
645 0x06fc => 0x042d, // Cyrillic_E Э CYRILLIC CAPITAL LETTER E
646 0x06fd => 0x0429, // Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA
647 0x06fe => 0x0427, // Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE
648 0x06ff => 0x042a, // Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN
649 0x07a1 => 0x0386, // Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS
650 0x07a2 => 0x0388, // Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS
651 0x07a3 => 0x0389, // Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS
652 0x07a4 => 0x038a, // Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS
653 0x07a5 => 0x03aa, // Greek_IOTAdiaeresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
654 0x07a7 => 0x038c, // Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS
655 0x07a8 => 0x038e, // Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS
656 0x07a9 => 0x03ab, // Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
657 0x07ab => 0x038f, // Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS
658 0x07ae => 0x0385, // Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS
659 0x07af => 0x2015, // Greek_horizbar ― HORIZONTAL BAR
660 0x07b1 => 0x03ac, // Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS
661 0x07b2 => 0x03ad, // Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS
662 0x07b3 => 0x03ae, // Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS
663 0x07b4 => 0x03af, // Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS
664 0x07b5 => 0x03ca, // Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA
665 0x07b6 => 0x0390, // Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
666 0x07b7 => 0x03cc, // Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS
667 0x07b8 => 0x03cd, // Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS
668 0x07b9 => 0x03cb, // Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA
669 0x07ba => 0x03b0, // Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
670 0x07bb => 0x03ce, // Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS
671 0x07c1 => 0x0391, // Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA
672 0x07c2 => 0x0392, // Greek_BETA Β GREEK CAPITAL LETTER BETA
673 0x07c3 => 0x0393, // Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA
674 0x07c4 => 0x0394, // Greek_DELTA Δ GREEK CAPITAL LETTER DELTA
675 0x07c5 => 0x0395, // Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON
676 0x07c6 => 0x0396, // Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA
677 0x07c7 => 0x0397, // Greek_ETA Η GREEK CAPITAL LETTER ETA
678 0x07c8 => 0x0398, // Greek_THETA Θ GREEK CAPITAL LETTER THETA
679 0x07c9 => 0x0399, // Greek_IOTA Ι GREEK CAPITAL LETTER IOTA
680 0x07ca => 0x039a, // Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA
681 0x07cb => 0x039b, // Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA
682 0x07cc => 0x039c, // Greek_MU Μ GREEK CAPITAL LETTER MU
683 0x07cd => 0x039d, // Greek_NU Ν GREEK CAPITAL LETTER NU
684 0x07ce => 0x039e, // Greek_XI Ξ GREEK CAPITAL LETTER XI
685 0x07cf => 0x039f, // Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON
686 0x07d0 => 0x03a0, // Greek_PI Π GREEK CAPITAL LETTER PI
687 0x07d1 => 0x03a1, // Greek_RHO Ρ GREEK CAPITAL LETTER RHO
688 0x07d2 => 0x03a3, // Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA
689 0x07d4 => 0x03a4, // Greek_TAU Τ GREEK CAPITAL LETTER TAU
690 0x07d5 => 0x03a5, // Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON
691 0x07d6 => 0x03a6, // Greek_PHI Φ GREEK CAPITAL LETTER PHI
692 0x07d7 => 0x03a7, // Greek_CHI Χ GREEK CAPITAL LETTER CHI
693 0x07d8 => 0x03a8, // Greek_PSI Ψ GREEK CAPITAL LETTER PSI
694 0x07d9 => 0x03a9, // Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA
695 0x07e1 => 0x03b1, // Greek_alpha α GREEK SMALL LETTER ALPHA
696 0x07e2 => 0x03b2, // Greek_beta β GREEK SMALL LETTER BETA
697 0x07e3 => 0x03b3, // Greek_gamma γ GREEK SMALL LETTER GAMMA
698 0x07e4 => 0x03b4, // Greek_delta δ GREEK SMALL LETTER DELTA
699 0x07e5 => 0x03b5, // Greek_epsilon ε GREEK SMALL LETTER EPSILON
700 0x07e6 => 0x03b6, // Greek_zeta ζ GREEK SMALL LETTER ZETA
701 0x07e7 => 0x03b7, // Greek_eta η GREEK SMALL LETTER ETA
702 0x07e8 => 0x03b8, // Greek_theta θ GREEK SMALL LETTER THETA
703 0x07e9 => 0x03b9, // Greek_iota ι GREEK SMALL LETTER IOTA
704 0x07ea => 0x03ba, // Greek_kappa κ GREEK SMALL LETTER KAPPA
705 0x07eb => 0x03bb, // Greek_lambda λ GREEK SMALL LETTER LAMDA
706 0x07ec => 0x03bc, // Greek_mu μ GREEK SMALL LETTER MU
707 0x07ed => 0x03bd, // Greek_nu ν GREEK SMALL LETTER NU
708 0x07ee => 0x03be, // Greek_xi ξ GREEK SMALL LETTER XI
709 0x07ef => 0x03bf, // Greek_omicron ο GREEK SMALL LETTER OMICRON
710 0x07f0 => 0x03c0, // Greek_pi π GREEK SMALL LETTER PI
711 0x07f1 => 0x03c1, // Greek_rho ρ GREEK SMALL LETTER RHO
712 0x07f2 => 0x03c3, // Greek_sigma σ GREEK SMALL LETTER SIGMA
713 0x07f3 => 0x03c2, // Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA
714 0x07f4 => 0x03c4, // Greek_tau τ GREEK SMALL LETTER TAU
715 0x07f5 => 0x03c5, // Greek_upsilon υ GREEK SMALL LETTER UPSILON
716 0x07f6 => 0x03c6, // Greek_phi φ GREEK SMALL LETTER PHI
717 0x07f7 => 0x03c7, // Greek_chi χ GREEK SMALL LETTER CHI
718 0x07f8 => 0x03c8, // Greek_psi ψ GREEK SMALL LETTER PSI
719 0x07f9 => 0x03c9, // Greek_omega ω GREEK SMALL LETTER OMEGA
720 0x08a1 => 0x23b7, // leftradical ⎷ ???
721 0x08a2 => 0x250c, // topleftradical ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT
722 0x08a3 => 0x2500, // horizconnector ─ BOX DRAWINGS LIGHT HORIZONTAL
723 0x08a4 => 0x2320, // topintegral ⌠ TOP HALF INTEGRAL
724 0x08a5 => 0x2321, // botintegral ⌡ BOTTOM HALF INTEGRAL
725 0x08a6 => 0x2502, // vertconnector │ BOX DRAWINGS LIGHT VERTICAL
726 0x08a7 => 0x23a1, // topleftsqbracket ⎡ ???
727 0x08a8 => 0x23a3, // botleftsqbracket ⎣ ???
728 0x08a9 => 0x23a4, // toprightsqbracket ⎤ ???
729 0x08aa => 0x23a6, // botrightsqbracket ⎦ ???
730 0x08ab => 0x239b, // topleftparens ⎛ ???
731 0x08ac => 0x239d, // botleftparens ⎝ ???
732 0x08ad => 0x239e, // toprightparens ⎞ ???
733 0x08ae => 0x23a0, // botrightparens ⎠ ???
734 0x08af => 0x23a8, // leftmiddlecurlybrace ⎨ ???
735 0x08b0 => 0x23ac, // rightmiddlecurlybrace ⎬ ???
736 // 0x08b1 topleftsummation ? ???
737 // 0x08b2 botleftsummation ? ???
738 // 0x08b3 topvertsummationconnector ? ???
739 // 0x08b4 botvertsummationconnector ? ???
740 // 0x08b5 toprightsummation ? ???
741 // 0x08b6 botrightsummation ? ???
742 // 0x08b7 rightmiddlesummation ? ???
743 0x08bc => 0x2264, // lessthanequal ≤ LESS-THAN OR EQUAL TO
744 0x08bd => 0x2260, // notequal ≠ NOT EQUAL TO
745 0x08be => 0x2265, // greaterthanequal ≥ GREATER-THAN OR EQUAL TO
746 0x08bf => 0x222b, // integral ∫ INTEGRAL
747 0x08c0 => 0x2234, // therefore ∴ THEREFORE
748 0x08c1 => 0x221d, // variation ∝ PROPORTIONAL TO
749 0x08c2 => 0x221e, // infinity ∞ INFINITY
750 0x08c5 => 0x2207, // nabla ∇ NABLA
751 0x08c8 => 0x223c, // approximate ∼ TILDE OPERATOR
752 0x08c9 => 0x2243, // similarequal ≃ ASYMPTOTICALLY EQUAL TO
753 0x08cd => 0x21d4, // ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW
754 0x08ce => 0x21d2, // implies ⇒ RIGHTWARDS DOUBLE ARROW
755 0x08cf => 0x2261, // identical ≡ IDENTICAL TO
756 0x08d6 => 0x221a, // radical √ SQUARE ROOT
757 0x08da => 0x2282, // includedin ⊂ SUBSET OF
758 0x08db => 0x2283, // includes ⊃ SUPERSET OF
759 0x08dc => 0x2229, // intersection ∩ INTERSECTION
760 0x08dd => 0x222a, // union ∪ UNION
761 0x08de => 0x2227, // logicaland ∧ LOGICAL AND
762 0x08df => 0x2228, // logicalor ∨ LOGICAL OR
763 0x08ef => 0x2202, // partialderivative ∂ PARTIAL DIFFERENTIAL
764 0x08f6 => 0x0192, // function ƒ LATIN SMALL LETTER F WITH HOOK
765 0x08fb => 0x2190, // leftarrow ← LEFTWARDS ARROW
766 0x08fc => 0x2191, // uparrow ↑ UPWARDS ARROW
767 0x08fd => 0x2192, // rightarrow → RIGHTWARDS ARROW
768 0x08fe => 0x2193, // downarrow ↓ DOWNWARDS ARROW
769 // 0x09df blank ? ???
770 0x09e0 => 0x25c6, // soliddiamond ◆ BLACK DIAMOND
771 0x09e1 => 0x2592, // checkerboard ▒ MEDIUM SHADE
772 0x09e2 => 0x2409, // ht ␉ SYMBOL FOR HORIZONTAL TABULATION
773 0x09e3 => 0x240c, // ff ␌ SYMBOL FOR FORM FEED
774 0x09e4 => 0x240d, // cr ␍ SYMBOL FOR CARRIAGE RETURN
775 0x09e5 => 0x240a, // lf ␊ SYMBOL FOR LINE FEED
776 0x09e8 => 0x2424, // nl  SYMBOL FOR NEWLINE
777 0x09e9 => 0x240b, // vt ␋ SYMBOL FOR VERTICAL TABULATION
778 0x09ea => 0x2518, // lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT
779 0x09eb => 0x2510, // uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT
780 0x09ec => 0x250c, // upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT
781 0x09ed => 0x2514, // lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT
782 0x09ee => 0x253c, // crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
783 0x09ef => 0x23ba, // horizlinescan1 ⎺ HORIZONTAL SCAN LINE-1 (Unicode 3.2 draft)
784 0x09f0 => 0x23bb, // horizlinescan3 ⎻ HORIZONTAL SCAN LINE-3 (Unicode 3.2 draft)
785 0x09f1 => 0x2500, // horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL
786 0x09f2 => 0x23bc, // horizlinescan7 ⎼ HORIZONTAL SCAN LINE-7 (Unicode 3.2 draft)
787 0x09f3 => 0x23bd, // horizlinescan9 ⎽ HORIZONTAL SCAN LINE-9 (Unicode 3.2 draft)
788 0x09f4 => 0x251c, // leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT
789 0x09f5 => 0x2524, // rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT
790 0x09f6 => 0x2534, // bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL
791 0x09f7 => 0x252c, // topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
792 0x09f8 => 0x2502, // vertbar │ BOX DRAWINGS LIGHT VERTICAL
793 0x0aa1 => 0x2003, // emspace EM SPACE
794 0x0aa2 => 0x2002, // enspace EN SPACE
795 0x0aa3 => 0x2004, // em3space THREE-PER-EM SPACE
796 0x0aa4 => 0x2005, // em4space FOUR-PER-EM SPACE
797 0x0aa5 => 0x2007, // digitspace FIGURE SPACE
798 0x0aa6 => 0x2008, // punctspace PUNCTUATION SPACE
799 0x0aa7 => 0x2009, // thinspace THIN SPACE
800 0x0aa8 => 0x200a, // hairspace HAIR SPACE
801 0x0aa9 => 0x2014, // emdash — EM DASH
802 0x0aaa => 0x2013, // endash – EN DASH
803 0x0aac => 0x2423, // signifblank ␣ OPEN BOX
804 0x0aae => 0x2026, // ellipsis … HORIZONTAL ELLIPSIS
805 0x0aaf => 0x2025, // doubbaselinedot ‥ TWO DOT LEADER
806 0x0ab0 => 0x2153, // onethird ⅓ VULGAR FRACTION ONE THIRD
807 0x0ab1 => 0x2154, // twothirds ⅔ VULGAR FRACTION TWO THIRDS
808 0x0ab2 => 0x2155, // onefifth ⅕ VULGAR FRACTION ONE FIFTH
809 0x0ab3 => 0x2156, // twofifths ⅖ VULGAR FRACTION TWO FIFTHS
810 0x0ab4 => 0x2157, // threefifths ⅗ VULGAR FRACTION THREE FIFTHS
811 0x0ab5 => 0x2158, // fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS
812 0x0ab6 => 0x2159, // onesixth ⅙ VULGAR FRACTION ONE SIXTH
813 0x0ab7 => 0x215a, // fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS
814 0x0ab8 => 0x2105, // careof ℅ CARE OF
815 0x0abb => 0x2012, // figdash ‒ FIGURE DASH
816 0x0abc => 0x27e8, // leftanglebracket ⟨ MATHEMATICAL LEFT ANGLE BRACKET
817 0x0abd => 0x002e, // decimalpoint . FULL STOP
818 0x0abe => 0x27e9, // rightanglebracket ⟩ MATHEMATICAL RIGHT ANGLE BRACKET
819 // 0x0abf marker ? ???
820 0x0ac3 => 0x215b, // oneeighth ⅛ VULGAR FRACTION ONE EIGHTH
821 0x0ac4 => 0x215c, // threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS
822 0x0ac5 => 0x215d, // fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS
823 0x0ac6 => 0x215e, // seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS
824 0x0ac9 => 0x2122, // trademark ™ TRADE MARK SIGN
825 0x0aca => 0x2613, // signaturemark ☓ SALTIRE
826 // 0x0acb trademarkincircle ? ???
827 0x0acc => 0x25c1, // leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE
828 0x0acd => 0x25b7, // rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE
829 0x0ace => 0x25cb, // emopencircle ○ WHITE CIRCLE
830 0x0acf => 0x25af, // emopenrectangle ▯ WHITE VERTICAL RECTANGLE
831 0x0ad0 => 0x2018, // leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK
832 0x0ad1 => 0x2019, // rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK
833 0x0ad2 => 0x201c, // leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK
834 0x0ad3 => 0x201d, // rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK
835 0x0ad4 => 0x211e, // prescription ℞ PRESCRIPTION TAKE
836 0x0ad5 => 0x2030, // permille ‰ PER MILLE SIGN
837 0x0ad6 => 0x2032, // minutes ′ PRIME
838 0x0ad7 => 0x2033, // seconds ″ DOUBLE PRIME
839 0x0ad9 => 0x271d, // latincross ✝ LATIN CROSS
840 // 0x0ada hexagram ? ???
841 0x0adb => 0x25ac, // filledrectbullet ▬ BLACK RECTANGLE
842 0x0adc => 0x25c0, // filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE
843 0x0add => 0x25b6, // filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE
844 0x0ade => 0x25cf, // emfilledcircle ● BLACK CIRCLE
845 0x0adf => 0x25ae, // emfilledrect ▮ BLACK VERTICAL RECTANGLE
846 0x0ae0 => 0x25e6, // enopencircbullet ◦ WHITE BULLET
847 0x0ae1 => 0x25ab, // enopensquarebullet ▫ WHITE SMALL SQUARE
848 0x0ae2 => 0x25ad, // openrectbullet ▭ WHITE RECTANGLE
849 0x0ae3 => 0x25b3, // opentribulletup △ WHITE UP-POINTING TRIANGLE
850 0x0ae4 => 0x25bd, // opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE
851 0x0ae5 => 0x2606, // openstar ☆ WHITE STAR
852 0x0ae6 => 0x2022, // enfilledcircbullet • BULLET
853 0x0ae7 => 0x25aa, // enfilledsqbullet ▪ BLACK SMALL SQUARE
854 0x0ae8 => 0x25b2, // filledtribulletup ▲ BLACK UP-POINTING TRIANGLE
855 0x0ae9 => 0x25bc, // filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE
856 0x0aea => 0x261c, // leftpointer ☜ WHITE LEFT POINTING INDEX
857 0x0aeb => 0x261e, // rightpointer ☞ WHITE RIGHT POINTING INDEX
858 0x0aec => 0x2663, // club ♣ BLACK CLUB SUIT
859 0x0aed => 0x2666, // diamond ♦ BLACK DIAMOND SUIT
860 0x0aee => 0x2665, // heart ♥ BLACK HEART SUIT
861 0x0af0 => 0x2720, // maltesecross ✠ MALTESE CROSS
862 0x0af1 => 0x2020, // dagger † DAGGER
863 0x0af2 => 0x2021, // doubledagger ‡ DOUBLE DAGGER
864 0x0af3 => 0x2713, // checkmark ✓ CHECK MARK
865 0x0af4 => 0x2717, // ballotcross ✗ BALLOT X
866 0x0af5 => 0x266f, // musicalsharp ♯ MUSIC SHARP SIGN
867 0x0af6 => 0x266d, // musicalflat ♭ MUSIC FLAT SIGN
868 0x0af7 => 0x2642, // malesymbol ♂ MALE SIGN
869 0x0af8 => 0x2640, // femalesymbol ♀ FEMALE SIGN
870 0x0af9 => 0x260e, // telephone ☎ BLACK TELEPHONE
871 0x0afa => 0x2315, // telephonerecorder ⌕ TELEPHONE RECORDER
872 0x0afb => 0x2117, // phonographcopyright ℗ SOUND RECORDING COPYRIGHT
873 0x0afc => 0x2038, // caret ‸ CARET
874 0x0afd => 0x201a, // singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK
875 0x0afe => 0x201e, // doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK
876 // 0x0aff cursor ? ???
877 0x0ba3 => 0x003c, // leftcaret < LESS-THAN SIGN
878 0x0ba6 => 0x003e, // rightcaret > GREATER-THAN SIGN
879 0x0ba8 => 0x2228, // downcaret ∨ LOGICAL OR
880 0x0ba9 => 0x2227, // upcaret ∧ LOGICAL AND
881 0x0bc0 => 0x00af, // overbar ¯ MACRON
882 0x0bc2 => 0x22a4, // downtack ⊤ DOWN TACK
883 0x0bc3 => 0x2229, // upshoe ∩ INTERSECTION
884 0x0bc4 => 0x230a, // downstile ⌊ LEFT FLOOR
885 0x0bc6 => 0x005f, // underbar _ LOW LINE
886 0x0bca => 0x2218, // jot ∘ RING OPERATOR
887 0x0bcc => 0x2395, // quad ⎕ APL FUNCTIONAL SYMBOL QUAD (Unicode 3.0)
888 0x0bce => 0x22a5, // uptack ⊥ UP TACK
889 0x0bcf => 0x25cb, // circle ○ WHITE CIRCLE
890 0x0bd3 => 0x2308, // upstile ⌈ LEFT CEILING
891 0x0bd6 => 0x222a, // downshoe ∪ UNION
892 0x0bd8 => 0x2283, // rightshoe ⊃ SUPERSET OF
893 0x0bda => 0x2282, // leftshoe ⊂ SUBSET OF
894 0x0bdc => 0x22a3, // lefttack ⊣ LEFT TACK
895 0x0bfc => 0x22a2, // righttack ⊢ RIGHT TACK
896 0x0cdf => 0x2017, // hebrew_doublelowline ‗ DOUBLE LOW LINE
897 0x0ce0 => 0x05d0, // hebrew_aleph א HEBREW LETTER ALEF
898 0x0ce1 => 0x05d1, // hebrew_bet ב HEBREW LETTER BET
899 0x0ce2 => 0x05d2, // hebrew_gimel ג HEBREW LETTER GIMEL
900 0x0ce3 => 0x05d3, // hebrew_dalet ד HEBREW LETTER DALET
901 0x0ce4 => 0x05d4, // hebrew_he ה HEBREW LETTER HE
902 0x0ce5 => 0x05d5, // hebrew_waw ו HEBREW LETTER VAV
903 0x0ce6 => 0x05d6, // hebrew_zain ז HEBREW LETTER ZAYIN
904 0x0ce7 => 0x05d7, // hebrew_chet ח HEBREW LETTER HET
905 0x0ce8 => 0x05d8, // hebrew_tet ט HEBREW LETTER TET
906 0x0ce9 => 0x05d9, // hebrew_yod י HEBREW LETTER YOD
907 0x0cea => 0x05da, // hebrew_finalkaph ך HEBREW LETTER FINAL KAF
908 0x0ceb => 0x05db, // hebrew_kaph כ HEBREW LETTER KAF
909 0x0cec => 0x05dc, // hebrew_lamed ל HEBREW LETTER LAMED
910 0x0ced => 0x05dd, // hebrew_finalmem ם HEBREW LETTER FINAL MEM
911 0x0cee => 0x05de, // hebrew_mem מ HEBREW LETTER MEM
912 0x0cef => 0x05df, // hebrew_finalnun ן HEBREW LETTER FINAL NUN
913 0x0cf0 => 0x05e0, // hebrew_nun נ HEBREW LETTER NUN
914 0x0cf1 => 0x05e1, // hebrew_samech ס HEBREW LETTER SAMEKH
915 0x0cf2 => 0x05e2, // hebrew_ayin ע HEBREW LETTER AYIN
916 0x0cf3 => 0x05e3, // hebrew_finalpe ף HEBREW LETTER FINAL PE
917 0x0cf4 => 0x05e4, // hebrew_pe פ HEBREW LETTER PE
918 0x0cf5 => 0x05e5, // hebrew_finalzade ץ HEBREW LETTER FINAL TSADI
919 0x0cf6 => 0x05e6, // hebrew_zade צ HEBREW LETTER TSADI
920 0x0cf7 => 0x05e7, // hebrew_qoph ק HEBREW LETTER QOF
921 0x0cf8 => 0x05e8, // hebrew_resh ר HEBREW LETTER RESH
922 0x0cf9 => 0x05e9, // hebrew_shin ש HEBREW LETTER SHIN
923 0x0cfa => 0x05ea, // hebrew_taw ת HEBREW LETTER TAV
924 0x0da1 => 0x0e01, // Thai_kokai ก THAI CHARACTER KO KAI
925 0x0da2 => 0x0e02, // Thai_khokhai ข THAI CHARACTER KHO KHAI
926 0x0da3 => 0x0e03, // Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT
927 0x0da4 => 0x0e04, // Thai_khokhwai ค THAI CHARACTER KHO KHWAI
928 0x0da5 => 0x0e05, // Thai_khokhon ฅ THAI CHARACTER KHO KHON
929 0x0da6 => 0x0e06, // Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG
930 0x0da7 => 0x0e07, // Thai_ngongu ง THAI CHARACTER NGO NGU
931 0x0da8 => 0x0e08, // Thai_chochan จ THAI CHARACTER CHO CHAN
932 0x0da9 => 0x0e09, // Thai_choching ฉ THAI CHARACTER CHO CHING
933 0x0daa => 0x0e0a, // Thai_chochang ช THAI CHARACTER CHO CHANG
934 0x0dab => 0x0e0b, // Thai_soso ซ THAI CHARACTER SO SO
935 0x0dac => 0x0e0c, // Thai_chochoe ฌ THAI CHARACTER CHO CHOE
936 0x0dad => 0x0e0d, // Thai_yoying ญ THAI CHARACTER YO YING
937 0x0dae => 0x0e0e, // Thai_dochada ฎ THAI CHARACTER DO CHADA
938 0x0daf => 0x0e0f, // Thai_topatak ฏ THAI CHARACTER TO PATAK
939 0x0db0 => 0x0e10, // Thai_thothan ฐ THAI CHARACTER THO THAN
940 0x0db1 => 0x0e11, // Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO
941 0x0db2 => 0x0e12, // Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO
942 0x0db3 => 0x0e13, // Thai_nonen ณ THAI CHARACTER NO NEN
943 0x0db4 => 0x0e14, // Thai_dodek ด THAI CHARACTER DO DEK
944 0x0db5 => 0x0e15, // Thai_totao ต THAI CHARACTER TO TAO
945 0x0db6 => 0x0e16, // Thai_thothung ถ THAI CHARACTER THO THUNG
946 0x0db7 => 0x0e17, // Thai_thothahan ท THAI CHARACTER THO THAHAN
947 0x0db8 => 0x0e18, // Thai_thothong ธ THAI CHARACTER THO THONG
948 0x0db9 => 0x0e19, // Thai_nonu น THAI CHARACTER NO NU
949 0x0dba => 0x0e1a, // Thai_bobaimai บ THAI CHARACTER BO BAIMAI
950 0x0dbb => 0x0e1b, // Thai_popla ป THAI CHARACTER PO PLA
951 0x0dbc => 0x0e1c, // Thai_phophung ผ THAI CHARACTER PHO PHUNG
952 0x0dbd => 0x0e1d, // Thai_fofa ฝ THAI CHARACTER FO FA
953 0x0dbe => 0x0e1e, // Thai_phophan พ THAI CHARACTER PHO PHAN
954 0x0dbf => 0x0e1f, // Thai_fofan ฟ THAI CHARACTER FO FAN
955 0x0dc0 => 0x0e20, // Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO
956 0x0dc1 => 0x0e21, // Thai_moma ม THAI CHARACTER MO MA
957 0x0dc2 => 0x0e22, // Thai_yoyak ย THAI CHARACTER YO YAK
958 0x0dc3 => 0x0e23, // Thai_rorua ร THAI CHARACTER RO RUA
959 0x0dc4 => 0x0e24, // Thai_ru ฤ THAI CHARACTER RU
960 0x0dc5 => 0x0e25, // Thai_loling ล THAI CHARACTER LO LING
961 0x0dc6 => 0x0e26, // Thai_lu ฦ THAI CHARACTER LU
962 0x0dc7 => 0x0e27, // Thai_wowaen ว THAI CHARACTER WO WAEN
963 0x0dc8 => 0x0e28, // Thai_sosala ศ THAI CHARACTER SO SALA
964 0x0dc9 => 0x0e29, // Thai_sorusi ษ THAI CHARACTER SO RUSI
965 0x0dca => 0x0e2a, // Thai_sosua ส THAI CHARACTER SO SUA
966 0x0dcb => 0x0e2b, // Thai_hohip ห THAI CHARACTER HO HIP
967 0x0dcc => 0x0e2c, // Thai_lochula ฬ THAI CHARACTER LO CHULA
968 0x0dcd => 0x0e2d, // Thai_oang อ THAI CHARACTER O ANG
969 0x0dce => 0x0e2e, // Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK
970 0x0dcf => 0x0e2f, // Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI
971 0x0dd0 => 0x0e30, // Thai_saraa ะ THAI CHARACTER SARA A
972 0x0dd1 => 0x0e31, // Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT
973 0x0dd2 => 0x0e32, // Thai_saraaa า THAI CHARACTER SARA AA
974 0x0dd3 => 0x0e33, // Thai_saraam ำ THAI CHARACTER SARA AM
975 0x0dd4 => 0x0e34, // Thai_sarai ิ THAI CHARACTER SARA I
976 0x0dd5 => 0x0e35, // Thai_saraii ี THAI CHARACTER SARA II
977 0x0dd6 => 0x0e36, // Thai_saraue ึ THAI CHARACTER SARA UE
978 0x0dd7 => 0x0e37, // Thai_sarauee ื THAI CHARACTER SARA UEE
979 0x0dd8 => 0x0e38, // Thai_sarau ุ THAI CHARACTER SARA U
980 0x0dd9 => 0x0e39, // Thai_sarauu ู THAI CHARACTER SARA UU
981 0x0dda => 0x0e3a, // Thai_phinthu ฺ THAI CHARACTER PHINTHU
982 0x0dde => 0x0e3e, // Thai_maihanakat_maitho ???
983 0x0ddf => 0x0e3f, // Thai_baht ฿ THAI CURRENCY SYMBOL BAHT
984 0x0de0 => 0x0e40, // Thai_sarae เ THAI CHARACTER SARA E
985 0x0de1 => 0x0e41, // Thai_saraae แ THAI CHARACTER SARA AE
986 0x0de2 => 0x0e42, // Thai_sarao โ THAI CHARACTER SARA O
987 0x0de3 => 0x0e43, // Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN
988 0x0de4 => 0x0e44, // Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI
989 0x0de5 => 0x0e45, // Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO
990 0x0de6 => 0x0e46, // Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK
991 0x0de7 => 0x0e47, // Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU
992 0x0de8 => 0x0e48, // Thai_maiek ่ THAI CHARACTER MAI EK
993 0x0de9 => 0x0e49, // Thai_maitho ้ THAI CHARACTER MAI THO
994 0x0dea => 0x0e4a, // Thai_maitri ๊ THAI CHARACTER MAI TRI
995 0x0deb => 0x0e4b, // Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA
996 0x0dec => 0x0e4c, // Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT
997 0x0ded => 0x0e4d, // Thai_nikhahit ํ THAI CHARACTER NIKHAHIT
998 0x0df0 => 0x0e50, // Thai_leksun ๐ THAI DIGIT ZERO
999 0x0df1 => 0x0e51, // Thai_leknung ๑ THAI DIGIT ONE
1000 0x0df2 => 0x0e52, // Thai_leksong ๒ THAI DIGIT TWO
1001 0x0df3 => 0x0e53, // Thai_leksam ๓ THAI DIGIT THREE
1002 0x0df4 => 0x0e54, // Thai_leksi ๔ THAI DIGIT FOUR
1003 0x0df5 => 0x0e55, // Thai_lekha ๕ THAI DIGIT FIVE
1004 0x0df6 => 0x0e56, // Thai_lekhok ๖ THAI DIGIT SIX
1005 0x0df7 => 0x0e57, // Thai_lekchet ๗ THAI DIGIT SEVEN
1006 0x0df8 => 0x0e58, // Thai_lekpaet ๘ THAI DIGIT EIGHT
1007 0x0df9 => 0x0e59, // Thai_lekkao ๙ THAI DIGIT NINE
1008 0x0ea1 => 0x3131, // Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK
1009 0x0ea2 => 0x3132, // Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK
1010 0x0ea3 => 0x3133, // Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS
1011 0x0ea4 => 0x3134, // Hangul_Nieun ㄴ HANGUL LETTER NIEUN
1012 0x0ea5 => 0x3135, // Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC
1013 0x0ea6 => 0x3136, // Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH
1014 0x0ea7 => 0x3137, // Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT
1015 0x0ea8 => 0x3138, // Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT
1016 0x0ea9 => 0x3139, // Hangul_Rieul ㄹ HANGUL LETTER RIEUL
1017 0x0eaa => 0x313a, // Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK
1018 0x0eab => 0x313b, // Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM
1019 0x0eac => 0x313c, // Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP
1020 0x0ead => 0x313d, // Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS
1021 0x0eae => 0x313e, // Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH
1022 0x0eaf => 0x313f, // Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH
1023 0x0eb0 => 0x3140, // Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH
1024 0x0eb1 => 0x3141, // Hangul_Mieum ㅁ HANGUL LETTER MIEUM
1025 0x0eb2 => 0x3142, // Hangul_Pieub ㅂ HANGUL LETTER PIEUP
1026 0x0eb3 => 0x3143, // Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP
1027 0x0eb4 => 0x3144, // Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS
1028 0x0eb5 => 0x3145, // Hangul_Sios ㅅ HANGUL LETTER SIOS
1029 0x0eb6 => 0x3146, // Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS
1030 0x0eb7 => 0x3147, // Hangul_Ieung ㅇ HANGUL LETTER IEUNG
1031 0x0eb8 => 0x3148, // Hangul_Jieuj ㅈ HANGUL LETTER CIEUC
1032 0x0eb9 => 0x3149, // Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC
1033 0x0eba => 0x314a, // Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH
1034 0x0ebb => 0x314b, // Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH
1035 0x0ebc => 0x314c, // Hangul_Tieut ㅌ HANGUL LETTER THIEUTH
1036 0x0ebd => 0x314d, // Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH
1037 0x0ebe => 0x314e, // Hangul_Hieuh ㅎ HANGUL LETTER HIEUH
1038 0x0ebf => 0x314f, // Hangul_A ㅏ HANGUL LETTER A
1039 0x0ec0 => 0x3150, // Hangul_AE ㅐ HANGUL LETTER AE
1040 0x0ec1 => 0x3151, // Hangul_YA ㅑ HANGUL LETTER YA
1041 0x0ec2 => 0x3152, // Hangul_YAE ㅒ HANGUL LETTER YAE
1042 0x0ec3 => 0x3153, // Hangul_EO ㅓ HANGUL LETTER EO
1043 0x0ec4 => 0x3154, // Hangul_E ㅔ HANGUL LETTER E
1044 0x0ec5 => 0x3155, // Hangul_YEO ㅕ HANGUL LETTER YEO
1045 0x0ec6 => 0x3156, // Hangul_YE ㅖ HANGUL LETTER YE
1046 0x0ec7 => 0x3157, // Hangul_O ㅗ HANGUL LETTER O
1047 0x0ec8 => 0x3158, // Hangul_WA ㅘ HANGUL LETTER WA
1048 0x0ec9 => 0x3159, // Hangul_WAE ㅙ HANGUL LETTER WAE
1049 0x0eca => 0x315a, // Hangul_OE ㅚ HANGUL LETTER OE
1050 0x0ecb => 0x315b, // Hangul_YO ㅛ HANGUL LETTER YO
1051 0x0ecc => 0x315c, // Hangul_U ㅜ HANGUL LETTER U
1052 0x0ecd => 0x315d, // Hangul_WEO ㅝ HANGUL LETTER WEO
1053 0x0ece => 0x315e, // Hangul_WE ㅞ HANGUL LETTER WE
1054 0x0ecf => 0x315f, // Hangul_WI ㅟ HANGUL LETTER WI
1055 0x0ed0 => 0x3160, // Hangul_YU ㅠ HANGUL LETTER YU
1056 0x0ed1 => 0x3161, // Hangul_EU ㅡ HANGUL LETTER EU
1057 0x0ed2 => 0x3162, // Hangul_YI ㅢ HANGUL LETTER YI
1058 0x0ed3 => 0x3163, // Hangul_I ㅣ HANGUL LETTER I
1059 0x0ed4 => 0x11a8, // Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK
1060 0x0ed5 => 0x11a9, // Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK
1061 0x0ed6 => 0x11aa, // Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS
1062 0x0ed7 => 0x11ab, // Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN
1063 0x0ed8 => 0x11ac, // Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC
1064 0x0ed9 => 0x11ad, // Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH
1065 0x0eda => 0x11ae, // Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT
1066 0x0edb => 0x11af, // Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL
1067 0x0edc => 0x11b0, // Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK
1068 0x0edd => 0x11b1, // Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM
1069 0x0ede => 0x11b2, // Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP
1070 0x0edf => 0x11b3, // Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS
1071 0x0ee0 => 0x11b4, // Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH
1072 0x0ee1 => 0x11b5, // Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH
1073 0x0ee2 => 0x11b6, // Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH
1074 0x0ee3 => 0x11b7, // Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM
1075 0x0ee4 => 0x11b8, // Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP
1076 0x0ee5 => 0x11b9, // Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS
1077 0x0ee6 => 0x11ba, // Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS
1078 0x0ee7 => 0x11bb, // Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS
1079 0x0ee8 => 0x11bc, // Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG
1080 0x0ee9 => 0x11bd, // Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC
1081 0x0eea => 0x11be, // Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH
1082 0x0eeb => 0x11bf, // Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH
1083 0x0eec => 0x11c0, // Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH
1084 0x0eed => 0x11c1, // Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH
1085 0x0eee => 0x11c2, // Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH
1086 0x0eef => 0x316d, // Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH
1087 0x0ef0 => 0x3171, // Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM
1088 0x0ef1 => 0x3178, // Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP
1089 0x0ef2 => 0x317f, // Hangul_PanSios ㅿ HANGUL LETTER PANSIOS
1090 0x0ef3 => 0x3181, // Hangul_KkogjiDalrinIeung ㆁ HANGUL LETTER YESIEUNG
1091 0x0ef4 => 0x3184, // Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH
1092 0x0ef5 => 0x3186, // Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH
1093 0x0ef6 => 0x318d, // Hangul_AraeA ㆍ HANGUL LETTER ARAEA
1094 0x0ef7 => 0x318e, // Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE
1095 0x0ef8 => 0x11eb, // Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS
1096 0x0ef9 => 0x11f0, // Hangul_J_KkogjiDalrinIeung ᇰ HANGUL JONGSEONG YESIEUNG
1097 0x0efa => 0x11f9, // Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH
1098 0x0eff => 0x20a9, // Korean_Won ₩ WON SIGN
1099 0x13bc => 0x0152, // OE Œ LATIN CAPITAL LIGATURE OE
1100 0x13bd => 0x0153, // oe œ LATIN SMALL LIGATURE OE
1101 0x13be => 0x0178, // Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS
1102 0x20ac => 0x20ac, // EuroSign € EURO SIGN
1103 _ => 0,
1104 }
1105}