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