]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - windows/winucs.c
GTK2: Return 2.20 compatibility back
[PuTTY.git] / windows / winucs.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 /* Mazovia (Polish) aka CP620
361  * from "Mazowia to Unicode table", 04/24/96, Mikolaj Jedrzejak */
362 static const wchar_t mazovia[] = {
363     /* Code point 0x9B is "zloty" symbol (z&#0142;), which is not
364      *   widely used and for which there is no Unicode equivalent.
365      * One reference shows 0xA8 as U+00A7 SECTION SIGN, but we're
366      *   told that's incorrect. */
367     0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x0105, 0x00E7,
368     0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0107, 0x00C4, 0x0104,
369     0x0118, 0x0119, 0x0142, 0x00F4, 0x00F6, 0x0106, 0x00FB, 0x00F9,
370     0x015a, 0x00D6, 0x00DC, 0xFFFD, 0x0141, 0x00A5, 0x015b, 0x0192,
371     0x0179, 0x017b, 0x00F3, 0x00d3, 0x0144, 0x0143, 0x017a, 0x017c,
372     0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
373     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
374     0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
375     0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
376     0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
377     0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
378     0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
379     0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4,
380     0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
381     0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248,
382     0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
383 };
384
385 struct cp_list_item {
386     char *name;
387     int codepage;
388     int cp_size;
389     const wchar_t *cp_table;
390 };
391
392 static const struct cp_list_item cp_list[] = {
393     {"UTF-8", CP_UTF8},
394
395     {"ISO-8859-1:1998 (Latin-1, West Europe)", 0, 96, iso_8859_1},
396     {"ISO-8859-2:1999 (Latin-2, East Europe)", 0, 96, iso_8859_2},
397     {"ISO-8859-3:1999 (Latin-3, South Europe)", 0, 96, iso_8859_3},
398     {"ISO-8859-4:1998 (Latin-4, North Europe)", 0, 96, iso_8859_4},
399     {"ISO-8859-5:1999 (Latin/Cyrillic)", 0, 96, iso_8859_5},
400     {"ISO-8859-6:1999 (Latin/Arabic)", 0, 96, iso_8859_6},
401     {"ISO-8859-7:1987 (Latin/Greek)", 0, 96, iso_8859_7},
402     {"ISO-8859-8:1999 (Latin/Hebrew)", 0, 96, iso_8859_8},
403     {"ISO-8859-9:1999 (Latin-5, Turkish)", 0, 96, iso_8859_9},
404     {"ISO-8859-10:1998 (Latin-6, Nordic)", 0, 96, iso_8859_10},
405     {"ISO-8859-11:2001 (Latin/Thai)", 0, 96, iso_8859_11},
406     {"ISO-8859-13:1998 (Latin-7, Baltic)", 0, 96, iso_8859_13},
407     {"ISO-8859-14:1998 (Latin-8, Celtic)", 0, 96, iso_8859_14},
408     {"ISO-8859-15:1999 (Latin-9, \"euro\")", 0, 96, iso_8859_15},
409     {"ISO-8859-16:2001 (Latin-10, Balkan)", 0, 96, iso_8859_16},
410
411     {"KOI8-U", 0, 128, koi8_u},
412     {"KOI8-R", 20866},
413     {"HP-ROMAN8", 0, 96, roman8},
414     {"VSCII", 0, 256, vscii},
415     {"DEC-MCS", 0, 96, dec_mcs},
416
417     {"Win1250 (Central European)", 1250},
418     {"Win1251 (Cyrillic)", 1251},
419     {"Win1252 (Western)", 1252},
420     {"Win1253 (Greek)", 1253},
421     {"Win1254 (Turkish)", 1254},
422     {"Win1255 (Hebrew)", 1255},
423     {"Win1256 (Arabic)", 1256},
424     {"Win1257 (Baltic)", 1257},
425     {"Win1258 (Vietnamese)", 1258},
426
427     {"CP437", 437},
428     {"CP620 (Mazovia)", 0, 128, mazovia},
429     {"CP819", 28591},
430     {"CP852", 852},
431     {"CP878", 20866},
432
433     {"Use font encoding", -1},
434
435     {0, 0}
436 };
437
438 static void link_font(WCHAR * line_tbl, WCHAR * font_tbl, WCHAR attr);
439
440 void init_ucs(Conf *conf, struct unicode_data *ucsdata)
441 {
442     int i, j;
443     int used_dtf = 0;
444     int vtmode;
445
446     /* Decide on the Line and Font codepages */
447     ucsdata->line_codepage = decode_codepage(conf_get_str(conf,
448                                                           CONF_line_codepage));
449
450     if (ucsdata->font_codepage <= 0) { 
451         ucsdata->font_codepage=0; 
452         ucsdata->dbcs_screenfont=0; 
453     }
454
455     vtmode = conf_get_int(conf, CONF_vtmode);
456     if (vtmode == VT_OEMONLY) {
457         ucsdata->font_codepage = 437;
458         ucsdata->dbcs_screenfont = 0;
459         if (ucsdata->line_codepage <= 0)
460             ucsdata->line_codepage = GetACP();
461     } else if (ucsdata->line_codepage <= 0)
462         ucsdata->line_codepage = ucsdata->font_codepage;
463
464     /* Collect screen font ucs table */
465     if (ucsdata->dbcs_screenfont || ucsdata->font_codepage == 0) {
466         get_unitab(ucsdata->font_codepage, ucsdata->unitab_font, 2);
467         for (i = 128; i < 256; i++)
468             ucsdata->unitab_font[i] = (WCHAR) (CSET_ACP + i);
469     } else {
470         get_unitab(ucsdata->font_codepage, ucsdata->unitab_font, 1);
471
472         /* CP437 fonts are often broken ... */
473         if (ucsdata->font_codepage == 437)
474             ucsdata->unitab_font[0] = ucsdata->unitab_font[255] = 0xFFFF;
475     }
476     if (vtmode == VT_XWINDOWS)
477         memcpy(ucsdata->unitab_font + 1, unitab_xterm_std,
478                sizeof(unitab_xterm_std));
479
480     /* Collect OEMCP ucs table */
481     get_unitab(CP_OEMCP, ucsdata->unitab_oemcp, 1);
482
483     /* Collect CP437 ucs table for SCO acs */
484     if (vtmode == VT_OEMANSI || vtmode == VT_XWINDOWS)
485         memcpy(ucsdata->unitab_scoacs, ucsdata->unitab_oemcp,
486                sizeof(ucsdata->unitab_scoacs));
487     else
488         get_unitab(437, ucsdata->unitab_scoacs, 1);
489
490     /* Collect line set ucs table */
491     if (ucsdata->line_codepage == ucsdata->font_codepage &&
492         (ucsdata->dbcs_screenfont ||
493          vtmode == VT_POORMAN || ucsdata->font_codepage==0)) {
494
495         /* For DBCS and POOR fonts force direct to font */
496         used_dtf = 1;
497         for (i = 0; i < 32; i++)
498             ucsdata->unitab_line[i] = (WCHAR) i;
499         for (i = 32; i < 256; i++)
500             ucsdata->unitab_line[i] = (WCHAR) (CSET_ACP + i);
501         ucsdata->unitab_line[127] = (WCHAR) 127;
502     } else {
503         get_unitab(ucsdata->line_codepage, ucsdata->unitab_line, 0);
504     }
505
506 #if 0
507     debug(
508           ("Line cp%d, Font cp%d%s\n", ucsdata->line_codepage,
509            ucsdata->font_codepage, ucsdata->dbcs_screenfont ? " DBCS" : ""));
510
511     for (i = 0; i < 256; i += 16) {
512         for (j = 0; j < 16; j++) {
513             debug(("%04x%s", ucsdata->unitab_line[i + j], j == 15 ? "" : ","));
514         }
515         debug(("\n"));
516     }
517 #endif
518
519     /* VT100 graphics - NB: Broken for non-ascii CP's */
520     memcpy(ucsdata->unitab_xterm, ucsdata->unitab_line,
521            sizeof(ucsdata->unitab_xterm));
522     memcpy(ucsdata->unitab_xterm + '`', unitab_xterm_std,
523            sizeof(unitab_xterm_std));
524     ucsdata->unitab_xterm['_'] = ' ';
525
526     /* Generate UCS ->line page table. */
527     if (ucsdata->uni_tbl) {
528         for (i = 0; i < 256; i++)
529             if (ucsdata->uni_tbl[i])
530                 sfree(ucsdata->uni_tbl[i]);
531         sfree(ucsdata->uni_tbl);
532         ucsdata->uni_tbl = 0;
533     }
534     if (!used_dtf) {
535         for (i = 0; i < 256; i++) {
536             if (DIRECT_CHAR(ucsdata->unitab_line[i]))
537                 continue;
538             if (DIRECT_FONT(ucsdata->unitab_line[i]))
539                 continue;
540             if (!ucsdata->uni_tbl) {
541                 ucsdata->uni_tbl = snewn(256, char *);
542                 memset(ucsdata->uni_tbl, 0, 256 * sizeof(char *));
543             }
544             j = ((ucsdata->unitab_line[i] >> 8) & 0xFF);
545             if (!ucsdata->uni_tbl[j]) {
546                 ucsdata->uni_tbl[j] = snewn(256, char);
547                 memset(ucsdata->uni_tbl[j], 0, 256 * sizeof(char));
548             }
549             ucsdata->uni_tbl[j][ucsdata->unitab_line[i] & 0xFF] = i;
550         }
551     }
552
553     /* Find the line control characters. */
554     for (i = 0; i < 256; i++)
555         if (ucsdata->unitab_line[i] < ' '
556             || (ucsdata->unitab_line[i] >= 0x7F && 
557                 ucsdata->unitab_line[i] < 0xA0))
558             ucsdata->unitab_ctrl[i] = i;
559         else
560             ucsdata->unitab_ctrl[i] = 0xFF;
561
562     /* Generate line->screen direct conversion links. */
563     if (vtmode == VT_OEMANSI || vtmode == VT_XWINDOWS)
564         link_font(ucsdata->unitab_scoacs, ucsdata->unitab_oemcp, CSET_OEMCP);
565
566     link_font(ucsdata->unitab_line, ucsdata->unitab_font, CSET_ACP);
567     link_font(ucsdata->unitab_scoacs, ucsdata->unitab_font, CSET_ACP);
568     link_font(ucsdata->unitab_xterm, ucsdata->unitab_font, CSET_ACP);
569
570     if (vtmode == VT_OEMANSI || vtmode == VT_XWINDOWS) {
571         link_font(ucsdata->unitab_line, ucsdata->unitab_oemcp, CSET_OEMCP);
572         link_font(ucsdata->unitab_xterm, ucsdata->unitab_oemcp, CSET_OEMCP);
573     }
574
575     if (ucsdata->dbcs_screenfont &&
576         ucsdata->font_codepage != ucsdata->line_codepage) {
577         /* F***ing Microsoft fonts, Japanese and Korean codepage fonts
578          * have a currency symbol at 0x5C but their unicode value is 
579          * still given as U+005C not the correct U+00A5. */
580         ucsdata->unitab_line['\\'] = CSET_OEMCP + '\\';
581     }
582
583     /* Last chance, if !unicode then try poorman links. */
584     if (vtmode != VT_UNICODE) {
585         static const char poorman_scoacs[] = 
586             "CueaaaaceeeiiiAAE**ooouuyOUc$YPsaiounNao?++**!<>###||||++||++++++--|-+||++--|-+----++++++++##||#aBTPEsyt******EN=+><++-=... n2* ";
587         static const char poorman_latin1[] =
588             " !cL.Y|S\"Ca<--R~o+23'u|.,1o>///?AAAAAAACEEEEIIIIDNOOOOOxOUUUUYPBaaaaaaaceeeeiiiionooooo/ouuuuypy";
589         static const char poorman_vt100[] = "*#****o~**+++++-----++++|****L.";
590
591         for (i = 160; i < 256; i++)
592             if (!DIRECT_FONT(ucsdata->unitab_line[i]) &&
593                 ucsdata->unitab_line[i] >= 160 &&
594                 ucsdata->unitab_line[i] < 256) {
595                 ucsdata->unitab_line[i] =
596                     (WCHAR) (CSET_ACP +
597                              poorman_latin1[ucsdata->unitab_line[i] - 160]);
598             }
599         for (i = 96; i < 127; i++)
600             if (!DIRECT_FONT(ucsdata->unitab_xterm[i]))
601                 ucsdata->unitab_xterm[i] =
602             (WCHAR) (CSET_ACP + poorman_vt100[i - 96]);
603         for(i=128;i<256;i++) 
604             if (!DIRECT_FONT(ucsdata->unitab_scoacs[i]))
605                 ucsdata->unitab_scoacs[i] = 
606                     (WCHAR) (CSET_ACP + poorman_scoacs[i - 128]);
607     }
608 }
609
610 static void link_font(WCHAR * line_tbl, WCHAR * font_tbl, WCHAR attr)
611 {
612     int font_index, line_index, i;
613     for (line_index = 0; line_index < 256; line_index++) {
614         if (DIRECT_FONT(line_tbl[line_index]))
615             continue;
616         for(i = 0; i < 256; i++) {
617             font_index = ((32 + i) & 0xFF);
618             if (line_tbl[line_index] == font_tbl[font_index]) {
619                 line_tbl[line_index] = (WCHAR) (attr + font_index);
620                 break;
621             }
622         }
623     }
624 }
625
626 wchar_t xlat_uskbd2cyrllic(int ch)
627 {
628     static const wchar_t cyrtab[] = {
629             0,      1,       2,      3,      4,      5,      6,      7,
630             8,      9,      10,     11,     12,     13,     14,     15,
631             16,     17,     18,     19,     20,     21,     22,     23,
632             24,     25,     26,     27,     28,     29,     30,     31,
633             32,     33, 0x042d,     35,     36,     37,     38, 0x044d,
634             40,     41,     42, 0x0406, 0x0431, 0x0454, 0x044e, 0x002e,
635             48,     49,     50,     51,     52,     53,     54,     55,
636             56,     57, 0x0416, 0x0436, 0x0411, 0x0456, 0x042e, 0x002c,
637             64, 0x0424, 0x0418, 0x0421, 0x0412, 0x0423, 0x0410, 0x041f,
638         0x0420, 0x0428, 0x041e, 0x041b, 0x0414, 0x042c, 0x0422, 0x0429,
639         0x0417, 0x0419, 0x041a, 0x042b, 0x0415, 0x0413, 0x041c, 0x0426,
640         0x0427, 0x041d, 0x042f, 0x0445, 0x0457, 0x044a,     94, 0x0404,
641             96, 0x0444, 0x0438, 0x0441, 0x0432, 0x0443, 0x0430, 0x043f,
642         0x0440, 0x0448, 0x043e, 0x043b, 0x0434, 0x044c, 0x0442, 0x0449,
643         0x0437, 0x0439, 0x043a, 0x044b, 0x0435, 0x0433, 0x043c, 0x0446,
644         0x0447, 0x043d, 0x044f, 0x0425, 0x0407, 0x042a,    126,    127
645        };
646     return cyrtab[ch&0x7F];
647 }
648
649 int check_compose_internal(int first, int second, int recurse)
650 {
651
652     static const struct {
653         char first, second;
654         wchar_t composed;
655     } composetbl[] = {
656         {
657         0x2b, 0x2b, 0x0023}, {
658         0x41, 0x41, 0x0040}, {
659         0x28, 0x28, 0x005b}, {
660         0x2f, 0x2f, 0x005c}, {
661         0x29, 0x29, 0x005d}, {
662         0x28, 0x2d, 0x007b}, {
663         0x2d, 0x29, 0x007d}, {
664         0x2f, 0x5e, 0x007c}, {
665         0x21, 0x21, 0x00a1}, {
666         0x43, 0x2f, 0x00a2}, {
667         0x43, 0x7c, 0x00a2}, {
668         0x4c, 0x2d, 0x00a3}, {
669         0x4c, 0x3d, 0x20a4}, {
670         0x58, 0x4f, 0x00a4}, {
671         0x58, 0x30, 0x00a4}, {
672         0x59, 0x2d, 0x00a5}, {
673         0x59, 0x3d, 0x00a5}, {
674         0x7c, 0x7c, 0x00a6}, {
675         0x53, 0x4f, 0x00a7}, {
676         0x53, 0x21, 0x00a7}, {
677         0x53, 0x30, 0x00a7}, {
678         0x22, 0x22, 0x00a8}, {
679         0x43, 0x4f, 0x00a9}, {
680         0x43, 0x30, 0x00a9}, {
681         0x41, 0x5f, 0x00aa}, {
682         0x3c, 0x3c, 0x00ab}, {
683         0x2c, 0x2d, 0x00ac}, {
684         0x2d, 0x2d, 0x00ad}, {
685         0x52, 0x4f, 0x00ae}, {
686         0x2d, 0x5e, 0x00af}, {
687         0x30, 0x5e, 0x00b0}, {
688         0x2b, 0x2d, 0x00b1}, {
689         0x32, 0x5e, 0x00b2}, {
690         0x33, 0x5e, 0x00b3}, {
691         0x27, 0x27, 0x00b4}, {
692         0x2f, 0x55, 0x00b5}, {
693         0x50, 0x21, 0x00b6}, {
694         0x2e, 0x5e, 0x00b7}, {
695         0x2c, 0x2c, 0x00b8}, {
696         0x31, 0x5e, 0x00b9}, {
697         0x4f, 0x5f, 0x00ba}, {
698         0x3e, 0x3e, 0x00bb}, {
699         0x31, 0x34, 0x00bc}, {
700         0x31, 0x32, 0x00bd}, {
701         0x33, 0x34, 0x00be}, {
702         0x3f, 0x3f, 0x00bf}, {
703         0x60, 0x41, 0x00c0}, {
704         0x27, 0x41, 0x00c1}, {
705         0x5e, 0x41, 0x00c2}, {
706         0x7e, 0x41, 0x00c3}, {
707         0x22, 0x41, 0x00c4}, {
708         0x2a, 0x41, 0x00c5}, {
709         0x41, 0x45, 0x00c6}, {
710         0x2c, 0x43, 0x00c7}, {
711         0x60, 0x45, 0x00c8}, {
712         0x27, 0x45, 0x00c9}, {
713         0x5e, 0x45, 0x00ca}, {
714         0x22, 0x45, 0x00cb}, {
715         0x60, 0x49, 0x00cc}, {
716         0x27, 0x49, 0x00cd}, {
717         0x5e, 0x49, 0x00ce}, {
718         0x22, 0x49, 0x00cf}, {
719         0x2d, 0x44, 0x00d0}, {
720         0x7e, 0x4e, 0x00d1}, {
721         0x60, 0x4f, 0x00d2}, {
722         0x27, 0x4f, 0x00d3}, {
723         0x5e, 0x4f, 0x00d4}, {
724         0x7e, 0x4f, 0x00d5}, {
725         0x22, 0x4f, 0x00d6}, {
726         0x58, 0x58, 0x00d7}, {
727         0x2f, 0x4f, 0x00d8}, {
728         0x60, 0x55, 0x00d9}, {
729         0x27, 0x55, 0x00da}, {
730         0x5e, 0x55, 0x00db}, {
731         0x22, 0x55, 0x00dc}, {
732         0x27, 0x59, 0x00dd}, {
733         0x48, 0x54, 0x00de}, {
734         0x73, 0x73, 0x00df}, {
735         0x60, 0x61, 0x00e0}, {
736         0x27, 0x61, 0x00e1}, {
737         0x5e, 0x61, 0x00e2}, {
738         0x7e, 0x61, 0x00e3}, {
739         0x22, 0x61, 0x00e4}, {
740         0x2a, 0x61, 0x00e5}, {
741         0x61, 0x65, 0x00e6}, {
742         0x2c, 0x63, 0x00e7}, {
743         0x60, 0x65, 0x00e8}, {
744         0x27, 0x65, 0x00e9}, {
745         0x5e, 0x65, 0x00ea}, {
746         0x22, 0x65, 0x00eb}, {
747         0x60, 0x69, 0x00ec}, {
748         0x27, 0x69, 0x00ed}, {
749         0x5e, 0x69, 0x00ee}, {
750         0x22, 0x69, 0x00ef}, {
751         0x2d, 0x64, 0x00f0}, {
752         0x7e, 0x6e, 0x00f1}, {
753         0x60, 0x6f, 0x00f2}, {
754         0x27, 0x6f, 0x00f3}, {
755         0x5e, 0x6f, 0x00f4}, {
756         0x7e, 0x6f, 0x00f5}, {
757         0x22, 0x6f, 0x00f6}, {
758         0x3a, 0x2d, 0x00f7}, {
759         0x6f, 0x2f, 0x00f8}, {
760         0x60, 0x75, 0x00f9}, {
761         0x27, 0x75, 0x00fa}, {
762         0x5e, 0x75, 0x00fb}, {
763         0x22, 0x75, 0x00fc}, {
764         0x27, 0x79, 0x00fd}, {
765         0x68, 0x74, 0x00fe}, {
766         0x22, 0x79, 0x00ff},
767             /* Unicode extras. */
768         {
769         0x6f, 0x65, 0x0153}, {
770         0x4f, 0x45, 0x0152},
771             /* Compose pairs from UCS */
772         {
773         0x41, 0x2D, 0x0100}, {
774         0x61, 0x2D, 0x0101}, {
775         0x43, 0x27, 0x0106}, {
776         0x63, 0x27, 0x0107}, {
777         0x43, 0x5E, 0x0108}, {
778         0x63, 0x5E, 0x0109}, {
779         0x45, 0x2D, 0x0112}, {
780         0x65, 0x2D, 0x0113}, {
781         0x47, 0x5E, 0x011C}, {
782         0x67, 0x5E, 0x011D}, {
783         0x47, 0x2C, 0x0122}, {
784         0x67, 0x2C, 0x0123}, {
785         0x48, 0x5E, 0x0124}, {
786         0x68, 0x5E, 0x0125}, {
787         0x49, 0x7E, 0x0128}, {
788         0x69, 0x7E, 0x0129}, {
789         0x49, 0x2D, 0x012A}, {
790         0x69, 0x2D, 0x012B}, {
791         0x4A, 0x5E, 0x0134}, {
792         0x6A, 0x5E, 0x0135}, {
793         0x4B, 0x2C, 0x0136}, {
794         0x6B, 0x2C, 0x0137}, {
795         0x4C, 0x27, 0x0139}, {
796         0x6C, 0x27, 0x013A}, {
797         0x4C, 0x2C, 0x013B}, {
798         0x6C, 0x2C, 0x013C}, {
799         0x4E, 0x27, 0x0143}, {
800         0x6E, 0x27, 0x0144}, {
801         0x4E, 0x2C, 0x0145}, {
802         0x6E, 0x2C, 0x0146}, {
803         0x4F, 0x2D, 0x014C}, {
804         0x6F, 0x2D, 0x014D}, {
805         0x52, 0x27, 0x0154}, {
806         0x72, 0x27, 0x0155}, {
807         0x52, 0x2C, 0x0156}, {
808         0x72, 0x2C, 0x0157}, {
809         0x53, 0x27, 0x015A}, {
810         0x73, 0x27, 0x015B}, {
811         0x53, 0x5E, 0x015C}, {
812         0x73, 0x5E, 0x015D}, {
813         0x53, 0x2C, 0x015E}, {
814         0x73, 0x2C, 0x015F}, {
815         0x54, 0x2C, 0x0162}, {
816         0x74, 0x2C, 0x0163}, {
817         0x55, 0x7E, 0x0168}, {
818         0x75, 0x7E, 0x0169}, {
819         0x55, 0x2D, 0x016A}, {
820         0x75, 0x2D, 0x016B}, {
821         0x55, 0x2A, 0x016E}, {
822         0x75, 0x2A, 0x016F}, {
823         0x57, 0x5E, 0x0174}, {
824         0x77, 0x5E, 0x0175}, {
825         0x59, 0x5E, 0x0176}, {
826         0x79, 0x5E, 0x0177}, {
827         0x59, 0x22, 0x0178}, {
828         0x5A, 0x27, 0x0179}, {
829         0x7A, 0x27, 0x017A}, {
830         0x47, 0x27, 0x01F4}, {
831         0x67, 0x27, 0x01F5}, {
832         0x4E, 0x60, 0x01F8}, {
833         0x6E, 0x60, 0x01F9}, {
834         0x45, 0x2C, 0x0228}, {
835         0x65, 0x2C, 0x0229}, {
836         0x59, 0x2D, 0x0232}, {
837         0x79, 0x2D, 0x0233}, {
838         0x44, 0x2C, 0x1E10}, {
839         0x64, 0x2C, 0x1E11}, {
840         0x47, 0x2D, 0x1E20}, {
841         0x67, 0x2D, 0x1E21}, {
842         0x48, 0x22, 0x1E26}, {
843         0x68, 0x22, 0x1E27}, {
844         0x48, 0x2C, 0x1E28}, {
845         0x68, 0x2C, 0x1E29}, {
846         0x4B, 0x27, 0x1E30}, {
847         0x6B, 0x27, 0x1E31}, {
848         0x4D, 0x27, 0x1E3E}, {
849         0x6D, 0x27, 0x1E3F}, {
850         0x50, 0x27, 0x1E54}, {
851         0x70, 0x27, 0x1E55}, {
852         0x56, 0x7E, 0x1E7C}, {
853         0x76, 0x7E, 0x1E7D}, {
854         0x57, 0x60, 0x1E80}, {
855         0x77, 0x60, 0x1E81}, {
856         0x57, 0x27, 0x1E82}, {
857         0x77, 0x27, 0x1E83}, {
858         0x57, 0x22, 0x1E84}, {
859         0x77, 0x22, 0x1E85}, {
860         0x58, 0x22, 0x1E8C}, {
861         0x78, 0x22, 0x1E8D}, {
862         0x5A, 0x5E, 0x1E90}, {
863         0x7A, 0x5E, 0x1E91}, {
864         0x74, 0x22, 0x1E97}, {
865         0x77, 0x2A, 0x1E98}, {
866         0x79, 0x2A, 0x1E99}, {
867         0x45, 0x7E, 0x1EBC}, {
868         0x65, 0x7E, 0x1EBD}, {
869         0x59, 0x60, 0x1EF2}, {
870         0x79, 0x60, 0x1EF3}, {
871         0x59, 0x7E, 0x1EF8}, {
872         0x79, 0x7E, 0x1EF9},
873             /* Compatible/possibles from UCS */
874         {
875         0x49, 0x4A, 0x0132}, {
876         0x69, 0x6A, 0x0133}, {
877         0x4C, 0x4A, 0x01C7}, {
878         0x4C, 0x6A, 0x01C8}, {
879         0x6C, 0x6A, 0x01C9}, {
880         0x4E, 0x4A, 0x01CA}, {
881         0x4E, 0x6A, 0x01CB}, {
882         0x6E, 0x6A, 0x01CC}, {
883         0x44, 0x5A, 0x01F1}, {
884         0x44, 0x7A, 0x01F2}, {
885         0x64, 0x7A, 0x01F3}, {
886         0x2E, 0x2E, 0x2025}, {
887         0x21, 0x21, 0x203C}, {
888         0x3F, 0x21, 0x2048}, {
889         0x21, 0x3F, 0x2049}, {
890         0x52, 0x73, 0x20A8}, {
891         0x4E, 0x6F, 0x2116}, {
892         0x53, 0x4D, 0x2120}, {
893         0x54, 0x4D, 0x2122}, {
894         0x49, 0x49, 0x2161}, {
895         0x49, 0x56, 0x2163}, {
896         0x56, 0x49, 0x2165}, {
897         0x49, 0x58, 0x2168}, {
898         0x58, 0x49, 0x216A}, {
899         0x69, 0x69, 0x2171}, {
900         0x69, 0x76, 0x2173}, {
901         0x76, 0x69, 0x2175}, {
902         0x69, 0x78, 0x2178}, {
903         0x78, 0x69, 0x217A}, {
904         0x31, 0x30, 0x2469}, {
905         0x31, 0x31, 0x246A}, {
906         0x31, 0x32, 0x246B}, {
907         0x31, 0x33, 0x246C}, {
908         0x31, 0x34, 0x246D}, {
909         0x31, 0x35, 0x246E}, {
910         0x31, 0x36, 0x246F}, {
911         0x31, 0x37, 0x2470}, {
912         0x31, 0x38, 0x2471}, {
913         0x31, 0x39, 0x2472}, {
914         0x32, 0x30, 0x2473}, {
915         0x31, 0x2E, 0x2488}, {
916         0x32, 0x2E, 0x2489}, {
917         0x33, 0x2E, 0x248A}, {
918         0x34, 0x2E, 0x248B}, {
919         0x35, 0x2E, 0x248C}, {
920         0x36, 0x2E, 0x248D}, {
921         0x37, 0x2E, 0x248E}, {
922         0x38, 0x2E, 0x248F}, {
923         0x39, 0x2E, 0x2490}, {
924         0x64, 0x61, 0x3372}, {
925         0x41, 0x55, 0x3373}, {
926         0x6F, 0x56, 0x3375}, {
927         0x70, 0x63, 0x3376}, {
928         0x70, 0x41, 0x3380}, {
929         0x6E, 0x41, 0x3381}, {
930         0x6D, 0x41, 0x3383}, {
931         0x6B, 0x41, 0x3384}, {
932         0x4B, 0x42, 0x3385}, {
933         0x4D, 0x42, 0x3386}, {
934         0x47, 0x42, 0x3387}, {
935         0x70, 0x46, 0x338A}, {
936         0x6E, 0x46, 0x338B}, {
937         0x6D, 0x67, 0x338E}, {
938         0x6B, 0x67, 0x338F}, {
939         0x48, 0x7A, 0x3390}, {
940         0x66, 0x6D, 0x3399}, {
941         0x6E, 0x6D, 0x339A}, {
942         0x6D, 0x6D, 0x339C}, {
943         0x63, 0x6D, 0x339D}, {
944         0x6B, 0x6D, 0x339E}, {
945         0x50, 0x61, 0x33A9}, {
946         0x70, 0x73, 0x33B0}, {
947         0x6E, 0x73, 0x33B1}, {
948         0x6D, 0x73, 0x33B3}, {
949         0x70, 0x56, 0x33B4}, {
950         0x6E, 0x56, 0x33B5}, {
951         0x6D, 0x56, 0x33B7}, {
952         0x6B, 0x56, 0x33B8}, {
953         0x4D, 0x56, 0x33B9}, {
954         0x70, 0x57, 0x33BA}, {
955         0x6E, 0x57, 0x33BB}, {
956         0x6D, 0x57, 0x33BD}, {
957         0x6B, 0x57, 0x33BE}, {
958         0x4D, 0x57, 0x33BF}, {
959         0x42, 0x71, 0x33C3}, {
960         0x63, 0x63, 0x33C4}, {
961         0x63, 0x64, 0x33C5}, {
962         0x64, 0x42, 0x33C8}, {
963         0x47, 0x79, 0x33C9}, {
964         0x68, 0x61, 0x33CA}, {
965         0x48, 0x50, 0x33CB}, {
966         0x69, 0x6E, 0x33CC}, {
967         0x4B, 0x4B, 0x33CD}, {
968         0x4B, 0x4D, 0x33CE}, {
969         0x6B, 0x74, 0x33CF}, {
970         0x6C, 0x6D, 0x33D0}, {
971         0x6C, 0x6E, 0x33D1}, {
972         0x6C, 0x78, 0x33D3}, {
973         0x6D, 0x62, 0x33D4}, {
974         0x50, 0x48, 0x33D7}, {
975         0x50, 0x52, 0x33DA}, {
976         0x73, 0x72, 0x33DB}, {
977         0x53, 0x76, 0x33DC}, {
978         0x57, 0x62, 0x33DD}, {
979         0x66, 0x66, 0xFB00}, {
980         0x66, 0x69, 0xFB01}, {
981         0x66, 0x6C, 0xFB02}, {
982         0x73, 0x74, 0xFB06}, {
983         0, 0, 0}
984     }, *c;
985
986     int nc = -1;
987
988     for (c = composetbl; c->first; c++) {
989         if (c->first == first && c->second == second)
990             return c->composed;
991     }
992
993     if (recurse == 0) {
994         nc = check_compose_internal(second, first, 1);
995         if (nc == -1)
996             nc = check_compose_internal(toupper(first), toupper(second), 1);
997         if (nc == -1)
998             nc = check_compose_internal(toupper(second), toupper(first), 1);
999     }
1000     return nc;
1001 }
1002
1003 int check_compose(int first, int second)
1004 {
1005     return check_compose_internal(first, second, 0);
1006 }
1007
1008 int decode_codepage(char *cp_name)
1009 {
1010     char *s, *d;
1011     const struct cp_list_item *cpi;
1012     int codepage = -1;
1013     CPINFO cpinfo;
1014
1015     if (!cp_name || !*cp_name)
1016         return CP_UTF8;                /* default */
1017
1018     for (cpi = cp_list; cpi->name; cpi++) {
1019         s = cp_name;
1020         d = cpi->name;
1021         for (;;) {
1022             while (*s && !isalnum(*s) && *s != ':')
1023                 s++;
1024             while (*d && !isalnum(*d) && *d != ':')
1025                 d++;
1026             if (*s == 0) {
1027                 codepage = cpi->codepage;
1028                 if (codepage == CP_UTF8)
1029                     goto break_break;
1030                 if (codepage == -1)
1031                     return codepage;
1032                 if (codepage == 0) {
1033                     codepage = 65536 + (cpi - cp_list);
1034                     goto break_break;
1035                 }
1036
1037                 if (GetCPInfo(codepage, &cpinfo) != 0)
1038                     goto break_break;
1039             }
1040             if (tolower((unsigned char)*s++) != tolower((unsigned char)*d++))
1041                 break;
1042         }
1043     }
1044
1045     d = cp_name;
1046     if (tolower((unsigned char)d[0]) == 'c' &&
1047         tolower((unsigned char)d[1]) == 'p')
1048         d += 2;
1049     if (tolower((unsigned char)d[0]) == 'i' &&
1050         tolower((unsigned char)d[1]) == 'b' &&
1051         tolower((unsigned char)d[2]) == 'm')
1052         d += 3;
1053     for (s = d; *s >= '0' && *s <= '9'; s++);
1054     if (*s == 0 && s != d)
1055         codepage = atoi(d);            /* CP999 or IBM999 */
1056
1057     if (codepage == CP_ACP)
1058         codepage = GetACP();
1059     if (codepage == CP_OEMCP)
1060         codepage = GetOEMCP();
1061     if (codepage > 65535)
1062         codepage = -2;
1063
1064   break_break:;
1065     if (codepage != -1) {
1066         if (codepage != CP_UTF8 && codepage < 65536) {
1067             if (GetCPInfo(codepage, &cpinfo) == 0) {
1068                 codepage = -2;
1069             } else if (cpinfo.MaxCharSize > 1)
1070                 codepage = -3;
1071         }
1072     }
1073     if (codepage == -1 && *cp_name)
1074         codepage = -2;
1075     return codepage;
1076 }
1077
1078 const char *cp_name(int codepage)
1079 {
1080     const struct cp_list_item *cpi, *cpno;
1081     static char buf[32];
1082
1083     if (codepage == -1) {
1084         sprintf(buf, "Use font encoding");
1085         return buf;
1086     }
1087
1088     if (codepage > 0 && codepage < 65536)
1089         sprintf(buf, "CP%03d", codepage);
1090     else
1091         *buf = 0;
1092
1093     if (codepage >= 65536) {
1094         cpno = 0;
1095         for (cpi = cp_list; cpi->name; cpi++)
1096             if (cpi == cp_list + (codepage - 65536)) {
1097                 cpno = cpi;
1098                 break;
1099             }
1100         if (cpno)
1101             for (cpi = cp_list; cpi->name; cpi++) {
1102                 if (cpno->cp_table == cpi->cp_table)
1103                     return cpi->name;
1104             }
1105     } else {
1106         for (cpi = cp_list; cpi->name; cpi++) {
1107             if (codepage == cpi->codepage)
1108                 return cpi->name;
1109         }
1110     }
1111     return buf;
1112 }
1113
1114 /*
1115  * Return the nth code page in the list, for use in the GUI
1116  * configurer.
1117  */
1118 const char *cp_enumerate(int index)
1119 {
1120     if (index < 0 || index >= lenof(cp_list))
1121         return NULL;
1122     return cp_list[index].name;
1123 }
1124
1125 void get_unitab(int codepage, wchar_t * unitab, int ftype)
1126 {
1127     char tbuf[4];
1128     int i, max = 256, flg = MB_ERR_INVALID_CHARS;
1129
1130     if (ftype)
1131         flg |= MB_USEGLYPHCHARS;
1132     if (ftype == 2)
1133         max = 128;
1134
1135     if (codepage == CP_UTF8) {
1136         for (i = 0; i < max; i++)
1137             unitab[i] = i;
1138         return;
1139     }
1140
1141     if (codepage == CP_ACP)
1142         codepage = GetACP();
1143     else if (codepage == CP_OEMCP)
1144         codepage = GetOEMCP();
1145
1146     if (codepage > 0 && codepage < 65536) {
1147         for (i = 0; i < max; i++) {
1148             tbuf[0] = i;
1149
1150             if (mb_to_wc(codepage, flg, tbuf, 1, unitab + i, 1)
1151                 != 1)
1152                 unitab[i] = 0xFFFD;
1153         }
1154     } else {
1155         int j = 256 - cp_list[codepage & 0xFFFF].cp_size;
1156         for (i = 0; i < max; i++)
1157             unitab[i] = i;
1158         for (i = j; i < max; i++)
1159             unitab[i] = cp_list[codepage & 0xFFFF].cp_table[i - j];
1160     }
1161 }
1162
1163 int wc_to_mb(int codepage, int flags, const wchar_t *wcstr, int wclen,
1164              char *mbstr, int mblen, const char *defchr, int *defused,
1165              struct unicode_data *ucsdata)
1166 {
1167     char *p;
1168     int i;
1169     if (ucsdata && codepage == ucsdata->line_codepage && ucsdata->uni_tbl) {
1170         /* Do this by array lookup if we can. */
1171         if (wclen < 0) {
1172             for (wclen = 0; wcstr[wclen++] ;);   /* will include the NUL */
1173         }
1174         for (p = mbstr, i = 0; i < wclen; i++) {
1175             wchar_t ch = wcstr[i];
1176             int by;
1177             char *p1;
1178             if (ucsdata->uni_tbl && (p1 = ucsdata->uni_tbl[(ch >> 8) & 0xFF])
1179                 && (by = p1[ch & 0xFF]))
1180                 *p++ = by;
1181             else if (ch < 0x80)
1182                 *p++ = (char) ch;
1183             else if (defchr) {
1184                 int j;
1185                 for (j = 0; defchr[j]; j++)
1186                     *p++ = defchr[j];
1187                 if (defused) *defused = 1;
1188             }
1189 #if 1
1190             else
1191                 *p++ = '.';
1192 #endif
1193             assert(p - mbstr < mblen);
1194         }
1195         return p - mbstr;
1196     } else
1197         return WideCharToMultiByte(codepage, flags, wcstr, wclen,
1198                                    mbstr, mblen, defchr, defused);
1199 }
1200
1201 int mb_to_wc(int codepage, int flags, const char *mbstr, int mblen,
1202              wchar_t *wcstr, int wclen)
1203 {
1204     return MultiByteToWideChar(codepage, flags, mbstr, mblen, wcstr, wclen);
1205 }
1206
1207 int is_dbcs_leadbyte(int codepage, char byte)
1208 {
1209     return IsDBCSLeadByteEx(codepage, byte);
1210 }