Post-release destabilisation! Completely remove the struct type
[u/mdw/putty] / 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 }