]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - windows/winucs.c
Various changes related to the Subversion migration.
[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     {"ISO-8859-1:1998 (Latin-1, West Europe)", 0, 96, iso_8859_1},
394     {"ISO-8859-2:1999 (Latin-2, East Europe)", 0, 96, iso_8859_2},
395     {"ISO-8859-3:1999 (Latin-3, South Europe)", 0, 96, iso_8859_3},
396     {"ISO-8859-4:1998 (Latin-4, North Europe)", 0, 96, iso_8859_4},
397     {"ISO-8859-5:1999 (Latin/Cyrillic)", 0, 96, iso_8859_5},
398     {"ISO-8859-6:1999 (Latin/Arabic)", 0, 96, iso_8859_6},
399     {"ISO-8859-7:1987 (Latin/Greek)", 0, 96, iso_8859_7},
400     {"ISO-8859-8:1999 (Latin/Hebrew)", 0, 96, iso_8859_8},
401     {"ISO-8859-9:1999 (Latin-5, Turkish)", 0, 96, iso_8859_9},
402     {"ISO-8859-10:1998 (Latin-6, Nordic)", 0, 96, iso_8859_10},
403     {"ISO-8859-11:2001 (Latin/Thai)", 0, 96, iso_8859_11},
404     {"ISO-8859-13:1998 (Latin-7, Baltic)", 0, 96, iso_8859_13},
405     {"ISO-8859-14:1998 (Latin-8, Celtic)", 0, 96, iso_8859_14},
406     {"ISO-8859-15:1999 (Latin-9, \"euro\")", 0, 96, iso_8859_15},
407     {"ISO-8859-16:2001 (Latin-10, Balkan)", 0, 96, iso_8859_16},
408
409     {"UTF-8", CP_UTF8},
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     {"CP878", 20866},
431
432     {"Use font encoding", -1},
433
434     {0, 0}
435 };
436
437 static void link_font(WCHAR * line_tbl, WCHAR * font_tbl, WCHAR attr);
438
439 void init_ucs(Config *cfg, struct unicode_data *ucsdata)
440 {
441     int i, j;
442     int used_dtf = 0;
443     char tbuf[256];
444
445     for (i = 0; i < 256; i++)
446         tbuf[i] = i;
447
448     /* Decide on the Line and Font codepages */
449     ucsdata->line_codepage = decode_codepage(cfg->line_codepage);
450
451     if (ucsdata->font_codepage <= 0) { 
452         ucsdata->font_codepage=0; 
453         ucsdata->dbcs_screenfont=0; 
454     }
455
456     if (cfg->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 (cfg->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 (cfg->vtmode == VT_OEMANSI || cfg->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          cfg->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 (cfg->vtmode == VT_OEMANSI || cfg->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 (cfg->vtmode == VT_OEMANSI || cfg->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 (cfg->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) {
1016         /*
1017          * Here we select a plausible default code page based on
1018          * the locale the user is in. We wish to select an ISO code
1019          * page or appropriate local default _rather_ than go with
1020          * the Win125* series, because it's more important to have
1021          * CSI and friends enabled by default than the ghastly
1022          * Windows extra quote characters, and because it's more
1023          * likely the user is connecting to a remote server that
1024          * does something Unixy or VMSy and hence standards-
1025          * compliant than that they're connecting back to a Windows
1026          * box using horrible nonstandard charsets.
1027          * 
1028          * Accordingly, Robert de Bath suggests a method for
1029          * picking a default character set that runs as follows:
1030          * first call GetACP to get the system's ANSI code page
1031          * identifier, and translate as follows:
1032          * 
1033          * 1250 -> ISO 8859-2
1034          * 1251 -> KOI8-U
1035          * 1252 -> ISO 8859-1
1036          * 1253 -> ISO 8859-7
1037          * 1254 -> ISO 8859-9
1038          * 1255 -> ISO 8859-8
1039          * 1256 -> ISO 8859-6
1040          * 1257 -> ISO 8859-13 (changed from 8859-4 on advice of a Lithuanian)
1041          * 
1042          * and for anything else, choose direct-to-font.
1043          */
1044         int cp = GetACP();
1045         switch (cp) {
1046           case 1250: cp_name = "ISO-8859-2"; break;
1047           case 1251: cp_name = "KOI8-U"; break;
1048           case 1252: cp_name = "ISO-8859-1"; break;
1049           case 1253: cp_name = "ISO-8859-7"; break;
1050           case 1254: cp_name = "ISO-8859-9"; break;
1051           case 1255: cp_name = "ISO-8859-8"; break;
1052           case 1256: cp_name = "ISO-8859-6"; break;
1053           case 1257: cp_name = "ISO-8859-13"; break;
1054             /* default: leave it blank, which will select -1, direct->font */
1055         }
1056     }
1057
1058     if (cp_name && *cp_name)
1059         for (cpi = cp_list; cpi->name; cpi++) {
1060             s = cp_name;
1061             d = cpi->name;
1062             for (;;) {
1063                 while (*s && !isalnum(*s) && *s != ':')
1064                     s++;
1065                 while (*d && !isalnum(*d) && *d != ':')
1066                     d++;
1067                 if (*s == 0) {
1068                     codepage = cpi->codepage;
1069                     if (codepage == CP_UTF8)
1070                         goto break_break;
1071                     if (codepage == -1)
1072                         return codepage;
1073                     if (codepage == 0) {
1074                         codepage = 65536 + (cpi - cp_list);
1075                         goto break_break;
1076                     }
1077
1078                     if (GetCPInfo(codepage, &cpinfo) != 0)
1079                         goto break_break;
1080                 }
1081                 if (tolower(*s++) != tolower(*d++))
1082                     break;
1083             }
1084         }
1085
1086     if (cp_name && *cp_name) {
1087         d = cp_name;
1088         if (tolower(d[0]) == 'c' && tolower(d[1]) == 'p')
1089             d += 2;
1090         if (tolower(d[0]) == 'i' && tolower(d[1]) == 'b'
1091             && tolower(d[1]) == 'm')
1092             d += 3;
1093         for (s = d; *s >= '0' && *s <= '9'; s++);
1094         if (*s == 0 && s != d)
1095             codepage = atoi(d);        /* CP999 or IBM999 */
1096
1097         if (codepage == CP_ACP)
1098             codepage = GetACP();
1099         if (codepage == CP_OEMCP)
1100             codepage = GetOEMCP();
1101         if (codepage > 65535)
1102             codepage = -2;
1103     }
1104
1105   break_break:;
1106     if (codepage != -1) {
1107         if (codepage != CP_UTF8 && codepage < 65536) {
1108             if (GetCPInfo(codepage, &cpinfo) == 0) {
1109                 codepage = -2;
1110             } else if (cpinfo.MaxCharSize > 1)
1111                 codepage = -3;
1112         }
1113     }
1114     if (codepage == -1 && *cp_name)
1115         codepage = -2;
1116     return codepage;
1117 }
1118
1119 const char *cp_name(int codepage)
1120 {
1121     const struct cp_list_item *cpi, *cpno;
1122     static char buf[32];
1123
1124     if (codepage == -1) {
1125         sprintf(buf, "Use font encoding");
1126         return buf;
1127     }
1128
1129     if (codepage > 0 && codepage < 65536)
1130         sprintf(buf, "CP%03d", codepage);
1131     else
1132         *buf = 0;
1133
1134     if (codepage >= 65536) {
1135         cpno = 0;
1136         for (cpi = cp_list; cpi->name; cpi++)
1137             if (cpi == cp_list + (codepage - 65536)) {
1138                 cpno = cpi;
1139                 break;
1140             }
1141         if (cpno)
1142             for (cpi = cp_list; cpi->name; cpi++) {
1143                 if (cpno->cp_table == cpi->cp_table)
1144                     return cpi->name;
1145             }
1146     } else {
1147         for (cpi = cp_list; cpi->name; cpi++) {
1148             if (codepage == cpi->codepage)
1149                 return cpi->name;
1150         }
1151     }
1152     return buf;
1153 }
1154
1155 /*
1156  * Return the nth code page in the list, for use in the GUI
1157  * configurer.
1158  */
1159 const char *cp_enumerate(int index)
1160 {
1161     if (index < 0 || index >= lenof(cp_list))
1162         return NULL;
1163     return cp_list[index].name;
1164 }
1165
1166 void get_unitab(int codepage, wchar_t * unitab, int ftype)
1167 {
1168     char tbuf[4];
1169     int i, max = 256, flg = MB_ERR_INVALID_CHARS;
1170
1171     if (ftype)
1172         flg |= MB_USEGLYPHCHARS;
1173     if (ftype == 2)
1174         max = 128;
1175
1176     if (codepage == CP_UTF8) {
1177         for (i = 0; i < max; i++)
1178             unitab[i] = i;
1179         return;
1180     }
1181
1182     if (codepage == CP_ACP)
1183         codepage = GetACP();
1184     else if (codepage == CP_OEMCP)
1185         codepage = GetOEMCP();
1186
1187     if (codepage > 0 && codepage < 65536) {
1188         for (i = 0; i < max; i++) {
1189             tbuf[0] = i;
1190
1191             if (mb_to_wc(codepage, flg, tbuf, 1, unitab + i, 1)
1192                 != 1)
1193                 unitab[i] = 0xFFFD;
1194         }
1195     } else {
1196         int j = 256 - cp_list[codepage & 0xFFFF].cp_size;
1197         for (i = 0; i < max; i++)
1198             unitab[i] = i;
1199         for (i = j; i < max; i++)
1200             unitab[i] = cp_list[codepage & 0xFFFF].cp_table[i - j];
1201     }
1202 }
1203
1204 int wc_to_mb(int codepage, int flags, wchar_t *wcstr, int wclen,
1205              char *mbstr, int mblen, char *defchr, int *defused,
1206              struct unicode_data *ucsdata)
1207 {
1208     char *p;
1209     int i;
1210     if (ucsdata && codepage == ucsdata->line_codepage && ucsdata->uni_tbl) {
1211         /* Do this by array lookup if we can. */
1212         if (wclen < 0) {
1213             for (wclen = 0; wcstr[wclen++] ;);   /* will include the NUL */
1214         }
1215         for (p = mbstr, i = 0; i < wclen; i++) {
1216             wchar_t ch = wcstr[i];
1217             int by;
1218             char *p1;
1219             if (ucsdata->uni_tbl && (p1 = ucsdata->uni_tbl[(ch >> 8) & 0xFF])
1220                 && (by = p1[ch & 0xFF]))
1221                 *p++ = by;
1222             else if (ch < 0x80)
1223                 *p++ = (char) ch;
1224             else if (defchr) {
1225                 int j;
1226                 for (j = 0; defchr[j]; j++)
1227                     *p++ = defchr[j];
1228                 if (defused) *defused = 1;
1229             }
1230 #if 1
1231             else
1232                 *p++ = '.';
1233 #endif
1234             assert(p - mbstr < mblen);
1235         }
1236         return p - mbstr;
1237     } else
1238         return WideCharToMultiByte(codepage, flags, wcstr, wclen,
1239                                    mbstr, mblen, defchr, defused);
1240 }
1241
1242 int mb_to_wc(int codepage, int flags, char *mbstr, int mblen,
1243              wchar_t *wcstr, int wclen)
1244 {
1245     return MultiByteToWideChar(codepage, flags, mbstr, mblen, wcstr, wclen);
1246 }
1247
1248 int is_dbcs_leadbyte(int codepage, char byte)
1249 {
1250     return IsDBCSLeadByteEx(codepage, byte);
1251 }