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