RDB's Unicode patch. Fonts are now used in Unicode mode where
[u/mdw/putty] / unicode.c
CommitLineData
4eeb7d09 1#include <windows.h>
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <ctype.h>
6
7#include <time.h>
8#include "putty.h"
9
10void init_ucs_tables(void);
11void lpage_send(int codepage, char *buf, int len);
12void luni_send(wchar_t * widebuf, int len);
13
14static void get_unitab(int codepage, wchar_t * unitab, int ftype);
15
16/* Character conversion arrays; they are usually taken from windows,
17 * the xterm one has the four scanlines that have no unicode 2.0
18 * equlivents mapped into the private area.
19 */
20static char **uni_tbl;
21
22static WCHAR unitab_xterm_std[32] = {
23 0x2666, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
24 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba,
25 0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c,
26 0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x0020
27};
28
29extern struct cp_list_item {
30 char *name;
31 int codepage;
32 int cp_size;
33 wchar_t *cp_table;
34} cp_list[];
35
36static void link_font(WCHAR * line_tbl, WCHAR * font_tbl, WCHAR attr);
37
38void init_ucs_tables(void)
39{
40 int i, j;
41 int used_dtf = 0;
42 char tbuf[256];
43 for (i = 0; i < 256; i++)
44 tbuf[i] = i;
45
46 /* Decide on the Line and Font codepages */
47 line_codepage = decode_codepage(cfg.line_codepage);
48
49 if (cfg.vtmode == VT_OEMONLY) {
50 font_codepage = 437;
51 dbcs_screenfont = 0;
52 if (line_codepage <= 0)
53 line_codepage = GetACP();
54 } else if (line_codepage <= 0)
55 line_codepage = font_codepage;
56 utf = (line_codepage == CP_UTF8);
57
58 /* Collect screen font ucs table */
59 if (dbcs_screenfont) {
60 get_unitab(font_codepage, unitab_font, 2);
61 for (i = 128; i < 256; i++)
62 unitab_font[i] = (WCHAR) (ATTR_ACP + i);
63 } else {
64 get_unitab(font_codepage, unitab_font, 1);
65
66 /* CP437 fonts are often broken ... */
67 if (font_codepage == 437)
68 unitab_font[0] = unitab_font[255] = 0xFFFF;
69 }
70 if (cfg.vtmode == VT_XWINDOWS)
71 memcpy(unitab_font + 1, unitab_xterm_std,
72 sizeof(unitab_xterm_std));
73
74 /* Collect OEMCP ucs table */
75 get_unitab(CP_OEMCP, unitab_oemcp, 1);
76
77 /* Collect line set ucs table */
78 if (line_codepage == font_codepage &&
79 (dbcs_screenfont || cfg.vtmode == VT_POORMAN)) {
80
81 /* For DBCS and POOR fonts force direct to font */
82 used_dtf = 1;
83 for (i = 0; i < 32; i++)
84 unitab_line[i] = (WCHAR) i;
85 for (i = 32; i < 256; i++)
86 unitab_line[i] = (WCHAR) (ATTR_ACP + i);
87 unitab_line[127] = (WCHAR) 127;
88 } else {
89 get_unitab(line_codepage, unitab_line, 0);
90 }
91
92#if 0
93 debug(
94 ("Line cp%d, Font cp%d%s\n", line_codepage, font_codepage,
95 dbcs_screenfont ? " DBCS" : ""));
96
97 for (i = 0; i < 256; i += 16) {
98 for (j = 0; j < 16; j++) {
99 debug(("%04x%s", unitab_line[i + j], j == 15 ? "" : ","));
100 }
101 debug(("\n"));
102 }
103#endif
104
105 /* VT100 graphics - NB: Broken for non-ascii CP's */
106 memcpy(unitab_xterm, unitab_line, sizeof(unitab_xterm));
107 memcpy(unitab_xterm + '`', unitab_xterm_std, sizeof(unitab_xterm_std));
108 unitab_xterm['_'] = ' ';
109
110 /* Generate UCS ->line page table. */
111 if (uni_tbl) {
112 for (i = 0; i < 256; i++)
113 if (uni_tbl[i])
114 sfree(uni_tbl[i]);
115 sfree(uni_tbl);
116 uni_tbl = 0;
117 }
118 if (!used_dtf) {
119 for (i = 0; i < 256; i++) {
120 if (DIRECT_CHAR(unitab_line[i]))
121 continue;
122 if (DIRECT_FONT(unitab_line[i]))
123 continue;
124 if (!uni_tbl) {
125 uni_tbl = smalloc(256 * sizeof(char *));
126 memset(uni_tbl, 0, 256 * sizeof(char *));
127 }
128 j = ((unitab_line[i] >> 8) & 0xFF);
129 if (!uni_tbl[j]) {
130 uni_tbl[j] = smalloc(256 * sizeof(char));
131 memset(uni_tbl[j], 0, 256 * sizeof(char));
132 }
133 uni_tbl[j][unitab_line[i] & 0xFF] = i;
134 }
135 }
136
137 /* Find the line control characters. */
138 for (i = 0; i < 256; i++)
139 if (unitab_line[i] < ' '
140 || (unitab_line[i] >= 0x7F && unitab_line[i] < 0xA0))
141 unitab_ctrl[i] = i;
142 else
143 unitab_ctrl[i] = 0xFF;
144
145 /* Generate line->screen direct conversion links. */
146 link_font(unitab_line, unitab_font, ATTR_ACP);
147 link_font(unitab_xterm, unitab_font, ATTR_ACP);
148
149 if (cfg.vtmode == VT_OEMANSI || cfg.vtmode == VT_XWINDOWS) {
150 link_font(unitab_line, unitab_oemcp, ATTR_OEMCP);
151 link_font(unitab_xterm, unitab_oemcp, ATTR_OEMCP);
152 }
153
154 /* Last chance, if !unicode then try poorman links. */
155 if (cfg.vtmode != VT_UNICODE) {
156 static char poorman_latin1[] =
157 " !cL.Y|S\"Ca<--R~o+23'u|.,1o>///?AAAAAAACEEEEIIIIDNOOOOOxOUUUUYPBaaaaaaaceeeeiiiionooooo/ouuuuypy";
158 static char poorman_vt100[] = "*#****o~**+++++-----++++|****L.";
159
160 for (i = 160; i < 256; i++)
161 if (!DIRECT_FONT(unitab_line[i]) &&
162 unitab_line[i] >= 160 && unitab_line[i] < 256)
163 unitab_line[i] = (WCHAR) (ATTR_ACP
164 + poorman_latin1[unitab_line[i] -
165 160]);
166 for (i = 96; i < 127; i++)
167 if (!DIRECT_FONT(unitab_xterm[i]))
168 unitab_xterm[i] =
169 (WCHAR) (ATTR_ACP + poorman_vt100[i - 96]);
170 }
171}
172
173static void link_font(WCHAR * line_tbl, WCHAR * font_tbl, WCHAR attr)
174{
175 int i, j, k;
176 for (k = 0; k < 256; k++) {
177 i = ((k + 32) & 0xFF);
178 if (DIRECT_FONT(line_tbl[i]))
179 continue;
180 for (j = 0; j < 256; j++) {
181 if (line_tbl[i] == font_tbl[j]) {
182 line_tbl[i] = (WCHAR) (attr + j);
183 break;
184 }
185 }
186 }
187}
188
189void lpage_send(int codepage, char *buf, int len)
190{
191 static wchar_t *widebuffer = 0;
192 static int widesize = 0;
193 int wclen;
194
195 if (codepage < 0) {
196 ldisc_send(buf, len);
197 return;
198 }
199
200 if (len > widesize) {
201 sfree(widebuffer);
202 widebuffer = smalloc(len * 2 * sizeof(wchar_t));
203 widesize = len * 2;
204 }
205
206 wclen =
207 MultiByteToWideChar(codepage, 0, buf, len, widebuffer, widesize);
208 luni_send(widebuffer, wclen);
209}
210
211void luni_send(wchar_t * widebuf, int len)
212{
213 static char *linebuffer = 0;
214 static int linesize = 0;
215 int ratio = (utf) ? 3 : 1;
216 int i;
217 char *p;
218
219 if (len * ratio > linesize) {
220 sfree(linebuffer);
221 linebuffer = smalloc(len * ratio * 2 * sizeof(wchar_t));
222 linesize = len * ratio * 2;
223 }
224
225 if (utf) {
226 /* UTF is a simple algorithm */
227 for (p = linebuffer, i = 0; i < len; i++) {
228 wchar_t ch = widebuf[i];
229 if (ch < 0x80) {
230 *p++ = (char) (ch);
231 } else if (ch < 0x800) {
232 *p++ = (0xC0 | (ch >> 6));
233 *p++ = (0x80 | (ch & 0x3F));
234 } else {
235 *p++ = (0xE0 | (ch >> 12));
236 *p++ = (0x80 | ((ch >> 6) & 0x3F));
237 *p++ = (0x80 | (ch & 0x3F));
238 }
239 }
240 } else if (!uni_tbl) {
241 int rv;
242 rv = WideCharToMultiByte(line_codepage, 0, widebuf, len,
243 linebuffer, linesize, NULL, NULL);
244 if (rv >= 0)
245 p = linebuffer + rv;
246 else
247 p = linebuffer;
248 } else {
249 /* Others are a lookup in an array */
250 for (p = linebuffer, i = 0; i < len; i++) {
251 wchar_t ch = widebuf[i];
252 int by;
253 char *p1;
254 if (uni_tbl && (p1 = uni_tbl[(ch >> 8) & 0xFF])
255 && (by = p1[ch & 0xFF]))
256 *p++ = by;
257 else if (ch < 0x80)
258 *p++ = (char) ch;
259#if 1
260 else
261 *p++ = '.';
262#endif
263 }
264 }
265 if (p > linebuffer)
266 ldisc_send(linebuffer, p - linebuffer);
267}
268
269int check_compose(int first, int second)
270{
271
272 static struct {
273 char first, second;
274 wchar_t composed;
275 } composetbl[] = {
276 {
277 0x2b, 0x2b, 0x0023}, {
278 0x41, 0x41, 0x0040}, {
279 0x28, 0x28, 0x005b}, {
280 0x2f, 0x2f, 0x005c}, {
281 0x29, 0x29, 0x005d}, {
282 0x28, 0x2d, 0x007b}, {
283 0x2d, 0x29, 0x007d}, {
284 0x2f, 0x5e, 0x007c}, {
285 0x21, 0x21, 0x00a1}, {
286 0x43, 0x2f, 0x00a2}, {
287 0x43, 0x7c, 0x00a2}, {
288 0x4c, 0x2d, 0x00a3}, {
289 0x4c, 0x3d, 0x00a3}, {
290 0x58, 0x4f, 0x00a4}, {
291 0x58, 0x30, 0x00a4}, {
292 0x59, 0x2d, 0x00a5}, {
293 0x59, 0x3d, 0x00a5}, {
294 0x7c, 0x7c, 0x00a6}, {
295 0x53, 0x4f, 0x00a7}, {
296 0x53, 0x21, 0x00a7}, {
297 0x53, 0x30, 0x00a7}, {
298 0x22, 0x22, 0x00a8}, {
299 0x43, 0x4f, 0x00a9}, {
300 0x43, 0x30, 0x00a9}, {
301 0x41, 0x5f, 0x00aa}, {
302 0x3c, 0x3c, 0x00ab}, {
303 0x2c, 0x2d, 0x00ac}, {
304 0x2d, 0x2d, 0x00ad}, {
305 0x52, 0x4f, 0x00ae}, {
306 0x2d, 0x5e, 0x00af}, {
307 0x30, 0x5e, 0x00b0}, {
308 0x2b, 0x2d, 0x00b1}, {
309 0x32, 0x5e, 0x00b2}, {
310 0x33, 0x5e, 0x00b3}, {
311 0x27, 0x27, 0x00b4}, {
312 0x2f, 0x55, 0x00b5}, {
313 0x50, 0x21, 0x00b6}, {
314 0x2e, 0x5e, 0x00b7}, {
315 0x2c, 0x2c, 0x00b8}, {
316 0x31, 0x5e, 0x00b9}, {
317 0x4f, 0x5f, 0x00ba}, {
318 0x3e, 0x3e, 0x00bb}, {
319 0x31, 0x34, 0x00bc}, {
320 0x31, 0x32, 0x00bd}, {
321 0x33, 0x34, 0x00be}, {
322 0x3f, 0x3f, 0x00bf}, {
323 0x60, 0x41, 0x00c0}, {
324 0x27, 0x41, 0x00c1}, {
325 0x5e, 0x41, 0x00c2}, {
326 0x7e, 0x41, 0x00c3}, {
327 0x22, 0x41, 0x00c4}, {
328 0x2a, 0x41, 0x00c5}, {
329 0x41, 0x45, 0x00c6}, {
330 0x2c, 0x43, 0x00c7}, {
331 0x60, 0x45, 0x00c8}, {
332 0x27, 0x45, 0x00c9}, {
333 0x5e, 0x45, 0x00ca}, {
334 0x22, 0x45, 0x00cb}, {
335 0x60, 0x49, 0x00cc}, {
336 0x27, 0x49, 0x00cd}, {
337 0x5e, 0x49, 0x00ce}, {
338 0x22, 0x49, 0x00cf}, {
339 0x2d, 0x44, 0x00d0}, {
340 0x7e, 0x4e, 0x00d1}, {
341 0x60, 0x4f, 0x00d2}, {
342 0x27, 0x4f, 0x00d3}, {
343 0x5e, 0x4f, 0x00d4}, {
344 0x7e, 0x4f, 0x00d5}, {
345 0x22, 0x4f, 0x00d6}, {
346 0x58, 0x58, 0x00d7}, {
347 0x2f, 0x4f, 0x00d8}, {
348 0x60, 0x55, 0x00d9}, {
349 0x27, 0x55, 0x00da}, {
350 0x5e, 0x55, 0x00db}, {
351 0x22, 0x55, 0x00dc}, {
352 0x27, 0x59, 0x00dd}, {
353 0x48, 0x54, 0x00de}, {
354 0x73, 0x73, 0x00df}, {
355 0x60, 0x61, 0x00e0}, {
356 0x27, 0x61, 0x00e1}, {
357 0x5e, 0x61, 0x00e2}, {
358 0x7e, 0x61, 0x00e3}, {
359 0x22, 0x61, 0x00e4}, {
360 0x2a, 0x61, 0x00e5}, {
361 0x61, 0x65, 0x00e6}, {
362 0x2c, 0x63, 0x00e7}, {
363 0x60, 0x65, 0x00e8}, {
364 0x27, 0x65, 0x00e9}, {
365 0x5e, 0x65, 0x00ea}, {
366 0x22, 0x65, 0x00eb}, {
367 0x60, 0x69, 0x00ec}, {
368 0x27, 0x69, 0x00ed}, {
369 0x5e, 0x69, 0x00ee}, {
370 0x22, 0x69, 0x00ef}, {
371 0x2d, 0x64, 0x00f0}, {
372 0x7e, 0x6e, 0x00f1}, {
373 0x60, 0x6f, 0x00f2}, {
374 0x27, 0x6f, 0x00f3}, {
375 0x5e, 0x6f, 0x00f4}, {
376 0x7e, 0x6f, 0x00f5}, {
377 0x22, 0x6f, 0x00f6}, {
378 0x3a, 0x2d, 0x00f7}, {
379 0x6f, 0x2f, 0x00f8}, {
380 0x60, 0x75, 0x00f9}, {
381 0x27, 0x75, 0x00fa}, {
382 0x5e, 0x75, 0x00fb}, {
383 0x22, 0x75, 0x00fc}, {
384 0x27, 0x79, 0x00fd}, {
385 0x68, 0x74, 0x00fe}, {
386 0x22, 0x79, 0x00ff},
387 /* Unicode extras. */
388 {
389 0x6f, 0x65, 0x0153}, {
390 0x4f, 0x45, 0x0152},
391 /* Compose pairs from UCS */
392 {
393 0x41, 0x2D, 0x0100}, {
394 0x61, 0x2D, 0x0101}, {
395 0x43, 0x27, 0x0106}, {
396 0x63, 0x27, 0x0107}, {
397 0x43, 0x5E, 0x0108}, {
398 0x63, 0x5E, 0x0109}, {
399 0x45, 0x2D, 0x0112}, {
400 0x65, 0x2D, 0x0113}, {
401 0x47, 0x5E, 0x011C}, {
402 0x67, 0x5E, 0x011D}, {
403 0x47, 0x2C, 0x0122}, {
404 0x67, 0x2C, 0x0123}, {
405 0x48, 0x5E, 0x0124}, {
406 0x68, 0x5E, 0x0125}, {
407 0x49, 0x7E, 0x0128}, {
408 0x69, 0x7E, 0x0129}, {
409 0x49, 0x2D, 0x012A}, {
410 0x69, 0x2D, 0x012B}, {
411 0x4A, 0x5E, 0x0134}, {
412 0x6A, 0x5E, 0x0135}, {
413 0x4B, 0x2C, 0x0136}, {
414 0x6B, 0x2C, 0x0137}, {
415 0x4C, 0x27, 0x0139}, {
416 0x6C, 0x27, 0x013A}, {
417 0x4C, 0x2C, 0x013B}, {
418 0x6C, 0x2C, 0x013C}, {
419 0x4E, 0x27, 0x0143}, {
420 0x6E, 0x27, 0x0144}, {
421 0x4E, 0x2C, 0x0145}, {
422 0x6E, 0x2C, 0x0146}, {
423 0x4F, 0x2D, 0x014C}, {
424 0x6F, 0x2D, 0x014D}, {
425 0x52, 0x27, 0x0154}, {
426 0x72, 0x27, 0x0155}, {
427 0x52, 0x2C, 0x0156}, {
428 0x72, 0x2C, 0x0157}, {
429 0x53, 0x27, 0x015A}, {
430 0x73, 0x27, 0x015B}, {
431 0x53, 0x5E, 0x015C}, {
432 0x73, 0x5E, 0x015D}, {
433 0x53, 0x2C, 0x015E}, {
434 0x73, 0x2C, 0x015F}, {
435 0x54, 0x2C, 0x0162}, {
436 0x74, 0x2C, 0x0163}, {
437 0x55, 0x7E, 0x0168}, {
438 0x75, 0x7E, 0x0169}, {
439 0x55, 0x2D, 0x016A}, {
440 0x75, 0x2D, 0x016B}, {
441 0x55, 0x2A, 0x016E}, {
442 0x75, 0x2A, 0x016F}, {
443 0x57, 0x5E, 0x0174}, {
444 0x77, 0x5E, 0x0175}, {
445 0x59, 0x5E, 0x0176}, {
446 0x79, 0x5E, 0x0177}, {
447 0x59, 0x22, 0x0178}, {
448 0x5A, 0x27, 0x0179}, {
449 0x7A, 0x27, 0x017A}, {
450 0x47, 0x27, 0x01F4}, {
451 0x67, 0x27, 0x01F5}, {
452 0x4E, 0x60, 0x01F8}, {
453 0x6E, 0x60, 0x01F9}, {
454 0x45, 0x2C, 0x0228}, {
455 0x65, 0x2C, 0x0229}, {
456 0x59, 0x2D, 0x0232}, {
457 0x79, 0x2D, 0x0233}, {
458 0x44, 0x2C, 0x1E10}, {
459 0x64, 0x2C, 0x1E11}, {
460 0x47, 0x2D, 0x1E20}, {
461 0x67, 0x2D, 0x1E21}, {
462 0x48, 0x22, 0x1E26}, {
463 0x68, 0x22, 0x1E27}, {
464 0x48, 0x2C, 0x1E28}, {
465 0x68, 0x2C, 0x1E29}, {
466 0x4B, 0x27, 0x1E30}, {
467 0x6B, 0x27, 0x1E31}, {
468 0x4D, 0x27, 0x1E3E}, {
469 0x6D, 0x27, 0x1E3F}, {
470 0x50, 0x27, 0x1E54}, {
471 0x70, 0x27, 0x1E55}, {
472 0x56, 0x7E, 0x1E7C}, {
473 0x76, 0x7E, 0x1E7D}, {
474 0x57, 0x60, 0x1E80}, {
475 0x77, 0x60, 0x1E81}, {
476 0x57, 0x27, 0x1E82}, {
477 0x77, 0x27, 0x1E83}, {
478 0x57, 0x22, 0x1E84}, {
479 0x77, 0x22, 0x1E85}, {
480 0x58, 0x22, 0x1E8C}, {
481 0x78, 0x22, 0x1E8D}, {
482 0x5A, 0x5E, 0x1E90}, {
483 0x7A, 0x5E, 0x1E91}, {
484 0x74, 0x22, 0x1E97}, {
485 0x77, 0x2A, 0x1E98}, {
486 0x79, 0x2A, 0x1E99}, {
487 0x45, 0x7E, 0x1EBC}, {
488 0x65, 0x7E, 0x1EBD}, {
489 0x59, 0x60, 0x1EF2}, {
490 0x79, 0x60, 0x1EF3}, {
491 0x59, 0x7E, 0x1EF8}, {
492 0x79, 0x7E, 0x1EF9},
493 /* Compatible/possibles from UCS */
494 {
495 0x49, 0x4A, 0x0132}, {
496 0x69, 0x6A, 0x0133}, {
497 0x4C, 0x4A, 0x01C7}, {
498 0x4C, 0x6A, 0x01C8}, {
499 0x6C, 0x6A, 0x01C9}, {
500 0x4E, 0x4A, 0x01CA}, {
501 0x4E, 0x6A, 0x01CB}, {
502 0x6E, 0x6A, 0x01CC}, {
503 0x44, 0x5A, 0x01F1}, {
504 0x44, 0x7A, 0x01F2}, {
505 0x64, 0x7A, 0x01F3}, {
506 0x2E, 0x2E, 0x2025}, {
507 0x21, 0x21, 0x203C}, {
508 0x3F, 0x21, 0x2048}, {
509 0x21, 0x3F, 0x2049}, {
510 0x52, 0x73, 0x20A8}, {
511 0x4E, 0x6F, 0x2116}, {
512 0x53, 0x4D, 0x2120}, {
513 0x54, 0x4D, 0x2122}, {
514 0x49, 0x49, 0x2161}, {
515 0x49, 0x56, 0x2163}, {
516 0x56, 0x49, 0x2165}, {
517 0x49, 0x58, 0x2168}, {
518 0x58, 0x49, 0x216A}, {
519 0x69, 0x69, 0x2171}, {
520 0x69, 0x76, 0x2173}, {
521 0x76, 0x69, 0x2175}, {
522 0x69, 0x78, 0x2178}, {
523 0x78, 0x69, 0x217A}, {
524 0x31, 0x30, 0x2469}, {
525 0x31, 0x31, 0x246A}, {
526 0x31, 0x32, 0x246B}, {
527 0x31, 0x33, 0x246C}, {
528 0x31, 0x34, 0x246D}, {
529 0x31, 0x35, 0x246E}, {
530 0x31, 0x36, 0x246F}, {
531 0x31, 0x37, 0x2470}, {
532 0x31, 0x38, 0x2471}, {
533 0x31, 0x39, 0x2472}, {
534 0x32, 0x30, 0x2473}, {
535 0x31, 0x2E, 0x2488}, {
536 0x32, 0x2E, 0x2489}, {
537 0x33, 0x2E, 0x248A}, {
538 0x34, 0x2E, 0x248B}, {
539 0x35, 0x2E, 0x248C}, {
540 0x36, 0x2E, 0x248D}, {
541 0x37, 0x2E, 0x248E}, {
542 0x38, 0x2E, 0x248F}, {
543 0x39, 0x2E, 0x2490}, {
544 0x64, 0x61, 0x3372}, {
545 0x41, 0x55, 0x3373}, {
546 0x6F, 0x56, 0x3375}, {
547 0x70, 0x63, 0x3376}, {
548 0x70, 0x41, 0x3380}, {
549 0x6E, 0x41, 0x3381}, {
550 0x6D, 0x41, 0x3383}, {
551 0x6B, 0x41, 0x3384}, {
552 0x4B, 0x42, 0x3385}, {
553 0x4D, 0x42, 0x3386}, {
554 0x47, 0x42, 0x3387}, {
555 0x70, 0x46, 0x338A}, {
556 0x6E, 0x46, 0x338B}, {
557 0x6D, 0x67, 0x338E}, {
558 0x6B, 0x67, 0x338F}, {
559 0x48, 0x7A, 0x3390}, {
560 0x66, 0x6D, 0x3399}, {
561 0x6E, 0x6D, 0x339A}, {
562 0x6D, 0x6D, 0x339C}, {
563 0x63, 0x6D, 0x339D}, {
564 0x6B, 0x6D, 0x339E}, {
565 0x50, 0x61, 0x33A9}, {
566 0x70, 0x73, 0x33B0}, {
567 0x6E, 0x73, 0x33B1}, {
568 0x6D, 0x73, 0x33B3}, {
569 0x70, 0x56, 0x33B4}, {
570 0x6E, 0x56, 0x33B5}, {
571 0x6D, 0x56, 0x33B7}, {
572 0x6B, 0x56, 0x33B8}, {
573 0x4D, 0x56, 0x33B9}, {
574 0x70, 0x57, 0x33BA}, {
575 0x6E, 0x57, 0x33BB}, {
576 0x6D, 0x57, 0x33BD}, {
577 0x6B, 0x57, 0x33BE}, {
578 0x4D, 0x57, 0x33BF}, {
579 0x42, 0x71, 0x33C3}, {
580 0x63, 0x63, 0x33C4}, {
581 0x63, 0x64, 0x33C5}, {
582 0x64, 0x42, 0x33C8}, {
583 0x47, 0x79, 0x33C9}, {
584 0x68, 0x61, 0x33CA}, {
585 0x48, 0x50, 0x33CB}, {
586 0x69, 0x6E, 0x33CC}, {
587 0x4B, 0x4B, 0x33CD}, {
588 0x4B, 0x4D, 0x33CE}, {
589 0x6B, 0x74, 0x33CF}, {
590 0x6C, 0x6D, 0x33D0}, {
591 0x6C, 0x6E, 0x33D1}, {
592 0x6C, 0x78, 0x33D3}, {
593 0x6D, 0x62, 0x33D4}, {
594 0x50, 0x48, 0x33D7}, {
595 0x50, 0x52, 0x33DA}, {
596 0x73, 0x72, 0x33DB}, {
597 0x53, 0x76, 0x33DC}, {
598 0x57, 0x62, 0x33DD}, {
599 0x66, 0x66, 0xFB00}, {
600 0x66, 0x69, 0xFB01}, {
601 0x66, 0x6C, 0xFB02}, {
602 0x73, 0x74, 0xFB06}, {
603 0, 0, 0}
604 }, *c;
605
606 static int recurse = 0;
607 int nc = -1;
608
609 for (c = composetbl; c->first; c++) {
610 if (c->first == first && c->second == second)
611 return c->composed;
612 }
613
614 if (recurse == 0) {
615 recurse = 1;
616 nc = check_compose(second, first);
617 if (nc == -1)
618 nc = check_compose(toupper(first), toupper(second));
619 if (nc == -1)
620 nc = check_compose(toupper(second), toupper(first));
621 recurse = 0;
622 }
623 return nc;
624}
625
626int decode_codepage(char *cp_name)
627{
628 char *s, *d;
629 struct cp_list_item *cpi;
630 int codepage = -1;
631 char ch;
632 CPINFO cpinfo;
633
634 if (cp_name && *cp_name)
635 for (cpi = cp_list; cpi->name; cpi++) {
636 s = cp_name;
637 d = cpi->name;
638 for (;;) {
639 while (*s && !isalnum(*s) && *s != ':')
640 s++;
641 while (*d && !isalnum(*d) && *d != ':')
642 d++;
643 if (*s == 0) {
644 codepage = cpi->codepage;
645 if (codepage == CP_UTF8)
646 goto break_break;
647 if (codepage == 0) {
648 codepage = 65536 + (cpi - cp_list);
649 goto break_break;
650 }
651
652 if (GetCPInfo(codepage, &cpinfo) != 0)
653 goto break_break;
654 }
655 if (islower(*s))
656 ch = toupper(*s++);
657 else
658 ch = *s++;
659 if (ch != *d++)
660 break;
661 }
662 }
663
664 if (cp_name && *cp_name) {
665 d = cp_name;
666 if (strnicmp(d, "cp", 2) == 0)
667 d += 2;
668 if (strnicmp(d, "ibm", 3) == 0)
669 d += 3;
670 for (s = d; *s >= '0' && *s <= '9'; s++);
671 if (*s == 0 && s != d)
672 codepage = atoi(d); /* CP999 or IBM999 */
673
674 if (codepage == CP_ACP)
675 codepage = GetACP();
676 if (codepage == CP_OEMCP)
677 codepage = GetOEMCP();
678 if (codepage > 65535)
679 codepage = -2;
680 }
681
682 break_break:;
683 if (codepage != -1) {
684 if (codepage != CP_UTF8 && codepage < 65536) {
685 if (GetCPInfo(codepage, &cpinfo) == 0) {
686 codepage = -2;
687 } else if (cpinfo.MaxCharSize > 1)
688 codepage = -3;
689 }
690 }
691 if (codepage == -1 && *cp_name)
692 codepage = -2;
693 return codepage;
694}
695
696char *cp_name(int codepage)
697{
698 struct cp_list_item *cpi, *cpno;
699 static char buf[32];
700 if (codepage > 0 && codepage < 65536)
701 sprintf(buf, "CP%03d", codepage);
702 else
703 *buf = 0;
704
705 if (codepage >= 65536) {
706 cpno = 0;
707 for (cpi = cp_list; cpi->name; cpi++)
708 if (cpi == cp_list + (codepage - 65536)) {
709 cpno = cpi;
710 break;
711 }
712 if (cpno)
713 for (cpi = cp_list; cpi->name; cpi++) {
714 if (cpno->cp_table == cpi->cp_table)
715 return cpi->name;
716 }
717 } else {
718 for (cpi = cp_list; cpi->name; cpi++) {
719 if (codepage == cpi->codepage)
720 return cpi->name;
721 }
722 }
723 return buf;
724}
725
726static void get_unitab(int codepage, wchar_t * unitab, int ftype)
727{
728 char tbuf[4];
729 int i, max = 256, flg = MB_ERR_INVALID_CHARS;
730
731 if (ftype)
732 flg |= MB_USEGLYPHCHARS;
733 if (ftype == 2)
734 max = 128;
735
736 if (codepage == CP_UTF8)
737 codepage = 28591;
738 else if (codepage == CP_ACP)
739 codepage = GetACP();
740 else if (codepage == CP_OEMCP)
741 codepage = GetOEMCP();
742
743 if (codepage > 0 && codepage < 65536) {
744 for (i = 0; i < max; i++) {
745 tbuf[0] = i;
746
747 if (MultiByteToWideChar(codepage, flg, tbuf, 1, unitab + i, 1)
748 != 1)
749 unitab[i] = 0xFFFD;
750 }
751 } else {
752 int j = 256 - cp_list[codepage & 0xFFFF].cp_size;
753 for (i = 0; i < max; i++)
754 unitab[i] = i;
755 for (i = j; i < max; i++)
756 unitab[i] = cp_list[codepage & 0xFFFF].cp_table[i - j];
757 }
758}
759
760/*
761 * From here down is the codepage data, if you want to add your own line
762 * codepage do it here.
763 *
764 * If the codepage is non-zero it's a window codepage, zero means use a
765 * local codepage. The name is always converted to the first of any
766 * duplicate definitions.
767 */
768extern wchar_t iso_8859_10[];
769extern wchar_t iso_8859_11[];
770extern wchar_t iso_8859_12[];
771extern wchar_t iso_8859_14[];
772extern wchar_t iso_8859_15[];
773extern wchar_t roman8[];
774extern wchar_t koi8_u[];
775extern wchar_t vscii[];
776extern wchar_t dec_mcs[];
777
778static struct cp_list_item cp_list[] = {
779 {"UTF-8", CP_UTF8},
780
781 {"ISO-8859-1:1987", 28591},
782 {"ISO-8859-2:1987", 28592},
783 {"ISO-8859-3:1988", 28593},
784 {"ISO-8859-4:1988", 28594},
785 {"ISO-8859-5:1988", 28595},
786 {"ISO-8859-6:1987", 28596},
787 {"ISO-8859-7:1987", 28597},
788 {"ISO-8859-8:1988", 28598},
789 {"ISO-8859-9:1989", 28599},
790 {"ISO-8859-10:1993", 0, 96, iso_8859_10},
791 {"ISO-8859-11", 0, 96, iso_8859_11},
792 {"ISO-8859-12", 0, 96, iso_8859_12},
793 {"ISO-8859-14", 0, 96, iso_8859_14},
794 {"ISO-8859-15:1998", 0, 96, iso_8859_15},
795
796 {"KOI8-U", 0, 128, koi8_u},
797 {"KOI8-R", 20866},
798 {"HP-ROMAN8", 0, 96, roman8},
799 {"VSCII", 0, 256, vscii},
800 {"DEC-MCS", 0, 96, dec_mcs},
801
802/* All below here are aliases */
803 {"ROMAN8", 0, 96, roman8},
804 {"R8", 0, 96, roman8},
805
806 /* Note this is Latin ->> */
807 {"LATIN0", 0, 96, iso_8859_15},
808 {"L0", 0, 96, iso_8859_15},
809
810 {"CP819", 28591},
811 {"CP878", 20866},
812 {"L1", 28591},
813 {"L2", 28592},
814 {"L3", 28593},
815 {"L4", 28594},
816 {"L5", 28599},
817 {"LATIN1", 28591},
818 {"LATIN2", 28592},
819 {"LATIN3", 28593},
820 {"LATIN4", 28594},
821 {"LATIN5", 28599},
822 {0, 0}
823};
824
825static wchar_t iso_8859_10[] = {
826 0x00A0, 0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7,
827 0x013B, 0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A,
828 0x00B0, 0x0105, 0x0113, 0x0123, 0x012B, 0x0129, 0x0137, 0x00B7,
829 0x013C, 0x0111, 0x0161, 0x0167, 0x017E, 0x2014, 0x016B, 0x014B,
830 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E,
831 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x00CF,
832 0x00D0, 0x0145, 0x014C, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0168,
833 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
834 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F,
835 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x00EF,
836 0x00F0, 0x0146, 0x014D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0169,
837 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138
838};
839
840static wchar_t iso_8859_11[] = {
841 0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07,
842 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F,
843 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17,
844 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F,
845 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
846 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F,
847 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37,
848 0x0E38, 0x0E39, 0x0E3A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x0E3F,
849 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47,
850 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F,
851 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57,
852 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD
853};
854
855static wchar_t iso_8859_12[] = {
856 0x00A0, 0x201D, 0x00A2, 0x00A3, 0x00A4, 0x201E, 0x00A6, 0x00A7,
857 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6,
858 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x201C, 0x00B5, 0x00B6, 0x00B7,
859 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6,
860 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112,
861 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B,
862 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7,
863 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF,
864 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113,
865 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C,
866 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7,
867 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x2019
868};
869
870static wchar_t iso_8859_14[] = {
871 0x00A0, 0x1E02, 0x1E03, 0x00A3, 0x010A, 0x010B, 0x1E0A, 0x00A7,
872 0x1E80, 0x00A9, 0x1E82, 0x1E0B, 0x1EF2, 0x00AD, 0x00AE, 0x0178,
873 0x1E1E, 0x1E1F, 0x0120, 0x0121, 0x1E40, 0x1E41, 0x00B6, 0x1E56,
874 0x1E81, 0x1E57, 0x1E83, 0x1E60, 0x1EF3, 0x1E84, 0x1E85, 0x1E61,
875 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
876 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
877 0x0174, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x1E6A,
878 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x0176, 0x00DF,
879 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
880 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
881 0x0175, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x1E6B,
882 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x0177, 0x00FF
883};
884
885static wchar_t iso_8859_15[] = {
886 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20ac, 0x00a5, 0x0160, 0x00a7,
887 0x0161, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
888 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x017d, 0x00b5, 0x00b6, 0x00b7,
889 0x017e, 0x00b9, 0x00ba, 0x00bb, 0x0152, 0x0153, 0x0178, 0x00bf,
890 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
891 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
892 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
893 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
894 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
895 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
896 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
897 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
898};
899
900static wchar_t roman8[] = {
901 0x00A0, 0x00C0, 0x00C2, 0x00C8, 0x00CA, 0x00CB, 0x00CE, 0x00CF,
902 0x00B4, 0x02CB, 0x02C6, 0x00A8, 0x02DC, 0x00D9, 0x00DB, 0x20A4,
903 0x00AF, 0x00DD, 0x00FD, 0x00B0, 0x00C7, 0x00E7, 0x00D1, 0x00F1,
904 0x00A1, 0x00BF, 0x00A4, 0x00A3, 0x00A5, 0x00A7, 0x0192, 0x00A2,
905 0x00E2, 0x00EA, 0x00F4, 0x00FB, 0x00E1, 0x00E9, 0x00F3, 0x00FA,
906 0x00E0, 0x00E8, 0x00F2, 0x00F9, 0x00E4, 0x00EB, 0x00F6, 0x00FC,
907 0x00C5, 0x00EE, 0x00D8, 0x00C6, 0x00E5, 0x00ED, 0x00F8, 0x00E6,
908 0x00C4, 0x00EC, 0x00D6, 0x00DC, 0x00C9, 0x00EF, 0x00DF, 0x00D4,
909 0x00C1, 0x00C3, 0x00E3, 0x00D0, 0x00F0, 0x00CD, 0x00CC, 0x00D3,
910 0x00D2, 0x00D5, 0x00F5, 0x0160, 0x0161, 0x00DA, 0x0178, 0x00FF,
911 0x00DE, 0x00FE, 0x00B7, 0x00B5, 0x00B6, 0x00BE, 0x2014, 0x00BC,
912 0x00BD, 0x00AA, 0x00BA, 0x00AB, 0x25A0, 0x00BB, 0x00B1, 0xFFFD
913};
914
915static wchar_t koi8_u[] = {
916 0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,
917 0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,
918 0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2022, 0x221A, 0x2248,
919 0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7,
920 0x2550, 0x2551, 0x2552, 0x0451, 0x0454, 0x2554, 0x0456, 0x0457,
921 0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x0491, 0x255D, 0x255E,
922 0x255F, 0x2560, 0x2561, 0x0401, 0x0404, 0x2563, 0x0406, 0x0407,
923 0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x0490, 0x256C, 0x00A9,
924 0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
925 0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E,
926 0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
927 0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A,
928 0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
929 0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E,
930 0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
931 0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A
932};
933
934static wchar_t vscii[] = {
935 0x0000, 0x0001, 0x1EB2, 0x0003, 0x0004, 0x1EB4, 0x1EAA, 0x0007,
936 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
937 0x0010, 0x0011, 0x0012, 0x0013, 0x1EF6, 0x0015, 0x0016, 0x0017,
938 0x0018, 0x1EF8, 0x001a, 0x001b, 0x001c, 0x001d, 0x1EF4, 0x001f,
939 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
940 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
941 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
942 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
943 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
944 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
945 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
946 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
947 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
948 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
949 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
950 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007f,
951 0x1EA0, 0x1EAE, 0x1EB0, 0x1EB6, 0x1EA4, 0x1EA6, 0x1EA8, 0x1EAC,
952 0x1EBC, 0x1EB8, 0x1EBE, 0x1EC0, 0x1EC2, 0x1EC4, 0x1EC6, 0x1ED0,
953 0x1ED2, 0x1ED4, 0x1ED6, 0x1ED8, 0x1EE2, 0x1EDA, 0x1EDC, 0x1EDE,
954 0x1ECA, 0x1ECE, 0x1ECC, 0x1EC8, 0x1EE6, 0x0168, 0x1EE4, 0x1EF2,
955 0x00D5, 0x1EAF, 0x1EB1, 0x1EB7, 0x1EA5, 0x1EA7, 0x1EA8, 0x1EAD,
956 0x1EBD, 0x1EB9, 0x1EBF, 0x1EC1, 0x1EC3, 0x1EC5, 0x1EC7, 0x1ED1,
957 0x1ED3, 0x1ED5, 0x1ED7, 0x1EE0, 0x01A0, 0x1ED9, 0x1EDD, 0x1EDF,
958 0x1ECB, 0x1EF0, 0x1EE8, 0x1EEA, 0x1EEC, 0x01A1, 0x1EDB, 0x01AF,
959 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x1EA2, 0x0102, 0x1EB3, 0x1EB5,
960 0x00C8, 0x00C9, 0x00CA, 0x1EBA, 0x00CC, 0x00CD, 0x0128, 0x1EF3,
961 0x0110, 0x1EE9, 0x00D2, 0x00D3, 0x00D4, 0x1EA1, 0x1EF7, 0x1EEB,
962 0x1EED, 0x00D9, 0x00DA, 0x1EF9, 0x1EF5, 0x00DD, 0x1EE1, 0x01B0,
963 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x1EA3, 0x0103, 0x1EEF, 0x1EAB,
964 0x00E8, 0x00E9, 0x00EA, 0x1EBB, 0x00EC, 0x00ED, 0x0129, 0x1EC9,
965 0x0111, 0x1EF1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x1ECF, 0x1ECD,
966 0x1EE5, 0x00F9, 0x00FA, 0x0169, 0x1EE7, 0x00FD, 0x1EE3, 0x1EEE
967};
968
969static wchar_t dec_mcs[] = {
970 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0xFFFD, 0x00A5, 0xFFFD, 0x00A7,
971 0x00A4, 0x00A9, 0x00AA, 0x00AB, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
972 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0xFFFD, 0x00B5, 0x00B6, 0x00B7,
973 0xFFFD, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0xFFFD, 0x00BF,
974 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
975 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
976 0xFFFD, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0152,
977 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0178, 0xFFFD, 0x00DF,
978 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
979 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
980 0xFFFD, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0153,
981 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FF, 0xFFFD, 0xFFFD
982};