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