]> asedeno.scripts.mit.edu Git - PuTTY_svn.git/blob - unicode.c
Deglobalise the Unicode module. Despite all my grand plans, I've
[PuTTY_svn.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 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(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 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(int first, int second)
628 {
629
630     static 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     static int recurse = 0;
965     int nc = -1;
966
967     for (c = composetbl; c->first; c++) {
968         if (c->first == first && c->second == second)
969             return c->composed;
970     }
971
972     if (recurse == 0) {
973         recurse = 1;
974         nc = check_compose(second, first);
975         if (nc == -1)
976             nc = check_compose(toupper(first), toupper(second));
977         if (nc == -1)
978             nc = check_compose(toupper(second), toupper(first));
979         recurse = 0;
980     }
981     return nc;
982 }
983
984 int decode_codepage(char *cp_name)
985 {
986     char *s, *d;
987     const struct cp_list_item *cpi;
988     int codepage = -1;
989     CPINFO cpinfo;
990
991     if (!*cp_name) {
992         /*
993          * Here we select a plausible default code page based on
994          * the locale the user is in. We wish to select an ISO code
995          * page or appropriate local default _rather_ than go with
996          * the Win125* series, because it's more important to have
997          * CSI and friends enabled by default than the ghastly
998          * Windows extra quote characters, and because it's more
999          * likely the user is connecting to a remote server that
1000          * does something Unixy or VMSy and hence standards-
1001          * compliant than that they're connecting back to a Windows
1002          * box using horrible nonstandard charsets.
1003          * 
1004          * Accordingly, Robert de Bath suggests a method for
1005          * picking a default character set that runs as follows:
1006          * first call GetACP to get the system's ANSI code page
1007          * identifier, and translate as follows:
1008          * 
1009          * 1250 -> ISO 8859-2
1010          * 1251 -> KOI8-U
1011          * 1252 -> ISO 8859-1
1012          * 1253 -> ISO 8859-7
1013          * 1254 -> ISO 8859-9
1014          * 1255 -> ISO 8859-8
1015          * 1256 -> ISO 8859-6
1016          * 1257 -> ISO 8859-4
1017          * 
1018          * and for anything else, choose direct-to-font.
1019          */
1020         int cp = GetACP();
1021         switch (cp) {
1022           case 1250: cp_name = "ISO-8859-2"; break;
1023           case 1251: cp_name = "KOI8-U"; break;
1024           case 1252: cp_name = "ISO-8859-1"; break;
1025           case 1253: cp_name = "ISO-8859-7"; break;
1026           case 1254: cp_name = "ISO-8859-9"; break;
1027           case 1255: cp_name = "ISO-8859-8"; break;
1028           case 1256: cp_name = "ISO-8859-6"; break;
1029           case 1257: cp_name = "ISO-8859-4"; break;
1030             /* default: leave it blank, which will select -1, direct->font */
1031         }
1032     }
1033
1034     if (cp_name && *cp_name)
1035         for (cpi = cp_list; cpi->name; cpi++) {
1036             s = cp_name;
1037             d = cpi->name;
1038             for (;;) {
1039                 while (*s && !isalnum(*s) && *s != ':')
1040                     s++;
1041                 while (*d && !isalnum(*d) && *d != ':')
1042                     d++;
1043                 if (*s == 0) {
1044                     codepage = cpi->codepage;
1045                     if (codepage == CP_UTF8)
1046                         goto break_break;
1047                     if (codepage == -1)
1048                         return codepage;
1049                     if (codepage == 0) {
1050                         codepage = 65536 + (cpi - cp_list);
1051                         goto break_break;
1052                     }
1053
1054                     if (GetCPInfo(codepage, &cpinfo) != 0)
1055                         goto break_break;
1056                 }
1057                 if (tolower(*s++) != tolower(*d++))
1058                     break;
1059             }
1060         }
1061
1062     if (cp_name && *cp_name) {
1063         d = cp_name;
1064         if (tolower(d[0]) == 'c' && tolower(d[1]) == 'p')
1065             d += 2;
1066         if (tolower(d[0]) == 'i' && tolower(d[1]) == 'b'
1067             && tolower(d[1]) == 'm')
1068             d += 3;
1069         for (s = d; *s >= '0' && *s <= '9'; s++);
1070         if (*s == 0 && s != d)
1071             codepage = atoi(d);        /* CP999 or IBM999 */
1072
1073         if (codepage == CP_ACP)
1074             codepage = GetACP();
1075         if (codepage == CP_OEMCP)
1076             codepage = GetOEMCP();
1077         if (codepage > 65535)
1078             codepage = -2;
1079     }
1080
1081   break_break:;
1082     if (codepage != -1) {
1083         if (codepage != CP_UTF8 && codepage < 65536) {
1084             if (GetCPInfo(codepage, &cpinfo) == 0) {
1085                 codepage = -2;
1086             } else if (cpinfo.MaxCharSize > 1)
1087                 codepage = -3;
1088         }
1089     }
1090     if (codepage == -1 && *cp_name)
1091         codepage = -2;
1092     return codepage;
1093 }
1094
1095 char *cp_name(int codepage)
1096 {
1097     const struct cp_list_item *cpi, *cpno;
1098     static char buf[32];
1099
1100     if (codepage == -1) {
1101         sprintf(buf, "Use font encoding");
1102         return buf;
1103     }
1104
1105     if (codepage > 0 && codepage < 65536)
1106         sprintf(buf, "CP%03d", codepage);
1107     else
1108         *buf = 0;
1109
1110     if (codepage >= 65536) {
1111         cpno = 0;
1112         for (cpi = cp_list; cpi->name; cpi++)
1113             if (cpi == cp_list + (codepage - 65536)) {
1114                 cpno = cpi;
1115                 break;
1116             }
1117         if (cpno)
1118             for (cpi = cp_list; cpi->name; cpi++) {
1119                 if (cpno->cp_table == cpi->cp_table)
1120                     return cpi->name;
1121             }
1122     } else {
1123         for (cpi = cp_list; cpi->name; cpi++) {
1124             if (codepage == cpi->codepage)
1125                 return cpi->name;
1126         }
1127     }
1128     return buf;
1129 }
1130
1131 /*
1132  * Return the nth code page in the list, for use in the GUI
1133  * configurer.
1134  */
1135 char *cp_enumerate(int index)
1136 {
1137     if (index < 0 || index >= lenof(cp_list))
1138         return NULL;
1139     return cp_list[index].name;
1140 }
1141
1142 void get_unitab(int codepage, wchar_t * unitab, int ftype)
1143 {
1144     char tbuf[4];
1145     int i, max = 256, flg = MB_ERR_INVALID_CHARS;
1146
1147     if (ftype)
1148         flg |= MB_USEGLYPHCHARS;
1149     if (ftype == 2)
1150         max = 128;
1151
1152     if (codepage == CP_UTF8) {
1153         for (i = 0; i < max; i++)
1154             unitab[i] = i;
1155         return;
1156     }
1157
1158     if (codepage == CP_ACP)
1159         codepage = GetACP();
1160     else if (codepage == CP_OEMCP)
1161         codepage = GetOEMCP();
1162
1163     if (codepage > 0 && codepage < 65536) {
1164         for (i = 0; i < max; i++) {
1165             tbuf[0] = i;
1166
1167             if (mb_to_wc(codepage, flg, tbuf, 1, unitab + i, 1)
1168                 != 1)
1169                 unitab[i] = 0xFFFD;
1170         }
1171     } else {
1172         int j = 256 - cp_list[codepage & 0xFFFF].cp_size;
1173         for (i = 0; i < max; i++)
1174             unitab[i] = i;
1175         for (i = j; i < max; i++)
1176             unitab[i] = cp_list[codepage & 0xFFFF].cp_table[i - j];
1177     }
1178 }
1179
1180 int wc_to_mb(int codepage, int flags, wchar_t *wcstr, int wclen,
1181              char *mbstr, int mblen, char *defchr, int *defused,
1182              struct unicode_data *ucsdata)
1183 {
1184     char *p;
1185     int i;
1186     if (ucsdata && codepage == ucsdata->line_codepage && ucsdata->uni_tbl) {
1187         /* Do this by array lookup if we can. */
1188         if (wclen < 0) {
1189             for (wclen = 0; wcstr[wclen++] ;);   /* will include the NUL */
1190         }
1191         for (p = mbstr, i = 0; i < wclen; i++) {
1192             wchar_t ch = wcstr[i];
1193             int by;
1194             char *p1;
1195             if (ucsdata->uni_tbl && (p1 = ucsdata->uni_tbl[(ch >> 8) & 0xFF])
1196                 && (by = p1[ch & 0xFF]))
1197                 *p++ = by;
1198             else if (ch < 0x80)
1199                 *p++ = (char) ch;
1200             else if (defchr) {
1201                 int j;
1202                 for (j = 0; defchr[j]; j++)
1203                     *p++ = defchr[j];
1204                 if (defused) *defused = 1;
1205             }
1206 #if 1
1207             else
1208                 *p++ = '.';
1209 #endif
1210             assert(p - mbstr < mblen);
1211         }
1212         return p - mbstr;
1213     } else
1214         return WideCharToMultiByte(codepage, flags, wcstr, wclen,
1215                                    mbstr, mblen, defchr, defused);
1216 }
1217
1218 int mb_to_wc(int codepage, int flags, char *mbstr, int mblen,
1219              wchar_t *wcstr, int wclen)
1220 {
1221     return MultiByteToWideChar(codepage, flags, mbstr, mblen, wcstr, wclen);
1222 }
1223
1224 int is_dbcs_leadbyte(int codepage, char byte)
1225 {
1226     return IsDBCSLeadByteEx(codepage, byte);
1227 }