1 /* -*-c-*- */
2 /* Copyright (C) 2003  Marcus Lundblad */
3 /* This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, see: <http://www.gnu.org/licenses/>
15  */
16 
17 #include "config.h"
18 
19 #include <stdio.h>
20 #include <X11/Xlib.h>
21 #include "fvwmlib.h"
22 #include "CombineChars.h"
23 
24 /* ---------------------------- local types -------------------------------- */
25 
26 typedef struct char_combclass
27 {
28 	unsigned short key;
29 	int combclass;
30 } char_combclass_t;
31 
32 
33 typedef struct char_comb
34 {
35 	unsigned short key;
36 	unsigned short first;
37 	unsigned short second;
38 } char_comb_t;
39 
40 /* ---------------------------- static variables --------------------------- */
41 
42 /* would like to use the Unicode replacement character here, but that would
43    result in expanding incoming UTF-8 strings when garbage characters occurs */
44 /* so for the time being use '?' */
45 static unsigned short REPLACEMENT_CHARACTER = 0x3f;
46 
47 /* maps characters to combination classes (not in list => 0) */
48 /* parsed from UnicodeData-3.2.0.txt */
49 static const char_combclass_t combclass_table[] =
50 {
51 	{ 0x0300, 230},
52 	{ 0x0301, 230},
53 	{ 0x0302, 230},
54 	{ 0x0303, 230},
55 	{ 0x0304, 230},
56 	{ 0x0305, 230},
57 	{ 0x0306, 230},
58 	{ 0x0307, 230},
59 	{ 0x0308, 230},
60 	{ 0x0309, 230},
61 	{ 0x030A, 230},
62 	{ 0x030B, 230},
63 	{ 0x030C, 230},
64 	{ 0x030D, 230},
65 	{ 0x030E, 230},
66 	{ 0x030F, 230},
67 	{ 0x0310, 230},
68 	{ 0x0311, 230},
69 	{ 0x0312, 230},
70 	{ 0x0313, 230},
71 	{ 0x0314, 230},
72 	{ 0x0315, 232},
73 	{ 0x0316, 220},
74 	{ 0x0317, 220},
75 	{ 0x0318, 220},
76 	{ 0x0319, 220},
77 	{ 0x031A, 232},
78 	{ 0x031B, 216},
79 	{ 0x031C, 220},
80 	{ 0x031D, 220},
81 	{ 0x031E, 220},
82 	{ 0x031F, 220},
83 	{ 0x0320, 220},
84 	{ 0x0321, 202},
85 	{ 0x0322, 202},
86 	{ 0x0323, 220},
87 	{ 0x0324, 220},
88 	{ 0x0325, 220},
89 	{ 0x0326, 220},
90 	{ 0x0327, 202},
91 	{ 0x0328, 202},
92 	{ 0x0329, 220},
93 	{ 0x032A, 220},
94 	{ 0x032B, 220},
95 	{ 0x032C, 220},
96 	{ 0x032D, 220},
97 	{ 0x032E, 220},
98 	{ 0x032F, 220},
99 	{ 0x0330, 220},
100 	{ 0x0331, 220},
101 	{ 0x0332, 220},
102 	{ 0x0333, 220},
103 	{ 0x0334, 1},
104 	{ 0x0335, 1},
105 	{ 0x0336, 1},
106 	{ 0x0337, 1},
107 	{ 0x0338, 1},
108 	{ 0x0339, 220},
109 	{ 0x033A, 220},
110 	{ 0x033B, 220},
111 	{ 0x033C, 220},
112 	{ 0x033D, 230},
113 	{ 0x033E, 230},
114 	{ 0x033F, 230},
115 	{ 0x0340, 230},
116 	{ 0x0341, 230},
117 	{ 0x0342, 230},
118 	{ 0x0343, 230},
119 	{ 0x0344, 230},
120 	{ 0x0345, 240},
121 	{ 0x0346, 230},
122 	{ 0x0347, 220},
123 	{ 0x0348, 220},
124 	{ 0x0349, 220},
125 	{ 0x034A, 230},
126 	{ 0x034B, 230},
127 	{ 0x034C, 230},
128 	{ 0x034D, 220},
129 	{ 0x034E, 220},
130 	{ 0x034F, -1 },
131 	{ 0x0360, 234},
132 	{ 0x0361, 234},
133 	{ 0x0362, 233},
134 	{ 0x0363, 230},
135 	{ 0x0364, 230},
136 	{ 0x0365, 230},
137 	{ 0x0366, 230},
138 	{ 0x0367, 230},
139 	{ 0x0368, 230},
140 	{ 0x0369, 230},
141 	{ 0x036A, 230},
142 	{ 0x036B, 230},
143 	{ 0x036C, 230},
144 	{ 0x036D, 230},
145 	{ 0x036E, 230},
146 	{ 0x036F, 230},
147 	{ 0x0483, 230},
148 	{ 0x0484, 230},
149 	{ 0x0485, 230},
150 	{ 0x0486, 230},
151 	{ 0x0488, -3 },
152 	{ 0x0489, -3 },
153 	{ 0x0591, 220},
154 	{ 0x0592, 230},
155 	{ 0x0593, 230},
156 	{ 0x0594, 230},
157 	{ 0x0595, 230},
158 	{ 0x0596, 220},
159 	{ 0x0597, 230},
160 	{ 0x0598, 230},
161 	{ 0x0599, 230},
162 	{ 0x059A, 222},
163 	{ 0x059B, 220},
164 	{ 0x059C, 230},
165 	{ 0x059D, 230},
166 	{ 0x059E, 230},
167 	{ 0x059F, 230},
168 	{ 0x05A0, 230},
169 	{ 0x05A1, 230},
170 	{ 0x05A3, 220},
171 	{ 0x05A4, 220},
172 	{ 0x05A5, 220},
173 	{ 0x05A6, 220},
174 	{ 0x05A7, 220},
175 	{ 0x05A8, 230},
176 	{ 0x05A9, 230},
177 	{ 0x05AA, 220},
178 	{ 0x05AB, 230},
179 	{ 0x05AC, 230},
180 	{ 0x05AD, 222},
181 	{ 0x05AE, 228},
182 	{ 0x05AF, 230},
183 	{ 0x05B0, 10},
184 	{ 0x05B1, 11},
185 	{ 0x05B2, 12},
186 	{ 0x05B3, 13},
187 	{ 0x05B4, 14},
188 	{ 0x05B5, 15},
189 	{ 0x05B6, 16},
190 	{ 0x05B7, 17},
191 	{ 0x05B8, 18},
192 	{ 0x05B9, 19},
193 	{ 0x05BB, 20},
194 	{ 0x05BC, 21},
195 	{ 0x05BD, 22},
196 	{ 0x05BF, 23},
197 	{ 0x05C1, 24},
198 	{ 0x05C2, 25},
199 	{ 0x05C4, 230},
200 	{ 0x064B, 27},
201 	{ 0x064C, 28},
202 	{ 0x064D, 29},
203 	{ 0x064E, 30},
204 	{ 0x064F, 31},
205 	{ 0x0650, 32},
206 	{ 0x0651, 33},
207 	{ 0x0652, 34},
208 	{ 0x0653, 230},
209 	{ 0x0654, 230},
210 	{ 0x0655, 220},
211 	{ 0x0670, 35},
212 	{ 0x06D6, 230},
213 	{ 0x06D7, 230},
214 	{ 0x06D8, 230},
215 	{ 0x06D9, 230},
216 	{ 0x06DA, 230},
217 	{ 0x06DB, 230},
218 	{ 0x06DC, 230},
219 	{ 0x06DE, -3 },
220 	{ 0x06DF, 230},
221 	{ 0x06E0, 230},
222 	{ 0x06E1, 230},
223 	{ 0x06E2, 230},
224 	{ 0x06E3, 220},
225 	{ 0x06E4, 230},
226 	{ 0x06E7, 230},
227 	{ 0x06E8, 230},
228 	{ 0x06EA, 220},
229 	{ 0x06EB, 230},
230 	{ 0x06EC, 230},
231 	{ 0x06ED, 220},
232 	{ 0x0711, 36},
233 	{ 0x0730, 230},
234 	{ 0x0731, 220},
235 	{ 0x0732, 230},
236 	{ 0x0733, 230},
237 	{ 0x0734, 220},
238 	{ 0x0735, 230},
239 	{ 0x0736, 230},
240 	{ 0x0737, 220},
241 	{ 0x0738, 220},
242 	{ 0x0739, 220},
243 	{ 0x073A, 230},
244 	{ 0x073B, 220},
245 	{ 0x073C, 220},
246 	{ 0x073D, 230},
247 	{ 0x073E, 220},
248 	{ 0x073F, 230},
249 	{ 0x0740, 230},
250 	{ 0x0741, 230},
251 	{ 0x0742, 220},
252 	{ 0x0743, 230},
253 	{ 0x0744, 220},
254 	{ 0x0745, 230},
255 	{ 0x0746, 220},
256 	{ 0x0747, 230},
257 	{ 0x0748, 220},
258 	{ 0x0749, 230},
259 	{ 0x074A, 230},
260 	{ 0x07A6, -1 },
261 	{ 0x07A7, -1 },
262 	{ 0x07A8, -1 },
263 	{ 0x07A9, -1 },
264 	{ 0x07AA, -1 },
265 	{ 0x07AB, -1 },
266 	{ 0x07AC, -1 },
267 	{ 0x07AD, -1 },
268 	{ 0x07AE, -1 },
269 	{ 0x07AF, -1 },
270 	{ 0x07B0, -1 },
271 	{ 0x0901, -1 },
272 	{ 0x0902, -1 },
273 	{ 0x0903, -2 },
274 	{ 0x093C, 7},
275 	{ 0x093E, -2 },
276 	{ 0x093F, -2 },
277 	{ 0x0940, -2 },
278 	{ 0x0941, -1 },
279 	{ 0x0942, -1 },
280 	{ 0x0943, -1 },
281 	{ 0x0944, -1 },
282 	{ 0x0945, -1 },
283 	{ 0x0946, -1 },
284 	{ 0x0947, -1 },
285 	{ 0x0948, -1 },
286 	{ 0x0949, -2 },
287 	{ 0x094A, -2 },
288 	{ 0x094B, -2 },
289 	{ 0x094C, -2 },
290 	{ 0x094D, 9},
291 	{ 0x0951, 230},
292 	{ 0x0952, 220},
293 	{ 0x0953, 230},
294 	{ 0x0954, 230},
295 	{ 0x0962, -1 },
296 	{ 0x0963, -1 },
297 	{ 0x0981, -1 },
298 	{ 0x0982, -2 },
299 	{ 0x0983, -2 },
300 	{ 0x09BC, 7},
301 	{ 0x09BE, -2 },
302 	{ 0x09BF, -2 },
303 	{ 0x09C0, -2 },
304 	{ 0x09C1, -1 },
305 	{ 0x09C2, -1 },
306 	{ 0x09C3, -1 },
307 	{ 0x09C4, -1 },
308 	{ 0x09C7, -2 },
309 	{ 0x09C8, -2 },
310 	{ 0x09CB, -2 },
311 	{ 0x09CC, -2 },
312 	{ 0x09CD, 9},
313 	{ 0x09D7, -2 },
314 	{ 0x09E2, -1 },
315 	{ 0x09E3, -1 },
316 	{ 0x0A02, -1 },
317 	{ 0x0A3C, 7},
318 	{ 0x0A3E, -2 },
319 	{ 0x0A3F, -2 },
320 	{ 0x0A40, -2 },
321 	{ 0x0A41, -1 },
322 	{ 0x0A42, -1 },
323 	{ 0x0A47, -1 },
324 	{ 0x0A48, -1 },
325 	{ 0x0A4B, -1 },
326 	{ 0x0A4C, -1 },
327 	{ 0x0A4D, 9},
328 	{ 0x0A70, -1 },
329 	{ 0x0A71, -1 },
330 	{ 0x0A81, -1 },
331 	{ 0x0A82, -1 },
332 	{ 0x0A83, -2 },
333 	{ 0x0ABC, 7},
334 	{ 0x0ABE, -2 },
335 	{ 0x0ABF, -2 },
336 	{ 0x0AC0, -2 },
337 	{ 0x0AC1, -1 },
338 	{ 0x0AC2, -1 },
339 	{ 0x0AC3, -1 },
340 	{ 0x0AC4, -1 },
341 	{ 0x0AC5, -1 },
342 	{ 0x0AC7, -1 },
343 	{ 0x0AC8, -1 },
344 	{ 0x0AC9, -2 },
345 	{ 0x0ACB, -2 },
346 	{ 0x0ACC, -2 },
347 	{ 0x0ACD, 9},
348 	{ 0x0B01, -1 },
349 	{ 0x0B02, -2 },
350 	{ 0x0B03, -2 },
351 	{ 0x0B3C, 7},
352 	{ 0x0B3E, -2 },
353 	{ 0x0B3F, -1 },
354 	{ 0x0B40, -2 },
355 	{ 0x0B41, -1 },
356 	{ 0x0B42, -1 },
357 	{ 0x0B43, -1 },
358 	{ 0x0B47, -2 },
359 	{ 0x0B48, -2 },
360 	{ 0x0B4B, -2 },
361 	{ 0x0B4C, -2 },
362 	{ 0x0B4D, 9},
363 	{ 0x0B56, -1 },
364 	{ 0x0B57, -2 },
365 	{ 0x0B82, -1 },
366 	{ 0x0BBE, -2 },
367 	{ 0x0BBF, -2 },
368 	{ 0x0BC0, -1 },
369 	{ 0x0BC1, -2 },
370 	{ 0x0BC2, -2 },
371 	{ 0x0BC6, -2 },
372 	{ 0x0BC7, -2 },
373 	{ 0x0BC8, -2 },
374 	{ 0x0BCA, -2 },
375 	{ 0x0BCB, -2 },
376 	{ 0x0BCC, -2 },
377 	{ 0x0BCD, 9},
378 	{ 0x0BD7, -2 },
379 	{ 0x0C01, -2 },
380 	{ 0x0C02, -2 },
381 	{ 0x0C03, -2 },
382 	{ 0x0C3E, -1 },
383 	{ 0x0C3F, -1 },
384 	{ 0x0C40, -1 },
385 	{ 0x0C41, -2 },
386 	{ 0x0C42, -2 },
387 	{ 0x0C43, -2 },
388 	{ 0x0C44, -2 },
389 	{ 0x0C46, -1 },
390 	{ 0x0C47, -1 },
391 	{ 0x0C48, -1 },
392 	{ 0x0C4A, -1 },
393 	{ 0x0C4B, -1 },
394 	{ 0x0C4C, -1 },
395 	{ 0x0C4D, 9},
396 	{ 0x0C55, 84},
397 	{ 0x0C56, 91},
398 	{ 0x0C82, -2 },
399 	{ 0x0C83, -2 },
400 	{ 0x0CBE, -2 },
401 	{ 0x0CBF, -1 },
402 	{ 0x0CC0, -2 },
403 	{ 0x0CC1, -2 },
404 	{ 0x0CC2, -2 },
405 	{ 0x0CC3, -2 },
406 	{ 0x0CC4, -2 },
407 	{ 0x0CC6, -1 },
408 	{ 0x0CC7, -2 },
409 	{ 0x0CC8, -2 },
410 	{ 0x0CCA, -2 },
411 	{ 0x0CCB, -2 },
412 	{ 0x0CCC, -1 },
413 	{ 0x0CCD, 9},
414 	{ 0x0CD5, -2 },
415 	{ 0x0CD6, -2 },
416 	{ 0x0D02, -2 },
417 	{ 0x0D03, -2 },
418 	{ 0x0D3E, -2 },
419 	{ 0x0D3F, -2 },
420 	{ 0x0D40, -2 },
421 	{ 0x0D41, -1 },
422 	{ 0x0D42, -1 },
423 	{ 0x0D43, -1 },
424 	{ 0x0D46, -2 },
425 	{ 0x0D47, -2 },
426 	{ 0x0D48, -2 },
427 	{ 0x0D4A, -2 },
428 	{ 0x0D4B, -2 },
429 	{ 0x0D4C, -2 },
430 	{ 0x0D4D, 9},
431 	{ 0x0D57, -2 },
432 	{ 0x0D82, -2 },
433 	{ 0x0D83, -2 },
434 	{ 0x0DCA, 9},
435 	{ 0x0DCF, -2 },
436 	{ 0x0DD0, -2 },
437 	{ 0x0DD1, -2 },
438 	{ 0x0DD2, -1 },
439 	{ 0x0DD3, -1 },
440 	{ 0x0DD4, -1 },
441 	{ 0x0DD6, -1 },
442 	{ 0x0DD8, -2 },
443 	{ 0x0DD9, -2 },
444 	{ 0x0DDA, -2 },
445 	{ 0x0DDB, -2 },
446 	{ 0x0DDC, -2 },
447 	{ 0x0DDD, -2 },
448 	{ 0x0DDE, -2 },
449 	{ 0x0DDF, -2 },
450 	{ 0x0DF2, -2 },
451 	{ 0x0DF3, -2 },
452 	{ 0x0E31, -1 },
453 	{ 0x0E34, -1 },
454 	{ 0x0E35, -1 },
455 	{ 0x0E36, -1 },
456 	{ 0x0E37, -1 },
457 	{ 0x0E38, 103},
458 	{ 0x0E39, 103},
459 	{ 0x0E3A, 9},
460 	{ 0x0E47, -1 },
461 	{ 0x0E48, 107},
462 	{ 0x0E49, 107},
463 	{ 0x0E4A, 107},
464 	{ 0x0E4B, 107},
465 	{ 0x0E4C, -1 },
466 	{ 0x0E4D, -1 },
467 	{ 0x0E4E, -1 },
468 	{ 0x0EB1, -1 },
469 	{ 0x0EB4, -1 },
470 	{ 0x0EB5, -1 },
471 	{ 0x0EB6, -1 },
472 	{ 0x0EB7, -1 },
473 	{ 0x0EB8, 118},
474 	{ 0x0EB9, 118},
475 	{ 0x0EBB, -1 },
476 	{ 0x0EBC, -1 },
477 	{ 0x0EC8, 122},
478 	{ 0x0EC9, 122},
479 	{ 0x0ECA, 122},
480 	{ 0x0ECB, 122},
481 	{ 0x0ECC, -1 },
482 	{ 0x0ECD, -1 },
483 	{ 0x0F18, 220},
484 	{ 0x0F19, 220},
485 	{ 0x0F35, 220},
486 	{ 0x0F37, 220},
487 	{ 0x0F39, 216},
488 	{ 0x0F3E, -2 },
489 	{ 0x0F3F, -2 },
490 	{ 0x0F71, 129},
491 	{ 0x0F72, 130},
492 	{ 0x0F73, -1 },
493 	{ 0x0F74, 132},
494 	{ 0x0F75, -1 },
495 	{ 0x0F76, -1 },
496 	{ 0x0F77, -1 },
497 	{ 0x0F78, -1 },
498 	{ 0x0F79, -1 },
499 	{ 0x0F7A, 130},
500 	{ 0x0F7B, 130},
501 	{ 0x0F7C, 130},
502 	{ 0x0F7D, 130},
503 	{ 0x0F7E, -1 },
504 	{ 0x0F7F, -2 },
505 	{ 0x0F80, 130},
506 	{ 0x0F81, -1 },
507 	{ 0x0F82, 230},
508 	{ 0x0F83, 230},
509 	{ 0x0F84, 9},
510 	{ 0x0F86, 230},
511 	{ 0x0F87, 230},
512 	{ 0x0F90, -1 },
513 	{ 0x0F91, -1 },
514 	{ 0x0F92, -1 },
515 	{ 0x0F93, -1 },
516 	{ 0x0F94, -1 },
517 	{ 0x0F95, -1 },
518 	{ 0x0F96, -1 },
519 	{ 0x0F97, -1 },
520 	{ 0x0F99, -1 },
521 	{ 0x0F9A, -1 },
522 	{ 0x0F9B, -1 },
523 	{ 0x0F9C, -1 },
524 	{ 0x0F9D, -1 },
525 	{ 0x0F9E, -1 },
526 	{ 0x0F9F, -1 },
527 	{ 0x0FA0, -1 },
528 	{ 0x0FA1, -1 },
529 	{ 0x0FA2, -1 },
530 	{ 0x0FA3, -1 },
531 	{ 0x0FA4, -1 },
532 	{ 0x0FA5, -1 },
533 	{ 0x0FA6, -1 },
534 	{ 0x0FA7, -1 },
535 	{ 0x0FA8, -1 },
536 	{ 0x0FA9, -1 },
537 	{ 0x0FAA, -1 },
538 	{ 0x0FAB, -1 },
539 	{ 0x0FAC, -1 },
540 	{ 0x0FAD, -1 },
541 	{ 0x0FAE, -1 },
542 	{ 0x0FAF, -1 },
543 	{ 0x0FB0, -1 },
544 	{ 0x0FB1, -1 },
545 	{ 0x0FB2, -1 },
546 	{ 0x0FB3, -1 },
547 	{ 0x0FB4, -1 },
548 	{ 0x0FB5, -1 },
549 	{ 0x0FB6, -1 },
550 	{ 0x0FB7, -1 },
551 	{ 0x0FB8, -1 },
552 	{ 0x0FB9, -1 },
553 	{ 0x0FBA, -1 },
554 	{ 0x0FBB, -1 },
555 	{ 0x0FBC, -1 },
556 	{ 0x0FC6, 220},
557 	{ 0x102C, -2 },
558 	{ 0x102D, -1 },
559 	{ 0x102E, -1 },
560 	{ 0x102F, -1 },
561 	{ 0x1030, -1 },
562 	{ 0x1031, -2 },
563 	{ 0x1032, -1 },
564 	{ 0x1036, -1 },
565 	{ 0x1037, 7},
566 	{ 0x1038, -2 },
567 	{ 0x1039, 9},
568 	{ 0x1056, -2 },
569 	{ 0x1057, -2 },
570 	{ 0x1058, -1 },
571 	{ 0x1059, -1 },
572 	{ 0x1712, -1 },
573 	{ 0x1713, -1 },
574 	{ 0x1714, 9},
575 	{ 0x1732, -1 },
576 	{ 0x1733, -1 },
577 	{ 0x1734, 9},
578 	{ 0x1752, -1 },
579 	{ 0x1753, -1 },
580 	{ 0x1772, -1 },
581 	{ 0x1773, -1 },
582 	{ 0x17B4, -2 },
583 	{ 0x17B5, -2 },
584 	{ 0x17B6, -2 },
585 	{ 0x17B7, -1 },
586 	{ 0x17B8, -1 },
587 	{ 0x17B9, -1 },
588 	{ 0x17BA, -1 },
589 	{ 0x17BB, -1 },
590 	{ 0x17BC, -1 },
591 	{ 0x17BD, -1 },
592 	{ 0x17BE, -2 },
593 	{ 0x17BF, -2 },
594 	{ 0x17C0, -2 },
595 	{ 0x17C1, -2 },
596 	{ 0x17C2, -2 },
597 	{ 0x17C3, -2 },
598 	{ 0x17C4, -2 },
599 	{ 0x17C5, -2 },
600 	{ 0x17C6, -1 },
601 	{ 0x17C7, -2 },
602 	{ 0x17C8, -2 },
603 	{ 0x17C9, -1 },
604 	{ 0x17CA, -1 },
605 	{ 0x17CB, -1 },
606 	{ 0x17CC, -1 },
607 	{ 0x17CD, -1 },
608 	{ 0x17CE, -1 },
609 	{ 0x17CF, -1 },
610 	{ 0x17D0, -1 },
611 	{ 0x17D1, -1 },
612 	{ 0x17D2, 9},
613 	{ 0x17D3, -1 },
614 	{ 0x180B, -1 },
615 	{ 0x180C, -1 },
616 	{ 0x180D, -1 },
617 	{ 0x18A9, 228},
618 	{ 0x20D0, 230},
619 	{ 0x20D1, 230},
620 	{ 0x20D2, 1},
621 	{ 0x20D3, 1},
622 	{ 0x20D4, 230},
623 	{ 0x20D5, 230},
624 	{ 0x20D6, 230},
625 	{ 0x20D7, 230},
626 	{ 0x20D8, 1},
627 	{ 0x20D9, 1},
628 	{ 0x20DA, 1},
629 	{ 0x20DB, 230},
630 	{ 0x20DC, 230},
631 	{ 0x20DD, -3 },
632 	{ 0x20DE, -3 },
633 	{ 0x20DF, -3 },
634 	{ 0x20E0, -3 },
635 	{ 0x20E1, 230},
636 	{ 0x20E2, -3 },
637 	{ 0x20E3, -3 },
638 	{ 0x20E4, -3 },
639 	{ 0x20E5, 1},
640 	{ 0x20E6, 1},
641 	{ 0x20E7, 230},
642 	{ 0x20E8, 220},
643 	{ 0x20E9, 230},
644 	{ 0x20EA, 1},
645 	{ 0x302A, 218},
646 	{ 0x302B, 228},
647 	{ 0x302C, 232},
648 	{ 0x302D, 222},
649 	{ 0x302E, 224},
650 	{ 0x302F, 224},
651 	{ 0x3099, 8},
652 	{ 0x309A, 8},
653 	{ 0xFB1E, 26},
654 	{ 0xFE00, -1 },
655 	{ 0xFE01, -1 },
656 	{ 0xFE02, -1 },
657 	{ 0xFE03, -1 },
658 	{ 0xFE04, -1 },
659 	{ 0xFE05, -1 },
660 	{ 0xFE06, -1 },
661 	{ 0xFE07, -1 },
662 	{ 0xFE08, -1 },
663 	{ 0xFE09, -1 },
664 	{ 0xFE0A, -1 },
665 	{ 0xFE0B, -1 },
666 	{ 0xFE0C, -1 },
667 	{ 0xFE0D, -1 },
668 	{ 0xFE0E, -1 },
669 	{ 0xFE0F, -1 },
670 	{ 0xFE20, 230},
671 	{ 0xFE21, 230},
672 	{ 0xFE22, 230},
673 	{ 0xFE23, 230},
674 	/*{ 0x1D165, 216},
675 	{ 0x1D166, 216},
676 	{ 0x1D167, 1},
677 	{ 0x1D168, 1},
678 	{ 0x1D169, 1},
679 	{ 0x1D16D, 226},
680 	{ 0x1D16E, 216},
681 	{ 0x1D16F, 216},
682 	{ 0x1D170, 216},
683 	{ 0x1D171, 216},
684 	{ 0x1D172, 216},
685 	{ 0x1D17B, 220},
686 	{ 0x1D17C, 220},
687 	{ 0x1D17D, 220},
688 	{ 0x1D17E, 220},
689 	{ 0x1D17F, 220},
690 	{ 0x1D180, 220},
691 	{ 0x1D181, 220},
692 	{ 0x1D182, 220},
693 	{ 0x1D185, 230},
694 	{ 0x1D186, 230},
695 	{ 0x1D187, 230},
696 	{ 0x1D188, 230},
697 	{ 0x1D189, 230},
698 	{ 0x1D18A, 220},
699 	{ 0x1D18B, 220},
700 	{ 0x1D1AA, 230},
701 	{ 0x1D1AB, 230},
702 	{ 0x1D1AC, 230},
703 	{ 0x1D1AD, 230},*/
704 };
705 
706 /* maps characters to decompositions */
707 /* parsed from UnicodeData-3.2.0.txt */
708 static const char_comb_t comb_table[] =
709 {
710 	{ 0x00C0, 0x0041, 0x0300 },
711 	{ 0x00C1, 0x0041, 0x0301 },
712 	{ 0x00C2, 0x0041, 0x0302 },
713 	{ 0x00C3, 0x0041, 0x0303 },
714 	{ 0x00C4, 0x0041, 0x0308 },
715 	{ 0x00C5, 0x0041, 0x030A },
716 	{ 0x00C7, 0x0043, 0x0327 },
717 	{ 0x00C8, 0x0045, 0x0300 },
718 	{ 0x00C9, 0x0045, 0x0301 },
719 	{ 0x00CA, 0x0045, 0x0302 },
720 	{ 0x00CB, 0x0045, 0x0308 },
721 	{ 0x00CC, 0x0049, 0x0300 },
722 	{ 0x00CD, 0x0049, 0x0301 },
723 	{ 0x00CE, 0x0049, 0x0302 },
724 	{ 0x00CF, 0x0049, 0x0308 },
725 	{ 0x00D1, 0x004E, 0x0303 },
726 	{ 0x00D2, 0x004F, 0x0300 },
727 	{ 0x00D3, 0x004F, 0x0301 },
728 	{ 0x00D4, 0x004F, 0x0302 },
729 	{ 0x00D5, 0x004F, 0x0303 },
730 	{ 0x00D6, 0x004F, 0x0308 },
731 	{ 0x00D9, 0x0055, 0x0300 },
732 	{ 0x00DA, 0x0055, 0x0301 },
733 	{ 0x00DB, 0x0055, 0x0302 },
734 	{ 0x00DC, 0x0055, 0x0308 },
735 	{ 0x00DD, 0x0059, 0x0301 },
736 	{ 0x00E0, 0x0061, 0x0300 },
737 	{ 0x00E1, 0x0061, 0x0301 },
738 	{ 0x00E2, 0x0061, 0x0302 },
739 	{ 0x00E3, 0x0061, 0x0303 },
740 	{ 0x00E4, 0x0061, 0x0308 },
741 	{ 0x00E5, 0x0061, 0x030A },
742 	{ 0x00E7, 0x0063, 0x0327 },
743 	{ 0x00E8, 0x0065, 0x0300 },
744 	{ 0x00E9, 0x0065, 0x0301 },
745 	{ 0x00EA, 0x0065, 0x0302 },
746 	{ 0x00EB, 0x0065, 0x0308 },
747 	{ 0x00EC, 0x0069, 0x0300 },
748 	{ 0x00ED, 0x0069, 0x0301 },
749 	{ 0x00EE, 0x0069, 0x0302 },
750 	{ 0x00EF, 0x0069, 0x0308 },
751 	{ 0x00F1, 0x006E, 0x0303 },
752 	{ 0x00F2, 0x006F, 0x0300 },
753 	{ 0x00F3, 0x006F, 0x0301 },
754 	{ 0x00F4, 0x006F, 0x0302 },
755 	{ 0x00F5, 0x006F, 0x0303 },
756 	{ 0x00F6, 0x006F, 0x0308 },
757 	{ 0x00F9, 0x0075, 0x0300 },
758 	{ 0x00FA, 0x0075, 0x0301 },
759 	{ 0x00FB, 0x0075, 0x0302 },
760 	{ 0x00FC, 0x0075, 0x0308 },
761 	{ 0x00FD, 0x0079, 0x0301 },
762 	{ 0x00FF, 0x0079, 0x0308 },
763 	{ 0x0100, 0x0041, 0x0304 },
764 	{ 0x0101, 0x0061, 0x0304 },
765 	{ 0x0102, 0x0041, 0x0306 },
766 	{ 0x0103, 0x0061, 0x0306 },
767 	{ 0x0104, 0x0041, 0x0328 },
768 	{ 0x0105, 0x0061, 0x0328 },
769 	{ 0x0106, 0x0043, 0x0301 },
770 	{ 0x0107, 0x0063, 0x0301 },
771 	{ 0x0108, 0x0043, 0x0302 },
772 	{ 0x0109, 0x0063, 0x0302 },
773 	{ 0x010A, 0x0043, 0x0307 },
774 	{ 0x010B, 0x0063, 0x0307 },
775 	{ 0x010C, 0x0043, 0x030C },
776 	{ 0x010D, 0x0063, 0x030C },
777 	{ 0x010E, 0x0044, 0x030C },
778 	{ 0x010F, 0x0064, 0x030C },
779 	{ 0x0112, 0x0045, 0x0304 },
780 	{ 0x0113, 0x0065, 0x0304 },
781 	{ 0x0114, 0x0045, 0x0306 },
782 	{ 0x0115, 0x0065, 0x0306 },
783 	{ 0x0116, 0x0045, 0x0307 },
784 	{ 0x0117, 0x0065, 0x0307 },
785 	{ 0x0118, 0x0045, 0x0328 },
786 	{ 0x0119, 0x0065, 0x0328 },
787 	{ 0x011A, 0x0045, 0x030C },
788 	{ 0x011B, 0x0065, 0x030C },
789 	{ 0x011C, 0x0047, 0x0302 },
790 	{ 0x011D, 0x0067, 0x0302 },
791 	{ 0x011E, 0x0047, 0x0306 },
792 	{ 0x011F, 0x0067, 0x0306 },
793 	{ 0x0120, 0x0047, 0x0307 },
794 	{ 0x0121, 0x0067, 0x0307 },
795 	{ 0x0122, 0x0047, 0x0327 },
796 	{ 0x0123, 0x0067, 0x0327 },
797 	{ 0x0124, 0x0048, 0x0302 },
798 	{ 0x0125, 0x0068, 0x0302 },
799 	{ 0x0128, 0x0049, 0x0303 },
800 	{ 0x0129, 0x0069, 0x0303 },
801 	{ 0x012A, 0x0049, 0x0304 },
802 	{ 0x012B, 0x0069, 0x0304 },
803 	{ 0x012C, 0x0049, 0x0306 },
804 	{ 0x012D, 0x0069, 0x0306 },
805 	{ 0x012E, 0x0049, 0x0328 },
806 	{ 0x012F, 0x0069, 0x0328 },
807 	{ 0x0130, 0x0049, 0x0307 },
808 	{ 0x0134, 0x004A, 0x0302 },
809 	{ 0x0135, 0x006A, 0x0302 },
810 	{ 0x0136, 0x004B, 0x0327 },
811 	{ 0x0137, 0x006B, 0x0327 },
812 	{ 0x0139, 0x004C, 0x0301 },
813 	{ 0x013A, 0x006C, 0x0301 },
814 	{ 0x013B, 0x004C, 0x0327 },
815 	{ 0x013C, 0x006C, 0x0327 },
816 	{ 0x013D, 0x004C, 0x030C },
817 	{ 0x013E, 0x006C, 0x030C },
818 	{ 0x0143, 0x004E, 0x0301 },
819 	{ 0x0144, 0x006E, 0x0301 },
820 	{ 0x0145, 0x004E, 0x0327 },
821 	{ 0x0146, 0x006E, 0x0327 },
822 	{ 0x0147, 0x004E, 0x030C },
823 	{ 0x0148, 0x006E, 0x030C },
824 	{ 0x014C, 0x004F, 0x0304 },
825 	{ 0x014D, 0x006F, 0x0304 },
826 	{ 0x014E, 0x004F, 0x0306 },
827 	{ 0x014F, 0x006F, 0x0306 },
828 	{ 0x0150, 0x004F, 0x030B },
829 	{ 0x0151, 0x006F, 0x030B },
830 	{ 0x0154, 0x0052, 0x0301 },
831 	{ 0x0155, 0x0072, 0x0301 },
832 	{ 0x0156, 0x0052, 0x0327 },
833 	{ 0x0157, 0x0072, 0x0327 },
834 	{ 0x0158, 0x0052, 0x030C },
835 	{ 0x0159, 0x0072, 0x030C },
836 	{ 0x015A, 0x0053, 0x0301 },
837 	{ 0x015B, 0x0073, 0x0301 },
838 	{ 0x015C, 0x0053, 0x0302 },
839 	{ 0x015D, 0x0073, 0x0302 },
840 	{ 0x015E, 0x0053, 0x0327 },
841 	{ 0x015F, 0x0073, 0x0327 },
842 	{ 0x0160, 0x0053, 0x030C },
843 	{ 0x0161, 0x0073, 0x030C },
844 	{ 0x0162, 0x0054, 0x0327 },
845 	{ 0x0163, 0x0074, 0x0327 },
846 	{ 0x0164, 0x0054, 0x030C },
847 	{ 0x0165, 0x0074, 0x030C },
848 	{ 0x0168, 0x0055, 0x0303 },
849 	{ 0x0169, 0x0075, 0x0303 },
850 	{ 0x016A, 0x0055, 0x0304 },
851 	{ 0x016B, 0x0075, 0x0304 },
852 	{ 0x016C, 0x0055, 0x0306 },
853 	{ 0x016D, 0x0075, 0x0306 },
854 	{ 0x016E, 0x0055, 0x030A },
855 	{ 0x016F, 0x0075, 0x030A },
856 	{ 0x0170, 0x0055, 0x030B },
857 	{ 0x0171, 0x0075, 0x030B },
858 	{ 0x0172, 0x0055, 0x0328 },
859 	{ 0x0173, 0x0075, 0x0328 },
860 	{ 0x0174, 0x0057, 0x0302 },
861 	{ 0x0175, 0x0077, 0x0302 },
862 	{ 0x0176, 0x0059, 0x0302 },
863 	{ 0x0177, 0x0079, 0x0302 },
864 	{ 0x0178, 0x0059, 0x0308 },
865 	{ 0x0179, 0x005A, 0x0301 },
866 	{ 0x017A, 0x007A, 0x0301 },
867 	{ 0x017B, 0x005A, 0x0307 },
868 	{ 0x017C, 0x007A, 0x0307 },
869 	{ 0x017D, 0x005A, 0x030C },
870 	{ 0x017E, 0x007A, 0x030C },
871 	{ 0x01A0, 0x004F, 0x031B },
872 	{ 0x01A1, 0x006F, 0x031B },
873 	{ 0x01AF, 0x0055, 0x031B },
874 	{ 0x01B0, 0x0075, 0x031B },
875 	{ 0x01CD, 0x0041, 0x030C },
876 	{ 0x01CE, 0x0061, 0x030C },
877 	{ 0x01CF, 0x0049, 0x030C },
878 	{ 0x01D0, 0x0069, 0x030C },
879 	{ 0x01D1, 0x004F, 0x030C },
880 	{ 0x01D2, 0x006F, 0x030C },
881 	{ 0x01D3, 0x0055, 0x030C },
882 	{ 0x01D4, 0x0075, 0x030C },
883 	{ 0x01D5, 0x00DC, 0x0304 },
884 	{ 0x01D6, 0x00FC, 0x0304 },
885 	{ 0x01D7, 0x00DC, 0x0301 },
886 	{ 0x01D8, 0x00FC, 0x0301 },
887 	{ 0x01D9, 0x00DC, 0x030C },
888 	{ 0x01DA, 0x00FC, 0x030C },
889 	{ 0x01DB, 0x00DC, 0x0300 },
890 	{ 0x01DC, 0x00FC, 0x0300 },
891 	{ 0x01DE, 0x00C4, 0x0304 },
892 	{ 0x01DF, 0x00E4, 0x0304 },
893 	{ 0x01E0, 0x0226, 0x0304 },
894 	{ 0x01E1, 0x0227, 0x0304 },
895 	{ 0x01E2, 0x00C6, 0x0304 },
896 	{ 0x01E3, 0x00E6, 0x0304 },
897 	{ 0x01E6, 0x0047, 0x030C },
898 	{ 0x01E7, 0x0067, 0x030C },
899 	{ 0x01E8, 0x004B, 0x030C },
900 	{ 0x01E9, 0x006B, 0x030C },
901 	{ 0x01EA, 0x004F, 0x0328 },
902 	{ 0x01EB, 0x006F, 0x0328 },
903 	{ 0x01EC, 0x01EA, 0x0304 },
904 	{ 0x01ED, 0x01EB, 0x0304 },
905 	{ 0x01EE, 0x01B7, 0x030C },
906 	{ 0x01EF, 0x0292, 0x030C },
907 	{ 0x01F0, 0x006A, 0x030C },
908 	{ 0x01F4, 0x0047, 0x0301 },
909 	{ 0x01F5, 0x0067, 0x0301 },
910 	{ 0x01F8, 0x004E, 0x0300 },
911 	{ 0x01F9, 0x006E, 0x0300 },
912 	{ 0x01FA, 0x00C5, 0x0301 },
913 	{ 0x01FB, 0x00E5, 0x0301 },
914 	{ 0x01FC, 0x00C6, 0x0301 },
915 	{ 0x01FD, 0x00E6, 0x0301 },
916 	{ 0x01FE, 0x00D8, 0x0301 },
917 	{ 0x01FF, 0x00F8, 0x0301 },
918 	{ 0x0200, 0x0041, 0x030F },
919 	{ 0x0201, 0x0061, 0x030F },
920 	{ 0x0202, 0x0041, 0x0311 },
921 	{ 0x0203, 0x0061, 0x0311 },
922 	{ 0x0204, 0x0045, 0x030F },
923 	{ 0x0205, 0x0065, 0x030F },
924 	{ 0x0206, 0x0045, 0x0311 },
925 	{ 0x0207, 0x0065, 0x0311 },
926 	{ 0x0208, 0x0049, 0x030F },
927 	{ 0x0209, 0x0069, 0x030F },
928 	{ 0x020A, 0x0049, 0x0311 },
929 	{ 0x020B, 0x0069, 0x0311 },
930 	{ 0x020C, 0x004F, 0x030F },
931 	{ 0x020D, 0x006F, 0x030F },
932 	{ 0x020E, 0x004F, 0x0311 },
933 	{ 0x020F, 0x006F, 0x0311 },
934 	{ 0x0210, 0x0052, 0x030F },
935 	{ 0x0211, 0x0072, 0x030F },
936 	{ 0x0212, 0x0052, 0x0311 },
937 	{ 0x0213, 0x0072, 0x0311 },
938 	{ 0x0214, 0x0055, 0x030F },
939 	{ 0x0215, 0x0075, 0x030F },
940 	{ 0x0216, 0x0055, 0x0311 },
941 	{ 0x0217, 0x0075, 0x0311 },
942 	{ 0x0218, 0x0053, 0x0326 },
943 	{ 0x0219, 0x0073, 0x0326 },
944 	{ 0x021A, 0x0054, 0x0326 },
945 	{ 0x021B, 0x0074, 0x0326 },
946 	{ 0x021E, 0x0048, 0x030C },
947 	{ 0x021F, 0x0068, 0x030C },
948 	{ 0x0226, 0x0041, 0x0307 },
949 	{ 0x0227, 0x0061, 0x0307 },
950 	{ 0x0228, 0x0045, 0x0327 },
951 	{ 0x0229, 0x0065, 0x0327 },
952 	{ 0x022A, 0x00D6, 0x0304 },
953 	{ 0x022B, 0x00F6, 0x0304 },
954 	{ 0x022C, 0x00D5, 0x0304 },
955 	{ 0x022D, 0x00F5, 0x0304 },
956 	{ 0x022E, 0x004F, 0x0307 },
957 	{ 0x022F, 0x006F, 0x0307 },
958 	{ 0x0230, 0x022E, 0x0304 },
959 	{ 0x0231, 0x022F, 0x0304 },
960 	{ 0x0232, 0x0059, 0x0304 },
961 	{ 0x0233, 0x0079, 0x0304 },
962 	{ 0x0344, 0x0308, 0x0301 },
963 	{ 0x0385, 0x00A8, 0x0301 },
964 	{ 0x0386, 0x0391, 0x0301 },
965 	{ 0x0388, 0x0395, 0x0301 },
966 	{ 0x0389, 0x0397, 0x0301 },
967 	{ 0x038A, 0x0399, 0x0301 },
968 	{ 0x038C, 0x039F, 0x0301 },
969 	{ 0x038E, 0x03A5, 0x0301 },
970 	{ 0x038F, 0x03A9, 0x0301 },
971 	{ 0x0390, 0x03CA, 0x0301 },
972 	{ 0x03AA, 0x0399, 0x0308 },
973 	{ 0x03AB, 0x03A5, 0x0308 },
974 	{ 0x03AC, 0x03B1, 0x0301 },
975 	{ 0x03AD, 0x03B5, 0x0301 },
976 	{ 0x03AE, 0x03B7, 0x0301 },
977 	{ 0x03AF, 0x03B9, 0x0301 },
978 	{ 0x03B0, 0x03CB, 0x0301 },
979 	{ 0x03CA, 0x03B9, 0x0308 },
980 	{ 0x03CB, 0x03C5, 0x0308 },
981 	{ 0x03CC, 0x03BF, 0x0301 },
982 	{ 0x03CD, 0x03C5, 0x0301 },
983 	{ 0x03CE, 0x03C9, 0x0301 },
984 	{ 0x03D3, 0x03D2, 0x0301 },
985 	{ 0x03D4, 0x03D2, 0x0308 },
986 	{ 0x0400, 0x0415, 0x0300 },
987 	{ 0x0401, 0x0415, 0x0308 },
988 	{ 0x0403, 0x0413, 0x0301 },
989 	{ 0x0407, 0x0406, 0x0308 },
990 	{ 0x040C, 0x041A, 0x0301 },
991 	{ 0x040D, 0x0418, 0x0300 },
992 	{ 0x040E, 0x0423, 0x0306 },
993 	{ 0x0419, 0x0418, 0x0306 },
994 	{ 0x0439, 0x0438, 0x0306 },
995 	{ 0x0450, 0x0435, 0x0300 },
996 	{ 0x0451, 0x0435, 0x0308 },
997 	{ 0x0453, 0x0433, 0x0301 },
998 	{ 0x0457, 0x0456, 0x0308 },
999 	{ 0x045C, 0x043A, 0x0301 },
1000 	{ 0x045D, 0x0438, 0x0300 },
1001 	{ 0x045E, 0x0443, 0x0306 },
1002 	{ 0x0476, 0x0474, 0x030F },
1003 	{ 0x0477, 0x0475, 0x030F },
1004 	{ 0x04C1, 0x0416, 0x0306 },
1005 	{ 0x04C2, 0x0436, 0x0306 },
1006 	{ 0x04D0, 0x0410, 0x0306 },
1007 	{ 0x04D1, 0x0430, 0x0306 },
1008 	{ 0x04D2, 0x0410, 0x0308 },
1009 	{ 0x04D3, 0x0430, 0x0308 },
1010 	{ 0x04D6, 0x0415, 0x0306 },
1011 	{ 0x04D7, 0x0435, 0x0306 },
1012 	{ 0x04DA, 0x04D8, 0x0308 },
1013 	{ 0x04DB, 0x04D9, 0x0308 },
1014 	{ 0x04DC, 0x0416, 0x0308 },
1015 	{ 0x04DD, 0x0436, 0x0308 },
1016 	{ 0x04DE, 0x0417, 0x0308 },
1017 	{ 0x04DF, 0x0437, 0x0308 },
1018 	{ 0x04E2, 0x0418, 0x0304 },
1019 	{ 0x04E3, 0x0438, 0x0304 },
1020 	{ 0x04E4, 0x0418, 0x0308 },
1021 	{ 0x04E5, 0x0438, 0x0308 },
1022 	{ 0x04E6, 0x041E, 0x0308 },
1023 	{ 0x04E7, 0x043E, 0x0308 },
1024 	{ 0x04EA, 0x04E8, 0x0308 },
1025 	{ 0x04EB, 0x04E9, 0x0308 },
1026 	{ 0x04EC, 0x042D, 0x0308 },
1027 	{ 0x04ED, 0x044D, 0x0308 },
1028 	{ 0x04EE, 0x0423, 0x0304 },
1029 	{ 0x04EF, 0x0443, 0x0304 },
1030 	{ 0x04F0, 0x0423, 0x0308 },
1031 	{ 0x04F1, 0x0443, 0x0308 },
1032 	{ 0x04F2, 0x0423, 0x030B },
1033 	{ 0x04F3, 0x0443, 0x030B },
1034 	{ 0x04F4, 0x0427, 0x0308 },
1035 	{ 0x04F5, 0x0447, 0x0308 },
1036 	{ 0x04F8, 0x042B, 0x0308 },
1037 	{ 0x04F9, 0x044B, 0x0308 },
1038 	{ 0x0622, 0x0627, 0x0653 },
1039 	{ 0x0623, 0x0627, 0x0654 },
1040 	{ 0x0624, 0x0648, 0x0654 },
1041 	{ 0x0625, 0x0627, 0x0655 },
1042 	{ 0x0626, 0x064A, 0x0654 },
1043 	{ 0x06C0, 0x06D5, 0x0654 },
1044 	{ 0x06C2, 0x06C1, 0x0654 },
1045 	{ 0x06D3, 0x06D2, 0x0654 },
1046 	{ 0x0929, 0x0928, 0x093C },
1047 	{ 0x0931, 0x0930, 0x093C },
1048 	{ 0x0934, 0x0933, 0x093C },
1049 	{ 0x0958, 0x0915, 0x093C },
1050 	{ 0x0959, 0x0916, 0x093C },
1051 	{ 0x095A, 0x0917, 0x093C },
1052 	{ 0x095B, 0x091C, 0x093C },
1053 	{ 0x095C, 0x0921, 0x093C },
1054 	{ 0x095D, 0x0922, 0x093C },
1055 	{ 0x095E, 0x092B, 0x093C },
1056 	{ 0x095F, 0x092F, 0x093C },
1057 	{ 0x09CB, 0x09C7, 0x09BE },
1058 	{ 0x09CC, 0x09C7, 0x09D7 },
1059 	{ 0x09DC, 0x09A1, 0x09BC },
1060 	{ 0x09DD, 0x09A2, 0x09BC },
1061 	{ 0x09DF, 0x09AF, 0x09BC },
1062 	{ 0x0A33, 0x0A32, 0x0A3C },
1063 	{ 0x0A36, 0x0A38, 0x0A3C },
1064 	{ 0x0A59, 0x0A16, 0x0A3C },
1065 	{ 0x0A5A, 0x0A17, 0x0A3C },
1066 	{ 0x0A5B, 0x0A1C, 0x0A3C },
1067 	{ 0x0A5E, 0x0A2B, 0x0A3C },
1068 	{ 0x0B48, 0x0B47, 0x0B56 },
1069 	{ 0x0B4B, 0x0B47, 0x0B3E },
1070 	{ 0x0B4C, 0x0B47, 0x0B57 },
1071 	{ 0x0B5C, 0x0B21, 0x0B3C },
1072 	{ 0x0B5D, 0x0B22, 0x0B3C },
1073 	{ 0x0B94, 0x0B92, 0x0BD7 },
1074 	{ 0x0BCA, 0x0BC6, 0x0BBE },
1075 	{ 0x0BCB, 0x0BC7, 0x0BBE },
1076 	{ 0x0BCC, 0x0BC6, 0x0BD7 },
1077 	{ 0x0C48, 0x0C46, 0x0C56 },
1078 	{ 0x0CC0, 0x0CBF, 0x0CD5 },
1079 	{ 0x0CC7, 0x0CC6, 0x0CD5 },
1080 	{ 0x0CC8, 0x0CC6, 0x0CD6 },
1081 	{ 0x0CCA, 0x0CC6, 0x0CC2 },
1082 	{ 0x0CCB, 0x0CCA, 0x0CD5 },
1083 	{ 0x0D4A, 0x0D46, 0x0D3E },
1084 	{ 0x0D4B, 0x0D47, 0x0D3E },
1085 	{ 0x0D4C, 0x0D46, 0x0D57 },
1086 	{ 0x0DDA, 0x0DD9, 0x0DCA },
1087 	{ 0x0DDC, 0x0DD9, 0x0DCF },
1088 	{ 0x0DDD, 0x0DDC, 0x0DCA },
1089 	{ 0x0DDE, 0x0DD9, 0x0DDF },
1090 	{ 0x0F43, 0x0F42, 0x0FB7 },
1091 	{ 0x0F4D, 0x0F4C, 0x0FB7 },
1092 	{ 0x0F52, 0x0F51, 0x0FB7 },
1093 	{ 0x0F57, 0x0F56, 0x0FB7 },
1094 	{ 0x0F5C, 0x0F5B, 0x0FB7 },
1095 	{ 0x0F69, 0x0F40, 0x0FB5 },
1096 	{ 0x0F73, 0x0F71, 0x0F72 },
1097 	{ 0x0F75, 0x0F71, 0x0F74 },
1098 	{ 0x0F76, 0x0FB2, 0x0F80 },
1099 	{ 0x0F78, 0x0FB3, 0x0F80 },
1100 	{ 0x0F81, 0x0F71, 0x0F80 },
1101 	{ 0x0F93, 0x0F92, 0x0FB7 },
1102 	{ 0x0F9D, 0x0F9C, 0x0FB7 },
1103 	{ 0x0FA2, 0x0FA1, 0x0FB7 },
1104 	{ 0x0FA7, 0x0FA6, 0x0FB7 },
1105 	{ 0x0FAC, 0x0FAB, 0x0FB7 },
1106 	{ 0x0FB9, 0x0F90, 0x0FB5 },
1107 	{ 0x1026, 0x1025, 0x102E },
1108 	{ 0x1E00, 0x0041, 0x0325 },
1109 	{ 0x1E01, 0x0061, 0x0325 },
1110 	{ 0x1E02, 0x0042, 0x0307 },
1111 	{ 0x1E03, 0x0062, 0x0307 },
1112 	{ 0x1E04, 0x0042, 0x0323 },
1113 	{ 0x1E05, 0x0062, 0x0323 },
1114 	{ 0x1E06, 0x0042, 0x0331 },
1115 	{ 0x1E07, 0x0062, 0x0331 },
1116 	{ 0x1E08, 0x00C7, 0x0301 },
1117 	{ 0x1E09, 0x00E7, 0x0301 },
1118 	{ 0x1E0A, 0x0044, 0x0307 },
1119 	{ 0x1E0B, 0x0064, 0x0307 },
1120 	{ 0x1E0C, 0x0044, 0x0323 },
1121 	{ 0x1E0D, 0x0064, 0x0323 },
1122 	{ 0x1E0E, 0x0044, 0x0331 },
1123 	{ 0x1E0F, 0x0064, 0x0331 },
1124 	{ 0x1E10, 0x0044, 0x0327 },
1125 	{ 0x1E11, 0x0064, 0x0327 },
1126 	{ 0x1E12, 0x0044, 0x032D },
1127 	{ 0x1E13, 0x0064, 0x032D },
1128 	{ 0x1E14, 0x0112, 0x0300 },
1129 	{ 0x1E15, 0x0113, 0x0300 },
1130 	{ 0x1E16, 0x0112, 0x0301 },
1131 	{ 0x1E17, 0x0113, 0x0301 },
1132 	{ 0x1E18, 0x0045, 0x032D },
1133 	{ 0x1E19, 0x0065, 0x032D },
1134 	{ 0x1E1A, 0x0045, 0x0330 },
1135 	{ 0x1E1B, 0x0065, 0x0330 },
1136 	{ 0x1E1C, 0x0228, 0x0306 },
1137 	{ 0x1E1D, 0x0229, 0x0306 },
1138 	{ 0x1E1E, 0x0046, 0x0307 },
1139 	{ 0x1E1F, 0x0066, 0x0307 },
1140 	{ 0x1E20, 0x0047, 0x0304 },
1141 	{ 0x1E21, 0x0067, 0x0304 },
1142 	{ 0x1E22, 0x0048, 0x0307 },
1143 	{ 0x1E23, 0x0068, 0x0307 },
1144 	{ 0x1E24, 0x0048, 0x0323 },
1145 	{ 0x1E25, 0x0068, 0x0323 },
1146 	{ 0x1E26, 0x0048, 0x0308 },
1147 	{ 0x1E27, 0x0068, 0x0308 },
1148 	{ 0x1E28, 0x0048, 0x0327 },
1149 	{ 0x1E29, 0x0068, 0x0327 },
1150 	{ 0x1E2A, 0x0048, 0x032E },
1151 	{ 0x1E2B, 0x0068, 0x032E },
1152 	{ 0x1E2C, 0x0049, 0x0330 },
1153 	{ 0x1E2D, 0x0069, 0x0330 },
1154 	{ 0x1E2E, 0x00CF, 0x0301 },
1155 	{ 0x1E2F, 0x00EF, 0x0301 },
1156 	{ 0x1E30, 0x004B, 0x0301 },
1157 	{ 0x1E31, 0x006B, 0x0301 },
1158 	{ 0x1E32, 0x004B, 0x0323 },
1159 	{ 0x1E33, 0x006B, 0x0323 },
1160 	{ 0x1E34, 0x004B, 0x0331 },
1161 	{ 0x1E35, 0x006B, 0x0331 },
1162 	{ 0x1E36, 0x004C, 0x0323 },
1163 	{ 0x1E37, 0x006C, 0x0323 },
1164 	{ 0x1E38, 0x1E36, 0x0304 },
1165 	{ 0x1E39, 0x1E37, 0x0304 },
1166 	{ 0x1E3A, 0x004C, 0x0331 },
1167 	{ 0x1E3B, 0x006C, 0x0331 },
1168 	{ 0x1E3C, 0x004C, 0x032D },
1169 	{ 0x1E3D, 0x006C, 0x032D },
1170 	{ 0x1E3E, 0x004D, 0x0301 },
1171 	{ 0x1E3F, 0x006D, 0x0301 },
1172 	{ 0x1E40, 0x004D, 0x0307 },
1173 	{ 0x1E41, 0x006D, 0x0307 },
1174 	{ 0x1E42, 0x004D, 0x0323 },
1175 	{ 0x1E43, 0x006D, 0x0323 },
1176 	{ 0x1E44, 0x004E, 0x0307 },
1177 	{ 0x1E45, 0x006E, 0x0307 },
1178 	{ 0x1E46, 0x004E, 0x0323 },
1179 	{ 0x1E47, 0x006E, 0x0323 },
1180 	{ 0x1E48, 0x004E, 0x0331 },
1181 	{ 0x1E49, 0x006E, 0x0331 },
1182 	{ 0x1E4A, 0x004E, 0x032D },
1183 	{ 0x1E4B, 0x006E, 0x032D },
1184 	{ 0x1E4C, 0x00D5, 0x0301 },
1185 	{ 0x1E4D, 0x00F5, 0x0301 },
1186 	{ 0x1E4E, 0x00D5, 0x0308 },
1187 	{ 0x1E4F, 0x00F5, 0x0308 },
1188 	{ 0x1E50, 0x014C, 0x0300 },
1189 	{ 0x1E51, 0x014D, 0x0300 },
1190 	{ 0x1E52, 0x014C, 0x0301 },
1191 	{ 0x1E53, 0x014D, 0x0301 },
1192 	{ 0x1E54, 0x0050, 0x0301 },
1193 	{ 0x1E55, 0x0070, 0x0301 },
1194 	{ 0x1E56, 0x0050, 0x0307 },
1195 	{ 0x1E57, 0x0070, 0x0307 },
1196 	{ 0x1E58, 0x0052, 0x0307 },
1197 	{ 0x1E59, 0x0072, 0x0307 },
1198 	{ 0x1E5A, 0x0052, 0x0323 },
1199 	{ 0x1E5B, 0x0072, 0x0323 },
1200 	{ 0x1E5C, 0x1E5A, 0x0304 },
1201 	{ 0x1E5D, 0x1E5B, 0x0304 },
1202 	{ 0x1E5E, 0x0052, 0x0331 },
1203 	{ 0x1E5F, 0x0072, 0x0331 },
1204 	{ 0x1E60, 0x0053, 0x0307 },
1205 	{ 0x1E61, 0x0073, 0x0307 },
1206 	{ 0x1E62, 0x0053, 0x0323 },
1207 	{ 0x1E63, 0x0073, 0x0323 },
1208 	{ 0x1E64, 0x015A, 0x0307 },
1209 	{ 0x1E65, 0x015B, 0x0307 },
1210 	{ 0x1E66, 0x0160, 0x0307 },
1211 	{ 0x1E67, 0x0161, 0x0307 },
1212 	{ 0x1E68, 0x1E62, 0x0307 },
1213 	{ 0x1E69, 0x1E63, 0x0307 },
1214 	{ 0x1E6A, 0x0054, 0x0307 },
1215 	{ 0x1E6B, 0x0074, 0x0307 },
1216 	{ 0x1E6C, 0x0054, 0x0323 },
1217 	{ 0x1E6D, 0x0074, 0x0323 },
1218 	{ 0x1E6E, 0x0054, 0x0331 },
1219 	{ 0x1E6F, 0x0074, 0x0331 },
1220 	{ 0x1E70, 0x0054, 0x032D },
1221 	{ 0x1E71, 0x0074, 0x032D },
1222 	{ 0x1E72, 0x0055, 0x0324 },
1223 	{ 0x1E73, 0x0075, 0x0324 },
1224 	{ 0x1E74, 0x0055, 0x0330 },
1225 	{ 0x1E75, 0x0075, 0x0330 },
1226 	{ 0x1E76, 0x0055, 0x032D },
1227 	{ 0x1E77, 0x0075, 0x032D },
1228 	{ 0x1E78, 0x0168, 0x0301 },
1229 	{ 0x1E79, 0x0169, 0x0301 },
1230 	{ 0x1E7A, 0x016A, 0x0308 },
1231 	{ 0x1E7B, 0x016B, 0x0308 },
1232 	{ 0x1E7C, 0x0056, 0x0303 },
1233 	{ 0x1E7D, 0x0076, 0x0303 },
1234 	{ 0x1E7E, 0x0056, 0x0323 },
1235 	{ 0x1E7F, 0x0076, 0x0323 },
1236 	{ 0x1E80, 0x0057, 0x0300 },
1237 	{ 0x1E81, 0x0077, 0x0300 },
1238 	{ 0x1E82, 0x0057, 0x0301 },
1239 	{ 0x1E83, 0x0077, 0x0301 },
1240 	{ 0x1E84, 0x0057, 0x0308 },
1241 	{ 0x1E85, 0x0077, 0x0308 },
1242 	{ 0x1E86, 0x0057, 0x0307 },
1243 	{ 0x1E87, 0x0077, 0x0307 },
1244 	{ 0x1E88, 0x0057, 0x0323 },
1245 	{ 0x1E89, 0x0077, 0x0323 },
1246 	{ 0x1E8A, 0x0058, 0x0307 },
1247 	{ 0x1E8B, 0x0078, 0x0307 },
1248 	{ 0x1E8C, 0x0058, 0x0308 },
1249 	{ 0x1E8D, 0x0078, 0x0308 },
1250 	{ 0x1E8E, 0x0059, 0x0307 },
1251 	{ 0x1E8F, 0x0079, 0x0307 },
1252 	{ 0x1E90, 0x005A, 0x0302 },
1253 	{ 0x1E91, 0x007A, 0x0302 },
1254 	{ 0x1E92, 0x005A, 0x0323 },
1255 	{ 0x1E93, 0x007A, 0x0323 },
1256 	{ 0x1E94, 0x005A, 0x0331 },
1257 	{ 0x1E95, 0x007A, 0x0331 },
1258 	{ 0x1E96, 0x0068, 0x0331 },
1259 	{ 0x1E97, 0x0074, 0x0308 },
1260 	{ 0x1E98, 0x0077, 0x030A },
1261 	{ 0x1E99, 0x0079, 0x030A },
1262 	{ 0x1E9B, 0x017F, 0x0307 },
1263 	{ 0x1EA0, 0x0041, 0x0323 },
1264 	{ 0x1EA1, 0x0061, 0x0323 },
1265 	{ 0x1EA2, 0x0041, 0x0309 },
1266 	{ 0x1EA3, 0x0061, 0x0309 },
1267 	{ 0x1EA4, 0x00C2, 0x0301 },
1268 	{ 0x1EA5, 0x00E2, 0x0301 },
1269 	{ 0x1EA6, 0x00C2, 0x0300 },
1270 	{ 0x1EA7, 0x00E2, 0x0300 },
1271 	{ 0x1EA8, 0x00C2, 0x0309 },
1272 	{ 0x1EA9, 0x00E2, 0x0309 },
1273 	{ 0x1EAA, 0x00C2, 0x0303 },
1274 	{ 0x1EAB, 0x00E2, 0x0303 },
1275 	{ 0x1EAC, 0x1EA0, 0x0302 },
1276 	{ 0x1EAD, 0x1EA1, 0x0302 },
1277 	{ 0x1EAE, 0x0102, 0x0301 },
1278 	{ 0x1EAF, 0x0103, 0x0301 },
1279 	{ 0x1EB0, 0x0102, 0x0300 },
1280 	{ 0x1EB1, 0x0103, 0x0300 },
1281 	{ 0x1EB2, 0x0102, 0x0309 },
1282 	{ 0x1EB3, 0x0103, 0x0309 },
1283 	{ 0x1EB4, 0x0102, 0x0303 },
1284 	{ 0x1EB5, 0x0103, 0x0303 },
1285 	{ 0x1EB6, 0x1EA0, 0x0306 },
1286 	{ 0x1EB7, 0x1EA1, 0x0306 },
1287 	{ 0x1EB8, 0x0045, 0x0323 },
1288 	{ 0x1EB9, 0x0065, 0x0323 },
1289 	{ 0x1EBA, 0x0045, 0x0309 },
1290 	{ 0x1EBB, 0x0065, 0x0309 },
1291 	{ 0x1EBC, 0x0045, 0x0303 },
1292 	{ 0x1EBD, 0x0065, 0x0303 },
1293 	{ 0x1EBE, 0x00CA, 0x0301 },
1294 	{ 0x1EBF, 0x00EA, 0x0301 },
1295 	{ 0x1EC0, 0x00CA, 0x0300 },
1296 	{ 0x1EC1, 0x00EA, 0x0300 },
1297 	{ 0x1EC2, 0x00CA, 0x0309 },
1298 	{ 0x1EC3, 0x00EA, 0x0309 },
1299 	{ 0x1EC4, 0x00CA, 0x0303 },
1300 	{ 0x1EC5, 0x00EA, 0x0303 },
1301 	{ 0x1EC6, 0x1EB8, 0x0302 },
1302 	{ 0x1EC7, 0x1EB9, 0x0302 },
1303 	{ 0x1EC8, 0x0049, 0x0309 },
1304 	{ 0x1EC9, 0x0069, 0x0309 },
1305 	{ 0x1ECA, 0x0049, 0x0323 },
1306 	{ 0x1ECB, 0x0069, 0x0323 },
1307 	{ 0x1ECC, 0x004F, 0x0323 },
1308 	{ 0x1ECD, 0x006F, 0x0323 },
1309 	{ 0x1ECE, 0x004F, 0x0309 },
1310 	{ 0x1ECF, 0x006F, 0x0309 },
1311 	{ 0x1ED0, 0x00D4, 0x0301 },
1312 	{ 0x1ED1, 0x00F4, 0x0301 },
1313 	{ 0x1ED2, 0x00D4, 0x0300 },
1314 	{ 0x1ED3, 0x00F4, 0x0300 },
1315 	{ 0x1ED4, 0x00D4, 0x0309 },
1316 	{ 0x1ED5, 0x00F4, 0x0309 },
1317 	{ 0x1ED6, 0x00D4, 0x0303 },
1318 	{ 0x1ED7, 0x00F4, 0x0303 },
1319 	{ 0x1ED8, 0x1ECC, 0x0302 },
1320 	{ 0x1ED9, 0x1ECD, 0x0302 },
1321 	{ 0x1EDA, 0x01A0, 0x0301 },
1322 	{ 0x1EDB, 0x01A1, 0x0301 },
1323 	{ 0x1EDC, 0x01A0, 0x0300 },
1324 	{ 0x1EDD, 0x01A1, 0x0300 },
1325 	{ 0x1EDE, 0x01A0, 0x0309 },
1326 	{ 0x1EDF, 0x01A1, 0x0309 },
1327 	{ 0x1EE0, 0x01A0, 0x0303 },
1328 	{ 0x1EE1, 0x01A1, 0x0303 },
1329 	{ 0x1EE2, 0x01A0, 0x0323 },
1330 	{ 0x1EE3, 0x01A1, 0x0323 },
1331 	{ 0x1EE4, 0x0055, 0x0323 },
1332 	{ 0x1EE5, 0x0075, 0x0323 },
1333 	{ 0x1EE6, 0x0055, 0x0309 },
1334 	{ 0x1EE7, 0x0075, 0x0309 },
1335 	{ 0x1EE8, 0x01AF, 0x0301 },
1336 	{ 0x1EE9, 0x01B0, 0x0301 },
1337 	{ 0x1EEA, 0x01AF, 0x0300 },
1338 	{ 0x1EEB, 0x01B0, 0x0300 },
1339 	{ 0x1EEC, 0x01AF, 0x0309 },
1340 	{ 0x1EED, 0x01B0, 0x0309 },
1341 	{ 0x1EEE, 0x01AF, 0x0303 },
1342 	{ 0x1EEF, 0x01B0, 0x0303 },
1343 	{ 0x1EF0, 0x01AF, 0x0323 },
1344 	{ 0x1EF1, 0x01B0, 0x0323 },
1345 	{ 0x1EF2, 0x0059, 0x0300 },
1346 	{ 0x1EF3, 0x0079, 0x0300 },
1347 	{ 0x1EF4, 0x0059, 0x0323 },
1348 	{ 0x1EF5, 0x0079, 0x0323 },
1349 	{ 0x1EF6, 0x0059, 0x0309 },
1350 	{ 0x1EF7, 0x0079, 0x0309 },
1351 	{ 0x1EF8, 0x0059, 0x0303 },
1352 	{ 0x1EF9, 0x0079, 0x0303 },
1353 	{ 0x1F00, 0x03B1, 0x0313 },
1354 	{ 0x1F01, 0x03B1, 0x0314 },
1355 	{ 0x1F02, 0x1F00, 0x0300 },
1356 	{ 0x1F03, 0x1F01, 0x0300 },
1357 	{ 0x1F04, 0x1F00, 0x0301 },
1358 	{ 0x1F05, 0x1F01, 0x0301 },
1359 	{ 0x1F06, 0x1F00, 0x0342 },
1360 	{ 0x1F07, 0x1F01, 0x0342 },
1361 	{ 0x1F08, 0x0391, 0x0313 },
1362 	{ 0x1F09, 0x0391, 0x0314 },
1363 	{ 0x1F0A, 0x1F08, 0x0300 },
1364 	{ 0x1F0B, 0x1F09, 0x0300 },
1365 	{ 0x1F0C, 0x1F08, 0x0301 },
1366 	{ 0x1F0D, 0x1F09, 0x0301 },
1367 	{ 0x1F0E, 0x1F08, 0x0342 },
1368 	{ 0x1F0F, 0x1F09, 0x0342 },
1369 	{ 0x1F10, 0x03B5, 0x0313 },
1370 	{ 0x1F11, 0x03B5, 0x0314 },
1371 	{ 0x1F12, 0x1F10, 0x0300 },
1372 	{ 0x1F13, 0x1F11, 0x0300 },
1373 	{ 0x1F14, 0x1F10, 0x0301 },
1374 	{ 0x1F15, 0x1F11, 0x0301 },
1375 	{ 0x1F18, 0x0395, 0x0313 },
1376 	{ 0x1F19, 0x0395, 0x0314 },
1377 	{ 0x1F1A, 0x1F18, 0x0300 },
1378 	{ 0x1F1B, 0x1F19, 0x0300 },
1379 	{ 0x1F1C, 0x1F18, 0x0301 },
1380 	{ 0x1F1D, 0x1F19, 0x0301 },
1381 	{ 0x1F20, 0x03B7, 0x0313 },
1382 	{ 0x1F21, 0x03B7, 0x0314 },
1383 	{ 0x1F22, 0x1F20, 0x0300 },
1384 	{ 0x1F23, 0x1F21, 0x0300 },
1385 	{ 0x1F24, 0x1F20, 0x0301 },
1386 	{ 0x1F25, 0x1F21, 0x0301 },
1387 	{ 0x1F26, 0x1F20, 0x0342 },
1388 	{ 0x1F27, 0x1F21, 0x0342 },
1389 	{ 0x1F28, 0x0397, 0x0313 },
1390 	{ 0x1F29, 0x0397, 0x0314 },
1391 	{ 0x1F2A, 0x1F28, 0x0300 },
1392 	{ 0x1F2B, 0x1F29, 0x0300 },
1393 	{ 0x1F2C, 0x1F28, 0x0301 },
1394 	{ 0x1F2D, 0x1F29, 0x0301 },
1395 	{ 0x1F2E, 0x1F28, 0x0342 },
1396 	{ 0x1F2F, 0x1F29, 0x0342 },
1397 	{ 0x1F30, 0x03B9, 0x0313 },
1398 	{ 0x1F31, 0x03B9, 0x0314 },
1399 	{ 0x1F32, 0x1F30, 0x0300 },
1400 	{ 0x1F33, 0x1F31, 0x0300 },
1401 	{ 0x1F34, 0x1F30, 0x0301 },
1402 	{ 0x1F35, 0x1F31, 0x0301 },
1403 	{ 0x1F36, 0x1F30, 0x0342 },
1404 	{ 0x1F37, 0x1F31, 0x0342 },
1405 	{ 0x1F38, 0x0399, 0x0313 },
1406 	{ 0x1F39, 0x0399, 0x0314 },
1407 	{ 0x1F3A, 0x1F38, 0x0300 },
1408 	{ 0x1F3B, 0x1F39, 0x0300 },
1409 	{ 0x1F3C, 0x1F38, 0x0301 },
1410 	{ 0x1F3D, 0x1F39, 0x0301 },
1411 	{ 0x1F3E, 0x1F38, 0x0342 },
1412 	{ 0x1F3F, 0x1F39, 0x0342 },
1413 	{ 0x1F40, 0x03BF, 0x0313 },
1414 	{ 0x1F41, 0x03BF, 0x0314 },
1415 	{ 0x1F42, 0x1F40, 0x0300 },
1416 	{ 0x1F43, 0x1F41, 0x0300 },
1417 	{ 0x1F44, 0x1F40, 0x0301 },
1418 	{ 0x1F45, 0x1F41, 0x0301 },
1419 	{ 0x1F48, 0x039F, 0x0313 },
1420 	{ 0x1F49, 0x039F, 0x0314 },
1421 	{ 0x1F4A, 0x1F48, 0x0300 },
1422 	{ 0x1F4B, 0x1F49, 0x0300 },
1423 	{ 0x1F4C, 0x1F48, 0x0301 },
1424 	{ 0x1F4D, 0x1F49, 0x0301 },
1425 	{ 0x1F50, 0x03C5, 0x0313 },
1426 	{ 0x1F51, 0x03C5, 0x0314 },
1427 	{ 0x1F52, 0x1F50, 0x0300 },
1428 	{ 0x1F53, 0x1F51, 0x0300 },
1429 	{ 0x1F54, 0x1F50, 0x0301 },
1430 	{ 0x1F55, 0x1F51, 0x0301 },
1431 	{ 0x1F56, 0x1F50, 0x0342 },
1432 	{ 0x1F57, 0x1F51, 0x0342 },
1433 	{ 0x1F59, 0x03A5, 0x0314 },
1434 	{ 0x1F5B, 0x1F59, 0x0300 },
1435 	{ 0x1F5D, 0x1F59, 0x0301 },
1436 	{ 0x1F5F, 0x1F59, 0x0342 },
1437 	{ 0x1F60, 0x03C9, 0x0313 },
1438 	{ 0x1F61, 0x03C9, 0x0314 },
1439 	{ 0x1F62, 0x1F60, 0x0300 },
1440 	{ 0x1F63, 0x1F61, 0x0300 },
1441 	{ 0x1F64, 0x1F60, 0x0301 },
1442 	{ 0x1F65, 0x1F61, 0x0301 },
1443 	{ 0x1F66, 0x1F60, 0x0342 },
1444 	{ 0x1F67, 0x1F61, 0x0342 },
1445 	{ 0x1F68, 0x03A9, 0x0313 },
1446 	{ 0x1F69, 0x03A9, 0x0314 },
1447 	{ 0x1F6A, 0x1F68, 0x0300 },
1448 	{ 0x1F6B, 0x1F69, 0x0300 },
1449 	{ 0x1F6C, 0x1F68, 0x0301 },
1450 	{ 0x1F6D, 0x1F69, 0x0301 },
1451 	{ 0x1F6E, 0x1F68, 0x0342 },
1452 	{ 0x1F6F, 0x1F69, 0x0342 },
1453 	{ 0x1F70, 0x03B1, 0x0300 },
1454 	{ 0x1F72, 0x03B5, 0x0300 },
1455 	{ 0x1F74, 0x03B7, 0x0300 },
1456 	{ 0x1F76, 0x03B9, 0x0300 },
1457 	{ 0x1F78, 0x03BF, 0x0300 },
1458 	{ 0x1F7A, 0x03C5, 0x0300 },
1459 	{ 0x1F7C, 0x03C9, 0x0300 },
1460 	{ 0x1F80, 0x1F00, 0x0345 },
1461 	{ 0x1F81, 0x1F01, 0x0345 },
1462 	{ 0x1F82, 0x1F02, 0x0345 },
1463 	{ 0x1F83, 0x1F03, 0x0345 },
1464 	{ 0x1F84, 0x1F04, 0x0345 },
1465 	{ 0x1F85, 0x1F05, 0x0345 },
1466 	{ 0x1F86, 0x1F06, 0x0345 },
1467 	{ 0x1F87, 0x1F07, 0x0345 },
1468 	{ 0x1F88, 0x1F08, 0x0345 },
1469 	{ 0x1F89, 0x1F09, 0x0345 },
1470 	{ 0x1F8A, 0x1F0A, 0x0345 },
1471 	{ 0x1F8B, 0x1F0B, 0x0345 },
1472 	{ 0x1F8C, 0x1F0C, 0x0345 },
1473 	{ 0x1F8D, 0x1F0D, 0x0345 },
1474 	{ 0x1F8E, 0x1F0E, 0x0345 },
1475 	{ 0x1F8F, 0x1F0F, 0x0345 },
1476 	{ 0x1F90, 0x1F20, 0x0345 },
1477 	{ 0x1F91, 0x1F21, 0x0345 },
1478 	{ 0x1F92, 0x1F22, 0x0345 },
1479 	{ 0x1F93, 0x1F23, 0x0345 },
1480 	{ 0x1F94, 0x1F24, 0x0345 },
1481 	{ 0x1F95, 0x1F25, 0x0345 },
1482 	{ 0x1F96, 0x1F26, 0x0345 },
1483 	{ 0x1F97, 0x1F27, 0x0345 },
1484 	{ 0x1F98, 0x1F28, 0x0345 },
1485 	{ 0x1F99, 0x1F29, 0x0345 },
1486 	{ 0x1F9A, 0x1F2A, 0x0345 },
1487 	{ 0x1F9B, 0x1F2B, 0x0345 },
1488 	{ 0x1F9C, 0x1F2C, 0x0345 },
1489 	{ 0x1F9D, 0x1F2D, 0x0345 },
1490 	{ 0x1F9E, 0x1F2E, 0x0345 },
1491 	{ 0x1F9F, 0x1F2F, 0x0345 },
1492 	{ 0x1FA0, 0x1F60, 0x0345 },
1493 	{ 0x1FA1, 0x1F61, 0x0345 },
1494 	{ 0x1FA2, 0x1F62, 0x0345 },
1495 	{ 0x1FA3, 0x1F63, 0x0345 },
1496 	{ 0x1FA4, 0x1F64, 0x0345 },
1497 	{ 0x1FA5, 0x1F65, 0x0345 },
1498 	{ 0x1FA6, 0x1F66, 0x0345 },
1499 	{ 0x1FA7, 0x1F67, 0x0345 },
1500 	{ 0x1FA8, 0x1F68, 0x0345 },
1501 	{ 0x1FA9, 0x1F69, 0x0345 },
1502 	{ 0x1FAA, 0x1F6A, 0x0345 },
1503 	{ 0x1FAB, 0x1F6B, 0x0345 },
1504 	{ 0x1FAC, 0x1F6C, 0x0345 },
1505 	{ 0x1FAD, 0x1F6D, 0x0345 },
1506 	{ 0x1FAE, 0x1F6E, 0x0345 },
1507 	{ 0x1FAF, 0x1F6F, 0x0345 },
1508 	{ 0x1FB0, 0x03B1, 0x0306 },
1509 	{ 0x1FB1, 0x03B1, 0x0304 },
1510 	{ 0x1FB2, 0x1F70, 0x0345 },
1511 	{ 0x1FB3, 0x03B1, 0x0345 },
1512 	{ 0x1FB4, 0x03AC, 0x0345 },
1513 	{ 0x1FB6, 0x03B1, 0x0342 },
1514 	{ 0x1FB7, 0x1FB6, 0x0345 },
1515 	{ 0x1FB8, 0x0391, 0x0306 },
1516 	{ 0x1FB9, 0x0391, 0x0304 },
1517 	{ 0x1FBA, 0x0391, 0x0300 },
1518 	{ 0x1FBC, 0x0391, 0x0345 },
1519 	{ 0x1FC1, 0x00A8, 0x0342 },
1520 	{ 0x1FC2, 0x1F74, 0x0345 },
1521 	{ 0x1FC3, 0x03B7, 0x0345 },
1522 	{ 0x1FC4, 0x03AE, 0x0345 },
1523 	{ 0x1FC6, 0x03B7, 0x0342 },
1524 	{ 0x1FC7, 0x1FC6, 0x0345 },
1525 	{ 0x1FC8, 0x0395, 0x0300 },
1526 	{ 0x1FCA, 0x0397, 0x0300 },
1527 	{ 0x1FCC, 0x0397, 0x0345 },
1528 	{ 0x1FCD, 0x1FBF, 0x0300 },
1529 	{ 0x1FCE, 0x1FBF, 0x0301 },
1530 	{ 0x1FCF, 0x1FBF, 0x0342 },
1531 	{ 0x1FD0, 0x03B9, 0x0306 },
1532 	{ 0x1FD1, 0x03B9, 0x0304 },
1533 	{ 0x1FD2, 0x03CA, 0x0300 },
1534 	{ 0x1FD6, 0x03B9, 0x0342 },
1535 	{ 0x1FD7, 0x03CA, 0x0342 },
1536 	{ 0x1FD8, 0x0399, 0x0306 },
1537 	{ 0x1FD9, 0x0399, 0x0304 },
1538 	{ 0x1FDA, 0x0399, 0x0300 },
1539 	{ 0x1FDD, 0x1FFE, 0x0300 },
1540 	{ 0x1FDE, 0x1FFE, 0x0301 },
1541 	{ 0x1FDF, 0x1FFE, 0x0342 },
1542 	{ 0x1FE0, 0x03C5, 0x0306 },
1543 	{ 0x1FE1, 0x03C5, 0x0304 },
1544 	{ 0x1FE2, 0x03CB, 0x0300 },
1545 	{ 0x1FE4, 0x03C1, 0x0313 },
1546 	{ 0x1FE5, 0x03C1, 0x0314 },
1547 	{ 0x1FE6, 0x03C5, 0x0342 },
1548 	{ 0x1FE7, 0x03CB, 0x0342 },
1549 	{ 0x1FE8, 0x03A5, 0x0306 },
1550 	{ 0x1FE9, 0x03A5, 0x0304 },
1551 	{ 0x1FEA, 0x03A5, 0x0300 },
1552 	{ 0x1FEC, 0x03A1, 0x0314 },
1553 	{ 0x1FED, 0x00A8, 0x0300 },
1554 	{ 0x1FF2, 0x1F7C, 0x0345 },
1555 	{ 0x1FF3, 0x03C9, 0x0345 },
1556 	{ 0x1FF4, 0x03CE, 0x0345 },
1557 	{ 0x1FF6, 0x03C9, 0x0342 },
1558 	{ 0x1FF7, 0x1FF6, 0x0345 },
1559 	{ 0x1FF8, 0x039F, 0x0300 },
1560 	{ 0x1FFA, 0x03A9, 0x0300 },
1561 	{ 0x1FFC, 0x03A9, 0x0345 },
1562 	{ 0x219A, 0x2190, 0x0338 },
1563 	{ 0x219B, 0x2192, 0x0338 },
1564 	{ 0x21AE, 0x2194, 0x0338 },
1565 	{ 0x21CD, 0x21D0, 0x0338 },
1566 	{ 0x21CE, 0x21D4, 0x0338 },
1567 	{ 0x21CF, 0x21D2, 0x0338 },
1568 	{ 0x2204, 0x2203, 0x0338 },
1569 	{ 0x2209, 0x2208, 0x0338 },
1570 	{ 0x220C, 0x220B, 0x0338 },
1571 	{ 0x2224, 0x2223, 0x0338 },
1572 	{ 0x2226, 0x2225, 0x0338 },
1573 	{ 0x2241, 0x223C, 0x0338 },
1574 	{ 0x2244, 0x2243, 0x0338 },
1575 	{ 0x2247, 0x2245, 0x0338 },
1576 	{ 0x2249, 0x2248, 0x0338 },
1577 	{ 0x2260, 0x003D, 0x0338 },
1578 	{ 0x2262, 0x2261, 0x0338 },
1579 	{ 0x226D, 0x224D, 0x0338 },
1580 	{ 0x226E, 0x003C, 0x0338 },
1581 	{ 0x226F, 0x003E, 0x0338 },
1582 	{ 0x2270, 0x2264, 0x0338 },
1583 	{ 0x2271, 0x2265, 0x0338 },
1584 	{ 0x2274, 0x2272, 0x0338 },
1585 	{ 0x2275, 0x2273, 0x0338 },
1586 	{ 0x2278, 0x2276, 0x0338 },
1587 	{ 0x2279, 0x2277, 0x0338 },
1588 	{ 0x2280, 0x227A, 0x0338 },
1589 	{ 0x2281, 0x227B, 0x0338 },
1590 	{ 0x2284, 0x2282, 0x0338 },
1591 	{ 0x2285, 0x2283, 0x0338 },
1592 	{ 0x2288, 0x2286, 0x0338 },
1593 	{ 0x2289, 0x2287, 0x0338 },
1594 	{ 0x22AC, 0x22A2, 0x0338 },
1595 	{ 0x22AD, 0x22A8, 0x0338 },
1596 	{ 0x22AE, 0x22A9, 0x0338 },
1597 	{ 0x22AF, 0x22AB, 0x0338 },
1598 	{ 0x22E0, 0x227C, 0x0338 },
1599 	{ 0x22E1, 0x227D, 0x0338 },
1600 	{ 0x22E2, 0x2291, 0x0338 },
1601 	{ 0x22E3, 0x2292, 0x0338 },
1602 	{ 0x22EA, 0x22B2, 0x0338 },
1603 	{ 0x22EB, 0x22B3, 0x0338 },
1604 	{ 0x22EC, 0x22B4, 0x0338 },
1605 	{ 0x22ED, 0x22B5, 0x0338 },
1606 	{ 0x2ADC, 0x2ADD, 0x0338 },
1607 	{ 0x304C, 0x304B, 0x3099 },
1608 	{ 0x304E, 0x304D, 0x3099 },
1609 	{ 0x3050, 0x304F, 0x3099 },
1610 	{ 0x3052, 0x3051, 0x3099 },
1611 	{ 0x3054, 0x3053, 0x3099 },
1612 	{ 0x3056, 0x3055, 0x3099 },
1613 	{ 0x3058, 0x3057, 0x3099 },
1614 	{ 0x305A, 0x3059, 0x3099 },
1615 	{ 0x305C, 0x305B, 0x3099 },
1616 	{ 0x305E, 0x305D, 0x3099 },
1617 	{ 0x3060, 0x305F, 0x3099 },
1618 	{ 0x3062, 0x3061, 0x3099 },
1619 	{ 0x3065, 0x3064, 0x3099 },
1620 	{ 0x3067, 0x3066, 0x3099 },
1621 	{ 0x3069, 0x3068, 0x3099 },
1622 	{ 0x3070, 0x306F, 0x3099 },
1623 	{ 0x3071, 0x306F, 0x309A },
1624 	{ 0x3073, 0x3072, 0x3099 },
1625 	{ 0x3074, 0x3072, 0x309A },
1626 	{ 0x3076, 0x3075, 0x3099 },
1627 	{ 0x3077, 0x3075, 0x309A },
1628 	{ 0x3079, 0x3078, 0x3099 },
1629 	{ 0x307A, 0x3078, 0x309A },
1630 	{ 0x307C, 0x307B, 0x3099 },
1631 	{ 0x307D, 0x307B, 0x309A },
1632 	{ 0x3094, 0x3046, 0x3099 },
1633 	{ 0x309E, 0x309D, 0x3099 },
1634 	{ 0x30AC, 0x30AB, 0x3099 },
1635 	{ 0x30AE, 0x30AD, 0x3099 },
1636 	{ 0x30B0, 0x30AF, 0x3099 },
1637 	{ 0x30B2, 0x30B1, 0x3099 },
1638 	{ 0x30B4, 0x30B3, 0x3099 },
1639 	{ 0x30B6, 0x30B5, 0x3099 },
1640 	{ 0x30B8, 0x30B7, 0x3099 },
1641 	{ 0x30BA, 0x30B9, 0x3099 },
1642 	{ 0x30BC, 0x30BB, 0x3099 },
1643 	{ 0x30BE, 0x30BD, 0x3099 },
1644 	{ 0x30C0, 0x30BF, 0x3099 },
1645 	{ 0x30C2, 0x30C1, 0x3099 },
1646 	{ 0x30C5, 0x30C4, 0x3099 },
1647 	{ 0x30C7, 0x30C6, 0x3099 },
1648 	{ 0x30C9, 0x30C8, 0x3099 },
1649 	{ 0x30D0, 0x30CF, 0x3099 },
1650 	{ 0x30D1, 0x30CF, 0x309A },
1651 	{ 0x30D3, 0x30D2, 0x3099 },
1652 	{ 0x30D4, 0x30D2, 0x309A },
1653 	{ 0x30D6, 0x30D5, 0x3099 },
1654 	{ 0x30D7, 0x30D5, 0x309A },
1655 	{ 0x30D9, 0x30D8, 0x3099 },
1656 	{ 0x30DA, 0x30D8, 0x309A },
1657 	{ 0x30DC, 0x30DB, 0x3099 },
1658 	{ 0x30DD, 0x30DB, 0x309A },
1659 	{ 0x30F4, 0x30A6, 0x3099 },
1660 	{ 0x30F7, 0x30EF, 0x3099 },
1661 	{ 0x30F8, 0x30F0, 0x3099 },
1662 	{ 0x30F9, 0x30F1, 0x3099 },
1663 	{ 0x30FA, 0x30F2, 0x3099 },
1664 	{ 0x30FE, 0x30FD, 0x3099 },
1665 	{ 0xFB1D, 0x05D9, 0x05B4 },
1666 	{ 0xFB1F, 0x05F2, 0x05B7 },
1667 	{ 0xFB2A, 0x05E9, 0x05C1 },
1668 	{ 0xFB2B, 0x05E9, 0x05C2 },
1669 	{ 0xFB2C, 0xFB49, 0x05C1 },
1670 	{ 0xFB2D, 0xFB49, 0x05C2 },
1671 	{ 0xFB2E, 0x05D0, 0x05B7 },
1672 	{ 0xFB2F, 0x05D0, 0x05B8 },
1673 	{ 0xFB30, 0x05D0, 0x05BC },
1674 	{ 0xFB31, 0x05D1, 0x05BC },
1675 	{ 0xFB32, 0x05D2, 0x05BC },
1676 	{ 0xFB33, 0x05D3, 0x05BC },
1677 	{ 0xFB34, 0x05D4, 0x05BC },
1678 	{ 0xFB35, 0x05D5, 0x05BC },
1679 	{ 0xFB36, 0x05D6, 0x05BC },
1680 	{ 0xFB38, 0x05D8, 0x05BC },
1681 	{ 0xFB39, 0x05D9, 0x05BC },
1682 	{ 0xFB3A, 0x05DA, 0x05BC },
1683 	{ 0xFB3B, 0x05DB, 0x05BC },
1684 	{ 0xFB3C, 0x05DC, 0x05BC },
1685 	{ 0xFB3E, 0x05DE, 0x05BC },
1686 	{ 0xFB40, 0x05E0, 0x05BC },
1687 	{ 0xFB41, 0x05E1, 0x05BC },
1688 	{ 0xFB43, 0x05E3, 0x05BC },
1689 	{ 0xFB44, 0x05E4, 0x05BC },
1690 	{ 0xFB46, 0x05E6, 0x05BC },
1691 	{ 0xFB47, 0x05E7, 0x05BC },
1692 	{ 0xFB48, 0x05E8, 0x05BC },
1693 	{ 0xFB49, 0x05E9, 0x05BC },
1694 	{ 0xFB4A, 0x05EA, 0x05BC },
1695 	{ 0xFB4B, 0x05D5, 0x05B9 },
1696 	{ 0xFB4C, 0x05D1, 0x05BF },
1697 	{ 0xFB4D, 0x05DB, 0x05BF },
1698 	{ 0xFB4E, 0x05E4, 0x05BF },
1699 	/* out of range of unsigned short... */
1700 #if 0
1701 	{ 0x1D15E, 0x1D157, 0x1D165 },
1702 	{ 0x1D15F, 0x1D158, 0x1D165 },
1703 	{ 0x1D160, 0x1D15F, 0x1D16E },
1704 	{ 0x1D161, 0x1D15F, 0x1D16F },
1705 	{ 0x1D162, 0x1D15F, 0x1D170 },
1706 	{ 0x1D163, 0x1D15F, 0x1D171 },
1707 	{ 0x1D164, 0x1D15F, 0x1D172 },
1708 	{ 0x1D1BB, 0x1D1B9, 0x1D165 },
1709 	{ 0x1D1BC, 0x1D1BA, 0x1D165 },
1710 	{ 0x1D1BD, 0x1D1BB, 0x1D16E },
1711 	{ 0x1D1BE, 0x1D1BC, 0x1D16E },
1712 	{ 0x1D1BF, 0x1D1BB, 0x1D16F },
1713 	{ 0x1D1C0, 0x1D1BC, 0x1D16F },
1714 #endif
1715 	/* special hack, treat Arabic ligatures as combining characters */
1716 	/* combine them to the isolated presentation form, then let
1717 	 * the shaping and joining take care of it */
1718 	{ 0xFEF5, 0x0644, 0x0622 }, /* LAM_ALEF_MADDA */
1719 	{ 0xFEF7, 0x0644, 0x0623 }, /* LAM_ALEF_HAMZA_ABOVE */
1720 	{ 0xFEF9, 0x0644, 0x0625 }, /* LAM_ALEF_HAMZA_BELOW */
1721 	{ 0xFEFB, 0x0644, 0x0627 }, /* LAM_ALEF */
1722 };
1723 
1724 /* -------------------------- local functions ------------------------------ */
1725 
1726 
1727 /* look-up functions, maybe theese should use binary search?
1728    would require a duplicate of comb_table to reverse map... */
1729 static int
get_combining_class(unsigned short ch)1730 get_combining_class(unsigned short ch)
1731 {
1732 	int count;
1733 	int table_size = sizeof(combclass_table) / sizeof(combclass_table[0]);
1734 
1735 	for (count = 0; count < table_size; count++)
1736 	{
1737 		if (combclass_table[count].key == ch)
1738 		{
1739 			return combclass_table[count].combclass;
1740 		}
1741 	}
1742 
1743 	return 0;
1744 }
1745 
1746 static const char_comb_t*
get_comb_entry_decomposed(unsigned short ch)1747 get_comb_entry_decomposed(unsigned short ch)
1748 {
1749 	int count;
1750 	int table_size = sizeof(comb_table) / sizeof(comb_table[0]);
1751 
1752 	for (count = 0; count < table_size; count++)
1753 	{
1754 		if (comb_table[count].key == ch)
1755 		{
1756 			return &comb_table[count];
1757 		}
1758 	}
1759 
1760 	return NULL;
1761 }
1762 
1763 static unsigned short
get_comb_entry_composed(unsigned short first,unsigned short second)1764 get_comb_entry_composed(unsigned short first, unsigned short second)
1765 {
1766 	int count;
1767 	int table_size = sizeof(comb_table) / sizeof(comb_table[0]);
1768 
1769 	for (count = 0; count < table_size; count++)
1770 	{
1771 		if (comb_table[count].first == first &&
1772 		    comb_table[count].second == second)
1773 		{
1774 			return comb_table[count].key;
1775 		}
1776 	}
1777 
1778 	return (unsigned short) 0;
1779 }
1780 
1781 static int
convert_to_ucs2(const unsigned char * str_utf8,unsigned short * str_ucs2,int len)1782 convert_to_ucs2(
1783 	const unsigned char *str_utf8, unsigned short *str_ucs2, int len)
1784 {
1785 	int in_pos = 0;
1786 	int out_pos = 0;
1787 	while (in_pos < len)
1788 	{
1789 		if (str_utf8[in_pos] <= 0x7f)
1790 		{
1791 			str_ucs2[out_pos] =
1792 				(unsigned short)str_utf8[in_pos];
1793 			in_pos++;
1794 		}
1795 		else
1796 		{
1797 			if ((str_utf8[in_pos] & 0300) != 0300)
1798 			{
1799 				/* out of sync */
1800 				str_ucs2[out_pos] = REPLACEMENT_CHARACTER;
1801 				in_pos++;
1802 			}
1803 			else if (in_pos < len-1 && str_utf8[in_pos] <= 0xdf &&
1804 				 str_utf8[in_pos + 1] <= 0xbf &&
1805 				 str_utf8[in_pos + 1] >= 0x80)
1806 			{
1807 				str_ucs2[out_pos] =
1808 					((str_utf8[in_pos] & 0x1f) << 6) +
1809 					(str_utf8[in_pos+1] & 0x3f);
1810 				/* check for overlong sequence */
1811 				if(str_ucs2[out_pos] < 0x80)
1812 					str_ucs2[out_pos] =
1813 						REPLACEMENT_CHARACTER;
1814 				in_pos += 2;
1815 			}
1816 			else if (in_pos < len-2 && str_utf8[in_pos] <= 0xef &&
1817 				 str_utf8[in_pos + 1] <= 0xbf &&
1818 				 str_utf8[in_pos + 1] >= 0x80 &&
1819 				 str_utf8[in_pos + 2] <= 0xbf &&
1820 				 str_utf8[in_pos + 2] >= 0x80)
1821 			{
1822 				str_ucs2[out_pos] =
1823 					((str_utf8[in_pos] & 0x0f) << 12) +
1824 					((str_utf8[in_pos+1] & 0x3f) << 6) +
1825 					(str_utf8[in_pos+2] & 0x3f);
1826 				/* check for overlong sequence */
1827 				if(str_ucs2[out_pos] < 0x800)
1828 					str_ucs2[out_pos] =
1829 						REPLACEMENT_CHARACTER;
1830 				in_pos += 3;
1831 			}
1832 			else
1833 			{
1834 				/* incomplete sequence */
1835 				str_ucs2[out_pos] = REPLACEMENT_CHARACTER;
1836 				in_pos++;
1837 			}
1838 		}
1839 		out_pos++;
1840 	}
1841 	return out_pos;
1842 }
1843 
1844 static int
convert_to_utf8(const unsigned short * str_ucs2,unsigned char * str_utf8,int len)1845 convert_to_utf8(
1846 	const unsigned short *str_ucs2, unsigned char *str_utf8, int len)
1847 {
1848 	int in_pos = 0;
1849 	int out_pos = 0;
1850 
1851 	for (in_pos = 0 ; in_pos < len ; in_pos++)
1852 	{
1853 		if (str_ucs2[in_pos] <= 0x7f)
1854 		{
1855 			str_utf8[out_pos] = str_ucs2[in_pos];
1856 			out_pos++;
1857 		}
1858 		else if (str_ucs2[in_pos] <= 0x7ff)
1859 		{
1860 			str_utf8[out_pos] =
1861 				(str_ucs2[in_pos] >> 6) | 0xc0;
1862 			str_utf8[out_pos+1] =
1863 				(str_ucs2[in_pos] & 0x3f) | 0x80;
1864 			out_pos += 2;
1865 		}
1866 		else
1867 		{
1868 			str_utf8[out_pos] =
1869 				(str_ucs2[in_pos] >> 12) | 0xe0;
1870 			str_utf8[out_pos+1] =
1871 				((str_ucs2[in_pos] & 0xfff) >> 6) | 0x80;
1872 			str_utf8[out_pos+2] =
1873 				(str_ucs2[in_pos] & 0x3f) | 0x80;
1874 			out_pos += 3;
1875 		}
1876 		/* this doesn't handle values outside UCS2 (16-bit) */
1877 	}
1878 	return out_pos;
1879 }
1880 
1881 
1882 /* main procedure:
1883    takes a pointer to a string (UTF-8)
1884    first decomposes string, then rearrange combining characters, the
1885    combines them back.
1886    Result is stored in original string (can never be "expanded" from
1887    original size), new length is returned
1888 */
1889 
1890 
1891 int
CombineChars(unsigned char * str_visual,int len,superimpose_char_t ** comb_chars,int ** l_to_v)1892 CombineChars(
1893 	unsigned char *str_visual, int len, superimpose_char_t **comb_chars,
1894 	int **l_to_v)
1895 {
1896 	int i,j,k;  /* counters */
1897 	unsigned short *source;
1898 	unsigned short *dest;
1899 	int *source_v_to_l;
1900 	int *dest_v_to_l;
1901 	int str_len;
1902 	int in_str_len;
1903 	int out_str_len;
1904 	int comp_str_len = 0;
1905   	Bool has_changed;
1906 
1907 	/* if input has zero length, return immediatly */
1908 	if (len == 0)
1909 	{
1910 		return 0;
1911 	}
1912 
1913 	/* decompose composed characters */
1914 	source = (unsigned short *)safemalloc(
1915 		(len + 1) * sizeof(unsigned short));
1916 	/* convert from UTF-8-encoded text to internal 16-bit encoding */
1917 	str_len = convert_to_ucs2(str_visual,source,len);
1918 	in_str_len = str_len;
1919 	/* we don't really need to NULL-terminate source, since we
1920 	   have string length */
1921 
1922 	/* be pessimistic, assume all characters are decomposed */
1923 	dest = (unsigned short *)safemalloc(
1924 		(str_len + 1) * 2 * sizeof(unsigned short));
1925 	/* use theese to keep track of the mapping of characters from
1926 	   logical to visual */
1927 	source_v_to_l = (int *)safemalloc(str_len * sizeof(int));
1928 	dest_v_to_l = (int *)safemalloc(str_len * 2 * sizeof(int));
1929 	/* setup initial mapping 1-to-1 */
1930 	for(i = 0 ; i < str_len ; i++)
1931 	{
1932 		source_v_to_l[i] = i;
1933 	}
1934 	do
1935 	{
1936 		has_changed = False;
1937 		for (i = 0, j = 0; i < str_len; i++)
1938 		{
1939 			const char_comb_t *decomp =
1940 				get_comb_entry_decomposed(source[i]);
1941 			/* current character is decomposable */
1942 			if (decomp)
1943 			{
1944 				dest[j] = decomp->first;
1945 				dest[j+1] = decomp->second;
1946 				dest_v_to_l[j] = source_v_to_l[i];
1947 				dest_v_to_l[j+1] = source_v_to_l[i];
1948 				j += 2;
1949 				has_changed = True;
1950 			}
1951 			else /* leave it as is */
1952 			{
1953 				dest[j] = source[i];
1954 				dest_v_to_l[j] = source_v_to_l[i];
1955 				j++;
1956 			}
1957 		}
1958 
1959 		/* now swap */
1960 		free(source);
1961 		free(source_v_to_l);
1962 		source = dest;
1963 		source_v_to_l = dest_v_to_l;
1964 		str_len = j;
1965 		dest = (unsigned short *)safemalloc(
1966 			(str_len + 1) * 2 * sizeof(unsigned short));
1967 		dest_v_to_l = (int *)safemalloc(str_len * 2 * sizeof(int));
1968 	} while (has_changed);
1969 	/* source now holds decomposed string (got swapped before exiting
1970 	   loop, str_len holds string length */
1971 	/* we reuse dest for composing, can use existing string lengths
1972 	   since it will only get shorter */
1973 	/* source_v_to_l holds the mapping from positions in decomposed
1974 	   string to original string */
1975 
1976 	/* rearrange combining characters */
1977 	do
1978 	{
1979 		has_changed = False;
1980 		for (i = 0; i < str_len - 1; i++)
1981 		{
1982 			/* swap if combining-class(c1) > combining-class(c2)
1983 			   and combining-class(c2) != 0 */
1984 			/* use negative values for marks that have combining
1985 			   class 0, but should be taken out for drawing
1986 			   superimposed */
1987 			int c1 = get_combining_class(source[i]);
1988 			int c2 = get_combining_class(source[i+1]);
1989 			if (c1 > c2 && c2 > 0)
1990 			{
1991 				unsigned short temp = source[i];
1992 				int temp_v_to_l = source_v_to_l[i];
1993 				source[i] = source[i+1];
1994 				source[i+1] = temp;
1995 				source_v_to_l[i] = source_v_to_l[i+1];
1996 				source_v_to_l[i+1] = temp_v_to_l;
1997 				has_changed = True;
1998 			}
1999 		}
2000 	} while (has_changed);
2001 
2002 	/* compose */
2003 	do
2004 	{
2005 		unsigned short *temp;
2006 		int *temp_v_to_l;
2007 		Bool last_changed = False;
2008 		has_changed = False;
2009 
2010 		for (i = 0, j = 0; i < str_len - 1; j++)
2011 		{
2012 			unsigned short composed =
2013 				get_comb_entry_composed(source[i],
2014 							source[i+1]);
2015 			dest_v_to_l[j] = source_v_to_l[i];
2016 			if (composed != 0)
2017 			{
2018 				dest[j] = composed;
2019 				/* if the last character was "absorbed" */
2020 				if (i == str_len - 2)
2021 				{
2022 					last_changed = True;
2023 				}
2024 				i += 2;
2025 				has_changed = True;
2026 			}
2027 			else
2028 			{
2029 				dest[j] = source[i];
2030 				i++;
2031 			}
2032 		}
2033 		temp = dest;
2034 		dest = source;
2035 		source = temp;
2036 		temp_v_to_l = dest_v_to_l;
2037 		dest_v_to_l = source_v_to_l;
2038 		source_v_to_l = temp_v_to_l;
2039 		/* fixup the last character, the loop above goes to second
2040 		   last, since it needs to look at 2 consecutive,
2041 		   if the last character is a non-combining character */
2042 		/* since we have an immediate return on zero length, this works
2043 		   otherwise this would introduce crap here */
2044 		if (!last_changed)
2045 		{
2046 			source[j] = dest[i];
2047 			source_v_to_l[j] = dest_v_to_l[i];
2048 			str_len = j+1;
2049 		}
2050 		else
2051 		{
2052 			str_len = j;
2053 		}
2054 	} while (has_changed);
2055 
2056 	/* source contains composed string */
2057 
2058 	/* gather "uncomposed" combining characters here for rendering
2059 	  over normal characters later */
2060 	comp_str_len = 0;
2061 	if (comb_chars != NULL)
2062 	{
2063 		/* calculate number of combining characters left */
2064 		for (i = 0 ; i < str_len ; i++)
2065 		{
2066 			if (get_combining_class(source[i]) != 0)
2067 			{
2068 				comp_str_len++;
2069 			}
2070 		}
2071 		/* allocate storage for combining characters */
2072 		*comb_chars = (superimpose_char_t *)
2073 			safemalloc((comp_str_len + 1) *
2074 				   sizeof(superimpose_char_t));
2075 	}
2076 	for (i = 0,j = 0,k = 0 ; i < str_len ; i++)
2077 	{
2078 		/* if character is non-combining,
2079 		   just copy it over to output */
2080 		/* if first character is a combing character, just output
2081 		   it as if it where a base character */
2082 		if (get_combining_class(source[i]) == 0)
2083 		{
2084 			dest[j] = source[i];
2085 			dest_v_to_l[j] = source_v_to_l[i];
2086 			j++;
2087 		}
2088 		else
2089 		{
2090 			if (comb_chars != NULL)
2091 			{
2092 				/* store composing character as associated
2093 				   with last base charcter */
2094 				(*comb_chars)[k].position = j == 0 ? 0 : j-1;
2095 				(*comb_chars)[k].c.byte1 = source[i] >> 8;
2096 				(*comb_chars)[k].c.byte2 = source[i] & 0xff;
2097 				k++;
2098 			}
2099 		}
2100 	}
2101 	/* terminate */
2102 	if (comb_chars != NULL)
2103 	{
2104 		(*comb_chars)[comp_str_len].position = 0;
2105 		(*comb_chars)[comp_str_len].c.byte1 = 0;
2106 		(*comb_chars)[comp_str_len].c.byte2 = 0;
2107 	}
2108 	str_len = convert_to_utf8(dest,str_visual,j);
2109 	out_str_len = j;
2110 	str_visual[str_len] = 0;
2111 
2112 	if(l_to_v != NULL)
2113 	{
2114 		*l_to_v = (int *)safemalloc((in_str_len + 1) * sizeof(int));
2115 		/* map the visual to logical mapping obtained above into
2116 		   a logical to visual mapping */
2117 		/* setup the final mapping from logical to visual positions */
2118 		/* if no base characters out, all positions map to zero,
2119 		   because there we have combining chars in that case */
2120 		if(out_str_len == 0)
2121 		{
2122 			for(i = 0 ; i < in_str_len ; i++)
2123 			{
2124 				(*l_to_v)[i] = 0;
2125 			}
2126 		}
2127 		for(i = 0, j = 0 ; i < out_str_len ; i++)
2128 		{
2129 			/* for each element in mapping from visual string
2130 			   insert "backtracked" references from logical
2131 			   string by inserting consequitive entries, as many
2132 			   as the step in the mapping from visual to logical
2133 			*/
2134 			int step = (i == out_str_len - 1) ?
2135 				    in_str_len - j :
2136 				    dest_v_to_l[i+1] - dest_v_to_l[i];
2137 			for(k = 0 ; k < step ; k++, j++)
2138 			{
2139 				(*l_to_v)[j] = i;
2140 			}
2141 		}
2142 		/* terminated it with -1, to avoid have to send around
2143 		   lenghts */
2144 		(*l_to_v)[in_str_len] = -1;
2145 	}
2146 
2147 	/* clean up */
2148 	free(source);
2149 	free(dest);
2150 	free(source_v_to_l);
2151 	free(dest_v_to_l);
2152 
2153 	return str_len;
2154 }
2155