]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - unicode.c
Reorganised the Unicode layer somewhat: moved luni_send and
[PuTTY.git] / unicode.c
1 #ifdef WINDOWS
2 #include <windows.h>
3 #endif
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <ctype.h>
8 #include <time.h>
9 #include <assert.h>
10
11 #include "putty.h"
12 #include "terminal.h"
13 #include "misc.h"
14
15 /* Character conversion arrays; they are usually taken from windows,
16  * the xterm one has the four scanlines that have no unicode 2.0
17  * equivalents mapped to their unicode 3.0 locations.
18  */
19 static char **uni_tbl;
20
21 static WCHAR unitab_xterm_std[32] = {
22     0x2666, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
23     0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba,
24     0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c,
25     0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x0020
26 };
27
28 /*
29  * If the codepage is non-zero it's a window codepage, zero means use a
30  * local codepage. The name is always converted to the first of any
31  * duplicate definitions.
32  */
33
34 /* 
35  * Tables for ISO-8859-{1-9,13-16} derived from those downloaded
36  * 2001-10-02 from <http://www.unicode.org/Public/MAPPINGS/> -- jtn
37  */
38
39 /* XXX: This could be done algorithmically, but I'm not sure it's
40  *      worth the hassle -- jtn */
41 /* ISO/IEC 8859-1:1998 (Latin-1, "Western", "West European") */
42 static wchar_t iso_8859_1[] = {
43     0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
44     0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
45     0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
46     0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
47     0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
48     0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
49     0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
50     0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
51     0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
52     0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
53     0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
54     0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
55 };
56
57 /* ISO 8859-2:1999 (Latin-2, "Central European", "East European") */
58 static wchar_t iso_8859_2[] = {
59     0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7,
60     0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B,
61     0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7,
62     0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C,
63     0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
64     0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
65     0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
66     0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
67     0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
68     0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
69     0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
70     0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9
71 };
72
73 /* ISO/IEC 8859-3:1999 (Latin-3, "South European", "Maltese & Esperanto") */
74 static wchar_t iso_8859_3[] = {
75     0x00A0, 0x0126, 0x02D8, 0x00A3, 0x00A4, 0xFFFD, 0x0124, 0x00A7,
76     0x00A8, 0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, 0xFFFD, 0x017B,
77     0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7,
78     0x00B8, 0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, 0xFFFD, 0x017C,
79     0x00C0, 0x00C1, 0x00C2, 0xFFFD, 0x00C4, 0x010A, 0x0108, 0x00C7,
80     0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
81     0xFFFD, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x0120, 0x00D6, 0x00D7,
82     0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x016C, 0x015C, 0x00DF,
83     0x00E0, 0x00E1, 0x00E2, 0xFFFD, 0x00E4, 0x010B, 0x0109, 0x00E7,
84     0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
85     0xFFFD, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7,
86     0x011D, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9
87 };
88
89 /* ISO/IEC 8859-4:1998 (Latin-4, "North European") */
90 static wchar_t iso_8859_4[] = {
91     0x00A0, 0x0104, 0x0138, 0x0156, 0x00A4, 0x0128, 0x013B, 0x00A7,
92     0x00A8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00AD, 0x017D, 0x00AF,
93     0x00B0, 0x0105, 0x02DB, 0x0157, 0x00B4, 0x0129, 0x013C, 0x02C7,
94     0x00B8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014A, 0x017E, 0x014B,
95     0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E,
96     0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A,
97     0x0110, 0x0145, 0x014C, 0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
98     0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x0168, 0x016A, 0x00DF,
99     0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F,
100     0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x012B,
101     0x0111, 0x0146, 0x014D, 0x0137, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
102     0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x02D9
103 };
104
105 /* ISO 8859-5:1999 (Latin/Cyrillic) */
106 static wchar_t iso_8859_5[] = {
107     0x00A0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
108     0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00AD, 0x040E, 0x040F,
109     0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
110     0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
111     0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
112     0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
113     0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
114     0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
115     0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
116     0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
117     0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
118     0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00A7, 0x045E, 0x045F
119 };
120
121 /* ISO 8859-6:1999 (Latin/Arabic) */
122 static wchar_t iso_8859_6[] = {
123     0x00A0, 0xFFFD, 0xFFFD, 0xFFFD, 0x00A4, 0xFFFD, 0xFFFD, 0xFFFD,
124     0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x060C, 0x00AD, 0xFFFD, 0xFFFD,
125     0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
126     0xFFFD, 0xFFFD, 0xFFFD, 0x061B, 0xFFFD, 0xFFFD, 0xFFFD, 0x061F,
127     0xFFFD, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
128     0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,
129     0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637,
130     0x0638, 0x0639, 0x063A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
131     0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647,
132     0x0648, 0x0649, 0x064A, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F,
133     0x0650, 0x0651, 0x0652, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
134     0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD
135 };
136
137 /* ISO 8859-7:1987 (Latin/Greek) */
138 static wchar_t iso_8859_7[] = {
139     0x00A0, 0x2018, 0x2019, 0x00A3, 0xFFFD, 0xFFFD, 0x00A6, 0x00A7,
140     0x00A8, 0x00A9, 0xFFFD, 0x00AB, 0x00AC, 0x00AD, 0xFFFD, 0x2015,
141     0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x0385, 0x0386, 0x00B7,
142     0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F,
143     0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
144     0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
145     0x03A0, 0x03A1, 0xFFFD, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
146     0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
147     0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
148     0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
149     0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
150     0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0xFFFD
151 };
152
153 /* ISO/IEC 8859-8:1999 (Latin/Hebrew) */
154 static wchar_t iso_8859_8[] = {
155     0x00A0, 0xFFFD, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
156     0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
157     0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
158     0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0xFFFD,
159     0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
160     0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
161     0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
162     0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x2017,
163     0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
164     0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
165     0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
166     0x05E8, 0x05E9, 0x05EA, 0xFFFD, 0xFFFD, 0x200E, 0x200F, 0xFFFD
167 };
168
169 /* ISO/IEC 8859-9:1999 (Latin-5, "Turkish") */
170 static wchar_t iso_8859_9[] = {
171     0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
172     0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
173     0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
174     0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
175     0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
176     0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
177     0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
178     0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF,
179     0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
180     0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
181     0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
182     0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF
183 };
184
185 /* ISO 8859-10:1993? (Latin-6, "Nordic" [Sami, Inuit, Icelandic]) */
186 /* Translation table from RDB. unicode.org (ISO/IEC 8859-10:1998) has
187  * U+2015 (HORIZONTAL BAR) at codepoint 0xBD instead
188  * (U+2014 is EM DASH). -- jtn */
189 static wchar_t iso_8859_10[] = {
190     0x00A0, 0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7,
191     0x013B, 0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A,
192     0x00B0, 0x0105, 0x0113, 0x0123, 0x012B, 0x0129, 0x0137, 0x00B7,
193     0x013C, 0x0111, 0x0161, 0x0167, 0x017E, 0x2014, 0x016B, 0x014B,
194     0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E,
195     0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x00CF,
196     0x00D0, 0x0145, 0x014C, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0168,
197     0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
198     0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F,
199     0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x00EF,
200     0x00F0, 0x0146, 0x014D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0169,
201     0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138
202 };
203
204 /* "ISO 8859-11:1997" ("Thai", "TIS620") */
205 /* From RDB -- ISO and unicode.org disclaim all knowledge of this one.
206  * Maybe still in draft. --jtn */
207 static wchar_t iso_8859_11[] = {
208     0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07,
209     0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F,
210     0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17,
211     0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F,
212     0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
213     0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F,
214     0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37,
215     0x0E38, 0x0E39, 0x0E3A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x0E3F,
216     0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47,
217     0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F,
218     0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57,
219     0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD
220 };
221
222 /* ISO/IEC 8859-13:1998 (Latin-7, "Baltic Rim") */
223 static wchar_t iso_8859_13[] = {
224     0x00A0, 0x201D, 0x00A2, 0x00A3, 0x00A4, 0x201E, 0x00A6, 0x00A7,
225     0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6,
226     0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x201C, 0x00B5, 0x00B6, 0x00B7,
227     0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6,
228     0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112,
229     0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B,
230     0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7,
231     0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF,
232     0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113,
233     0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C,
234     0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7,
235     0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x2019
236 };
237
238 /* ISO/IEC 8859-14:1998 (Latin-8, "Celtic", "Gaelic/Welsh") */
239 static wchar_t iso_8859_14[] = {
240     0x00A0, 0x1E02, 0x1E03, 0x00A3, 0x010A, 0x010B, 0x1E0A, 0x00A7,
241     0x1E80, 0x00A9, 0x1E82, 0x1E0B, 0x1EF2, 0x00AD, 0x00AE, 0x0178,
242     0x1E1E, 0x1E1F, 0x0120, 0x0121, 0x1E40, 0x1E41, 0x00B6, 0x1E56,
243     0x1E81, 0x1E57, 0x1E83, 0x1E60, 0x1EF3, 0x1E84, 0x1E85, 0x1E61,
244     0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
245     0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
246     0x0174, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x1E6A,
247     0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x0176, 0x00DF,
248     0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
249     0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
250     0x0175, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x1E6B,
251     0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x0177, 0x00FF
252 };
253
254 /* ISO/IEC 8859-15:1999 (Latin-9 aka -0, "euro") */
255 static wchar_t iso_8859_15[] = {
256     0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AC, 0x00A5, 0x0160, 0x00A7,
257     0x0161, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
258     0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x017D, 0x00B5, 0x00B6, 0x00B7,
259     0x017E, 0x00B9, 0x00BA, 0x00BB, 0x0152, 0x0153, 0x0178, 0x00BF,
260     0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
261     0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
262     0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
263     0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
264     0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
265     0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
266     0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
267     0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
268 };
269
270 /* ISO/IEC 8859-16:2001 (Latin-10, "Balkan") */
271 static wchar_t iso_8859_16[] = {
272     0x00A0, 0x0104, 0x0105, 0x0141, 0x20AC, 0x201E, 0x0160, 0x00A7,
273     0x0161, 0x00A9, 0x0218, 0x00AB, 0x0179, 0x00AD, 0x017A, 0x017B,
274     0x00B0, 0x00B1, 0x010C, 0x0142, 0x017D, 0x201D, 0x00B6, 0x00B7,
275     0x017E, 0x010D, 0x0219, 0x00BB, 0x0152, 0x0153, 0x0178, 0x017C,
276     0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0106, 0x00C6, 0x00C7,
277     0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
278     0x0110, 0x0143, 0x00D2, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x015A,
279     0x0170, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0118, 0x021A, 0x00DF,
280     0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x0107, 0x00E6, 0x00E7,
281     0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
282     0x0111, 0x0144, 0x00F2, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x015B,
283     0x0171, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0119, 0x021B, 0x00FF
284 };
285
286 static wchar_t roman8[] = {
287     0x00A0, 0x00C0, 0x00C2, 0x00C8, 0x00CA, 0x00CB, 0x00CE, 0x00CF,
288     0x00B4, 0x02CB, 0x02C6, 0x00A8, 0x02DC, 0x00D9, 0x00DB, 0x20A4,
289     0x00AF, 0x00DD, 0x00FD, 0x00B0, 0x00C7, 0x00E7, 0x00D1, 0x00F1,
290     0x00A1, 0x00BF, 0x00A4, 0x00A3, 0x00A5, 0x00A7, 0x0192, 0x00A2,
291     0x00E2, 0x00EA, 0x00F4, 0x00FB, 0x00E1, 0x00E9, 0x00F3, 0x00FA,
292     0x00E0, 0x00E8, 0x00F2, 0x00F9, 0x00E4, 0x00EB, 0x00F6, 0x00FC,
293     0x00C5, 0x00EE, 0x00D8, 0x00C6, 0x00E5, 0x00ED, 0x00F8, 0x00E6,
294     0x00C4, 0x00EC, 0x00D6, 0x00DC, 0x00C9, 0x00EF, 0x00DF, 0x00D4,
295     0x00C1, 0x00C3, 0x00E3, 0x00D0, 0x00F0, 0x00CD, 0x00CC, 0x00D3,
296     0x00D2, 0x00D5, 0x00F5, 0x0160, 0x0161, 0x00DA, 0x0178, 0x00FF,
297     0x00DE, 0x00FE, 0x00B7, 0x00B5, 0x00B6, 0x00BE, 0x2014, 0x00BC,
298     0x00BD, 0x00AA, 0x00BA, 0x00AB, 0x25A0, 0x00BB, 0x00B1, 0xFFFD
299 };
300
301 static wchar_t koi8_u[] = {
302     0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,
303     0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,
304     0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2022, 0x221A, 0x2248,
305     0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7,
306     0x2550, 0x2551, 0x2552, 0x0451, 0x0454, 0x2554, 0x0456, 0x0457,
307     0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x0491, 0x255D, 0x255E,
308     0x255F, 0x2560, 0x2561, 0x0401, 0x0404, 0x2563, 0x0406, 0x0407,
309     0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x0490, 0x256C, 0x00A9,
310     0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
311     0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E,
312     0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
313     0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A,
314     0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
315     0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E,
316     0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
317     0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A
318 };
319
320 static wchar_t vscii[] = {
321     0x0000, 0x0001, 0x1EB2, 0x0003, 0x0004, 0x1EB4, 0x1EAA, 0x0007,
322     0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
323     0x0010, 0x0011, 0x0012, 0x0013, 0x1EF6, 0x0015, 0x0016, 0x0017,
324     0x0018, 0x1EF8, 0x001a, 0x001b, 0x001c, 0x001d, 0x1EF4, 0x001f,
325     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
326     0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
327     0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
328     0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
329     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
330     0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
331     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
332     0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
333     0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
334     0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
335     0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
336     0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007f,
337     0x1EA0, 0x1EAE, 0x1EB0, 0x1EB6, 0x1EA4, 0x1EA6, 0x1EA8, 0x1EAC,
338     0x1EBC, 0x1EB8, 0x1EBE, 0x1EC0, 0x1EC2, 0x1EC4, 0x1EC6, 0x1ED0,
339     0x1ED2, 0x1ED4, 0x1ED6, 0x1ED8, 0x1EE2, 0x1EDA, 0x1EDC, 0x1EDE,
340     0x1ECA, 0x1ECE, 0x1ECC, 0x1EC8, 0x1EE6, 0x0168, 0x1EE4, 0x1EF2,
341     0x00D5, 0x1EAF, 0x1EB1, 0x1EB7, 0x1EA5, 0x1EA7, 0x1EA8, 0x1EAD,
342     0x1EBD, 0x1EB9, 0x1EBF, 0x1EC1, 0x1EC3, 0x1EC5, 0x1EC7, 0x1ED1,
343     0x1ED3, 0x1ED5, 0x1ED7, 0x1EE0, 0x01A0, 0x1ED9, 0x1EDD, 0x1EDF,
344     0x1ECB, 0x1EF0, 0x1EE8, 0x1EEA, 0x1EEC, 0x01A1, 0x1EDB, 0x01AF,
345     0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x1EA2, 0x0102, 0x1EB3, 0x1EB5,
346     0x00C8, 0x00C9, 0x00CA, 0x1EBA, 0x00CC, 0x00CD, 0x0128, 0x1EF3,
347     0x0110, 0x1EE9, 0x00D2, 0x00D3, 0x00D4, 0x1EA1, 0x1EF7, 0x1EEB,
348     0x1EED, 0x00D9, 0x00DA, 0x1EF9, 0x1EF5, 0x00DD, 0x1EE1, 0x01B0,
349     0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x1EA3, 0x0103, 0x1EEF, 0x1EAB,
350     0x00E8, 0x00E9, 0x00EA, 0x1EBB, 0x00EC, 0x00ED, 0x0129, 0x1EC9,
351     0x0111, 0x1EF1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x1ECF, 0x1ECD,
352     0x1EE5, 0x00F9, 0x00FA, 0x0169, 0x1EE7, 0x00FD, 0x1EE3, 0x1EEE
353 };
354
355 static wchar_t dec_mcs[] = {
356     0x00A0, 0x00A1, 0x00A2, 0x00A3, 0xFFFD, 0x00A5, 0xFFFD, 0x00A7,
357     0x00A4, 0x00A9, 0x00AA, 0x00AB, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
358     0x00B0, 0x00B1, 0x00B2, 0x00B3, 0xFFFD, 0x00B5, 0x00B6, 0x00B7,
359     0xFFFD, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0xFFFD, 0x00BF,
360     0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
361     0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
362     0xFFFD, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0152,
363     0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0178, 0xFFFD, 0x00DF,
364     0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
365     0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
366     0xFFFD, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0153,
367     0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FF, 0xFFFD, 0xFFFD
368 };
369
370 struct cp_list_item {
371     char *name;
372     int codepage;
373     int cp_size;
374     wchar_t *cp_table;
375 };
376
377 static struct cp_list_item cp_list[] = {
378     {"ISO-8859-1:1998 (Latin-1, West Europe)", 0, 96, iso_8859_1},
379     {"ISO-8859-2:1999 (Latin-2, East Europe)", 0, 96, iso_8859_2},
380     {"ISO-8859-3:1999 (Latin-3, South Europe)", 0, 96, iso_8859_3},
381     {"ISO-8859-4:1998 (Latin-4, North Europe)", 0, 96, iso_8859_4},
382     {"ISO-8859-5:1999 (Latin/Cyrillic)", 0, 96, iso_8859_5},
383     {"ISO-8859-6:1999 (Latin/Arabic)", 0, 96, iso_8859_6},
384     {"ISO-8859-7:1987 (Latin/Greek)", 0, 96, iso_8859_7},
385     {"ISO-8859-8:1999 (Latin/Hebrew)", 0, 96, iso_8859_8},
386     {"ISO-8859-9:1999 (Latin-5, Turkish)", 0, 96, iso_8859_9},
387     {"ISO-8859-10:1993 (Latin-6, Nordic)", 0, 96, iso_8859_10},
388     {"ISO-8859-11:1997 (Latin/Thai)", 0, 96, iso_8859_11},
389     {"ISO-8859-13:1998 (Latin-7, Baltic)", 0, 96, iso_8859_13},
390     {"ISO-8859-14:1998 (Latin-8, Celtic)", 0, 96, iso_8859_14},
391     {"ISO-8859-15:1999 (Latin-9, \"euro\")", 0, 96, iso_8859_15},
392     {"ISO-8859-16:2001 (Latin-10, Balkan)", 0, 96, iso_8859_16},
393
394     {"UTF-8", CP_UTF8},
395
396     {"KOI8-U", 0, 128, koi8_u},
397     {"KOI8-R", 20866},
398     {"HP-ROMAN8", 0, 96, roman8},
399     {"VSCII", 0, 256, vscii},
400     {"DEC-MCS", 0, 96, dec_mcs},
401
402     {"Win1250 (Central European)", 1250},
403     {"Win1251 (Cyrillic)", 1251},
404     {"Win1252 (Western)", 1252},
405     {"Win1253 (Greek)", 1253},
406     {"Win1254 (Turkish)", 1254},
407     {"Win1255 (Hebrew)", 1255},
408     {"Win1256 (Arabic)", 1256},
409     {"Win1257 (Baltic)", 1257},
410     {"Win1258 (Vietnamese)", 1258},
411
412     {"CP437", 437},
413     {"CP819", 28591},
414     {"CP878", 20866},
415
416     {"Use font encoding", -1},
417
418     {0, 0}
419 };
420
421 static void link_font(WCHAR * line_tbl, WCHAR * font_tbl, WCHAR attr);
422
423 void init_ucs(void)
424 {
425     int i, j;
426     int used_dtf = 0;
427     char tbuf[256];
428
429     for (i = 0; i < 256; i++)
430         tbuf[i] = i;
431
432     /* Decide on the Line and Font codepages */
433     line_codepage = decode_codepage(cfg.line_codepage);
434
435     if (font_codepage <= 0) { 
436         font_codepage=0; 
437         dbcs_screenfont=0; 
438     }
439
440     if (cfg.vtmode == VT_OEMONLY) {
441         font_codepage = 437;
442         dbcs_screenfont = 0;
443         if (line_codepage <= 0)
444             line_codepage = GetACP();
445     } else if (line_codepage <= 0)
446         line_codepage = font_codepage;
447
448     /* Collect screen font ucs table */
449     if (dbcs_screenfont || font_codepage == 0) {
450         get_unitab(font_codepage, unitab_font, 2);
451         for (i = 128; i < 256; i++)
452             unitab_font[i] = (WCHAR) (ATTR_ACP + i);
453     } else {
454         get_unitab(font_codepage, unitab_font, 1);
455
456         /* CP437 fonts are often broken ... */
457         if (font_codepage == 437)
458             unitab_font[0] = unitab_font[255] = 0xFFFF;
459     }
460     if (cfg.vtmode == VT_XWINDOWS)
461         memcpy(unitab_font + 1, unitab_xterm_std,
462                sizeof(unitab_xterm_std));
463
464     /* Collect OEMCP ucs table */
465     get_unitab(CP_OEMCP, unitab_oemcp, 1);
466
467     /* Collect CP437 ucs table for SCO acs */
468     if (cfg.vtmode == VT_OEMANSI || cfg.vtmode == VT_XWINDOWS)
469         memcpy(unitab_scoacs, unitab_oemcp, sizeof(unitab_scoacs));
470     else
471         get_unitab(437, unitab_scoacs, 1);
472
473     /* Collect line set ucs table */
474     if (line_codepage == font_codepage &&
475         (dbcs_screenfont || cfg.vtmode == VT_POORMAN || font_codepage==0)) {
476
477         /* For DBCS and POOR fonts force direct to font */
478         used_dtf = 1;
479         for (i = 0; i < 32; i++)
480             unitab_line[i] = (WCHAR) i;
481         for (i = 32; i < 256; i++)
482             unitab_line[i] = (WCHAR) (ATTR_ACP + i);
483         unitab_line[127] = (WCHAR) 127;
484     } else {
485         get_unitab(line_codepage, unitab_line, 0);
486     }
487
488 #if 0
489     debug(
490           ("Line cp%d, Font cp%d%s\n", line_codepage, font_codepage,
491            dbcs_screenfont ? " DBCS" : ""));
492
493     for (i = 0; i < 256; i += 16) {
494         for (j = 0; j < 16; j++) {
495             debug(("%04x%s", unitab_line[i + j], j == 15 ? "" : ","));
496         }
497         debug(("\n"));
498     }
499 #endif
500
501     /* VT100 graphics - NB: Broken for non-ascii CP's */
502     memcpy(unitab_xterm, unitab_line, sizeof(unitab_xterm));
503     memcpy(unitab_xterm + '`', unitab_xterm_std, sizeof(unitab_xterm_std));
504     unitab_xterm['_'] = ' ';
505
506     /* Generate UCS ->line page table. */
507     if (uni_tbl) {
508         for (i = 0; i < 256; i++)
509             if (uni_tbl[i])
510                 sfree(uni_tbl[i]);
511         sfree(uni_tbl);
512         uni_tbl = 0;
513     }
514     if (!used_dtf) {
515         for (i = 0; i < 256; i++) {
516             if (DIRECT_CHAR(unitab_line[i]))
517                 continue;
518             if (DIRECT_FONT(unitab_line[i]))
519                 continue;
520             if (!uni_tbl) {
521                 uni_tbl = smalloc(256 * sizeof(char *));
522                 memset(uni_tbl, 0, 256 * sizeof(char *));
523             }
524             j = ((unitab_line[i] >> 8) & 0xFF);
525             if (!uni_tbl[j]) {
526                 uni_tbl[j] = smalloc(256 * sizeof(char));
527                 memset(uni_tbl[j], 0, 256 * sizeof(char));
528             }
529             uni_tbl[j][unitab_line[i] & 0xFF] = i;
530         }
531     }
532
533     /* Find the line control characters. */
534     for (i = 0; i < 256; i++)
535         if (unitab_line[i] < ' '
536             || (unitab_line[i] >= 0x7F && unitab_line[i] < 0xA0))
537             unitab_ctrl[i] = i;
538         else
539             unitab_ctrl[i] = 0xFF;
540
541     /* Generate line->screen direct conversion links. */
542     if (cfg.vtmode == VT_OEMANSI || cfg.vtmode == VT_XWINDOWS)
543         link_font(unitab_scoacs, unitab_oemcp, ATTR_OEMCP);
544
545     link_font(unitab_line, unitab_font, ATTR_ACP);
546     link_font(unitab_scoacs, unitab_font, ATTR_ACP);
547     link_font(unitab_xterm, unitab_font, ATTR_ACP);
548
549     if (cfg.vtmode == VT_OEMANSI || cfg.vtmode == VT_XWINDOWS) {
550         link_font(unitab_line, unitab_oemcp, ATTR_OEMCP);
551         link_font(unitab_xterm, unitab_oemcp, ATTR_OEMCP);
552     }
553
554     if (dbcs_screenfont && font_codepage != line_codepage) {
555         /* F***ing Microsoft fonts, Japanese and Korean codepage fonts
556          * have a currency symbol at 0x5C but their unicode value is 
557          * still given as U+005C not the correct U+00A5. */
558         unitab_line['\\'] = ATTR_OEMCP + '\\';
559     }
560
561     /* Last chance, if !unicode then try poorman links. */
562     if (cfg.vtmode != VT_UNICODE) {
563         static char poorman_scoacs[] = 
564             "CueaaaaceeeiiiAAE**ooouuyOUc$YPsaiounNao?++**!<>###||||++||++++++--|-+||++--|-+----++++++++##||#aBTPEsyt******EN=+><++-=... n2* ";
565         static char poorman_latin1[] =
566             " !cL.Y|S\"Ca<--R~o+23'u|.,1o>///?AAAAAAACEEEEIIIIDNOOOOOxOUUUUYPBaaaaaaaceeeeiiiionooooo/ouuuuypy";
567         static char poorman_vt100[] = "*#****o~**+++++-----++++|****L.";
568
569         for (i = 160; i < 256; i++)
570             if (!DIRECT_FONT(unitab_line[i]) &&
571                 unitab_line[i] >= 160 && unitab_line[i] < 256)
572                 unitab_line[i] = (WCHAR) (ATTR_ACP
573                                           + poorman_latin1[unitab_line[i] -
574                                                            160]);
575         for (i = 96; i < 127; i++)
576             if (!DIRECT_FONT(unitab_xterm[i]))
577                 unitab_xterm[i] =
578                     (WCHAR) (ATTR_ACP + poorman_vt100[i - 96]);
579         for(i=128;i<256;i++) 
580             if (!DIRECT_FONT(unitab_scoacs[i]))
581                 unitab_scoacs[i] = 
582                     (WCHAR) (ATTR_ACP + poorman_scoacs[i - 128]);
583     }
584 }
585
586 static void link_font(WCHAR * line_tbl, WCHAR * font_tbl, WCHAR attr)
587 {
588     int font_index, line_index, i;
589     for (line_index = 0; line_index < 256; line_index++) {
590         if (DIRECT_FONT(line_tbl[line_index]))
591             continue;
592         for(i = 0; i < 256; i++) {
593             font_index = ((32 + i) & 0xFF);
594             if (line_tbl[line_index] == font_tbl[font_index]) {
595                 line_tbl[line_index] = (WCHAR) (attr + font_index);
596                 break;
597             }
598         }
599     }
600 }
601
602 wchar_t xlat_uskbd2cyrllic(int ch)
603 {
604     static wchar_t cyrtab[] = {
605             0,      1,       2,      3,      4,      5,      6,      7,
606             8,      9,      10,     11,     12,     13,     14,     15,
607             16,     17,     18,     19,     20,     21,     22,     23,
608             24,     25,     26,     27,     28,     29,     30,     31,
609             32,     33, 0x042d,     35,     36,     37,     38, 0x044d,
610             40,     41,     42, 0x0406, 0x0431, 0x0454, 0x044e, 0x002e,
611             48,     49,     50,     51,     52,     53,     54,     55,
612             56,     57, 0x0416, 0x0436, 0x0411, 0x0456, 0x042e, 0x002c,
613             64, 0x0424, 0x0418, 0x0421, 0x0412, 0x0423, 0x0410, 0x041f,
614         0x0420, 0x0428, 0x041e, 0x041b, 0x0414, 0x042c, 0x0422, 0x0429,
615         0x0417, 0x0419, 0x041a, 0x042b, 0x0415, 0x0413, 0x041c, 0x0426,
616         0x0427, 0x041d, 0x042f, 0x0445, 0x0457, 0x044a,     94, 0x0404,
617             96, 0x0444, 0x0438, 0x0441, 0x0432, 0x0443, 0x0430, 0x043f,
618         0x0440, 0x0448, 0x043e, 0x043b, 0x0434, 0x044c, 0x0442, 0x0449,
619         0x0437, 0x0439, 0x043a, 0x044b, 0x0435, 0x0433, 0x043c, 0x0446,
620         0x0447, 0x043d, 0x044f, 0x0425, 0x0407, 0x042a,    126,    127
621        };
622     return cyrtab[ch&0x7F];
623 }
624
625 int check_compose(int first, int second)
626 {
627
628     static struct {
629         char first, second;
630         wchar_t composed;
631     } composetbl[] = {
632         {
633         0x2b, 0x2b, 0x0023}, {
634         0x41, 0x41, 0x0040}, {
635         0x28, 0x28, 0x005b}, {
636         0x2f, 0x2f, 0x005c}, {
637         0x29, 0x29, 0x005d}, {
638         0x28, 0x2d, 0x007b}, {
639         0x2d, 0x29, 0x007d}, {
640         0x2f, 0x5e, 0x007c}, {
641         0x21, 0x21, 0x00a1}, {
642         0x43, 0x2f, 0x00a2}, {
643         0x43, 0x7c, 0x00a2}, {
644         0x4c, 0x2d, 0x00a3}, {
645         0x4c, 0x3d, 0x20a4}, {
646         0x58, 0x4f, 0x00a4}, {
647         0x58, 0x30, 0x00a4}, {
648         0x59, 0x2d, 0x00a5}, {
649         0x59, 0x3d, 0x00a5}, {
650         0x7c, 0x7c, 0x00a6}, {
651         0x53, 0x4f, 0x00a7}, {
652         0x53, 0x21, 0x00a7}, {
653         0x53, 0x30, 0x00a7}, {
654         0x22, 0x22, 0x00a8}, {
655         0x43, 0x4f, 0x00a9}, {
656         0x43, 0x30, 0x00a9}, {
657         0x41, 0x5f, 0x00aa}, {
658         0x3c, 0x3c, 0x00ab}, {
659         0x2c, 0x2d, 0x00ac}, {
660         0x2d, 0x2d, 0x00ad}, {
661         0x52, 0x4f, 0x00ae}, {
662         0x2d, 0x5e, 0x00af}, {
663         0x30, 0x5e, 0x00b0}, {
664         0x2b, 0x2d, 0x00b1}, {
665         0x32, 0x5e, 0x00b2}, {
666         0x33, 0x5e, 0x00b3}, {
667         0x27, 0x27, 0x00b4}, {
668         0x2f, 0x55, 0x00b5}, {
669         0x50, 0x21, 0x00b6}, {
670         0x2e, 0x5e, 0x00b7}, {
671         0x2c, 0x2c, 0x00b8}, {
672         0x31, 0x5e, 0x00b9}, {
673         0x4f, 0x5f, 0x00ba}, {
674         0x3e, 0x3e, 0x00bb}, {
675         0x31, 0x34, 0x00bc}, {
676         0x31, 0x32, 0x00bd}, {
677         0x33, 0x34, 0x00be}, {
678         0x3f, 0x3f, 0x00bf}, {
679         0x60, 0x41, 0x00c0}, {
680         0x27, 0x41, 0x00c1}, {
681         0x5e, 0x41, 0x00c2}, {
682         0x7e, 0x41, 0x00c3}, {
683         0x22, 0x41, 0x00c4}, {
684         0x2a, 0x41, 0x00c5}, {
685         0x41, 0x45, 0x00c6}, {
686         0x2c, 0x43, 0x00c7}, {
687         0x60, 0x45, 0x00c8}, {
688         0x27, 0x45, 0x00c9}, {
689         0x5e, 0x45, 0x00ca}, {
690         0x22, 0x45, 0x00cb}, {
691         0x60, 0x49, 0x00cc}, {
692         0x27, 0x49, 0x00cd}, {
693         0x5e, 0x49, 0x00ce}, {
694         0x22, 0x49, 0x00cf}, {
695         0x2d, 0x44, 0x00d0}, {
696         0x7e, 0x4e, 0x00d1}, {
697         0x60, 0x4f, 0x00d2}, {
698         0x27, 0x4f, 0x00d3}, {
699         0x5e, 0x4f, 0x00d4}, {
700         0x7e, 0x4f, 0x00d5}, {
701         0x22, 0x4f, 0x00d6}, {
702         0x58, 0x58, 0x00d7}, {
703         0x2f, 0x4f, 0x00d8}, {
704         0x60, 0x55, 0x00d9}, {
705         0x27, 0x55, 0x00da}, {
706         0x5e, 0x55, 0x00db}, {
707         0x22, 0x55, 0x00dc}, {
708         0x27, 0x59, 0x00dd}, {
709         0x48, 0x54, 0x00de}, {
710         0x73, 0x73, 0x00df}, {
711         0x60, 0x61, 0x00e0}, {
712         0x27, 0x61, 0x00e1}, {
713         0x5e, 0x61, 0x00e2}, {
714         0x7e, 0x61, 0x00e3}, {
715         0x22, 0x61, 0x00e4}, {
716         0x2a, 0x61, 0x00e5}, {
717         0x61, 0x65, 0x00e6}, {
718         0x2c, 0x63, 0x00e7}, {
719         0x60, 0x65, 0x00e8}, {
720         0x27, 0x65, 0x00e9}, {
721         0x5e, 0x65, 0x00ea}, {
722         0x22, 0x65, 0x00eb}, {
723         0x60, 0x69, 0x00ec}, {
724         0x27, 0x69, 0x00ed}, {
725         0x5e, 0x69, 0x00ee}, {
726         0x22, 0x69, 0x00ef}, {
727         0x2d, 0x64, 0x00f0}, {
728         0x7e, 0x6e, 0x00f1}, {
729         0x60, 0x6f, 0x00f2}, {
730         0x27, 0x6f, 0x00f3}, {
731         0x5e, 0x6f, 0x00f4}, {
732         0x7e, 0x6f, 0x00f5}, {
733         0x22, 0x6f, 0x00f6}, {
734         0x3a, 0x2d, 0x00f7}, {
735         0x6f, 0x2f, 0x00f8}, {
736         0x60, 0x75, 0x00f9}, {
737         0x27, 0x75, 0x00fa}, {
738         0x5e, 0x75, 0x00fb}, {
739         0x22, 0x75, 0x00fc}, {
740         0x27, 0x79, 0x00fd}, {
741         0x68, 0x74, 0x00fe}, {
742         0x22, 0x79, 0x00ff},
743             /* Unicode extras. */
744         {
745         0x6f, 0x65, 0x0153}, {
746         0x4f, 0x45, 0x0152},
747             /* Compose pairs from UCS */
748         {
749         0x41, 0x2D, 0x0100}, {
750         0x61, 0x2D, 0x0101}, {
751         0x43, 0x27, 0x0106}, {
752         0x63, 0x27, 0x0107}, {
753         0x43, 0x5E, 0x0108}, {
754         0x63, 0x5E, 0x0109}, {
755         0x45, 0x2D, 0x0112}, {
756         0x65, 0x2D, 0x0113}, {
757         0x47, 0x5E, 0x011C}, {
758         0x67, 0x5E, 0x011D}, {
759         0x47, 0x2C, 0x0122}, {
760         0x67, 0x2C, 0x0123}, {
761         0x48, 0x5E, 0x0124}, {
762         0x68, 0x5E, 0x0125}, {
763         0x49, 0x7E, 0x0128}, {
764         0x69, 0x7E, 0x0129}, {
765         0x49, 0x2D, 0x012A}, {
766         0x69, 0x2D, 0x012B}, {
767         0x4A, 0x5E, 0x0134}, {
768         0x6A, 0x5E, 0x0135}, {
769         0x4B, 0x2C, 0x0136}, {
770         0x6B, 0x2C, 0x0137}, {
771         0x4C, 0x27, 0x0139}, {
772         0x6C, 0x27, 0x013A}, {
773         0x4C, 0x2C, 0x013B}, {
774         0x6C, 0x2C, 0x013C}, {
775         0x4E, 0x27, 0x0143}, {
776         0x6E, 0x27, 0x0144}, {
777         0x4E, 0x2C, 0x0145}, {
778         0x6E, 0x2C, 0x0146}, {
779         0x4F, 0x2D, 0x014C}, {
780         0x6F, 0x2D, 0x014D}, {
781         0x52, 0x27, 0x0154}, {
782         0x72, 0x27, 0x0155}, {
783         0x52, 0x2C, 0x0156}, {
784         0x72, 0x2C, 0x0157}, {
785         0x53, 0x27, 0x015A}, {
786         0x73, 0x27, 0x015B}, {
787         0x53, 0x5E, 0x015C}, {
788         0x73, 0x5E, 0x015D}, {
789         0x53, 0x2C, 0x015E}, {
790         0x73, 0x2C, 0x015F}, {
791         0x54, 0x2C, 0x0162}, {
792         0x74, 0x2C, 0x0163}, {
793         0x55, 0x7E, 0x0168}, {
794         0x75, 0x7E, 0x0169}, {
795         0x55, 0x2D, 0x016A}, {
796         0x75, 0x2D, 0x016B}, {
797         0x55, 0x2A, 0x016E}, {
798         0x75, 0x2A, 0x016F}, {
799         0x57, 0x5E, 0x0174}, {
800         0x77, 0x5E, 0x0175}, {
801         0x59, 0x5E, 0x0176}, {
802         0x79, 0x5E, 0x0177}, {
803         0x59, 0x22, 0x0178}, {
804         0x5A, 0x27, 0x0179}, {
805         0x7A, 0x27, 0x017A}, {
806         0x47, 0x27, 0x01F4}, {
807         0x67, 0x27, 0x01F5}, {
808         0x4E, 0x60, 0x01F8}, {
809         0x6E, 0x60, 0x01F9}, {
810         0x45, 0x2C, 0x0228}, {
811         0x65, 0x2C, 0x0229}, {
812         0x59, 0x2D, 0x0232}, {
813         0x79, 0x2D, 0x0233}, {
814         0x44, 0x2C, 0x1E10}, {
815         0x64, 0x2C, 0x1E11}, {
816         0x47, 0x2D, 0x1E20}, {
817         0x67, 0x2D, 0x1E21}, {
818         0x48, 0x22, 0x1E26}, {
819         0x68, 0x22, 0x1E27}, {
820         0x48, 0x2C, 0x1E28}, {
821         0x68, 0x2C, 0x1E29}, {
822         0x4B, 0x27, 0x1E30}, {
823         0x6B, 0x27, 0x1E31}, {
824         0x4D, 0x27, 0x1E3E}, {
825         0x6D, 0x27, 0x1E3F}, {
826         0x50, 0x27, 0x1E54}, {
827         0x70, 0x27, 0x1E55}, {
828         0x56, 0x7E, 0x1E7C}, {
829         0x76, 0x7E, 0x1E7D}, {
830         0x57, 0x60, 0x1E80}, {
831         0x77, 0x60, 0x1E81}, {
832         0x57, 0x27, 0x1E82}, {
833         0x77, 0x27, 0x1E83}, {
834         0x57, 0x22, 0x1E84}, {
835         0x77, 0x22, 0x1E85}, {
836         0x58, 0x22, 0x1E8C}, {
837         0x78, 0x22, 0x1E8D}, {
838         0x5A, 0x5E, 0x1E90}, {
839         0x7A, 0x5E, 0x1E91}, {
840         0x74, 0x22, 0x1E97}, {
841         0x77, 0x2A, 0x1E98}, {
842         0x79, 0x2A, 0x1E99}, {
843         0x45, 0x7E, 0x1EBC}, {
844         0x65, 0x7E, 0x1EBD}, {
845         0x59, 0x60, 0x1EF2}, {
846         0x79, 0x60, 0x1EF3}, {
847         0x59, 0x7E, 0x1EF8}, {
848         0x79, 0x7E, 0x1EF9},
849             /* Compatible/possibles from UCS */
850         {
851         0x49, 0x4A, 0x0132}, {
852         0x69, 0x6A, 0x0133}, {
853         0x4C, 0x4A, 0x01C7}, {
854         0x4C, 0x6A, 0x01C8}, {
855         0x6C, 0x6A, 0x01C9}, {
856         0x4E, 0x4A, 0x01CA}, {
857         0x4E, 0x6A, 0x01CB}, {
858         0x6E, 0x6A, 0x01CC}, {
859         0x44, 0x5A, 0x01F1}, {
860         0x44, 0x7A, 0x01F2}, {
861         0x64, 0x7A, 0x01F3}, {
862         0x2E, 0x2E, 0x2025}, {
863         0x21, 0x21, 0x203C}, {
864         0x3F, 0x21, 0x2048}, {
865         0x21, 0x3F, 0x2049}, {
866         0x52, 0x73, 0x20A8}, {
867         0x4E, 0x6F, 0x2116}, {
868         0x53, 0x4D, 0x2120}, {
869         0x54, 0x4D, 0x2122}, {
870         0x49, 0x49, 0x2161}, {
871         0x49, 0x56, 0x2163}, {
872         0x56, 0x49, 0x2165}, {
873         0x49, 0x58, 0x2168}, {
874         0x58, 0x49, 0x216A}, {
875         0x69, 0x69, 0x2171}, {
876         0x69, 0x76, 0x2173}, {
877         0x76, 0x69, 0x2175}, {
878         0x69, 0x78, 0x2178}, {
879         0x78, 0x69, 0x217A}, {
880         0x31, 0x30, 0x2469}, {
881         0x31, 0x31, 0x246A}, {
882         0x31, 0x32, 0x246B}, {
883         0x31, 0x33, 0x246C}, {
884         0x31, 0x34, 0x246D}, {
885         0x31, 0x35, 0x246E}, {
886         0x31, 0x36, 0x246F}, {
887         0x31, 0x37, 0x2470}, {
888         0x31, 0x38, 0x2471}, {
889         0x31, 0x39, 0x2472}, {
890         0x32, 0x30, 0x2473}, {
891         0x31, 0x2E, 0x2488}, {
892         0x32, 0x2E, 0x2489}, {
893         0x33, 0x2E, 0x248A}, {
894         0x34, 0x2E, 0x248B}, {
895         0x35, 0x2E, 0x248C}, {
896         0x36, 0x2E, 0x248D}, {
897         0x37, 0x2E, 0x248E}, {
898         0x38, 0x2E, 0x248F}, {
899         0x39, 0x2E, 0x2490}, {
900         0x64, 0x61, 0x3372}, {
901         0x41, 0x55, 0x3373}, {
902         0x6F, 0x56, 0x3375}, {
903         0x70, 0x63, 0x3376}, {
904         0x70, 0x41, 0x3380}, {
905         0x6E, 0x41, 0x3381}, {
906         0x6D, 0x41, 0x3383}, {
907         0x6B, 0x41, 0x3384}, {
908         0x4B, 0x42, 0x3385}, {
909         0x4D, 0x42, 0x3386}, {
910         0x47, 0x42, 0x3387}, {
911         0x70, 0x46, 0x338A}, {
912         0x6E, 0x46, 0x338B}, {
913         0x6D, 0x67, 0x338E}, {
914         0x6B, 0x67, 0x338F}, {
915         0x48, 0x7A, 0x3390}, {
916         0x66, 0x6D, 0x3399}, {
917         0x6E, 0x6D, 0x339A}, {
918         0x6D, 0x6D, 0x339C}, {
919         0x63, 0x6D, 0x339D}, {
920         0x6B, 0x6D, 0x339E}, {
921         0x50, 0x61, 0x33A9}, {
922         0x70, 0x73, 0x33B0}, {
923         0x6E, 0x73, 0x33B1}, {
924         0x6D, 0x73, 0x33B3}, {
925         0x70, 0x56, 0x33B4}, {
926         0x6E, 0x56, 0x33B5}, {
927         0x6D, 0x56, 0x33B7}, {
928         0x6B, 0x56, 0x33B8}, {
929         0x4D, 0x56, 0x33B9}, {
930         0x70, 0x57, 0x33BA}, {
931         0x6E, 0x57, 0x33BB}, {
932         0x6D, 0x57, 0x33BD}, {
933         0x6B, 0x57, 0x33BE}, {
934         0x4D, 0x57, 0x33BF}, {
935         0x42, 0x71, 0x33C3}, {
936         0x63, 0x63, 0x33C4}, {
937         0x63, 0x64, 0x33C5}, {
938         0x64, 0x42, 0x33C8}, {
939         0x47, 0x79, 0x33C9}, {
940         0x68, 0x61, 0x33CA}, {
941         0x48, 0x50, 0x33CB}, {
942         0x69, 0x6E, 0x33CC}, {
943         0x4B, 0x4B, 0x33CD}, {
944         0x4B, 0x4D, 0x33CE}, {
945         0x6B, 0x74, 0x33CF}, {
946         0x6C, 0x6D, 0x33D0}, {
947         0x6C, 0x6E, 0x33D1}, {
948         0x6C, 0x78, 0x33D3}, {
949         0x6D, 0x62, 0x33D4}, {
950         0x50, 0x48, 0x33D7}, {
951         0x50, 0x52, 0x33DA}, {
952         0x73, 0x72, 0x33DB}, {
953         0x53, 0x76, 0x33DC}, {
954         0x57, 0x62, 0x33DD}, {
955         0x66, 0x66, 0xFB00}, {
956         0x66, 0x69, 0xFB01}, {
957         0x66, 0x6C, 0xFB02}, {
958         0x73, 0x74, 0xFB06}, {
959         0, 0, 0}
960     }, *c;
961
962     static int recurse = 0;
963     int nc = -1;
964
965     for (c = composetbl; c->first; c++) {
966         if (c->first == first && c->second == second)
967             return c->composed;
968     }
969
970     if (recurse == 0) {
971         recurse = 1;
972         nc = check_compose(second, first);
973         if (nc == -1)
974             nc = check_compose(toupper(first), toupper(second));
975         if (nc == -1)
976             nc = check_compose(toupper(second), toupper(first));
977         recurse = 0;
978     }
979     return nc;
980 }
981
982 int decode_codepage(char *cp_name)
983 {
984     char *s, *d;
985     struct cp_list_item *cpi;
986     int codepage = -1;
987     CPINFO cpinfo;
988
989     if (!*cp_name) {
990         /*
991          * Here we select a plausible default code page based on
992          * the locale the user is in. We wish to select an ISO code
993          * page or appropriate local default _rather_ than go with
994          * the Win125* series, because it's more important to have
995          * CSI and friends enabled by default than the ghastly
996          * Windows extra quote characters, and because it's more
997          * likely the user is connecting to a remote server that
998          * does something Unixy or VMSy and hence standards-
999          * compliant than that they're connecting back to a Windows
1000          * box using horrible nonstandard charsets.
1001          * 
1002          * Accordingly, Robert de Bath suggests a method for
1003          * picking a default character set that runs as follows:
1004          * first call GetACP to get the system's ANSI code page
1005          * identifier, and translate as follows:
1006          * 
1007          * 1250 -> ISO 8859-2
1008          * 1251 -> KOI8-U
1009          * 1252 -> ISO 8859-1
1010          * 1253 -> ISO 8859-7
1011          * 1254 -> ISO 8859-9
1012          * 1255 -> ISO 8859-8
1013          * 1256 -> ISO 8859-6
1014          * 1257 -> ISO 8859-4
1015          * 
1016          * and for anything else, choose direct-to-font.
1017          */
1018         int cp = GetACP();
1019         switch (cp) {
1020           case 1250: cp_name = "ISO-8859-2"; break;
1021           case 1251: cp_name = "KOI8-U"; break;
1022           case 1252: cp_name = "ISO-8859-1"; break;
1023           case 1253: cp_name = "ISO-8859-7"; break;
1024           case 1254: cp_name = "ISO-8859-9"; break;
1025           case 1255: cp_name = "ISO-8859-8"; break;
1026           case 1256: cp_name = "ISO-8859-6"; break;
1027           case 1257: cp_name = "ISO-8859-4"; break;
1028             /* default: leave it blank, which will select -1, direct->font */
1029         }
1030     }
1031
1032     if (cp_name && *cp_name)
1033         for (cpi = cp_list; cpi->name; cpi++) {
1034             s = cp_name;
1035             d = cpi->name;
1036             for (;;) {
1037                 while (*s && !isalnum(*s) && *s != ':')
1038                     s++;
1039                 while (*d && !isalnum(*d) && *d != ':')
1040                     d++;
1041                 if (*s == 0) {
1042                     codepage = cpi->codepage;
1043                     if (codepage == CP_UTF8)
1044                         goto break_break;
1045                     if (codepage == -1)
1046                         return codepage;
1047                     if (codepage == 0) {
1048                         codepage = 65536 + (cpi - cp_list);
1049                         goto break_break;
1050                     }
1051
1052                     if (GetCPInfo(codepage, &cpinfo) != 0)
1053                         goto break_break;
1054                 }
1055                 if (tolower(*s++) != tolower(*d++))
1056                     break;
1057             }
1058         }
1059
1060     if (cp_name && *cp_name) {
1061         d = cp_name;
1062         if (tolower(d[0]) == 'c' && tolower(d[1]) == 'p')
1063             d += 2;
1064         if (tolower(d[0]) == 'i' && tolower(d[1]) == 'b'
1065             && tolower(d[1]) == 'm')
1066             d += 3;
1067         for (s = d; *s >= '0' && *s <= '9'; s++);
1068         if (*s == 0 && s != d)
1069             codepage = atoi(d);        /* CP999 or IBM999 */
1070
1071         if (codepage == CP_ACP)
1072             codepage = GetACP();
1073         if (codepage == CP_OEMCP)
1074             codepage = GetOEMCP();
1075         if (codepage > 65535)
1076             codepage = -2;
1077     }
1078
1079   break_break:;
1080     if (codepage != -1) {
1081         if (codepage != CP_UTF8 && codepage < 65536) {
1082             if (GetCPInfo(codepage, &cpinfo) == 0) {
1083                 codepage = -2;
1084             } else if (cpinfo.MaxCharSize > 1)
1085                 codepage = -3;
1086         }
1087     }
1088     if (codepage == -1 && *cp_name)
1089         codepage = -2;
1090     return codepage;
1091 }
1092
1093 char *cp_name(int codepage)
1094 {
1095     struct cp_list_item *cpi, *cpno;
1096     static char buf[32];
1097
1098     if (codepage == -1) {
1099         sprintf(buf, "Use font encoding");
1100         return buf;
1101     }
1102
1103     if (codepage > 0 && codepage < 65536)
1104         sprintf(buf, "CP%03d", codepage);
1105     else
1106         *buf = 0;
1107
1108     if (codepage >= 65536) {
1109         cpno = 0;
1110         for (cpi = cp_list; cpi->name; cpi++)
1111             if (cpi == cp_list + (codepage - 65536)) {
1112                 cpno = cpi;
1113                 break;
1114             }
1115         if (cpno)
1116             for (cpi = cp_list; cpi->name; cpi++) {
1117                 if (cpno->cp_table == cpi->cp_table)
1118                     return cpi->name;
1119             }
1120     } else {
1121         for (cpi = cp_list; cpi->name; cpi++) {
1122             if (codepage == cpi->codepage)
1123                 return cpi->name;
1124         }
1125     }
1126     return buf;
1127 }
1128
1129 /*
1130  * Return the nth code page in the list, for use in the GUI
1131  * configurer.
1132  */
1133 char *cp_enumerate(int index)
1134 {
1135     if (index < 0 || index >= lenof(cp_list))
1136         return NULL;
1137     return cp_list[index].name;
1138 }
1139
1140 void get_unitab(int codepage, wchar_t * unitab, int ftype)
1141 {
1142     char tbuf[4];
1143     int i, max = 256, flg = MB_ERR_INVALID_CHARS;
1144
1145     if (ftype)
1146         flg |= MB_USEGLYPHCHARS;
1147     if (ftype == 2)
1148         max = 128;
1149
1150     if (codepage == CP_UTF8) {
1151         for (i = 0; i < max; i++)
1152             unitab[i] = i;
1153         return;
1154     }
1155
1156     if (codepage == CP_ACP)
1157         codepage = GetACP();
1158     else if (codepage == CP_OEMCP)
1159         codepage = GetOEMCP();
1160
1161     if (codepage > 0 && codepage < 65536) {
1162         for (i = 0; i < max; i++) {
1163             tbuf[0] = i;
1164
1165             if (mb_to_wc(codepage, flg, tbuf, 1, unitab + i, 1)
1166                 != 1)
1167                 unitab[i] = 0xFFFD;
1168         }
1169     } else {
1170         int j = 256 - cp_list[codepage & 0xFFFF].cp_size;
1171         for (i = 0; i < max; i++)
1172             unitab[i] = i;
1173         for (i = j; i < max; i++)
1174             unitab[i] = cp_list[codepage & 0xFFFF].cp_table[i - j];
1175     }
1176 }
1177
1178 int wc_to_mb(int codepage, int flags, wchar_t *wcstr, int wclen,
1179              char *mbstr, int mblen, char *defchr, int *defused)
1180 {
1181     char *p;
1182     int i;
1183     if (codepage == line_codepage && uni_tbl) {
1184         /* Do this by array lookup if we can. */
1185         if (wclen < 0) {
1186             for (wclen = 0; wcstr[wclen++] ;);   /* will include the NUL */
1187         }
1188         for (p = mbstr, i = 0; i < wclen; i++) {
1189             wchar_t ch = wcstr[i];
1190             int by;
1191             char *p1;
1192             if (uni_tbl && (p1 = uni_tbl[(ch >> 8) & 0xFF])
1193                 && (by = p1[ch & 0xFF]))
1194                 *p++ = by;
1195             else if (ch < 0x80)
1196                 *p++ = (char) ch;
1197             else if (defchr) {
1198                 int j;
1199                 for (j = 0; defchr[j]; j++)
1200                     *p++ = defchr[j];
1201                 if (defused) *defused = 1;
1202             }
1203 #if 1
1204             else
1205                 *p++ = '.';
1206 #endif
1207             assert(p - mbstr < mblen);
1208         }
1209         return p - mbstr;
1210     } else
1211         return WideCharToMultiByte(codepage, flags, wcstr, wclen,
1212                                    mbstr, mblen, defchr, defused);
1213 }
1214
1215 int mb_to_wc(int codepage, int flags, char *mbstr, int mblen,
1216              wchar_t *wcstr, int wclen)
1217 {
1218     return MultiByteToWideChar(codepage, flags, mbstr, mblen, wcstr, wclen);
1219 }
1220
1221 int is_dbcs_leadbyte(int codepage, char byte)
1222 {
1223     return IsDBCSLeadByteEx(codepage, byte);
1224 }