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