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