Introduced wrapper macros snew(), snewn() and sresize() for the
[u/mdw/putty] / unicode.c
1 #ifdef WINDOWS
2 #include <windows.h>
3 #endif
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <ctype.h>
8 #include <time.h>
9 #include <assert.h>
10
11 #include "putty.h"
12 #include "terminal.h"
13 #include "misc.h"
14
15 /* Character conversion arrays; they are usually taken from windows,
16 * the xterm one has the four scanlines that have no unicode 2.0
17 * equivalents mapped to their unicode 3.0 locations.
18 */
19 static const WCHAR unitab_xterm_std[32] = {
20 0x2666, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
21 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba,
22 0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c,
23 0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x0020
24 };
25
26 /*
27 * If the codepage is non-zero it's a window codepage, zero means use a
28 * local codepage. The name is always converted to the first of any
29 * duplicate definitions.
30 */
31
32 /*
33 * Tables for ISO-8859-{1-10,13-16} derived from those downloaded
34 * 2001-10-02 from <http://www.unicode.org/Public/MAPPINGS/> -- jtn
35 * Table for ISO-8859-11 derived from same on 2002-11-18. -- bjh21
36 */
37
38 /* XXX: This could be done algorithmically, but I'm not sure it's
39 * worth the hassle -- jtn */
40 /* ISO/IEC 8859-1:1998 (Latin-1, "Western", "West European") */
41 static const wchar_t iso_8859_1[] = {
42 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
43 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
44 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
45 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
46 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
47 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
48 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
49 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
50 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
51 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
52 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
53 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
54 };
55
56 /* ISO/IEC 8859-2:1999 (Latin-2, "Central European", "East European") */
57 static const wchar_t iso_8859_2[] = {
58 0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7,
59 0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B,
60 0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7,
61 0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C,
62 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
63 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
64 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
65 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
66 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
67 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
68 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
69 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9
70 };
71
72 /* ISO/IEC 8859-3:1999 (Latin-3, "South European", "Maltese & Esperanto") */
73 static const wchar_t iso_8859_3[] = {
74 0x00A0, 0x0126, 0x02D8, 0x00A3, 0x00A4, 0xFFFD, 0x0124, 0x00A7,
75 0x00A8, 0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, 0xFFFD, 0x017B,
76 0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7,
77 0x00B8, 0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, 0xFFFD, 0x017C,
78 0x00C0, 0x00C1, 0x00C2, 0xFFFD, 0x00C4, 0x010A, 0x0108, 0x00C7,
79 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
80 0xFFFD, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x0120, 0x00D6, 0x00D7,
81 0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x016C, 0x015C, 0x00DF,
82 0x00E0, 0x00E1, 0x00E2, 0xFFFD, 0x00E4, 0x010B, 0x0109, 0x00E7,
83 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
84 0xFFFD, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7,
85 0x011D, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9
86 };
87
88 /* ISO/IEC 8859-4:1998 (Latin-4, "North European") */
89 static const wchar_t iso_8859_4[] = {
90 0x00A0, 0x0104, 0x0138, 0x0156, 0x00A4, 0x0128, 0x013B, 0x00A7,
91 0x00A8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00AD, 0x017D, 0x00AF,
92 0x00B0, 0x0105, 0x02DB, 0x0157, 0x00B4, 0x0129, 0x013C, 0x02C7,
93 0x00B8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014A, 0x017E, 0x014B,
94 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E,
95 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A,
96 0x0110, 0x0145, 0x014C, 0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
97 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x0168, 0x016A, 0x00DF,
98 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F,
99 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x012B,
100 0x0111, 0x0146, 0x014D, 0x0137, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
101 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x02D9
102 };
103
104 /* ISO/IEC 8859-5:1999 (Latin/Cyrillic) */
105 static const wchar_t iso_8859_5[] = {
106 0x00A0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
107 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00AD, 0x040E, 0x040F,
108 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
109 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
110 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
111 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
112 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
113 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
114 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
115 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
116 0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
117 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00A7, 0x045E, 0x045F
118 };
119
120 /* ISO/IEC 8859-6:1999 (Latin/Arabic) */
121 static const wchar_t iso_8859_6[] = {
122 0x00A0, 0xFFFD, 0xFFFD, 0xFFFD, 0x00A4, 0xFFFD, 0xFFFD, 0xFFFD,
123 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x060C, 0x00AD, 0xFFFD, 0xFFFD,
124 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
125 0xFFFD, 0xFFFD, 0xFFFD, 0x061B, 0xFFFD, 0xFFFD, 0xFFFD, 0x061F,
126 0xFFFD, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
127 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,
128 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637,
129 0x0638, 0x0639, 0x063A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
130 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647,
131 0x0648, 0x0649, 0x064A, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F,
132 0x0650, 0x0651, 0x0652, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
133 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD
134 };
135
136 /* ISO 8859-7:1987 (Latin/Greek) */
137 static const wchar_t iso_8859_7[] = {
138 0x00A0, 0x2018, 0x2019, 0x00A3, 0xFFFD, 0xFFFD, 0x00A6, 0x00A7,
139 0x00A8, 0x00A9, 0xFFFD, 0x00AB, 0x00AC, 0x00AD, 0xFFFD, 0x2015,
140 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x0385, 0x0386, 0x00B7,
141 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F,
142 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
143 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
144 0x03A0, 0x03A1, 0xFFFD, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
145 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
146 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
147 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
148 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
149 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0xFFFD
150 };
151
152 /* ISO/IEC 8859-8:1999 (Latin/Hebrew) */
153 static const wchar_t iso_8859_8[] = {
154 0x00A0, 0xFFFD, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
155 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
156 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
157 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0xFFFD,
158 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
159 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
160 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
161 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x2017,
162 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
163 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
164 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
165 0x05E8, 0x05E9, 0x05EA, 0xFFFD, 0xFFFD, 0x200E, 0x200F, 0xFFFD
166 };
167
168 /* ISO/IEC 8859-9:1999 (Latin-5, "Turkish") */
169 static const wchar_t iso_8859_9[] = {
170 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
171 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
172 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
173 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
174 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
175 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
176 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
177 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF,
178 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
179 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
180 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
181 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF
182 };
183
184 /* ISO/IEC 8859-10:1998 (Latin-6, "Nordic" [Sami, Inuit, Icelandic]) */
185 static const wchar_t iso_8859_10[] = {
186 0x00A0, 0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7,
187 0x013B, 0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A,
188 0x00B0, 0x0105, 0x0113, 0x0123, 0x012B, 0x0129, 0x0137, 0x00B7,
189 0x013C, 0x0111, 0x0161, 0x0167, 0x017E, 0x2015, 0x016B, 0x014B,
190 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E,
191 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x00CF,
192 0x00D0, 0x0145, 0x014C, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0168,
193 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
194 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F,
195 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x00EF,
196 0x00F0, 0x0146, 0x014D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0169,
197 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138
198 };
199
200 /* ISO/IEC 8859-11:2001 ("Thai", "TIS620") */
201 static const wchar_t iso_8859_11[] = {
202 0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07,
203 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F,
204 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17,
205 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F,
206 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
207 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F,
208 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37,
209 0x0E38, 0x0E39, 0x0E3A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x0E3F,
210 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47,
211 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F,
212 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57,
213 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD
214 };
215
216 /* ISO/IEC 8859-13:1998 (Latin-7, "Baltic Rim") */
217 static const wchar_t iso_8859_13[] = {
218 0x00A0, 0x201D, 0x00A2, 0x00A3, 0x00A4, 0x201E, 0x00A6, 0x00A7,
219 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6,
220 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x201C, 0x00B5, 0x00B6, 0x00B7,
221 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6,
222 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112,
223 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B,
224 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7,
225 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF,
226 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113,
227 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C,
228 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7,
229 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x2019
230 };
231
232 /* ISO/IEC 8859-14:1998 (Latin-8, "Celtic", "Gaelic/Welsh") */
233 static const wchar_t iso_8859_14[] = {
234 0x00A0, 0x1E02, 0x1E03, 0x00A3, 0x010A, 0x010B, 0x1E0A, 0x00A7,
235 0x1E80, 0x00A9, 0x1E82, 0x1E0B, 0x1EF2, 0x00AD, 0x00AE, 0x0178,
236 0x1E1E, 0x1E1F, 0x0120, 0x0121, 0x1E40, 0x1E41, 0x00B6, 0x1E56,
237 0x1E81, 0x1E57, 0x1E83, 0x1E60, 0x1EF3, 0x1E84, 0x1E85, 0x1E61,
238 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
239 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
240 0x0174, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x1E6A,
241 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x0176, 0x00DF,
242 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
243 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
244 0x0175, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x1E6B,
245 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x0177, 0x00FF
246 };
247
248 /* ISO/IEC 8859-15:1999 (Latin-9 aka -0, "euro") */
249 static const wchar_t iso_8859_15[] = {
250 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AC, 0x00A5, 0x0160, 0x00A7,
251 0x0161, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
252 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x017D, 0x00B5, 0x00B6, 0x00B7,
253 0x017E, 0x00B9, 0x00BA, 0x00BB, 0x0152, 0x0153, 0x0178, 0x00BF,
254 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
255 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
256 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
257 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
258 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
259 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
260 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
261 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
262 };
263
264 /* ISO/IEC 8859-16:2001 (Latin-10, "Balkan") */
265 static const wchar_t iso_8859_16[] = {
266 0x00A0, 0x0104, 0x0105, 0x0141, 0x20AC, 0x201E, 0x0160, 0x00A7,
267 0x0161, 0x00A9, 0x0218, 0x00AB, 0x0179, 0x00AD, 0x017A, 0x017B,
268 0x00B0, 0x00B1, 0x010C, 0x0142, 0x017D, 0x201D, 0x00B6, 0x00B7,
269 0x017E, 0x010D, 0x0219, 0x00BB, 0x0152, 0x0153, 0x0178, 0x017C,
270 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0106, 0x00C6, 0x00C7,
271 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
272 0x0110, 0x0143, 0x00D2, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x015A,
273 0x0170, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0118, 0x021A, 0x00DF,
274 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x0107, 0x00E6, 0x00E7,
275 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
276 0x0111, 0x0144, 0x00F2, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x015B,
277 0x0171, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0119, 0x021B, 0x00FF
278 };
279
280 static const wchar_t roman8[] = {
281 0x00A0, 0x00C0, 0x00C2, 0x00C8, 0x00CA, 0x00CB, 0x00CE, 0x00CF,
282 0x00B4, 0x02CB, 0x02C6, 0x00A8, 0x02DC, 0x00D9, 0x00DB, 0x20A4,
283 0x00AF, 0x00DD, 0x00FD, 0x00B0, 0x00C7, 0x00E7, 0x00D1, 0x00F1,
284 0x00A1, 0x00BF, 0x00A4, 0x00A3, 0x00A5, 0x00A7, 0x0192, 0x00A2,
285 0x00E2, 0x00EA, 0x00F4, 0x00FB, 0x00E1, 0x00E9, 0x00F3, 0x00FA,
286 0x00E0, 0x00E8, 0x00F2, 0x00F9, 0x00E4, 0x00EB, 0x00F6, 0x00FC,
287 0x00C5, 0x00EE, 0x00D8, 0x00C6, 0x00E5, 0x00ED, 0x00F8, 0x00E6,
288 0x00C4, 0x00EC, 0x00D6, 0x00DC, 0x00C9, 0x00EF, 0x00DF, 0x00D4,
289 0x00C1, 0x00C3, 0x00E3, 0x00D0, 0x00F0, 0x00CD, 0x00CC, 0x00D3,
290 0x00D2, 0x00D5, 0x00F5, 0x0160, 0x0161, 0x00DA, 0x0178, 0x00FF,
291 0x00DE, 0x00FE, 0x00B7, 0x00B5, 0x00B6, 0x00BE, 0x2014, 0x00BC,
292 0x00BD, 0x00AA, 0x00BA, 0x00AB, 0x25A0, 0x00BB, 0x00B1, 0xFFFD
293 };
294
295 static const wchar_t koi8_u[] = {
296 0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,
297 0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,
298 0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2022, 0x221A, 0x2248,
299 0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7,
300 0x2550, 0x2551, 0x2552, 0x0451, 0x0454, 0x2554, 0x0456, 0x0457,
301 0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x0491, 0x255D, 0x255E,
302 0x255F, 0x2560, 0x2561, 0x0401, 0x0404, 0x2563, 0x0406, 0x0407,
303 0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x0490, 0x256C, 0x00A9,
304 0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
305 0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E,
306 0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
307 0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A,
308 0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
309 0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E,
310 0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
311 0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A
312 };
313
314 static const wchar_t vscii[] = {
315 0x0000, 0x0001, 0x1EB2, 0x0003, 0x0004, 0x1EB4, 0x1EAA, 0x0007,
316 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
317 0x0010, 0x0011, 0x0012, 0x0013, 0x1EF6, 0x0015, 0x0016, 0x0017,
318 0x0018, 0x1EF8, 0x001a, 0x001b, 0x001c, 0x001d, 0x1EF4, 0x001f,
319 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
320 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
321 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
322 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
323 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
324 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
325 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
326 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
327 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
328 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
329 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
330 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007f,
331 0x1EA0, 0x1EAE, 0x1EB0, 0x1EB6, 0x1EA4, 0x1EA6, 0x1EA8, 0x1EAC,
332 0x1EBC, 0x1EB8, 0x1EBE, 0x1EC0, 0x1EC2, 0x1EC4, 0x1EC6, 0x1ED0,
333 0x1ED2, 0x1ED4, 0x1ED6, 0x1ED8, 0x1EE2, 0x1EDA, 0x1EDC, 0x1EDE,
334 0x1ECA, 0x1ECE, 0x1ECC, 0x1EC8, 0x1EE6, 0x0168, 0x1EE4, 0x1EF2,
335 0x00D5, 0x1EAF, 0x1EB1, 0x1EB7, 0x1EA5, 0x1EA7, 0x1EA8, 0x1EAD,
336 0x1EBD, 0x1EB9, 0x1EBF, 0x1EC1, 0x1EC3, 0x1EC5, 0x1EC7, 0x1ED1,
337 0x1ED3, 0x1ED5, 0x1ED7, 0x1EE0, 0x01A0, 0x1ED9, 0x1EDD, 0x1EDF,
338 0x1ECB, 0x1EF0, 0x1EE8, 0x1EEA, 0x1EEC, 0x01A1, 0x1EDB, 0x01AF,
339 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x1EA2, 0x0102, 0x1EB3, 0x1EB5,
340 0x00C8, 0x00C9, 0x00CA, 0x1EBA, 0x00CC, 0x00CD, 0x0128, 0x1EF3,
341 0x0110, 0x1EE9, 0x00D2, 0x00D3, 0x00D4, 0x1EA1, 0x1EF7, 0x1EEB,
342 0x1EED, 0x00D9, 0x00DA, 0x1EF9, 0x1EF5, 0x00DD, 0x1EE1, 0x01B0,
343 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x1EA3, 0x0103, 0x1EEF, 0x1EAB,
344 0x00E8, 0x00E9, 0x00EA, 0x1EBB, 0x00EC, 0x00ED, 0x0129, 0x1EC9,
345 0x0111, 0x1EF1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x1ECF, 0x1ECD,
346 0x1EE5, 0x00F9, 0x00FA, 0x0169, 0x1EE7, 0x00FD, 0x1EE3, 0x1EEE
347 };
348
349 static const wchar_t dec_mcs[] = {
350 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0xFFFD, 0x00A5, 0xFFFD, 0x00A7,
351 0x00A4, 0x00A9, 0x00AA, 0x00AB, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
352 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0xFFFD, 0x00B5, 0x00B6, 0x00B7,
353 0xFFFD, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0xFFFD, 0x00BF,
354 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
355 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
356 0xFFFD, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0152,
357 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0178, 0xFFFD, 0x00DF,
358 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
359 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
360 0xFFFD, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0153,
361 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FF, 0xFFFD, 0xFFFD
362 };
363
364 struct cp_list_item {
365 char *name;
366 int codepage;
367 int cp_size;
368 const wchar_t *cp_table;
369 };
370
371 static const struct cp_list_item cp_list[] = {
372 {"ISO-8859-1:1998 (Latin-1, West Europe)", 0, 96, iso_8859_1},
373 {"ISO-8859-2:1999 (Latin-2, East Europe)", 0, 96, iso_8859_2},
374 {"ISO-8859-3:1999 (Latin-3, South Europe)", 0, 96, iso_8859_3},
375 {"ISO-8859-4:1998 (Latin-4, North Europe)", 0, 96, iso_8859_4},
376 {"ISO-8859-5:1999 (Latin/Cyrillic)", 0, 96, iso_8859_5},
377 {"ISO-8859-6:1999 (Latin/Arabic)", 0, 96, iso_8859_6},
378 {"ISO-8859-7:1987 (Latin/Greek)", 0, 96, iso_8859_7},
379 {"ISO-8859-8:1999 (Latin/Hebrew)", 0, 96, iso_8859_8},
380 {"ISO-8859-9:1999 (Latin-5, Turkish)", 0, 96, iso_8859_9},
381 {"ISO-8859-10:1998 (Latin-6, Nordic)", 0, 96, iso_8859_10},
382 {"ISO-8859-11:2001 (Latin/Thai)", 0, 96, iso_8859_11},
383 {"ISO-8859-13:1998 (Latin-7, Baltic)", 0, 96, iso_8859_13},
384 {"ISO-8859-14:1998 (Latin-8, Celtic)", 0, 96, iso_8859_14},
385 {"ISO-8859-15:1999 (Latin-9, \"euro\")", 0, 96, iso_8859_15},
386 {"ISO-8859-16:2001 (Latin-10, Balkan)", 0, 96, iso_8859_16},
387
388 {"UTF-8", CP_UTF8},
389
390 {"KOI8-U", 0, 128, koi8_u},
391 {"KOI8-R", 20866},
392 {"HP-ROMAN8", 0, 96, roman8},
393 {"VSCII", 0, 256, vscii},
394 {"DEC-MCS", 0, 96, dec_mcs},
395
396 {"Win1250 (Central European)", 1250},
397 {"Win1251 (Cyrillic)", 1251},
398 {"Win1252 (Western)", 1252},
399 {"Win1253 (Greek)", 1253},
400 {"Win1254 (Turkish)", 1254},
401 {"Win1255 (Hebrew)", 1255},
402 {"Win1256 (Arabic)", 1256},
403 {"Win1257 (Baltic)", 1257},
404 {"Win1258 (Vietnamese)", 1258},
405
406 {"CP437", 437},
407 {"CP819", 28591},
408 {"CP878", 20866},
409
410 {"Use font encoding", -1},
411
412 {0, 0}
413 };
414
415 static void link_font(WCHAR * line_tbl, WCHAR * font_tbl, WCHAR attr);
416
417 void init_ucs(Config *cfg, struct unicode_data *ucsdata)
418 {
419 int i, j;
420 int used_dtf = 0;
421 char tbuf[256];
422
423 for (i = 0; i < 256; i++)
424 tbuf[i] = i;
425
426 /* Decide on the Line and Font codepages */
427 ucsdata->line_codepage = decode_codepage(cfg->line_codepage);
428
429 if (ucsdata->font_codepage <= 0) {
430 ucsdata->font_codepage=0;
431 ucsdata->dbcs_screenfont=0;
432 }
433
434 if (cfg->vtmode == VT_OEMONLY) {
435 ucsdata->font_codepage = 437;
436 ucsdata->dbcs_screenfont = 0;
437 if (ucsdata->line_codepage <= 0)
438 ucsdata->line_codepage = GetACP();
439 } else if (ucsdata->line_codepage <= 0)
440 ucsdata->line_codepage = ucsdata->font_codepage;
441
442 /* Collect screen font ucs table */
443 if (ucsdata->dbcs_screenfont || ucsdata->font_codepage == 0) {
444 get_unitab(ucsdata->font_codepage, ucsdata->unitab_font, 2);
445 for (i = 128; i < 256; i++)
446 ucsdata->unitab_font[i] = (WCHAR) (ATTR_ACP + i);
447 } else {
448 get_unitab(ucsdata->font_codepage, ucsdata->unitab_font, 1);
449
450 /* CP437 fonts are often broken ... */
451 if (ucsdata->font_codepage == 437)
452 ucsdata->unitab_font[0] = ucsdata->unitab_font[255] = 0xFFFF;
453 }
454 if (cfg->vtmode == VT_XWINDOWS)
455 memcpy(ucsdata->unitab_font + 1, unitab_xterm_std,
456 sizeof(unitab_xterm_std));
457
458 /* Collect OEMCP ucs table */
459 get_unitab(CP_OEMCP, ucsdata->unitab_oemcp, 1);
460
461 /* Collect CP437 ucs table for SCO acs */
462 if (cfg->vtmode == VT_OEMANSI || cfg->vtmode == VT_XWINDOWS)
463 memcpy(ucsdata->unitab_scoacs, ucsdata->unitab_oemcp,
464 sizeof(ucsdata->unitab_scoacs));
465 else
466 get_unitab(437, ucsdata->unitab_scoacs, 1);
467
468 /* Collect line set ucs table */
469 if (ucsdata->line_codepage == ucsdata->font_codepage &&
470 (ucsdata->dbcs_screenfont ||
471 cfg->vtmode == VT_POORMAN || ucsdata->font_codepage==0)) {
472
473 /* For DBCS and POOR fonts force direct to font */
474 used_dtf = 1;
475 for (i = 0; i < 32; i++)
476 ucsdata->unitab_line[i] = (WCHAR) i;
477 for (i = 32; i < 256; i++)
478 ucsdata->unitab_line[i] = (WCHAR) (ATTR_ACP + i);
479 ucsdata->unitab_line[127] = (WCHAR) 127;
480 } else {
481 get_unitab(ucsdata->line_codepage, ucsdata->unitab_line, 0);
482 }
483
484 #if 0
485 debug(
486 ("Line cp%d, Font cp%d%s\n", ucsdata->line_codepage,
487 ucsdata->font_codepage, ucsdata->dbcs_screenfont ? " DBCS" : ""));
488
489 for (i = 0; i < 256; i += 16) {
490 for (j = 0; j < 16; j++) {
491 debug(("%04x%s", ucsdata->unitab_line[i + j], j == 15 ? "" : ","));
492 }
493 debug(("\n"));
494 }
495 #endif
496
497 /* VT100 graphics - NB: Broken for non-ascii CP's */
498 memcpy(ucsdata->unitab_xterm, ucsdata->unitab_line,
499 sizeof(ucsdata->unitab_xterm));
500 memcpy(ucsdata->unitab_xterm + '`', unitab_xterm_std,
501 sizeof(unitab_xterm_std));
502 ucsdata->unitab_xterm['_'] = ' ';
503
504 /* Generate UCS ->line page table. */
505 if (ucsdata->uni_tbl) {
506 for (i = 0; i < 256; i++)
507 if (ucsdata->uni_tbl[i])
508 sfree(ucsdata->uni_tbl[i]);
509 sfree(ucsdata->uni_tbl);
510 ucsdata->uni_tbl = 0;
511 }
512 if (!used_dtf) {
513 for (i = 0; i < 256; i++) {
514 if (DIRECT_CHAR(ucsdata->unitab_line[i]))
515 continue;
516 if (DIRECT_FONT(ucsdata->unitab_line[i]))
517 continue;
518 if (!ucsdata->uni_tbl) {
519 ucsdata->uni_tbl = snewn(256, char *);
520 memset(ucsdata->uni_tbl, 0, 256 * sizeof(char *));
521 }
522 j = ((ucsdata->unitab_line[i] >> 8) & 0xFF);
523 if (!ucsdata->uni_tbl[j]) {
524 ucsdata->uni_tbl[j] = snewn(256, char);
525 memset(ucsdata->uni_tbl[j], 0, 256 * sizeof(char));
526 }
527 ucsdata->uni_tbl[j][ucsdata->unitab_line[i] & 0xFF] = i;
528 }
529 }
530
531 /* Find the line control characters. */
532 for (i = 0; i < 256; i++)
533 if (ucsdata->unitab_line[i] < ' '
534 || (ucsdata->unitab_line[i] >= 0x7F &&
535 ucsdata->unitab_line[i] < 0xA0))
536 ucsdata->unitab_ctrl[i] = i;
537 else
538 ucsdata->unitab_ctrl[i] = 0xFF;
539
540 /* Generate line->screen direct conversion links. */
541 if (cfg->vtmode == VT_OEMANSI || cfg->vtmode == VT_XWINDOWS)
542 link_font(ucsdata->unitab_scoacs, ucsdata->unitab_oemcp, ATTR_OEMCP);
543
544 link_font(ucsdata->unitab_line, ucsdata->unitab_font, ATTR_ACP);
545 link_font(ucsdata->unitab_scoacs, ucsdata->unitab_font, ATTR_ACP);
546 link_font(ucsdata->unitab_xterm, ucsdata->unitab_font, ATTR_ACP);
547
548 if (cfg->vtmode == VT_OEMANSI || cfg->vtmode == VT_XWINDOWS) {
549 link_font(ucsdata->unitab_line, ucsdata->unitab_oemcp, ATTR_OEMCP);
550 link_font(ucsdata->unitab_xterm, ucsdata->unitab_oemcp, ATTR_OEMCP);
551 }
552
553 if (ucsdata->dbcs_screenfont &&
554 ucsdata->font_codepage != ucsdata->line_codepage) {
555 /* F***ing Microsoft fonts, Japanese and Korean codepage fonts
556 * have a currency symbol at 0x5C but their unicode value is
557 * still given as U+005C not the correct U+00A5. */
558 ucsdata->unitab_line['\\'] = ATTR_OEMCP + '\\';
559 }
560
561 /* Last chance, if !unicode then try poorman links. */
562 if (cfg->vtmode != VT_UNICODE) {
563 static const char poorman_scoacs[] =
564 "CueaaaaceeeiiiAAE**ooouuyOUc$YPsaiounNao?++**!<>###||||++||++++++--|-+||++--|-+----++++++++##||#aBTPEsyt******EN=+><++-=... n2* ";
565 static const char poorman_latin1[] =
566 " !cL.Y|S\"Ca<--R~o+23'u|.,1o>///?AAAAAAACEEEEIIIIDNOOOOOxOUUUUYPBaaaaaaaceeeeiiiionooooo/ouuuuypy";
567 static const char poorman_vt100[] = "*#****o~**+++++-----++++|****L.";
568
569 for (i = 160; i < 256; i++)
570 if (!DIRECT_FONT(ucsdata->unitab_line[i]) &&
571 ucsdata->unitab_line[i] >= 160 &&
572 ucsdata->unitab_line[i] < 256) {
573 ucsdata->unitab_line[i] =
574 (WCHAR) (ATTR_ACP +
575 poorman_latin1[ucsdata->unitab_line[i] - 160]);
576 }
577 for (i = 96; i < 127; i++)
578 if (!DIRECT_FONT(ucsdata->unitab_xterm[i]))
579 ucsdata->unitab_xterm[i] =
580 (WCHAR) (ATTR_ACP + poorman_vt100[i - 96]);
581 for(i=128;i<256;i++)
582 if (!DIRECT_FONT(ucsdata->unitab_scoacs[i]))
583 ucsdata->unitab_scoacs[i] =
584 (WCHAR) (ATTR_ACP + poorman_scoacs[i - 128]);
585 }
586 }
587
588 static void link_font(WCHAR * line_tbl, WCHAR * font_tbl, WCHAR attr)
589 {
590 int font_index, line_index, i;
591 for (line_index = 0; line_index < 256; line_index++) {
592 if (DIRECT_FONT(line_tbl[line_index]))
593 continue;
594 for(i = 0; i < 256; i++) {
595 font_index = ((32 + i) & 0xFF);
596 if (line_tbl[line_index] == font_tbl[font_index]) {
597 line_tbl[line_index] = (WCHAR) (attr + font_index);
598 break;
599 }
600 }
601 }
602 }
603
604 wchar_t xlat_uskbd2cyrllic(int ch)
605 {
606 static const wchar_t cyrtab[] = {
607 0, 1, 2, 3, 4, 5, 6, 7,
608 8, 9, 10, 11, 12, 13, 14, 15,
609 16, 17, 18, 19, 20, 21, 22, 23,
610 24, 25, 26, 27, 28, 29, 30, 31,
611 32, 33, 0x042d, 35, 36, 37, 38, 0x044d,
612 40, 41, 42, 0x0406, 0x0431, 0x0454, 0x044e, 0x002e,
613 48, 49, 50, 51, 52, 53, 54, 55,
614 56, 57, 0x0416, 0x0436, 0x0411, 0x0456, 0x042e, 0x002c,
615 64, 0x0424, 0x0418, 0x0421, 0x0412, 0x0423, 0x0410, 0x041f,
616 0x0420, 0x0428, 0x041e, 0x041b, 0x0414, 0x042c, 0x0422, 0x0429,
617 0x0417, 0x0419, 0x041a, 0x042b, 0x0415, 0x0413, 0x041c, 0x0426,
618 0x0427, 0x041d, 0x042f, 0x0445, 0x0457, 0x044a, 94, 0x0404,
619 96, 0x0444, 0x0438, 0x0441, 0x0432, 0x0443, 0x0430, 0x043f,
620 0x0440, 0x0448, 0x043e, 0x043b, 0x0434, 0x044c, 0x0442, 0x0449,
621 0x0437, 0x0439, 0x043a, 0x044b, 0x0435, 0x0433, 0x043c, 0x0446,
622 0x0447, 0x043d, 0x044f, 0x0425, 0x0407, 0x042a, 126, 127
623 };
624 return cyrtab[ch&0x7F];
625 }
626
627 int check_compose_internal(int first, int second, int recurse)
628 {
629
630 static const struct {
631 char first, second;
632 wchar_t composed;
633 } composetbl[] = {
634 {
635 0x2b, 0x2b, 0x0023}, {
636 0x41, 0x41, 0x0040}, {
637 0x28, 0x28, 0x005b}, {
638 0x2f, 0x2f, 0x005c}, {
639 0x29, 0x29, 0x005d}, {
640 0x28, 0x2d, 0x007b}, {
641 0x2d, 0x29, 0x007d}, {
642 0x2f, 0x5e, 0x007c}, {
643 0x21, 0x21, 0x00a1}, {
644 0x43, 0x2f, 0x00a2}, {
645 0x43, 0x7c, 0x00a2}, {
646 0x4c, 0x2d, 0x00a3}, {
647 0x4c, 0x3d, 0x20a4}, {
648 0x58, 0x4f, 0x00a4}, {
649 0x58, 0x30, 0x00a4}, {
650 0x59, 0x2d, 0x00a5}, {
651 0x59, 0x3d, 0x00a5}, {
652 0x7c, 0x7c, 0x00a6}, {
653 0x53, 0x4f, 0x00a7}, {
654 0x53, 0x21, 0x00a7}, {
655 0x53, 0x30, 0x00a7}, {
656 0x22, 0x22, 0x00a8}, {
657 0x43, 0x4f, 0x00a9}, {
658 0x43, 0x30, 0x00a9}, {
659 0x41, 0x5f, 0x00aa}, {
660 0x3c, 0x3c, 0x00ab}, {
661 0x2c, 0x2d, 0x00ac}, {
662 0x2d, 0x2d, 0x00ad}, {
663 0x52, 0x4f, 0x00ae}, {
664 0x2d, 0x5e, 0x00af}, {
665 0x30, 0x5e, 0x00b0}, {
666 0x2b, 0x2d, 0x00b1}, {
667 0x32, 0x5e, 0x00b2}, {
668 0x33, 0x5e, 0x00b3}, {
669 0x27, 0x27, 0x00b4}, {
670 0x2f, 0x55, 0x00b5}, {
671 0x50, 0x21, 0x00b6}, {
672 0x2e, 0x5e, 0x00b7}, {
673 0x2c, 0x2c, 0x00b8}, {
674 0x31, 0x5e, 0x00b9}, {
675 0x4f, 0x5f, 0x00ba}, {
676 0x3e, 0x3e, 0x00bb}, {
677 0x31, 0x34, 0x00bc}, {
678 0x31, 0x32, 0x00bd}, {
679 0x33, 0x34, 0x00be}, {
680 0x3f, 0x3f, 0x00bf}, {
681 0x60, 0x41, 0x00c0}, {
682 0x27, 0x41, 0x00c1}, {
683 0x5e, 0x41, 0x00c2}, {
684 0x7e, 0x41, 0x00c3}, {
685 0x22, 0x41, 0x00c4}, {
686 0x2a, 0x41, 0x00c5}, {
687 0x41, 0x45, 0x00c6}, {
688 0x2c, 0x43, 0x00c7}, {
689 0x60, 0x45, 0x00c8}, {
690 0x27, 0x45, 0x00c9}, {
691 0x5e, 0x45, 0x00ca}, {
692 0x22, 0x45, 0x00cb}, {
693 0x60, 0x49, 0x00cc}, {
694 0x27, 0x49, 0x00cd}, {
695 0x5e, 0x49, 0x00ce}, {
696 0x22, 0x49, 0x00cf}, {
697 0x2d, 0x44, 0x00d0}, {
698 0x7e, 0x4e, 0x00d1}, {
699 0x60, 0x4f, 0x00d2}, {
700 0x27, 0x4f, 0x00d3}, {
701 0x5e, 0x4f, 0x00d4}, {
702 0x7e, 0x4f, 0x00d5}, {
703 0x22, 0x4f, 0x00d6}, {
704 0x58, 0x58, 0x00d7}, {
705 0x2f, 0x4f, 0x00d8}, {
706 0x60, 0x55, 0x00d9}, {
707 0x27, 0x55, 0x00da}, {
708 0x5e, 0x55, 0x00db}, {
709 0x22, 0x55, 0x00dc}, {
710 0x27, 0x59, 0x00dd}, {
711 0x48, 0x54, 0x00de}, {
712 0x73, 0x73, 0x00df}, {
713 0x60, 0x61, 0x00e0}, {
714 0x27, 0x61, 0x00e1}, {
715 0x5e, 0x61, 0x00e2}, {
716 0x7e, 0x61, 0x00e3}, {
717 0x22, 0x61, 0x00e4}, {
718 0x2a, 0x61, 0x00e5}, {
719 0x61, 0x65, 0x00e6}, {
720 0x2c, 0x63, 0x00e7}, {
721 0x60, 0x65, 0x00e8}, {
722 0x27, 0x65, 0x00e9}, {
723 0x5e, 0x65, 0x00ea}, {
724 0x22, 0x65, 0x00eb}, {
725 0x60, 0x69, 0x00ec}, {
726 0x27, 0x69, 0x00ed}, {
727 0x5e, 0x69, 0x00ee}, {
728 0x22, 0x69, 0x00ef}, {
729 0x2d, 0x64, 0x00f0}, {
730 0x7e, 0x6e, 0x00f1}, {
731 0x60, 0x6f, 0x00f2}, {
732 0x27, 0x6f, 0x00f3}, {
733 0x5e, 0x6f, 0x00f4}, {
734 0x7e, 0x6f, 0x00f5}, {
735 0x22, 0x6f, 0x00f6}, {
736 0x3a, 0x2d, 0x00f7}, {
737 0x6f, 0x2f, 0x00f8}, {
738 0x60, 0x75, 0x00f9}, {
739 0x27, 0x75, 0x00fa}, {
740 0x5e, 0x75, 0x00fb}, {
741 0x22, 0x75, 0x00fc}, {
742 0x27, 0x79, 0x00fd}, {
743 0x68, 0x74, 0x00fe}, {
744 0x22, 0x79, 0x00ff},
745 /* Unicode extras. */
746 {
747 0x6f, 0x65, 0x0153}, {
748 0x4f, 0x45, 0x0152},
749 /* Compose pairs from UCS */
750 {
751 0x41, 0x2D, 0x0100}, {
752 0x61, 0x2D, 0x0101}, {
753 0x43, 0x27, 0x0106}, {
754 0x63, 0x27, 0x0107}, {
755 0x43, 0x5E, 0x0108}, {
756 0x63, 0x5E, 0x0109}, {
757 0x45, 0x2D, 0x0112}, {
758 0x65, 0x2D, 0x0113}, {
759 0x47, 0x5E, 0x011C}, {
760 0x67, 0x5E, 0x011D}, {
761 0x47, 0x2C, 0x0122}, {
762 0x67, 0x2C, 0x0123}, {
763 0x48, 0x5E, 0x0124}, {
764 0x68, 0x5E, 0x0125}, {
765 0x49, 0x7E, 0x0128}, {
766 0x69, 0x7E, 0x0129}, {
767 0x49, 0x2D, 0x012A}, {
768 0x69, 0x2D, 0x012B}, {
769 0x4A, 0x5E, 0x0134}, {
770 0x6A, 0x5E, 0x0135}, {
771 0x4B, 0x2C, 0x0136}, {
772 0x6B, 0x2C, 0x0137}, {
773 0x4C, 0x27, 0x0139}, {
774 0x6C, 0x27, 0x013A}, {
775 0x4C, 0x2C, 0x013B}, {
776 0x6C, 0x2C, 0x013C}, {
777 0x4E, 0x27, 0x0143}, {
778 0x6E, 0x27, 0x0144}, {
779 0x4E, 0x2C, 0x0145}, {
780 0x6E, 0x2C, 0x0146}, {
781 0x4F, 0x2D, 0x014C}, {
782 0x6F, 0x2D, 0x014D}, {
783 0x52, 0x27, 0x0154}, {
784 0x72, 0x27, 0x0155}, {
785 0x52, 0x2C, 0x0156}, {
786 0x72, 0x2C, 0x0157}, {
787 0x53, 0x27, 0x015A}, {
788 0x73, 0x27, 0x015B}, {
789 0x53, 0x5E, 0x015C}, {
790 0x73, 0x5E, 0x015D}, {
791 0x53, 0x2C, 0x015E}, {
792 0x73, 0x2C, 0x015F}, {
793 0x54, 0x2C, 0x0162}, {
794 0x74, 0x2C, 0x0163}, {
795 0x55, 0x7E, 0x0168}, {
796 0x75, 0x7E, 0x0169}, {
797 0x55, 0x2D, 0x016A}, {
798 0x75, 0x2D, 0x016B}, {
799 0x55, 0x2A, 0x016E}, {
800 0x75, 0x2A, 0x016F}, {
801 0x57, 0x5E, 0x0174}, {
802 0x77, 0x5E, 0x0175}, {
803 0x59, 0x5E, 0x0176}, {
804 0x79, 0x5E, 0x0177}, {
805 0x59, 0x22, 0x0178}, {
806 0x5A, 0x27, 0x0179}, {
807 0x7A, 0x27, 0x017A}, {
808 0x47, 0x27, 0x01F4}, {
809 0x67, 0x27, 0x01F5}, {
810 0x4E, 0x60, 0x01F8}, {
811 0x6E, 0x60, 0x01F9}, {
812 0x45, 0x2C, 0x0228}, {
813 0x65, 0x2C, 0x0229}, {
814 0x59, 0x2D, 0x0232}, {
815 0x79, 0x2D, 0x0233}, {
816 0x44, 0x2C, 0x1E10}, {
817 0x64, 0x2C, 0x1E11}, {
818 0x47, 0x2D, 0x1E20}, {
819 0x67, 0x2D, 0x1E21}, {
820 0x48, 0x22, 0x1E26}, {
821 0x68, 0x22, 0x1E27}, {
822 0x48, 0x2C, 0x1E28}, {
823 0x68, 0x2C, 0x1E29}, {
824 0x4B, 0x27, 0x1E30}, {
825 0x6B, 0x27, 0x1E31}, {
826 0x4D, 0x27, 0x1E3E}, {
827 0x6D, 0x27, 0x1E3F}, {
828 0x50, 0x27, 0x1E54}, {
829 0x70, 0x27, 0x1E55}, {
830 0x56, 0x7E, 0x1E7C}, {
831 0x76, 0x7E, 0x1E7D}, {
832 0x57, 0x60, 0x1E80}, {
833 0x77, 0x60, 0x1E81}, {
834 0x57, 0x27, 0x1E82}, {
835 0x77, 0x27, 0x1E83}, {
836 0x57, 0x22, 0x1E84}, {
837 0x77, 0x22, 0x1E85}, {
838 0x58, 0x22, 0x1E8C}, {
839 0x78, 0x22, 0x1E8D}, {
840 0x5A, 0x5E, 0x1E90}, {
841 0x7A, 0x5E, 0x1E91}, {
842 0x74, 0x22, 0x1E97}, {
843 0x77, 0x2A, 0x1E98}, {
844 0x79, 0x2A, 0x1E99}, {
845 0x45, 0x7E, 0x1EBC}, {
846 0x65, 0x7E, 0x1EBD}, {
847 0x59, 0x60, 0x1EF2}, {
848 0x79, 0x60, 0x1EF3}, {
849 0x59, 0x7E, 0x1EF8}, {
850 0x79, 0x7E, 0x1EF9},
851 /* Compatible/possibles from UCS */
852 {
853 0x49, 0x4A, 0x0132}, {
854 0x69, 0x6A, 0x0133}, {
855 0x4C, 0x4A, 0x01C7}, {
856 0x4C, 0x6A, 0x01C8}, {
857 0x6C, 0x6A, 0x01C9}, {
858 0x4E, 0x4A, 0x01CA}, {
859 0x4E, 0x6A, 0x01CB}, {
860 0x6E, 0x6A, 0x01CC}, {
861 0x44, 0x5A, 0x01F1}, {
862 0x44, 0x7A, 0x01F2}, {
863 0x64, 0x7A, 0x01F3}, {
864 0x2E, 0x2E, 0x2025}, {
865 0x21, 0x21, 0x203C}, {
866 0x3F, 0x21, 0x2048}, {
867 0x21, 0x3F, 0x2049}, {
868 0x52, 0x73, 0x20A8}, {
869 0x4E, 0x6F, 0x2116}, {
870 0x53, 0x4D, 0x2120}, {
871 0x54, 0x4D, 0x2122}, {
872 0x49, 0x49, 0x2161}, {
873 0x49, 0x56, 0x2163}, {
874 0x56, 0x49, 0x2165}, {
875 0x49, 0x58, 0x2168}, {
876 0x58, 0x49, 0x216A}, {
877 0x69, 0x69, 0x2171}, {
878 0x69, 0x76, 0x2173}, {
879 0x76, 0x69, 0x2175}, {
880 0x69, 0x78, 0x2178}, {
881 0x78, 0x69, 0x217A}, {
882 0x31, 0x30, 0x2469}, {
883 0x31, 0x31, 0x246A}, {
884 0x31, 0x32, 0x246B}, {
885 0x31, 0x33, 0x246C}, {
886 0x31, 0x34, 0x246D}, {
887 0x31, 0x35, 0x246E}, {
888 0x31, 0x36, 0x246F}, {
889 0x31, 0x37, 0x2470}, {
890 0x31, 0x38, 0x2471}, {
891 0x31, 0x39, 0x2472}, {
892 0x32, 0x30, 0x2473}, {
893 0x31, 0x2E, 0x2488}, {
894 0x32, 0x2E, 0x2489}, {
895 0x33, 0x2E, 0x248A}, {
896 0x34, 0x2E, 0x248B}, {
897 0x35, 0x2E, 0x248C}, {
898 0x36, 0x2E, 0x248D}, {
899 0x37, 0x2E, 0x248E}, {
900 0x38, 0x2E, 0x248F}, {
901 0x39, 0x2E, 0x2490}, {
902 0x64, 0x61, 0x3372}, {
903 0x41, 0x55, 0x3373}, {
904 0x6F, 0x56, 0x3375}, {
905 0x70, 0x63, 0x3376}, {
906 0x70, 0x41, 0x3380}, {
907 0x6E, 0x41, 0x3381}, {
908 0x6D, 0x41, 0x3383}, {
909 0x6B, 0x41, 0x3384}, {
910 0x4B, 0x42, 0x3385}, {
911 0x4D, 0x42, 0x3386}, {
912 0x47, 0x42, 0x3387}, {
913 0x70, 0x46, 0x338A}, {
914 0x6E, 0x46, 0x338B}, {
915 0x6D, 0x67, 0x338E}, {
916 0x6B, 0x67, 0x338F}, {
917 0x48, 0x7A, 0x3390}, {
918 0x66, 0x6D, 0x3399}, {
919 0x6E, 0x6D, 0x339A}, {
920 0x6D, 0x6D, 0x339C}, {
921 0x63, 0x6D, 0x339D}, {
922 0x6B, 0x6D, 0x339E}, {
923 0x50, 0x61, 0x33A9}, {
924 0x70, 0x73, 0x33B0}, {
925 0x6E, 0x73, 0x33B1}, {
926 0x6D, 0x73, 0x33B3}, {
927 0x70, 0x56, 0x33B4}, {
928 0x6E, 0x56, 0x33B5}, {
929 0x6D, 0x56, 0x33B7}, {
930 0x6B, 0x56, 0x33B8}, {
931 0x4D, 0x56, 0x33B9}, {
932 0x70, 0x57, 0x33BA}, {
933 0x6E, 0x57, 0x33BB}, {
934 0x6D, 0x57, 0x33BD}, {
935 0x6B, 0x57, 0x33BE}, {
936 0x4D, 0x57, 0x33BF}, {
937 0x42, 0x71, 0x33C3}, {
938 0x63, 0x63, 0x33C4}, {
939 0x63, 0x64, 0x33C5}, {
940 0x64, 0x42, 0x33C8}, {
941 0x47, 0x79, 0x33C9}, {
942 0x68, 0x61, 0x33CA}, {
943 0x48, 0x50, 0x33CB}, {
944 0x69, 0x6E, 0x33CC}, {
945 0x4B, 0x4B, 0x33CD}, {
946 0x4B, 0x4D, 0x33CE}, {
947 0x6B, 0x74, 0x33CF}, {
948 0x6C, 0x6D, 0x33D0}, {
949 0x6C, 0x6E, 0x33D1}, {
950 0x6C, 0x78, 0x33D3}, {
951 0x6D, 0x62, 0x33D4}, {
952 0x50, 0x48, 0x33D7}, {
953 0x50, 0x52, 0x33DA}, {
954 0x73, 0x72, 0x33DB}, {
955 0x53, 0x76, 0x33DC}, {
956 0x57, 0x62, 0x33DD}, {
957 0x66, 0x66, 0xFB00}, {
958 0x66, 0x69, 0xFB01}, {
959 0x66, 0x6C, 0xFB02}, {
960 0x73, 0x74, 0xFB06}, {
961 0, 0, 0}
962 }, *c;
963
964 int nc = -1;
965
966 for (c = composetbl; c->first; c++) {
967 if (c->first == first && c->second == second)
968 return c->composed;
969 }
970
971 if (recurse == 0) {
972 nc = check_compose_internal(second, first, 1);
973 if (nc == -1)
974 nc = check_compose_internal(toupper(first), toupper(second), 1);
975 if (nc == -1)
976 nc = check_compose_internal(toupper(second), toupper(first), 1);
977 }
978 return nc;
979 }
980
981 int check_compose(int first, int second)
982 {
983 return check_compose_internal(first, second, 0);
984 }
985
986 int decode_codepage(char *cp_name)
987 {
988 char *s, *d;
989 const struct cp_list_item *cpi;
990 int codepage = -1;
991 CPINFO cpinfo;
992
993 if (!*cp_name) {
994 /*
995 * Here we select a plausible default code page based on
996 * the locale the user is in. We wish to select an ISO code
997 * page or appropriate local default _rather_ than go with
998 * the Win125* series, because it's more important to have
999 * CSI and friends enabled by default than the ghastly
1000 * Windows extra quote characters, and because it's more
1001 * likely the user is connecting to a remote server that
1002 * does something Unixy or VMSy and hence standards-
1003 * compliant than that they're connecting back to a Windows
1004 * box using horrible nonstandard charsets.
1005 *
1006 * Accordingly, Robert de Bath suggests a method for
1007 * picking a default character set that runs as follows:
1008 * first call GetACP to get the system's ANSI code page
1009 * identifier, and translate as follows:
1010 *
1011 * 1250 -> ISO 8859-2
1012 * 1251 -> KOI8-U
1013 * 1252 -> ISO 8859-1
1014 * 1253 -> ISO 8859-7
1015 * 1254 -> ISO 8859-9
1016 * 1255 -> ISO 8859-8
1017 * 1256 -> ISO 8859-6
1018 * 1257 -> ISO 8859-4
1019 *
1020 * and for anything else, choose direct-to-font.
1021 */
1022 int cp = GetACP();
1023 switch (cp) {
1024 case 1250: cp_name = "ISO-8859-2"; break;
1025 case 1251: cp_name = "KOI8-U"; break;
1026 case 1252: cp_name = "ISO-8859-1"; break;
1027 case 1253: cp_name = "ISO-8859-7"; break;
1028 case 1254: cp_name = "ISO-8859-9"; break;
1029 case 1255: cp_name = "ISO-8859-8"; break;
1030 case 1256: cp_name = "ISO-8859-6"; break;
1031 case 1257: cp_name = "ISO-8859-4"; break;
1032 /* default: leave it blank, which will select -1, direct->font */
1033 }
1034 }
1035
1036 if (cp_name && *cp_name)
1037 for (cpi = cp_list; cpi->name; cpi++) {
1038 s = cp_name;
1039 d = cpi->name;
1040 for (;;) {
1041 while (*s && !isalnum(*s) && *s != ':')
1042 s++;
1043 while (*d && !isalnum(*d) && *d != ':')
1044 d++;
1045 if (*s == 0) {
1046 codepage = cpi->codepage;
1047 if (codepage == CP_UTF8)
1048 goto break_break;
1049 if (codepage == -1)
1050 return codepage;
1051 if (codepage == 0) {
1052 codepage = 65536 + (cpi - cp_list);
1053 goto break_break;
1054 }
1055
1056 if (GetCPInfo(codepage, &cpinfo) != 0)
1057 goto break_break;
1058 }
1059 if (tolower(*s++) != tolower(*d++))
1060 break;
1061 }
1062 }
1063
1064 if (cp_name && *cp_name) {
1065 d = cp_name;
1066 if (tolower(d[0]) == 'c' && tolower(d[1]) == 'p')
1067 d += 2;
1068 if (tolower(d[0]) == 'i' && tolower(d[1]) == 'b'
1069 && tolower(d[1]) == 'm')
1070 d += 3;
1071 for (s = d; *s >= '0' && *s <= '9'; s++);
1072 if (*s == 0 && s != d)
1073 codepage = atoi(d); /* CP999 or IBM999 */
1074
1075 if (codepage == CP_ACP)
1076 codepage = GetACP();
1077 if (codepage == CP_OEMCP)
1078 codepage = GetOEMCP();
1079 if (codepage > 65535)
1080 codepage = -2;
1081 }
1082
1083 break_break:;
1084 if (codepage != -1) {
1085 if (codepage != CP_UTF8 && codepage < 65536) {
1086 if (GetCPInfo(codepage, &cpinfo) == 0) {
1087 codepage = -2;
1088 } else if (cpinfo.MaxCharSize > 1)
1089 codepage = -3;
1090 }
1091 }
1092 if (codepage == -1 && *cp_name)
1093 codepage = -2;
1094 return codepage;
1095 }
1096
1097 char *cp_name(int codepage)
1098 {
1099 const struct cp_list_item *cpi, *cpno;
1100 static char buf[32];
1101
1102 if (codepage == -1) {
1103 sprintf(buf, "Use font encoding");
1104 return buf;
1105 }
1106
1107 if (codepage > 0 && codepage < 65536)
1108 sprintf(buf, "CP%03d", codepage);
1109 else
1110 *buf = 0;
1111
1112 if (codepage >= 65536) {
1113 cpno = 0;
1114 for (cpi = cp_list; cpi->name; cpi++)
1115 if (cpi == cp_list + (codepage - 65536)) {
1116 cpno = cpi;
1117 break;
1118 }
1119 if (cpno)
1120 for (cpi = cp_list; cpi->name; cpi++) {
1121 if (cpno->cp_table == cpi->cp_table)
1122 return cpi->name;
1123 }
1124 } else {
1125 for (cpi = cp_list; cpi->name; cpi++) {
1126 if (codepage == cpi->codepage)
1127 return cpi->name;
1128 }
1129 }
1130 return buf;
1131 }
1132
1133 /*
1134 * Return the nth code page in the list, for use in the GUI
1135 * configurer.
1136 */
1137 char *cp_enumerate(int index)
1138 {
1139 if (index < 0 || index >= lenof(cp_list))
1140 return NULL;
1141 return cp_list[index].name;
1142 }
1143
1144 void get_unitab(int codepage, wchar_t * unitab, int ftype)
1145 {
1146 char tbuf[4];
1147 int i, max = 256, flg = MB_ERR_INVALID_CHARS;
1148
1149 if (ftype)
1150 flg |= MB_USEGLYPHCHARS;
1151 if (ftype == 2)
1152 max = 128;
1153
1154 if (codepage == CP_UTF8) {
1155 for (i = 0; i < max; i++)
1156 unitab[i] = i;
1157 return;
1158 }
1159
1160 if (codepage == CP_ACP)
1161 codepage = GetACP();
1162 else if (codepage == CP_OEMCP)
1163 codepage = GetOEMCP();
1164
1165 if (codepage > 0 && codepage < 65536) {
1166 for (i = 0; i < max; i++) {
1167 tbuf[0] = i;
1168
1169 if (mb_to_wc(codepage, flg, tbuf, 1, unitab + i, 1)
1170 != 1)
1171 unitab[i] = 0xFFFD;
1172 }
1173 } else {
1174 int j = 256 - cp_list[codepage & 0xFFFF].cp_size;
1175 for (i = 0; i < max; i++)
1176 unitab[i] = i;
1177 for (i = j; i < max; i++)
1178 unitab[i] = cp_list[codepage & 0xFFFF].cp_table[i - j];
1179 }
1180 }
1181
1182 int wc_to_mb(int codepage, int flags, wchar_t *wcstr, int wclen,
1183 char *mbstr, int mblen, char *defchr, int *defused,
1184 struct unicode_data *ucsdata)
1185 {
1186 char *p;
1187 int i;
1188 if (ucsdata && codepage == ucsdata->line_codepage && ucsdata->uni_tbl) {
1189 /* Do this by array lookup if we can. */
1190 if (wclen < 0) {
1191 for (wclen = 0; wcstr[wclen++] ;); /* will include the NUL */
1192 }
1193 for (p = mbstr, i = 0; i < wclen; i++) {
1194 wchar_t ch = wcstr[i];
1195 int by;
1196 char *p1;
1197 if (ucsdata->uni_tbl && (p1 = ucsdata->uni_tbl[(ch >> 8) & 0xFF])
1198 && (by = p1[ch & 0xFF]))
1199 *p++ = by;
1200 else if (ch < 0x80)
1201 *p++ = (char) ch;
1202 else if (defchr) {
1203 int j;
1204 for (j = 0; defchr[j]; j++)
1205 *p++ = defchr[j];
1206 if (defused) *defused = 1;
1207 }
1208 #if 1
1209 else
1210 *p++ = '.';
1211 #endif
1212 assert(p - mbstr < mblen);
1213 }
1214 return p - mbstr;
1215 } else
1216 return WideCharToMultiByte(codepage, flags, wcstr, wclen,
1217 mbstr, mblen, defchr, defused);
1218 }
1219
1220 int mb_to_wc(int codepage, int flags, char *mbstr, int mblen,
1221 wchar_t *wcstr, int wclen)
1222 {
1223 return MultiByteToWideChar(codepage, flags, mbstr, mblen, wcstr, wclen);
1224 }
1225
1226 int is_dbcs_leadbyte(int codepage, char byte)
1227 {
1228 return IsDBCSLeadByteEx(codepage, byte);
1229 }