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