]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - windows/winucs.c
Post-release destabilisation! Completely remove the struct type
[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(Conf *conf, struct unicode_data *ucsdata)
440 {
441     int i, j;
442     int used_dtf = 0;
443     char tbuf[256];
444     int vtmode;
445
446     for (i = 0; i < 256; i++)
447         tbuf[i] = i;
448
449     /* Decide on the Line and Font codepages */
450     ucsdata->line_codepage = decode_codepage(conf_get_str(conf,
451                                                           CONF_line_codepage));
452
453     if (ucsdata->font_codepage <= 0) { 
454         ucsdata->font_codepage=0; 
455         ucsdata->dbcs_screenfont=0; 
456     }
457
458     vtmode = conf_get_int(conf, CONF_vtmode);
459     if (vtmode == VT_OEMONLY) {
460         ucsdata->font_codepage = 437;
461         ucsdata->dbcs_screenfont = 0;
462         if (ucsdata->line_codepage <= 0)
463             ucsdata->line_codepage = GetACP();
464     } else if (ucsdata->line_codepage <= 0)
465         ucsdata->line_codepage = ucsdata->font_codepage;
466
467     /* Collect screen font ucs table */
468     if (ucsdata->dbcs_screenfont || ucsdata->font_codepage == 0) {
469         get_unitab(ucsdata->font_codepage, ucsdata->unitab_font, 2);
470         for (i = 128; i < 256; i++)
471             ucsdata->unitab_font[i] = (WCHAR) (CSET_ACP + i);
472     } else {
473         get_unitab(ucsdata->font_codepage, ucsdata->unitab_font, 1);
474
475         /* CP437 fonts are often broken ... */
476         if (ucsdata->font_codepage == 437)
477             ucsdata->unitab_font[0] = ucsdata->unitab_font[255] = 0xFFFF;
478     }
479     if (vtmode == VT_XWINDOWS)
480         memcpy(ucsdata->unitab_font + 1, unitab_xterm_std,
481                sizeof(unitab_xterm_std));
482
483     /* Collect OEMCP ucs table */
484     get_unitab(CP_OEMCP, ucsdata->unitab_oemcp, 1);
485
486     /* Collect CP437 ucs table for SCO acs */
487     if (vtmode == VT_OEMANSI || vtmode == VT_XWINDOWS)
488         memcpy(ucsdata->unitab_scoacs, ucsdata->unitab_oemcp,
489                sizeof(ucsdata->unitab_scoacs));
490     else
491         get_unitab(437, ucsdata->unitab_scoacs, 1);
492
493     /* Collect line set ucs table */
494     if (ucsdata->line_codepage == ucsdata->font_codepage &&
495         (ucsdata->dbcs_screenfont ||
496          vtmode == VT_POORMAN || ucsdata->font_codepage==0)) {
497
498         /* For DBCS and POOR fonts force direct to font */
499         used_dtf = 1;
500         for (i = 0; i < 32; i++)
501             ucsdata->unitab_line[i] = (WCHAR) i;
502         for (i = 32; i < 256; i++)
503             ucsdata->unitab_line[i] = (WCHAR) (CSET_ACP + i);
504         ucsdata->unitab_line[127] = (WCHAR) 127;
505     } else {
506         get_unitab(ucsdata->line_codepage, ucsdata->unitab_line, 0);
507     }
508
509 #if 0
510     debug(
511           ("Line cp%d, Font cp%d%s\n", ucsdata->line_codepage,
512            ucsdata->font_codepage, ucsdata->dbcs_screenfont ? " DBCS" : ""));
513
514     for (i = 0; i < 256; i += 16) {
515         for (j = 0; j < 16; j++) {
516             debug(("%04x%s", ucsdata->unitab_line[i + j], j == 15 ? "" : ","));
517         }
518         debug(("\n"));
519     }
520 #endif
521
522     /* VT100 graphics - NB: Broken for non-ascii CP's */
523     memcpy(ucsdata->unitab_xterm, ucsdata->unitab_line,
524            sizeof(ucsdata->unitab_xterm));
525     memcpy(ucsdata->unitab_xterm + '`', unitab_xterm_std,
526            sizeof(unitab_xterm_std));
527     ucsdata->unitab_xterm['_'] = ' ';
528
529     /* Generate UCS ->line page table. */
530     if (ucsdata->uni_tbl) {
531         for (i = 0; i < 256; i++)
532             if (ucsdata->uni_tbl[i])
533                 sfree(ucsdata->uni_tbl[i]);
534         sfree(ucsdata->uni_tbl);
535         ucsdata->uni_tbl = 0;
536     }
537     if (!used_dtf) {
538         for (i = 0; i < 256; i++) {
539             if (DIRECT_CHAR(ucsdata->unitab_line[i]))
540                 continue;
541             if (DIRECT_FONT(ucsdata->unitab_line[i]))
542                 continue;
543             if (!ucsdata->uni_tbl) {
544                 ucsdata->uni_tbl = snewn(256, char *);
545                 memset(ucsdata->uni_tbl, 0, 256 * sizeof(char *));
546             }
547             j = ((ucsdata->unitab_line[i] >> 8) & 0xFF);
548             if (!ucsdata->uni_tbl[j]) {
549                 ucsdata->uni_tbl[j] = snewn(256, char);
550                 memset(ucsdata->uni_tbl[j], 0, 256 * sizeof(char));
551             }
552             ucsdata->uni_tbl[j][ucsdata->unitab_line[i] & 0xFF] = i;
553         }
554     }
555
556     /* Find the line control characters. */
557     for (i = 0; i < 256; i++)
558         if (ucsdata->unitab_line[i] < ' '
559             || (ucsdata->unitab_line[i] >= 0x7F && 
560                 ucsdata->unitab_line[i] < 0xA0))
561             ucsdata->unitab_ctrl[i] = i;
562         else
563             ucsdata->unitab_ctrl[i] = 0xFF;
564
565     /* Generate line->screen direct conversion links. */
566     if (vtmode == VT_OEMANSI || vtmode == VT_XWINDOWS)
567         link_font(ucsdata->unitab_scoacs, ucsdata->unitab_oemcp, CSET_OEMCP);
568
569     link_font(ucsdata->unitab_line, ucsdata->unitab_font, CSET_ACP);
570     link_font(ucsdata->unitab_scoacs, ucsdata->unitab_font, CSET_ACP);
571     link_font(ucsdata->unitab_xterm, ucsdata->unitab_font, CSET_ACP);
572
573     if (vtmode == VT_OEMANSI || vtmode == VT_XWINDOWS) {
574         link_font(ucsdata->unitab_line, ucsdata->unitab_oemcp, CSET_OEMCP);
575         link_font(ucsdata->unitab_xterm, ucsdata->unitab_oemcp, CSET_OEMCP);
576     }
577
578     if (ucsdata->dbcs_screenfont &&
579         ucsdata->font_codepage != ucsdata->line_codepage) {
580         /* F***ing Microsoft fonts, Japanese and Korean codepage fonts
581          * have a currency symbol at 0x5C but their unicode value is 
582          * still given as U+005C not the correct U+00A5. */
583         ucsdata->unitab_line['\\'] = CSET_OEMCP + '\\';
584     }
585
586     /* Last chance, if !unicode then try poorman links. */
587     if (vtmode != VT_UNICODE) {
588         static const char poorman_scoacs[] = 
589             "CueaaaaceeeiiiAAE**ooouuyOUc$YPsaiounNao?++**!<>###||||++||++++++--|-+||++--|-+----++++++++##||#aBTPEsyt******EN=+><++-=... n2* ";
590         static const char poorman_latin1[] =
591             " !cL.Y|S\"Ca<--R~o+23'u|.,1o>///?AAAAAAACEEEEIIIIDNOOOOOxOUUUUYPBaaaaaaaceeeeiiiionooooo/ouuuuypy";
592         static const char poorman_vt100[] = "*#****o~**+++++-----++++|****L.";
593
594         for (i = 160; i < 256; i++)
595             if (!DIRECT_FONT(ucsdata->unitab_line[i]) &&
596                 ucsdata->unitab_line[i] >= 160 &&
597                 ucsdata->unitab_line[i] < 256) {
598                 ucsdata->unitab_line[i] =
599                     (WCHAR) (CSET_ACP +
600                              poorman_latin1[ucsdata->unitab_line[i] - 160]);
601             }
602         for (i = 96; i < 127; i++)
603             if (!DIRECT_FONT(ucsdata->unitab_xterm[i]))
604                 ucsdata->unitab_xterm[i] =
605             (WCHAR) (CSET_ACP + poorman_vt100[i - 96]);
606         for(i=128;i<256;i++) 
607             if (!DIRECT_FONT(ucsdata->unitab_scoacs[i]))
608                 ucsdata->unitab_scoacs[i] = 
609                     (WCHAR) (CSET_ACP + poorman_scoacs[i - 128]);
610     }
611 }
612
613 static void link_font(WCHAR * line_tbl, WCHAR * font_tbl, WCHAR attr)
614 {
615     int font_index, line_index, i;
616     for (line_index = 0; line_index < 256; line_index++) {
617         if (DIRECT_FONT(line_tbl[line_index]))
618             continue;
619         for(i = 0; i < 256; i++) {
620             font_index = ((32 + i) & 0xFF);
621             if (line_tbl[line_index] == font_tbl[font_index]) {
622                 line_tbl[line_index] = (WCHAR) (attr + font_index);
623                 break;
624             }
625         }
626     }
627 }
628
629 wchar_t xlat_uskbd2cyrllic(int ch)
630 {
631     static const wchar_t cyrtab[] = {
632             0,      1,       2,      3,      4,      5,      6,      7,
633             8,      9,      10,     11,     12,     13,     14,     15,
634             16,     17,     18,     19,     20,     21,     22,     23,
635             24,     25,     26,     27,     28,     29,     30,     31,
636             32,     33, 0x042d,     35,     36,     37,     38, 0x044d,
637             40,     41,     42, 0x0406, 0x0431, 0x0454, 0x044e, 0x002e,
638             48,     49,     50,     51,     52,     53,     54,     55,
639             56,     57, 0x0416, 0x0436, 0x0411, 0x0456, 0x042e, 0x002c,
640             64, 0x0424, 0x0418, 0x0421, 0x0412, 0x0423, 0x0410, 0x041f,
641         0x0420, 0x0428, 0x041e, 0x041b, 0x0414, 0x042c, 0x0422, 0x0429,
642         0x0417, 0x0419, 0x041a, 0x042b, 0x0415, 0x0413, 0x041c, 0x0426,
643         0x0427, 0x041d, 0x042f, 0x0445, 0x0457, 0x044a,     94, 0x0404,
644             96, 0x0444, 0x0438, 0x0441, 0x0432, 0x0443, 0x0430, 0x043f,
645         0x0440, 0x0448, 0x043e, 0x043b, 0x0434, 0x044c, 0x0442, 0x0449,
646         0x0437, 0x0439, 0x043a, 0x044b, 0x0435, 0x0433, 0x043c, 0x0446,
647         0x0447, 0x043d, 0x044f, 0x0425, 0x0407, 0x042a,    126,    127
648        };
649     return cyrtab[ch&0x7F];
650 }
651
652 int check_compose_internal(int first, int second, int recurse)
653 {
654
655     static const struct {
656         char first, second;
657         wchar_t composed;
658     } composetbl[] = {
659         {
660         0x2b, 0x2b, 0x0023}, {
661         0x41, 0x41, 0x0040}, {
662         0x28, 0x28, 0x005b}, {
663         0x2f, 0x2f, 0x005c}, {
664         0x29, 0x29, 0x005d}, {
665         0x28, 0x2d, 0x007b}, {
666         0x2d, 0x29, 0x007d}, {
667         0x2f, 0x5e, 0x007c}, {
668         0x21, 0x21, 0x00a1}, {
669         0x43, 0x2f, 0x00a2}, {
670         0x43, 0x7c, 0x00a2}, {
671         0x4c, 0x2d, 0x00a3}, {
672         0x4c, 0x3d, 0x20a4}, {
673         0x58, 0x4f, 0x00a4}, {
674         0x58, 0x30, 0x00a4}, {
675         0x59, 0x2d, 0x00a5}, {
676         0x59, 0x3d, 0x00a5}, {
677         0x7c, 0x7c, 0x00a6}, {
678         0x53, 0x4f, 0x00a7}, {
679         0x53, 0x21, 0x00a7}, {
680         0x53, 0x30, 0x00a7}, {
681         0x22, 0x22, 0x00a8}, {
682         0x43, 0x4f, 0x00a9}, {
683         0x43, 0x30, 0x00a9}, {
684         0x41, 0x5f, 0x00aa}, {
685         0x3c, 0x3c, 0x00ab}, {
686         0x2c, 0x2d, 0x00ac}, {
687         0x2d, 0x2d, 0x00ad}, {
688         0x52, 0x4f, 0x00ae}, {
689         0x2d, 0x5e, 0x00af}, {
690         0x30, 0x5e, 0x00b0}, {
691         0x2b, 0x2d, 0x00b1}, {
692         0x32, 0x5e, 0x00b2}, {
693         0x33, 0x5e, 0x00b3}, {
694         0x27, 0x27, 0x00b4}, {
695         0x2f, 0x55, 0x00b5}, {
696         0x50, 0x21, 0x00b6}, {
697         0x2e, 0x5e, 0x00b7}, {
698         0x2c, 0x2c, 0x00b8}, {
699         0x31, 0x5e, 0x00b9}, {
700         0x4f, 0x5f, 0x00ba}, {
701         0x3e, 0x3e, 0x00bb}, {
702         0x31, 0x34, 0x00bc}, {
703         0x31, 0x32, 0x00bd}, {
704         0x33, 0x34, 0x00be}, {
705         0x3f, 0x3f, 0x00bf}, {
706         0x60, 0x41, 0x00c0}, {
707         0x27, 0x41, 0x00c1}, {
708         0x5e, 0x41, 0x00c2}, {
709         0x7e, 0x41, 0x00c3}, {
710         0x22, 0x41, 0x00c4}, {
711         0x2a, 0x41, 0x00c5}, {
712         0x41, 0x45, 0x00c6}, {
713         0x2c, 0x43, 0x00c7}, {
714         0x60, 0x45, 0x00c8}, {
715         0x27, 0x45, 0x00c9}, {
716         0x5e, 0x45, 0x00ca}, {
717         0x22, 0x45, 0x00cb}, {
718         0x60, 0x49, 0x00cc}, {
719         0x27, 0x49, 0x00cd}, {
720         0x5e, 0x49, 0x00ce}, {
721         0x22, 0x49, 0x00cf}, {
722         0x2d, 0x44, 0x00d0}, {
723         0x7e, 0x4e, 0x00d1}, {
724         0x60, 0x4f, 0x00d2}, {
725         0x27, 0x4f, 0x00d3}, {
726         0x5e, 0x4f, 0x00d4}, {
727         0x7e, 0x4f, 0x00d5}, {
728         0x22, 0x4f, 0x00d6}, {
729         0x58, 0x58, 0x00d7}, {
730         0x2f, 0x4f, 0x00d8}, {
731         0x60, 0x55, 0x00d9}, {
732         0x27, 0x55, 0x00da}, {
733         0x5e, 0x55, 0x00db}, {
734         0x22, 0x55, 0x00dc}, {
735         0x27, 0x59, 0x00dd}, {
736         0x48, 0x54, 0x00de}, {
737         0x73, 0x73, 0x00df}, {
738         0x60, 0x61, 0x00e0}, {
739         0x27, 0x61, 0x00e1}, {
740         0x5e, 0x61, 0x00e2}, {
741         0x7e, 0x61, 0x00e3}, {
742         0x22, 0x61, 0x00e4}, {
743         0x2a, 0x61, 0x00e5}, {
744         0x61, 0x65, 0x00e6}, {
745         0x2c, 0x63, 0x00e7}, {
746         0x60, 0x65, 0x00e8}, {
747         0x27, 0x65, 0x00e9}, {
748         0x5e, 0x65, 0x00ea}, {
749         0x22, 0x65, 0x00eb}, {
750         0x60, 0x69, 0x00ec}, {
751         0x27, 0x69, 0x00ed}, {
752         0x5e, 0x69, 0x00ee}, {
753         0x22, 0x69, 0x00ef}, {
754         0x2d, 0x64, 0x00f0}, {
755         0x7e, 0x6e, 0x00f1}, {
756         0x60, 0x6f, 0x00f2}, {
757         0x27, 0x6f, 0x00f3}, {
758         0x5e, 0x6f, 0x00f4}, {
759         0x7e, 0x6f, 0x00f5}, {
760         0x22, 0x6f, 0x00f6}, {
761         0x3a, 0x2d, 0x00f7}, {
762         0x6f, 0x2f, 0x00f8}, {
763         0x60, 0x75, 0x00f9}, {
764         0x27, 0x75, 0x00fa}, {
765         0x5e, 0x75, 0x00fb}, {
766         0x22, 0x75, 0x00fc}, {
767         0x27, 0x79, 0x00fd}, {
768         0x68, 0x74, 0x00fe}, {
769         0x22, 0x79, 0x00ff},
770             /* Unicode extras. */
771         {
772         0x6f, 0x65, 0x0153}, {
773         0x4f, 0x45, 0x0152},
774             /* Compose pairs from UCS */
775         {
776         0x41, 0x2D, 0x0100}, {
777         0x61, 0x2D, 0x0101}, {
778         0x43, 0x27, 0x0106}, {
779         0x63, 0x27, 0x0107}, {
780         0x43, 0x5E, 0x0108}, {
781         0x63, 0x5E, 0x0109}, {
782         0x45, 0x2D, 0x0112}, {
783         0x65, 0x2D, 0x0113}, {
784         0x47, 0x5E, 0x011C}, {
785         0x67, 0x5E, 0x011D}, {
786         0x47, 0x2C, 0x0122}, {
787         0x67, 0x2C, 0x0123}, {
788         0x48, 0x5E, 0x0124}, {
789         0x68, 0x5E, 0x0125}, {
790         0x49, 0x7E, 0x0128}, {
791         0x69, 0x7E, 0x0129}, {
792         0x49, 0x2D, 0x012A}, {
793         0x69, 0x2D, 0x012B}, {
794         0x4A, 0x5E, 0x0134}, {
795         0x6A, 0x5E, 0x0135}, {
796         0x4B, 0x2C, 0x0136}, {
797         0x6B, 0x2C, 0x0137}, {
798         0x4C, 0x27, 0x0139}, {
799         0x6C, 0x27, 0x013A}, {
800         0x4C, 0x2C, 0x013B}, {
801         0x6C, 0x2C, 0x013C}, {
802         0x4E, 0x27, 0x0143}, {
803         0x6E, 0x27, 0x0144}, {
804         0x4E, 0x2C, 0x0145}, {
805         0x6E, 0x2C, 0x0146}, {
806         0x4F, 0x2D, 0x014C}, {
807         0x6F, 0x2D, 0x014D}, {
808         0x52, 0x27, 0x0154}, {
809         0x72, 0x27, 0x0155}, {
810         0x52, 0x2C, 0x0156}, {
811         0x72, 0x2C, 0x0157}, {
812         0x53, 0x27, 0x015A}, {
813         0x73, 0x27, 0x015B}, {
814         0x53, 0x5E, 0x015C}, {
815         0x73, 0x5E, 0x015D}, {
816         0x53, 0x2C, 0x015E}, {
817         0x73, 0x2C, 0x015F}, {
818         0x54, 0x2C, 0x0162}, {
819         0x74, 0x2C, 0x0163}, {
820         0x55, 0x7E, 0x0168}, {
821         0x75, 0x7E, 0x0169}, {
822         0x55, 0x2D, 0x016A}, {
823         0x75, 0x2D, 0x016B}, {
824         0x55, 0x2A, 0x016E}, {
825         0x75, 0x2A, 0x016F}, {
826         0x57, 0x5E, 0x0174}, {
827         0x77, 0x5E, 0x0175}, {
828         0x59, 0x5E, 0x0176}, {
829         0x79, 0x5E, 0x0177}, {
830         0x59, 0x22, 0x0178}, {
831         0x5A, 0x27, 0x0179}, {
832         0x7A, 0x27, 0x017A}, {
833         0x47, 0x27, 0x01F4}, {
834         0x67, 0x27, 0x01F5}, {
835         0x4E, 0x60, 0x01F8}, {
836         0x6E, 0x60, 0x01F9}, {
837         0x45, 0x2C, 0x0228}, {
838         0x65, 0x2C, 0x0229}, {
839         0x59, 0x2D, 0x0232}, {
840         0x79, 0x2D, 0x0233}, {
841         0x44, 0x2C, 0x1E10}, {
842         0x64, 0x2C, 0x1E11}, {
843         0x47, 0x2D, 0x1E20}, {
844         0x67, 0x2D, 0x1E21}, {
845         0x48, 0x22, 0x1E26}, {
846         0x68, 0x22, 0x1E27}, {
847         0x48, 0x2C, 0x1E28}, {
848         0x68, 0x2C, 0x1E29}, {
849         0x4B, 0x27, 0x1E30}, {
850         0x6B, 0x27, 0x1E31}, {
851         0x4D, 0x27, 0x1E3E}, {
852         0x6D, 0x27, 0x1E3F}, {
853         0x50, 0x27, 0x1E54}, {
854         0x70, 0x27, 0x1E55}, {
855         0x56, 0x7E, 0x1E7C}, {
856         0x76, 0x7E, 0x1E7D}, {
857         0x57, 0x60, 0x1E80}, {
858         0x77, 0x60, 0x1E81}, {
859         0x57, 0x27, 0x1E82}, {
860         0x77, 0x27, 0x1E83}, {
861         0x57, 0x22, 0x1E84}, {
862         0x77, 0x22, 0x1E85}, {
863         0x58, 0x22, 0x1E8C}, {
864         0x78, 0x22, 0x1E8D}, {
865         0x5A, 0x5E, 0x1E90}, {
866         0x7A, 0x5E, 0x1E91}, {
867         0x74, 0x22, 0x1E97}, {
868         0x77, 0x2A, 0x1E98}, {
869         0x79, 0x2A, 0x1E99}, {
870         0x45, 0x7E, 0x1EBC}, {
871         0x65, 0x7E, 0x1EBD}, {
872         0x59, 0x60, 0x1EF2}, {
873         0x79, 0x60, 0x1EF3}, {
874         0x59, 0x7E, 0x1EF8}, {
875         0x79, 0x7E, 0x1EF9},
876             /* Compatible/possibles from UCS */
877         {
878         0x49, 0x4A, 0x0132}, {
879         0x69, 0x6A, 0x0133}, {
880         0x4C, 0x4A, 0x01C7}, {
881         0x4C, 0x6A, 0x01C8}, {
882         0x6C, 0x6A, 0x01C9}, {
883         0x4E, 0x4A, 0x01CA}, {
884         0x4E, 0x6A, 0x01CB}, {
885         0x6E, 0x6A, 0x01CC}, {
886         0x44, 0x5A, 0x01F1}, {
887         0x44, 0x7A, 0x01F2}, {
888         0x64, 0x7A, 0x01F3}, {
889         0x2E, 0x2E, 0x2025}, {
890         0x21, 0x21, 0x203C}, {
891         0x3F, 0x21, 0x2048}, {
892         0x21, 0x3F, 0x2049}, {
893         0x52, 0x73, 0x20A8}, {
894         0x4E, 0x6F, 0x2116}, {
895         0x53, 0x4D, 0x2120}, {
896         0x54, 0x4D, 0x2122}, {
897         0x49, 0x49, 0x2161}, {
898         0x49, 0x56, 0x2163}, {
899         0x56, 0x49, 0x2165}, {
900         0x49, 0x58, 0x2168}, {
901         0x58, 0x49, 0x216A}, {
902         0x69, 0x69, 0x2171}, {
903         0x69, 0x76, 0x2173}, {
904         0x76, 0x69, 0x2175}, {
905         0x69, 0x78, 0x2178}, {
906         0x78, 0x69, 0x217A}, {
907         0x31, 0x30, 0x2469}, {
908         0x31, 0x31, 0x246A}, {
909         0x31, 0x32, 0x246B}, {
910         0x31, 0x33, 0x246C}, {
911         0x31, 0x34, 0x246D}, {
912         0x31, 0x35, 0x246E}, {
913         0x31, 0x36, 0x246F}, {
914         0x31, 0x37, 0x2470}, {
915         0x31, 0x38, 0x2471}, {
916         0x31, 0x39, 0x2472}, {
917         0x32, 0x30, 0x2473}, {
918         0x31, 0x2E, 0x2488}, {
919         0x32, 0x2E, 0x2489}, {
920         0x33, 0x2E, 0x248A}, {
921         0x34, 0x2E, 0x248B}, {
922         0x35, 0x2E, 0x248C}, {
923         0x36, 0x2E, 0x248D}, {
924         0x37, 0x2E, 0x248E}, {
925         0x38, 0x2E, 0x248F}, {
926         0x39, 0x2E, 0x2490}, {
927         0x64, 0x61, 0x3372}, {
928         0x41, 0x55, 0x3373}, {
929         0x6F, 0x56, 0x3375}, {
930         0x70, 0x63, 0x3376}, {
931         0x70, 0x41, 0x3380}, {
932         0x6E, 0x41, 0x3381}, {
933         0x6D, 0x41, 0x3383}, {
934         0x6B, 0x41, 0x3384}, {
935         0x4B, 0x42, 0x3385}, {
936         0x4D, 0x42, 0x3386}, {
937         0x47, 0x42, 0x3387}, {
938         0x70, 0x46, 0x338A}, {
939         0x6E, 0x46, 0x338B}, {
940         0x6D, 0x67, 0x338E}, {
941         0x6B, 0x67, 0x338F}, {
942         0x48, 0x7A, 0x3390}, {
943         0x66, 0x6D, 0x3399}, {
944         0x6E, 0x6D, 0x339A}, {
945         0x6D, 0x6D, 0x339C}, {
946         0x63, 0x6D, 0x339D}, {
947         0x6B, 0x6D, 0x339E}, {
948         0x50, 0x61, 0x33A9}, {
949         0x70, 0x73, 0x33B0}, {
950         0x6E, 0x73, 0x33B1}, {
951         0x6D, 0x73, 0x33B3}, {
952         0x70, 0x56, 0x33B4}, {
953         0x6E, 0x56, 0x33B5}, {
954         0x6D, 0x56, 0x33B7}, {
955         0x6B, 0x56, 0x33B8}, {
956         0x4D, 0x56, 0x33B9}, {
957         0x70, 0x57, 0x33BA}, {
958         0x6E, 0x57, 0x33BB}, {
959         0x6D, 0x57, 0x33BD}, {
960         0x6B, 0x57, 0x33BE}, {
961         0x4D, 0x57, 0x33BF}, {
962         0x42, 0x71, 0x33C3}, {
963         0x63, 0x63, 0x33C4}, {
964         0x63, 0x64, 0x33C5}, {
965         0x64, 0x42, 0x33C8}, {
966         0x47, 0x79, 0x33C9}, {
967         0x68, 0x61, 0x33CA}, {
968         0x48, 0x50, 0x33CB}, {
969         0x69, 0x6E, 0x33CC}, {
970         0x4B, 0x4B, 0x33CD}, {
971         0x4B, 0x4D, 0x33CE}, {
972         0x6B, 0x74, 0x33CF}, {
973         0x6C, 0x6D, 0x33D0}, {
974         0x6C, 0x6E, 0x33D1}, {
975         0x6C, 0x78, 0x33D3}, {
976         0x6D, 0x62, 0x33D4}, {
977         0x50, 0x48, 0x33D7}, {
978         0x50, 0x52, 0x33DA}, {
979         0x73, 0x72, 0x33DB}, {
980         0x53, 0x76, 0x33DC}, {
981         0x57, 0x62, 0x33DD}, {
982         0x66, 0x66, 0xFB00}, {
983         0x66, 0x69, 0xFB01}, {
984         0x66, 0x6C, 0xFB02}, {
985         0x73, 0x74, 0xFB06}, {
986         0, 0, 0}
987     }, *c;
988
989     int nc = -1;
990
991     for (c = composetbl; c->first; c++) {
992         if (c->first == first && c->second == second)
993             return c->composed;
994     }
995
996     if (recurse == 0) {
997         nc = check_compose_internal(second, first, 1);
998         if (nc == -1)
999             nc = check_compose_internal(toupper(first), toupper(second), 1);
1000         if (nc == -1)
1001             nc = check_compose_internal(toupper(second), toupper(first), 1);
1002     }
1003     return nc;
1004 }
1005
1006 int check_compose(int first, int second)
1007 {
1008     return check_compose_internal(first, second, 0);
1009 }
1010
1011 int decode_codepage(char *cp_name)
1012 {
1013     char *s, *d;
1014     const struct cp_list_item *cpi;
1015     int codepage = -1;
1016     CPINFO cpinfo;
1017
1018     if (!*cp_name) {
1019         /*
1020          * Here we select a plausible default code page based on
1021          * the locale the user is in. We wish to select an ISO code
1022          * page or appropriate local default _rather_ than go with
1023          * the Win125* series, because it's more important to have
1024          * CSI and friends enabled by default than the ghastly
1025          * Windows extra quote characters, and because it's more
1026          * likely the user is connecting to a remote server that
1027          * does something Unixy or VMSy and hence standards-
1028          * compliant than that they're connecting back to a Windows
1029          * box using horrible nonstandard charsets.
1030          * 
1031          * Accordingly, Robert de Bath suggests a method for
1032          * picking a default character set that runs as follows:
1033          * first call GetACP to get the system's ANSI code page
1034          * identifier, and translate as follows:
1035          * 
1036          * 1250 -> ISO 8859-2
1037          * 1251 -> KOI8-U
1038          * 1252 -> ISO 8859-1
1039          * 1253 -> ISO 8859-7
1040          * 1254 -> ISO 8859-9
1041          * 1255 -> ISO 8859-8
1042          * 1256 -> ISO 8859-6
1043          * 1257 -> ISO 8859-13 (changed from 8859-4 on advice of a Lithuanian)
1044          * 
1045          * and for anything else, choose direct-to-font.
1046          */
1047         int cp = GetACP();
1048         switch (cp) {
1049           case 1250: cp_name = "ISO-8859-2"; break;
1050           case 1251: cp_name = "KOI8-U"; break;
1051           case 1252: cp_name = "ISO-8859-1"; break;
1052           case 1253: cp_name = "ISO-8859-7"; break;
1053           case 1254: cp_name = "ISO-8859-9"; break;
1054           case 1255: cp_name = "ISO-8859-8"; break;
1055           case 1256: cp_name = "ISO-8859-6"; break;
1056           case 1257: cp_name = "ISO-8859-13"; break;
1057             /* default: leave it blank, which will select -1, direct->font */
1058         }
1059     }
1060
1061     if (cp_name && *cp_name)
1062         for (cpi = cp_list; cpi->name; cpi++) {
1063             s = cp_name;
1064             d = cpi->name;
1065             for (;;) {
1066                 while (*s && !isalnum(*s) && *s != ':')
1067                     s++;
1068                 while (*d && !isalnum(*d) && *d != ':')
1069                     d++;
1070                 if (*s == 0) {
1071                     codepage = cpi->codepage;
1072                     if (codepage == CP_UTF8)
1073                         goto break_break;
1074                     if (codepage == -1)
1075                         return codepage;
1076                     if (codepage == 0) {
1077                         codepage = 65536 + (cpi - cp_list);
1078                         goto break_break;
1079                     }
1080
1081                     if (GetCPInfo(codepage, &cpinfo) != 0)
1082                         goto break_break;
1083                 }
1084                 if (tolower(*s++) != tolower(*d++))
1085                     break;
1086             }
1087         }
1088
1089     if (cp_name && *cp_name) {
1090         d = cp_name;
1091         if (tolower(d[0]) == 'c' && tolower(d[1]) == 'p')
1092             d += 2;
1093         if (tolower(d[0]) == 'i' && tolower(d[1]) == 'b'
1094             && tolower(d[2]) == 'm')
1095             d += 3;
1096         for (s = d; *s >= '0' && *s <= '9'; s++);
1097         if (*s == 0 && s != d)
1098             codepage = atoi(d);        /* CP999 or IBM999 */
1099
1100         if (codepage == CP_ACP)
1101             codepage = GetACP();
1102         if (codepage == CP_OEMCP)
1103             codepage = GetOEMCP();
1104         if (codepage > 65535)
1105             codepage = -2;
1106     }
1107
1108   break_break:;
1109     if (codepage != -1) {
1110         if (codepage != CP_UTF8 && codepage < 65536) {
1111             if (GetCPInfo(codepage, &cpinfo) == 0) {
1112                 codepage = -2;
1113             } else if (cpinfo.MaxCharSize > 1)
1114                 codepage = -3;
1115         }
1116     }
1117     if (codepage == -1 && *cp_name)
1118         codepage = -2;
1119     return codepage;
1120 }
1121
1122 const char *cp_name(int codepage)
1123 {
1124     const struct cp_list_item *cpi, *cpno;
1125     static char buf[32];
1126
1127     if (codepage == -1) {
1128         sprintf(buf, "Use font encoding");
1129         return buf;
1130     }
1131
1132     if (codepage > 0 && codepage < 65536)
1133         sprintf(buf, "CP%03d", codepage);
1134     else
1135         *buf = 0;
1136
1137     if (codepage >= 65536) {
1138         cpno = 0;
1139         for (cpi = cp_list; cpi->name; cpi++)
1140             if (cpi == cp_list + (codepage - 65536)) {
1141                 cpno = cpi;
1142                 break;
1143             }
1144         if (cpno)
1145             for (cpi = cp_list; cpi->name; cpi++) {
1146                 if (cpno->cp_table == cpi->cp_table)
1147                     return cpi->name;
1148             }
1149     } else {
1150         for (cpi = cp_list; cpi->name; cpi++) {
1151             if (codepage == cpi->codepage)
1152                 return cpi->name;
1153         }
1154     }
1155     return buf;
1156 }
1157
1158 /*
1159  * Return the nth code page in the list, for use in the GUI
1160  * configurer.
1161  */
1162 const char *cp_enumerate(int index)
1163 {
1164     if (index < 0 || index >= lenof(cp_list))
1165         return NULL;
1166     return cp_list[index].name;
1167 }
1168
1169 void get_unitab(int codepage, wchar_t * unitab, int ftype)
1170 {
1171     char tbuf[4];
1172     int i, max = 256, flg = MB_ERR_INVALID_CHARS;
1173
1174     if (ftype)
1175         flg |= MB_USEGLYPHCHARS;
1176     if (ftype == 2)
1177         max = 128;
1178
1179     if (codepage == CP_UTF8) {
1180         for (i = 0; i < max; i++)
1181             unitab[i] = i;
1182         return;
1183     }
1184
1185     if (codepage == CP_ACP)
1186         codepage = GetACP();
1187     else if (codepage == CP_OEMCP)
1188         codepage = GetOEMCP();
1189
1190     if (codepage > 0 && codepage < 65536) {
1191         for (i = 0; i < max; i++) {
1192             tbuf[0] = i;
1193
1194             if (mb_to_wc(codepage, flg, tbuf, 1, unitab + i, 1)
1195                 != 1)
1196                 unitab[i] = 0xFFFD;
1197         }
1198     } else {
1199         int j = 256 - cp_list[codepage & 0xFFFF].cp_size;
1200         for (i = 0; i < max; i++)
1201             unitab[i] = i;
1202         for (i = j; i < max; i++)
1203             unitab[i] = cp_list[codepage & 0xFFFF].cp_table[i - j];
1204     }
1205 }
1206
1207 int wc_to_mb(int codepage, int flags, wchar_t *wcstr, int wclen,
1208              char *mbstr, int mblen, char *defchr, int *defused,
1209              struct unicode_data *ucsdata)
1210 {
1211     char *p;
1212     int i;
1213     if (ucsdata && codepage == ucsdata->line_codepage && ucsdata->uni_tbl) {
1214         /* Do this by array lookup if we can. */
1215         if (wclen < 0) {
1216             for (wclen = 0; wcstr[wclen++] ;);   /* will include the NUL */
1217         }
1218         for (p = mbstr, i = 0; i < wclen; i++) {
1219             wchar_t ch = wcstr[i];
1220             int by;
1221             char *p1;
1222             if (ucsdata->uni_tbl && (p1 = ucsdata->uni_tbl[(ch >> 8) & 0xFF])
1223                 && (by = p1[ch & 0xFF]))
1224                 *p++ = by;
1225             else if (ch < 0x80)
1226                 *p++ = (char) ch;
1227             else if (defchr) {
1228                 int j;
1229                 for (j = 0; defchr[j]; j++)
1230                     *p++ = defchr[j];
1231                 if (defused) *defused = 1;
1232             }
1233 #if 1
1234             else
1235                 *p++ = '.';
1236 #endif
1237             assert(p - mbstr < mblen);
1238         }
1239         return p - mbstr;
1240     } else
1241         return WideCharToMultiByte(codepage, flags, wcstr, wclen,
1242                                    mbstr, mblen, defchr, defused);
1243 }
1244
1245 int mb_to_wc(int codepage, int flags, char *mbstr, int mblen,
1246              wchar_t *wcstr, int wclen)
1247 {
1248     return MultiByteToWideChar(codepage, flags, mbstr, mblen, wcstr, wclen);
1249 }
1250
1251 int is_dbcs_leadbyte(int codepage, char byte)
1252 {
1253     return IsDBCSLeadByteEx(codepage, byte);
1254 }