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