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