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