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