Fix the `SERIOUS NETWORK INTERNAL ERROR' oversight in winnet.c. See
[u/mdw/putty] / unicode.c
CommitLineData
4eeb7d09 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"
875b193f 9#include "misc.h"
4eeb7d09 10
4eeb7d09 11static 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
dc3c8261 15 * equivalents mapped to their unicode 3.0 locations.
4eeb7d09 16 */
17static char **uni_tbl;
18
19static 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
875b193f 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
32static 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
47static 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
a0c1ddf1 62static wchar_t iso_8859_13[] = {
875b193f 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
77static 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
92static 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
a0c1ddf1 107static 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
875b193f 122static 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
137static 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
156static 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
191static 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
206struct cp_list_item {
4eeb7d09 207 char *name;
208 int codepage;
209 int cp_size;
210 wchar_t *cp_table;
875b193f 211};
212
213static 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},
a0c1ddf1 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},
875b193f 227 {"ISO-8859-15:1998", 0, 96, iso_8859_15},
a0c1ddf1 228 {"ISO-8859-16:2001", 0, 96, iso_8859_16},
875b193f 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
b8ae1f0f 248 {"CP437", 437},
875b193f 249 {"CP819", 28591},
250 {"CP878", 20866},
b8ae1f0f 251
252 {"Use font encoding", -1},
253
875b193f 254 {0, 0}
255};
4eeb7d09 256
257static void link_font(WCHAR * line_tbl, WCHAR * font_tbl, WCHAR attr);
258
259void init_ucs_tables(void)
260{
261 int i, j;
262 int used_dtf = 0;
263 char tbuf[256];
dc3c8261 264
4eeb7d09 265 for (i = 0; i < 256; i++)
266 tbuf[i] = i;
267
268 /* Decide on the Line and Font codepages */
269 line_codepage = decode_codepage(cfg.line_codepage);
270
8f22582c 271 if (font_codepage <= 0) {
272 font_codepage=0;
273 dbcs_screenfont=0;
274 }
275
4eeb7d09 276 if (cfg.vtmode == VT_OEMONLY) {
277 font_codepage = 437;
278 dbcs_screenfont = 0;
279 if (line_codepage <= 0)
280 line_codepage = GetACP();
281 } else if (line_codepage <= 0)
282 line_codepage = font_codepage;
4eeb7d09 283
284 /* Collect screen font ucs table */
8f22582c 285 if (dbcs_screenfont || font_codepage == 0) {
4eeb7d09 286 get_unitab(font_codepage, unitab_font, 2);
287 for (i = 128; i < 256; i++)
288 unitab_font[i] = (WCHAR) (ATTR_ACP + i);
289 } else {
290 get_unitab(font_codepage, unitab_font, 1);
291
292 /* CP437 fonts are often broken ... */
293 if (font_codepage == 437)
294 unitab_font[0] = unitab_font[255] = 0xFFFF;
295 }
296 if (cfg.vtmode == VT_XWINDOWS)
297 memcpy(unitab_font + 1, unitab_xterm_std,
298 sizeof(unitab_xterm_std));
299
300 /* Collect OEMCP ucs table */
301 get_unitab(CP_OEMCP, unitab_oemcp, 1);
302
d3cb5465 303 /* Collect CP437 ucs table for SCO acs */
304 if (cfg.vtmode == VT_OEMANSI || cfg.vtmode == VT_XWINDOWS)
305 memcpy(unitab_scoacs, unitab_oemcp, sizeof(unitab_scoacs));
306 else
307 get_unitab(437, unitab_scoacs, 1);
308
4eeb7d09 309 /* Collect line set ucs table */
310 if (line_codepage == font_codepage &&
8f22582c 311 (dbcs_screenfont || cfg.vtmode == VT_POORMAN || font_codepage==0)) {
4eeb7d09 312
313 /* For DBCS and POOR fonts force direct to font */
314 used_dtf = 1;
315 for (i = 0; i < 32; i++)
316 unitab_line[i] = (WCHAR) i;
317 for (i = 32; i < 256; i++)
318 unitab_line[i] = (WCHAR) (ATTR_ACP + i);
319 unitab_line[127] = (WCHAR) 127;
320 } else {
321 get_unitab(line_codepage, unitab_line, 0);
322 }
323
324#if 0
325 debug(
326 ("Line cp%d, Font cp%d%s\n", line_codepage, font_codepage,
327 dbcs_screenfont ? " DBCS" : ""));
328
329 for (i = 0; i < 256; i += 16) {
330 for (j = 0; j < 16; j++) {
331 debug(("%04x%s", unitab_line[i + j], j == 15 ? "" : ","));
332 }
333 debug(("\n"));
334 }
335#endif
336
337 /* VT100 graphics - NB: Broken for non-ascii CP's */
338 memcpy(unitab_xterm, unitab_line, sizeof(unitab_xterm));
339 memcpy(unitab_xterm + '`', unitab_xterm_std, sizeof(unitab_xterm_std));
340 unitab_xterm['_'] = ' ';
341
342 /* Generate UCS ->line page table. */
343 if (uni_tbl) {
344 for (i = 0; i < 256; i++)
345 if (uni_tbl[i])
346 sfree(uni_tbl[i]);
347 sfree(uni_tbl);
348 uni_tbl = 0;
349 }
350 if (!used_dtf) {
351 for (i = 0; i < 256; i++) {
352 if (DIRECT_CHAR(unitab_line[i]))
353 continue;
354 if (DIRECT_FONT(unitab_line[i]))
355 continue;
356 if (!uni_tbl) {
357 uni_tbl = smalloc(256 * sizeof(char *));
358 memset(uni_tbl, 0, 256 * sizeof(char *));
359 }
360 j = ((unitab_line[i] >> 8) & 0xFF);
361 if (!uni_tbl[j]) {
362 uni_tbl[j] = smalloc(256 * sizeof(char));
363 memset(uni_tbl[j], 0, 256 * sizeof(char));
364 }
365 uni_tbl[j][unitab_line[i] & 0xFF] = i;
366 }
367 }
368
369 /* Find the line control characters. */
370 for (i = 0; i < 256; i++)
371 if (unitab_line[i] < ' '
372 || (unitab_line[i] >= 0x7F && unitab_line[i] < 0xA0))
373 unitab_ctrl[i] = i;
374 else
375 unitab_ctrl[i] = 0xFF;
376
377 /* Generate line->screen direct conversion links. */
d3cb5465 378 if (cfg.vtmode == VT_OEMANSI || cfg.vtmode == VT_XWINDOWS)
379 link_font(unitab_scoacs, unitab_oemcp, ATTR_OEMCP);
380
4eeb7d09 381 link_font(unitab_line, unitab_font, ATTR_ACP);
d3cb5465 382 link_font(unitab_scoacs, unitab_font, ATTR_ACP);
4eeb7d09 383 link_font(unitab_xterm, unitab_font, ATTR_ACP);
384
385 if (cfg.vtmode == VT_OEMANSI || cfg.vtmode == VT_XWINDOWS) {
386 link_font(unitab_line, unitab_oemcp, ATTR_OEMCP);
387 link_font(unitab_xterm, unitab_oemcp, ATTR_OEMCP);
388 }
389
5a73255e 390 if (dbcs_screenfont && font_codepage != line_codepage) {
391 /* F***ing Microsoft fonts, Japanese and Korean codepage fonts
392 * have a currency symbol at 0x5C but their unicode value is
393 * still given as U+005C not the correct U+00A5. */
394 unitab_line['\\'] = ATTR_OEMCP + '\\';
395 }
396
4eeb7d09 397 /* Last chance, if !unicode then try poorman links. */
398 if (cfg.vtmode != VT_UNICODE) {
d3cb5465 399 static char poorman_scoacs[] =
400 "CueaaaaceeeiiiAAE**ooouuyOUc$YPsaiounNao?++**!<>###||||++||++++++--|-+||++--|-+----++++++++##||#aBTPEsyt******EN=+><++-=... n2* ";
4eeb7d09 401 static char poorman_latin1[] =
402 " !cL.Y|S\"Ca<--R~o+23'u|.,1o>///?AAAAAAACEEEEIIIIDNOOOOOxOUUUUYPBaaaaaaaceeeeiiiionooooo/ouuuuypy";
403 static char poorman_vt100[] = "*#****o~**+++++-----++++|****L.";
404
405 for (i = 160; i < 256; i++)
406 if (!DIRECT_FONT(unitab_line[i]) &&
407 unitab_line[i] >= 160 && unitab_line[i] < 256)
408 unitab_line[i] = (WCHAR) (ATTR_ACP
409 + poorman_latin1[unitab_line[i] -
410 160]);
411 for (i = 96; i < 127; i++)
412 if (!DIRECT_FONT(unitab_xterm[i]))
413 unitab_xterm[i] =
414 (WCHAR) (ATTR_ACP + poorman_vt100[i - 96]);
d3cb5465 415 for(i=128;i<256;i++)
416 if (!DIRECT_FONT(unitab_scoacs[i]))
417 unitab_scoacs[i] =
418 (WCHAR) (ATTR_ACP + poorman_scoacs[i - 128]);
4eeb7d09 419 }
420}
421
422static void link_font(WCHAR * line_tbl, WCHAR * font_tbl, WCHAR attr)
423{
614e8f54 424 int font_index, line_index, i;
425 for (line_index = 0; line_index < 256; line_index++) {
426 if (DIRECT_FONT(line_tbl[line_index]))
4eeb7d09 427 continue;
614e8f54 428 for(i = 0; i < 256; i++) {
429 font_index = ((32 + i) & 0xFF);
430 if (line_tbl[line_index] == font_tbl[font_index]) {
431 line_tbl[line_index] = (WCHAR) (attr + font_index);
4eeb7d09 432 break;
433 }
434 }
435 }
436}
437
760e88b2 438void lpage_send(int codepage, char *buf, int len, int interactive)
4eeb7d09 439{
440 static wchar_t *widebuffer = 0;
441 static int widesize = 0;
442 int wclen;
443
444 if (codepage < 0) {
760e88b2 445 ldisc_send(buf, len, interactive);
4eeb7d09 446 return;
447 }
448
449 if (len > widesize) {
450 sfree(widebuffer);
451 widebuffer = smalloc(len * 2 * sizeof(wchar_t));
452 widesize = len * 2;
453 }
454
455 wclen =
456 MultiByteToWideChar(codepage, 0, buf, len, widebuffer, widesize);
760e88b2 457 luni_send(widebuffer, wclen, interactive);
4eeb7d09 458}
459
760e88b2 460void luni_send(wchar_t * widebuf, int len, int interactive)
4eeb7d09 461{
462 static char *linebuffer = 0;
463 static int linesize = 0;
8f22582c 464 int ratio = (in_utf)?3:1;
4eeb7d09 465 int i;
466 char *p;
467
468 if (len * ratio > linesize) {
469 sfree(linebuffer);
470 linebuffer = smalloc(len * ratio * 2 * sizeof(wchar_t));
471 linesize = len * ratio * 2;
472 }
473
8f22582c 474 if (in_utf) {
4eeb7d09 475 /* UTF is a simple algorithm */
476 for (p = linebuffer, i = 0; i < len; i++) {
477 wchar_t ch = widebuf[i];
05054a30 478 /* Windows wchar_t is UTF-16 */
479 if ((ch&0xF800) == 0xD800) ch = '.';
480
4eeb7d09 481 if (ch < 0x80) {
482 *p++ = (char) (ch);
483 } else if (ch < 0x800) {
484 *p++ = (0xC0 | (ch >> 6));
485 *p++ = (0x80 | (ch & 0x3F));
486 } else {
487 *p++ = (0xE0 | (ch >> 12));
488 *p++ = (0x80 | ((ch >> 6) & 0x3F));
489 *p++ = (0x80 | (ch & 0x3F));
490 }
491 }
492 } else if (!uni_tbl) {
493 int rv;
494 rv = WideCharToMultiByte(line_codepage, 0, widebuf, len,
495 linebuffer, linesize, NULL, NULL);
496 if (rv >= 0)
497 p = linebuffer + rv;
498 else
499 p = linebuffer;
500 } else {
501 /* Others are a lookup in an array */
502 for (p = linebuffer, i = 0; i < len; i++) {
503 wchar_t ch = widebuf[i];
504 int by;
505 char *p1;
506 if (uni_tbl && (p1 = uni_tbl[(ch >> 8) & 0xFF])
507 && (by = p1[ch & 0xFF]))
508 *p++ = by;
509 else if (ch < 0x80)
510 *p++ = (char) ch;
511#if 1
512 else
513 *p++ = '.';
514#endif
515 }
516 }
517 if (p > linebuffer)
760e88b2 518 ldisc_send(linebuffer, p - linebuffer, interactive);
4eeb7d09 519}
520
a9c02454 521wchar_t xlat_uskbd2cyrllic(int ch)
522{
523 static wchar_t cyrtab[] = {
524 0, 1, 2, 3, 4, 5, 6, 7,
525 8, 9, 10, 11, 12, 13, 14, 15,
526 16, 17, 18, 19, 20, 21, 22, 23,
527 24, 25, 26, 27, 28, 29, 30, 31,
528 32, 33, 0x042d, 35, 36, 37, 38, 0x044d,
529 40, 41, 42, 0x0406, 0x0431, 0x0454, 0x044e, 0x002e,
530 48, 49, 50, 51, 52, 53, 54, 55,
531 56, 57, 0x0416, 0x0436, 0x0411, 0x0456, 0x042e, 0x002c,
532 64, 0x0424, 0x0418, 0x0421, 0x0412, 0x0423, 0x0410, 0x041f,
533 0x0420, 0x0428, 0x041e, 0x041b, 0x0414, 0x042c, 0x0422, 0x0429,
534 0x0417, 0x0419, 0x041a, 0x042b, 0x0415, 0x0413, 0x041c, 0x0426,
535 0x0427, 0x041d, 0x042f, 0x0445, 0x0457, 0x044a, 94, 0x0404,
536 96, 0x0444, 0x0438, 0x0441, 0x0432, 0x0443, 0x0430, 0x043f,
537 0x0440, 0x0448, 0x043e, 0x043b, 0x0434, 0x044c, 0x0442, 0x0449,
538 0x0437, 0x0439, 0x043a, 0x044b, 0x0435, 0x0433, 0x043c, 0x0446,
539 0x0447, 0x043d, 0x044f, 0x0425, 0x0407, 0x042a, 126, 127
540 };
541 return cyrtab[ch&0x7F];
542}
543
4eeb7d09 544int check_compose(int first, int second)
545{
546
547 static struct {
548 char first, second;
549 wchar_t composed;
550 } composetbl[] = {
551 {
552 0x2b, 0x2b, 0x0023}, {
553 0x41, 0x41, 0x0040}, {
554 0x28, 0x28, 0x005b}, {
555 0x2f, 0x2f, 0x005c}, {
556 0x29, 0x29, 0x005d}, {
557 0x28, 0x2d, 0x007b}, {
558 0x2d, 0x29, 0x007d}, {
559 0x2f, 0x5e, 0x007c}, {
560 0x21, 0x21, 0x00a1}, {
561 0x43, 0x2f, 0x00a2}, {
562 0x43, 0x7c, 0x00a2}, {
563 0x4c, 0x2d, 0x00a3}, {
5a73255e 564 0x4c, 0x3d, 0x20a4}, {
4eeb7d09 565 0x58, 0x4f, 0x00a4}, {
566 0x58, 0x30, 0x00a4}, {
567 0x59, 0x2d, 0x00a5}, {
568 0x59, 0x3d, 0x00a5}, {
569 0x7c, 0x7c, 0x00a6}, {
570 0x53, 0x4f, 0x00a7}, {
571 0x53, 0x21, 0x00a7}, {
572 0x53, 0x30, 0x00a7}, {
573 0x22, 0x22, 0x00a8}, {
574 0x43, 0x4f, 0x00a9}, {
575 0x43, 0x30, 0x00a9}, {
576 0x41, 0x5f, 0x00aa}, {
577 0x3c, 0x3c, 0x00ab}, {
578 0x2c, 0x2d, 0x00ac}, {
579 0x2d, 0x2d, 0x00ad}, {
580 0x52, 0x4f, 0x00ae}, {
581 0x2d, 0x5e, 0x00af}, {
582 0x30, 0x5e, 0x00b0}, {
583 0x2b, 0x2d, 0x00b1}, {
584 0x32, 0x5e, 0x00b2}, {
585 0x33, 0x5e, 0x00b3}, {
586 0x27, 0x27, 0x00b4}, {
587 0x2f, 0x55, 0x00b5}, {
588 0x50, 0x21, 0x00b6}, {
589 0x2e, 0x5e, 0x00b7}, {
590 0x2c, 0x2c, 0x00b8}, {
591 0x31, 0x5e, 0x00b9}, {
592 0x4f, 0x5f, 0x00ba}, {
593 0x3e, 0x3e, 0x00bb}, {
594 0x31, 0x34, 0x00bc}, {
595 0x31, 0x32, 0x00bd}, {
596 0x33, 0x34, 0x00be}, {
597 0x3f, 0x3f, 0x00bf}, {
598 0x60, 0x41, 0x00c0}, {
599 0x27, 0x41, 0x00c1}, {
600 0x5e, 0x41, 0x00c2}, {
601 0x7e, 0x41, 0x00c3}, {
602 0x22, 0x41, 0x00c4}, {
603 0x2a, 0x41, 0x00c5}, {
604 0x41, 0x45, 0x00c6}, {
605 0x2c, 0x43, 0x00c7}, {
606 0x60, 0x45, 0x00c8}, {
607 0x27, 0x45, 0x00c9}, {
608 0x5e, 0x45, 0x00ca}, {
609 0x22, 0x45, 0x00cb}, {
610 0x60, 0x49, 0x00cc}, {
611 0x27, 0x49, 0x00cd}, {
612 0x5e, 0x49, 0x00ce}, {
613 0x22, 0x49, 0x00cf}, {
614 0x2d, 0x44, 0x00d0}, {
615 0x7e, 0x4e, 0x00d1}, {
616 0x60, 0x4f, 0x00d2}, {
617 0x27, 0x4f, 0x00d3}, {
618 0x5e, 0x4f, 0x00d4}, {
619 0x7e, 0x4f, 0x00d5}, {
620 0x22, 0x4f, 0x00d6}, {
621 0x58, 0x58, 0x00d7}, {
622 0x2f, 0x4f, 0x00d8}, {
623 0x60, 0x55, 0x00d9}, {
624 0x27, 0x55, 0x00da}, {
625 0x5e, 0x55, 0x00db}, {
626 0x22, 0x55, 0x00dc}, {
627 0x27, 0x59, 0x00dd}, {
628 0x48, 0x54, 0x00de}, {
629 0x73, 0x73, 0x00df}, {
630 0x60, 0x61, 0x00e0}, {
631 0x27, 0x61, 0x00e1}, {
632 0x5e, 0x61, 0x00e2}, {
633 0x7e, 0x61, 0x00e3}, {
634 0x22, 0x61, 0x00e4}, {
635 0x2a, 0x61, 0x00e5}, {
636 0x61, 0x65, 0x00e6}, {
637 0x2c, 0x63, 0x00e7}, {
638 0x60, 0x65, 0x00e8}, {
639 0x27, 0x65, 0x00e9}, {
640 0x5e, 0x65, 0x00ea}, {
641 0x22, 0x65, 0x00eb}, {
642 0x60, 0x69, 0x00ec}, {
643 0x27, 0x69, 0x00ed}, {
644 0x5e, 0x69, 0x00ee}, {
645 0x22, 0x69, 0x00ef}, {
646 0x2d, 0x64, 0x00f0}, {
647 0x7e, 0x6e, 0x00f1}, {
648 0x60, 0x6f, 0x00f2}, {
649 0x27, 0x6f, 0x00f3}, {
650 0x5e, 0x6f, 0x00f4}, {
651 0x7e, 0x6f, 0x00f5}, {
652 0x22, 0x6f, 0x00f6}, {
653 0x3a, 0x2d, 0x00f7}, {
654 0x6f, 0x2f, 0x00f8}, {
655 0x60, 0x75, 0x00f9}, {
656 0x27, 0x75, 0x00fa}, {
657 0x5e, 0x75, 0x00fb}, {
658 0x22, 0x75, 0x00fc}, {
659 0x27, 0x79, 0x00fd}, {
660 0x68, 0x74, 0x00fe}, {
661 0x22, 0x79, 0x00ff},
662 /* Unicode extras. */
663 {
664 0x6f, 0x65, 0x0153}, {
665 0x4f, 0x45, 0x0152},
666 /* Compose pairs from UCS */
667 {
668 0x41, 0x2D, 0x0100}, {
669 0x61, 0x2D, 0x0101}, {
670 0x43, 0x27, 0x0106}, {
671 0x63, 0x27, 0x0107}, {
672 0x43, 0x5E, 0x0108}, {
673 0x63, 0x5E, 0x0109}, {
674 0x45, 0x2D, 0x0112}, {
675 0x65, 0x2D, 0x0113}, {
676 0x47, 0x5E, 0x011C}, {
677 0x67, 0x5E, 0x011D}, {
678 0x47, 0x2C, 0x0122}, {
679 0x67, 0x2C, 0x0123}, {
680 0x48, 0x5E, 0x0124}, {
681 0x68, 0x5E, 0x0125}, {
682 0x49, 0x7E, 0x0128}, {
683 0x69, 0x7E, 0x0129}, {
684 0x49, 0x2D, 0x012A}, {
685 0x69, 0x2D, 0x012B}, {
686 0x4A, 0x5E, 0x0134}, {
687 0x6A, 0x5E, 0x0135}, {
688 0x4B, 0x2C, 0x0136}, {
689 0x6B, 0x2C, 0x0137}, {
690 0x4C, 0x27, 0x0139}, {
691 0x6C, 0x27, 0x013A}, {
692 0x4C, 0x2C, 0x013B}, {
693 0x6C, 0x2C, 0x013C}, {
694 0x4E, 0x27, 0x0143}, {
695 0x6E, 0x27, 0x0144}, {
696 0x4E, 0x2C, 0x0145}, {
697 0x6E, 0x2C, 0x0146}, {
698 0x4F, 0x2D, 0x014C}, {
699 0x6F, 0x2D, 0x014D}, {
700 0x52, 0x27, 0x0154}, {
701 0x72, 0x27, 0x0155}, {
702 0x52, 0x2C, 0x0156}, {
703 0x72, 0x2C, 0x0157}, {
704 0x53, 0x27, 0x015A}, {
705 0x73, 0x27, 0x015B}, {
706 0x53, 0x5E, 0x015C}, {
707 0x73, 0x5E, 0x015D}, {
708 0x53, 0x2C, 0x015E}, {
709 0x73, 0x2C, 0x015F}, {
710 0x54, 0x2C, 0x0162}, {
711 0x74, 0x2C, 0x0163}, {
712 0x55, 0x7E, 0x0168}, {
713 0x75, 0x7E, 0x0169}, {
714 0x55, 0x2D, 0x016A}, {
715 0x75, 0x2D, 0x016B}, {
716 0x55, 0x2A, 0x016E}, {
717 0x75, 0x2A, 0x016F}, {
718 0x57, 0x5E, 0x0174}, {
719 0x77, 0x5E, 0x0175}, {
720 0x59, 0x5E, 0x0176}, {
721 0x79, 0x5E, 0x0177}, {
722 0x59, 0x22, 0x0178}, {
723 0x5A, 0x27, 0x0179}, {
724 0x7A, 0x27, 0x017A}, {
725 0x47, 0x27, 0x01F4}, {
726 0x67, 0x27, 0x01F5}, {
727 0x4E, 0x60, 0x01F8}, {
728 0x6E, 0x60, 0x01F9}, {
729 0x45, 0x2C, 0x0228}, {
730 0x65, 0x2C, 0x0229}, {
731 0x59, 0x2D, 0x0232}, {
732 0x79, 0x2D, 0x0233}, {
733 0x44, 0x2C, 0x1E10}, {
734 0x64, 0x2C, 0x1E11}, {
735 0x47, 0x2D, 0x1E20}, {
736 0x67, 0x2D, 0x1E21}, {
737 0x48, 0x22, 0x1E26}, {
738 0x68, 0x22, 0x1E27}, {
739 0x48, 0x2C, 0x1E28}, {
740 0x68, 0x2C, 0x1E29}, {
741 0x4B, 0x27, 0x1E30}, {
742 0x6B, 0x27, 0x1E31}, {
743 0x4D, 0x27, 0x1E3E}, {
744 0x6D, 0x27, 0x1E3F}, {
745 0x50, 0x27, 0x1E54}, {
746 0x70, 0x27, 0x1E55}, {
747 0x56, 0x7E, 0x1E7C}, {
748 0x76, 0x7E, 0x1E7D}, {
749 0x57, 0x60, 0x1E80}, {
750 0x77, 0x60, 0x1E81}, {
751 0x57, 0x27, 0x1E82}, {
752 0x77, 0x27, 0x1E83}, {
753 0x57, 0x22, 0x1E84}, {
754 0x77, 0x22, 0x1E85}, {
755 0x58, 0x22, 0x1E8C}, {
756 0x78, 0x22, 0x1E8D}, {
757 0x5A, 0x5E, 0x1E90}, {
758 0x7A, 0x5E, 0x1E91}, {
759 0x74, 0x22, 0x1E97}, {
760 0x77, 0x2A, 0x1E98}, {
761 0x79, 0x2A, 0x1E99}, {
762 0x45, 0x7E, 0x1EBC}, {
763 0x65, 0x7E, 0x1EBD}, {
764 0x59, 0x60, 0x1EF2}, {
765 0x79, 0x60, 0x1EF3}, {
766 0x59, 0x7E, 0x1EF8}, {
767 0x79, 0x7E, 0x1EF9},
768 /* Compatible/possibles from UCS */
769 {
770 0x49, 0x4A, 0x0132}, {
771 0x69, 0x6A, 0x0133}, {
772 0x4C, 0x4A, 0x01C7}, {
773 0x4C, 0x6A, 0x01C8}, {
774 0x6C, 0x6A, 0x01C9}, {
775 0x4E, 0x4A, 0x01CA}, {
776 0x4E, 0x6A, 0x01CB}, {
777 0x6E, 0x6A, 0x01CC}, {
778 0x44, 0x5A, 0x01F1}, {
779 0x44, 0x7A, 0x01F2}, {
780 0x64, 0x7A, 0x01F3}, {
781 0x2E, 0x2E, 0x2025}, {
782 0x21, 0x21, 0x203C}, {
783 0x3F, 0x21, 0x2048}, {
784 0x21, 0x3F, 0x2049}, {
785 0x52, 0x73, 0x20A8}, {
786 0x4E, 0x6F, 0x2116}, {
787 0x53, 0x4D, 0x2120}, {
788 0x54, 0x4D, 0x2122}, {
789 0x49, 0x49, 0x2161}, {
790 0x49, 0x56, 0x2163}, {
791 0x56, 0x49, 0x2165}, {
792 0x49, 0x58, 0x2168}, {
793 0x58, 0x49, 0x216A}, {
794 0x69, 0x69, 0x2171}, {
795 0x69, 0x76, 0x2173}, {
796 0x76, 0x69, 0x2175}, {
797 0x69, 0x78, 0x2178}, {
798 0x78, 0x69, 0x217A}, {
799 0x31, 0x30, 0x2469}, {
800 0x31, 0x31, 0x246A}, {
801 0x31, 0x32, 0x246B}, {
802 0x31, 0x33, 0x246C}, {
803 0x31, 0x34, 0x246D}, {
804 0x31, 0x35, 0x246E}, {
805 0x31, 0x36, 0x246F}, {
806 0x31, 0x37, 0x2470}, {
807 0x31, 0x38, 0x2471}, {
808 0x31, 0x39, 0x2472}, {
809 0x32, 0x30, 0x2473}, {
810 0x31, 0x2E, 0x2488}, {
811 0x32, 0x2E, 0x2489}, {
812 0x33, 0x2E, 0x248A}, {
813 0x34, 0x2E, 0x248B}, {
814 0x35, 0x2E, 0x248C}, {
815 0x36, 0x2E, 0x248D}, {
816 0x37, 0x2E, 0x248E}, {
817 0x38, 0x2E, 0x248F}, {
818 0x39, 0x2E, 0x2490}, {
819 0x64, 0x61, 0x3372}, {
820 0x41, 0x55, 0x3373}, {
821 0x6F, 0x56, 0x3375}, {
822 0x70, 0x63, 0x3376}, {
823 0x70, 0x41, 0x3380}, {
824 0x6E, 0x41, 0x3381}, {
825 0x6D, 0x41, 0x3383}, {
826 0x6B, 0x41, 0x3384}, {
827 0x4B, 0x42, 0x3385}, {
828 0x4D, 0x42, 0x3386}, {
829 0x47, 0x42, 0x3387}, {
830 0x70, 0x46, 0x338A}, {
831 0x6E, 0x46, 0x338B}, {
832 0x6D, 0x67, 0x338E}, {
833 0x6B, 0x67, 0x338F}, {
834 0x48, 0x7A, 0x3390}, {
835 0x66, 0x6D, 0x3399}, {
836 0x6E, 0x6D, 0x339A}, {
837 0x6D, 0x6D, 0x339C}, {
838 0x63, 0x6D, 0x339D}, {
839 0x6B, 0x6D, 0x339E}, {
840 0x50, 0x61, 0x33A9}, {
841 0x70, 0x73, 0x33B0}, {
842 0x6E, 0x73, 0x33B1}, {
843 0x6D, 0x73, 0x33B3}, {
844 0x70, 0x56, 0x33B4}, {
845 0x6E, 0x56, 0x33B5}, {
846 0x6D, 0x56, 0x33B7}, {
847 0x6B, 0x56, 0x33B8}, {
848 0x4D, 0x56, 0x33B9}, {
849 0x70, 0x57, 0x33BA}, {
850 0x6E, 0x57, 0x33BB}, {
851 0x6D, 0x57, 0x33BD}, {
852 0x6B, 0x57, 0x33BE}, {
853 0x4D, 0x57, 0x33BF}, {
854 0x42, 0x71, 0x33C3}, {
855 0x63, 0x63, 0x33C4}, {
856 0x63, 0x64, 0x33C5}, {
857 0x64, 0x42, 0x33C8}, {
858 0x47, 0x79, 0x33C9}, {
859 0x68, 0x61, 0x33CA}, {
860 0x48, 0x50, 0x33CB}, {
861 0x69, 0x6E, 0x33CC}, {
862 0x4B, 0x4B, 0x33CD}, {
863 0x4B, 0x4D, 0x33CE}, {
864 0x6B, 0x74, 0x33CF}, {
865 0x6C, 0x6D, 0x33D0}, {
866 0x6C, 0x6E, 0x33D1}, {
867 0x6C, 0x78, 0x33D3}, {
868 0x6D, 0x62, 0x33D4}, {
869 0x50, 0x48, 0x33D7}, {
870 0x50, 0x52, 0x33DA}, {
871 0x73, 0x72, 0x33DB}, {
872 0x53, 0x76, 0x33DC}, {
873 0x57, 0x62, 0x33DD}, {
874 0x66, 0x66, 0xFB00}, {
875 0x66, 0x69, 0xFB01}, {
876 0x66, 0x6C, 0xFB02}, {
877 0x73, 0x74, 0xFB06}, {
878 0, 0, 0}
879 }, *c;
880
881 static int recurse = 0;
882 int nc = -1;
883
884 for (c = composetbl; c->first; c++) {
885 if (c->first == first && c->second == second)
886 return c->composed;
887 }
888
889 if (recurse == 0) {
890 recurse = 1;
891 nc = check_compose(second, first);
892 if (nc == -1)
893 nc = check_compose(toupper(first), toupper(second));
894 if (nc == -1)
895 nc = check_compose(toupper(second), toupper(first));
896 recurse = 0;
897 }
898 return nc;
899}
900
901int decode_codepage(char *cp_name)
902{
903 char *s, *d;
904 struct cp_list_item *cpi;
905 int codepage = -1;
4eeb7d09 906 CPINFO cpinfo;
907
b8ae1f0f 908 if (!*cp_name) {
909 /*
910 * Here we select a plausible default code page based on
911 * the locale the user is in. We wish to select an ISO code
912 * page or appropriate local default _rather_ than go with
913 * the Win125* series, because it's more important to have
914 * CSI and friends enabled by default than the ghastly
915 * Windows extra quote characters, and because it's more
916 * likely the user is connecting to a remote server that
917 * does something Unixy or VMSy and hence standards-
918 * compliant than that they're connecting back to a Windows
919 * box using horrible nonstandard charsets.
920 *
921 * Accordingly, Robert de Bath suggests a method for
922 * picking a default character set that runs as follows:
923 * first call GetACP to get the system's ANSI code page
924 * identifier, and translate as follows:
925 *
926 * 1250 -> ISO 8859-2
927 * 1251 -> KOI8-U
928 * 1252 -> ISO 8859-1
929 * 1253 -> ISO 8859-7
930 * 1254 -> ISO 8859-9
931 * 1255 -> ISO 8859-8
932 * 1256 -> ISO 8859-6
933 * 1257 -> ISO 8859-4
934 *
935 * and for anything else, choose direct-to-font.
936 */
937 int cp = GetACP();
938 switch (cp) {
939 case 1250: cp_name = "ISO-8859-2"; break;
940 case 1251: cp_name = "KOI8-U"; break;
941 case 1252: cp_name = "ISO-8859-1"; break;
942 case 1253: cp_name = "ISO-8859-7"; break;
943 case 1254: cp_name = "ISO-8859-9"; break;
944 case 1255: cp_name = "ISO-8859-8"; break;
945 case 1256: cp_name = "ISO-8859-6"; break;
946 case 1257: cp_name = "ISO-8859-4"; break;
947 /* default: leave it blank, which will select -1, direct->font */
948 }
949 }
950
4eeb7d09 951 if (cp_name && *cp_name)
952 for (cpi = cp_list; cpi->name; cpi++) {
953 s = cp_name;
954 d = cpi->name;
955 for (;;) {
956 while (*s && !isalnum(*s) && *s != ':')
957 s++;
958 while (*d && !isalnum(*d) && *d != ':')
959 d++;
960 if (*s == 0) {
961 codepage = cpi->codepage;
962 if (codepage == CP_UTF8)
963 goto break_break;
792de8f6 964 if (codepage == -1)
965 return codepage;
4eeb7d09 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 }
274a5b41 974 if (tolower(*s++) != tolower(*d++))
4eeb7d09 975 break;
976 }
977 }
978
979 if (cp_name && *cp_name) {
980 d = cp_name;
2d466ffd 981 if (tolower(d[0]) == 'c' && tolower(d[1]) == 'p')
4eeb7d09 982 d += 2;
2d466ffd 983 if (tolower(d[0]) == 'i' && tolower(d[1]) == 'b'
984 && tolower(d[1]) == 'm')
4eeb7d09 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
1012char *cp_name(int codepage)
1013{
1014 struct cp_list_item *cpi, *cpno;
1015 static char buf[32];
b8ae1f0f 1016
1017 if (codepage == -1) {
1018 sprintf(buf, "Use font encoding");
1019 return buf;
1020 }
1021
4eeb7d09 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
875b193f 1048/*
1049 * Return the nth code page in the list, for use in the GUI
1050 * configurer.
1051 */
1052char *cp_enumerate(int index)
1053{
1054 if (index < 0 || index >= lenof(cp_list))
1055 return NULL;
1056 return cp_list[index].name;
1057}
1058
4eeb7d09 1059static 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}