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