Better yet, look for sftp-server on the user's PATH as well, which
[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
236 /* All below here are aliases - First the windows ones. */
237 {"Central European (Win1250)", 1250},
238 {"Cyrillic (Win1251)", 1251},
239 {"Western (Win1252)", 1252},
240 {"Greek (Win1253)", 1253},
241 {"Turkish (Win1254)", 1254},
242 {"Hebrew (Win1255)", 1255},
243 {"Arabic (Win1256)", 1256},
244 {"Baltic (Win1257)", 1257},
245 {"Vietnamese (Win1258)", 1258},
246
247 {"ROMAN8", 0, 96, roman8},
248 {"R8", 0, 96, roman8},
249
250 /* Note this is Latin ->> */
251 {"LATIN0", 0, 96, iso_8859_15},
252 {"L0", 0, 96, iso_8859_15},
253
254 {"CP819", 28591},
255 {"CP878", 20866},
256 {"L1", 28591},
257 {"L2", 28592},
258 {"L3", 28593},
259 {"L4", 28594},
260 {"L5", 28599},
261 {"LATIN1", 28591},
262 {"LATIN2", 28592},
263 {"LATIN3", 28593},
264 {"LATIN4", 28594},
265 {"LATIN5", 28599},
266 {0, 0}
267};
4eeb7d09 268
269static void link_font(WCHAR * line_tbl, WCHAR * font_tbl, WCHAR attr);
270
271void init_ucs_tables(void)
272{
273 int i, j;
274 int used_dtf = 0;
275 char tbuf[256];
8f22582c 276 int old_codepage = line_codepage;
4eeb7d09 277 for (i = 0; i < 256; i++)
278 tbuf[i] = i;
279
280 /* Decide on the Line and Font codepages */
281 line_codepage = decode_codepage(cfg.line_codepage);
282
8f22582c 283 if (font_codepage <= 0) {
284 font_codepage=0;
285 dbcs_screenfont=0;
286 }
287
4eeb7d09 288 if (cfg.vtmode == VT_OEMONLY) {
289 font_codepage = 437;
290 dbcs_screenfont = 0;
291 if (line_codepage <= 0)
292 line_codepage = GetACP();
293 } else if (line_codepage <= 0)
294 line_codepage = font_codepage;
4eeb7d09 295
296 /* Collect screen font ucs table */
8f22582c 297 if (dbcs_screenfont || font_codepage == 0) {
4eeb7d09 298 get_unitab(font_codepage, unitab_font, 2);
299 for (i = 128; i < 256; i++)
300 unitab_font[i] = (WCHAR) (ATTR_ACP + i);
301 } else {
302 get_unitab(font_codepage, unitab_font, 1);
303
304 /* CP437 fonts are often broken ... */
305 if (font_codepage == 437)
306 unitab_font[0] = unitab_font[255] = 0xFFFF;
307 }
308 if (cfg.vtmode == VT_XWINDOWS)
309 memcpy(unitab_font + 1, unitab_xterm_std,
310 sizeof(unitab_xterm_std));
311
312 /* Collect OEMCP ucs table */
313 get_unitab(CP_OEMCP, unitab_oemcp, 1);
314
d3cb5465 315 /* Collect CP437 ucs table for SCO acs */
316 if (cfg.vtmode == VT_OEMANSI || cfg.vtmode == VT_XWINDOWS)
317 memcpy(unitab_scoacs, unitab_oemcp, sizeof(unitab_scoacs));
318 else
319 get_unitab(437, unitab_scoacs, 1);
320
4eeb7d09 321 /* Collect line set ucs table */
322 if (line_codepage == font_codepage &&
8f22582c 323 (dbcs_screenfont || cfg.vtmode == VT_POORMAN || font_codepage==0)) {
4eeb7d09 324
325 /* For DBCS and POOR fonts force direct to font */
326 used_dtf = 1;
327 for (i = 0; i < 32; i++)
328 unitab_line[i] = (WCHAR) i;
329 for (i = 32; i < 256; i++)
330 unitab_line[i] = (WCHAR) (ATTR_ACP + i);
331 unitab_line[127] = (WCHAR) 127;
332 } else {
333 get_unitab(line_codepage, unitab_line, 0);
334 }
335
336#if 0
337 debug(
338 ("Line cp%d, Font cp%d%s\n", line_codepage, font_codepage,
339 dbcs_screenfont ? " DBCS" : ""));
340
341 for (i = 0; i < 256; i += 16) {
342 for (j = 0; j < 16; j++) {
343 debug(("%04x%s", unitab_line[i + j], j == 15 ? "" : ","));
344 }
345 debug(("\n"));
346 }
347#endif
348
349 /* VT100 graphics - NB: Broken for non-ascii CP's */
350 memcpy(unitab_xterm, unitab_line, sizeof(unitab_xterm));
351 memcpy(unitab_xterm + '`', unitab_xterm_std, sizeof(unitab_xterm_std));
352 unitab_xterm['_'] = ' ';
353
354 /* Generate UCS ->line page table. */
355 if (uni_tbl) {
356 for (i = 0; i < 256; i++)
357 if (uni_tbl[i])
358 sfree(uni_tbl[i]);
359 sfree(uni_tbl);
360 uni_tbl = 0;
361 }
362 if (!used_dtf) {
363 for (i = 0; i < 256; i++) {
364 if (DIRECT_CHAR(unitab_line[i]))
365 continue;
366 if (DIRECT_FONT(unitab_line[i]))
367 continue;
368 if (!uni_tbl) {
369 uni_tbl = smalloc(256 * sizeof(char *));
370 memset(uni_tbl, 0, 256 * sizeof(char *));
371 }
372 j = ((unitab_line[i] >> 8) & 0xFF);
373 if (!uni_tbl[j]) {
374 uni_tbl[j] = smalloc(256 * sizeof(char));
375 memset(uni_tbl[j], 0, 256 * sizeof(char));
376 }
377 uni_tbl[j][unitab_line[i] & 0xFF] = i;
378 }
379 }
380
381 /* Find the line control characters. */
382 for (i = 0; i < 256; i++)
383 if (unitab_line[i] < ' '
384 || (unitab_line[i] >= 0x7F && unitab_line[i] < 0xA0))
385 unitab_ctrl[i] = i;
386 else
387 unitab_ctrl[i] = 0xFF;
388
389 /* Generate line->screen direct conversion links. */
d3cb5465 390 if (cfg.vtmode == VT_OEMANSI || cfg.vtmode == VT_XWINDOWS)
391 link_font(unitab_scoacs, unitab_oemcp, ATTR_OEMCP);
392
4eeb7d09 393 link_font(unitab_line, unitab_font, ATTR_ACP);
d3cb5465 394 link_font(unitab_scoacs, unitab_font, ATTR_ACP);
4eeb7d09 395 link_font(unitab_xterm, unitab_font, ATTR_ACP);
396
397 if (cfg.vtmode == VT_OEMANSI || cfg.vtmode == VT_XWINDOWS) {
398 link_font(unitab_line, unitab_oemcp, ATTR_OEMCP);
399 link_font(unitab_xterm, unitab_oemcp, ATTR_OEMCP);
400 }
401
402 /* Last chance, if !unicode then try poorman links. */
403 if (cfg.vtmode != VT_UNICODE) {
d3cb5465 404 static char poorman_scoacs[] =
405 "CueaaaaceeeiiiAAE**ooouuyOUc$YPsaiounNao?++**!<>###||||++||++++++--|-+||++--|-+----++++++++##||#aBTPEsyt******EN=+><++-=... n2* ";
4eeb7d09 406 static char poorman_latin1[] =
407 " !cL.Y|S\"Ca<--R~o+23'u|.,1o>///?AAAAAAACEEEEIIIIDNOOOOOxOUUUUYPBaaaaaaaceeeeiiiionooooo/ouuuuypy";
408 static char poorman_vt100[] = "*#****o~**+++++-----++++|****L.";
409
410 for (i = 160; i < 256; i++)
411 if (!DIRECT_FONT(unitab_line[i]) &&
412 unitab_line[i] >= 160 && unitab_line[i] < 256)
413 unitab_line[i] = (WCHAR) (ATTR_ACP
414 + poorman_latin1[unitab_line[i] -
415 160]);
416 for (i = 96; i < 127; i++)
417 if (!DIRECT_FONT(unitab_xterm[i]))
418 unitab_xterm[i] =
419 (WCHAR) (ATTR_ACP + poorman_vt100[i - 96]);
d3cb5465 420 for(i=128;i<256;i++)
421 if (!DIRECT_FONT(unitab_scoacs[i]))
422 unitab_scoacs[i] =
423 (WCHAR) (ATTR_ACP + poorman_scoacs[i - 128]);
4eeb7d09 424 }
425}
426
427static void link_font(WCHAR * line_tbl, WCHAR * font_tbl, WCHAR attr)
428{
429 int i, j, k;
430 for (k = 0; k < 256; k++) {
431 i = ((k + 32) & 0xFF);
432 if (DIRECT_FONT(line_tbl[i]))
433 continue;
434 for (j = 0; j < 256; j++) {
435 if (line_tbl[i] == font_tbl[j]) {
436 line_tbl[i] = (WCHAR) (attr + j);
437 break;
438 }
439 }
440 }
441}
442
443void lpage_send(int codepage, char *buf, int len)
444{
445 static wchar_t *widebuffer = 0;
446 static int widesize = 0;
447 int wclen;
448
449 if (codepage < 0) {
450 ldisc_send(buf, len);
451 return;
452 }
453
454 if (len > widesize) {
455 sfree(widebuffer);
456 widebuffer = smalloc(len * 2 * sizeof(wchar_t));
457 widesize = len * 2;
458 }
459
460 wclen =
461 MultiByteToWideChar(codepage, 0, buf, len, widebuffer, widesize);
462 luni_send(widebuffer, wclen);
463}
464
465void luni_send(wchar_t * widebuf, int len)
466{
467 static char *linebuffer = 0;
468 static int linesize = 0;
8f22582c 469 int ratio = (in_utf)?3:1;
4eeb7d09 470 int i;
471 char *p;
472
473 if (len * ratio > linesize) {
474 sfree(linebuffer);
475 linebuffer = smalloc(len * ratio * 2 * sizeof(wchar_t));
476 linesize = len * ratio * 2;
477 }
478
8f22582c 479 if (in_utf) {
4eeb7d09 480 /* UTF is a simple algorithm */
481 for (p = linebuffer, i = 0; i < len; i++) {
482 wchar_t ch = widebuf[i];
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);
521}
522
523int check_compose(int first, int second)
524{
525
526 static struct {
527 char first, second;
528 wchar_t composed;
529 } composetbl[] = {
530 {
531 0x2b, 0x2b, 0x0023}, {
532 0x41, 0x41, 0x0040}, {
533 0x28, 0x28, 0x005b}, {
534 0x2f, 0x2f, 0x005c}, {
535 0x29, 0x29, 0x005d}, {
536 0x28, 0x2d, 0x007b}, {
537 0x2d, 0x29, 0x007d}, {
538 0x2f, 0x5e, 0x007c}, {
539 0x21, 0x21, 0x00a1}, {
540 0x43, 0x2f, 0x00a2}, {
541 0x43, 0x7c, 0x00a2}, {
542 0x4c, 0x2d, 0x00a3}, {
543 0x4c, 0x3d, 0x00a3}, {
544 0x58, 0x4f, 0x00a4}, {
545 0x58, 0x30, 0x00a4}, {
546 0x59, 0x2d, 0x00a5}, {
547 0x59, 0x3d, 0x00a5}, {
548 0x7c, 0x7c, 0x00a6}, {
549 0x53, 0x4f, 0x00a7}, {
550 0x53, 0x21, 0x00a7}, {
551 0x53, 0x30, 0x00a7}, {
552 0x22, 0x22, 0x00a8}, {
553 0x43, 0x4f, 0x00a9}, {
554 0x43, 0x30, 0x00a9}, {
555 0x41, 0x5f, 0x00aa}, {
556 0x3c, 0x3c, 0x00ab}, {
557 0x2c, 0x2d, 0x00ac}, {
558 0x2d, 0x2d, 0x00ad}, {
559 0x52, 0x4f, 0x00ae}, {
560 0x2d, 0x5e, 0x00af}, {
561 0x30, 0x5e, 0x00b0}, {
562 0x2b, 0x2d, 0x00b1}, {
563 0x32, 0x5e, 0x00b2}, {
564 0x33, 0x5e, 0x00b3}, {
565 0x27, 0x27, 0x00b4}, {
566 0x2f, 0x55, 0x00b5}, {
567 0x50, 0x21, 0x00b6}, {
568 0x2e, 0x5e, 0x00b7}, {
569 0x2c, 0x2c, 0x00b8}, {
570 0x31, 0x5e, 0x00b9}, {
571 0x4f, 0x5f, 0x00ba}, {
572 0x3e, 0x3e, 0x00bb}, {
573 0x31, 0x34, 0x00bc}, {
574 0x31, 0x32, 0x00bd}, {
575 0x33, 0x34, 0x00be}, {
576 0x3f, 0x3f, 0x00bf}, {
577 0x60, 0x41, 0x00c0}, {
578 0x27, 0x41, 0x00c1}, {
579 0x5e, 0x41, 0x00c2}, {
580 0x7e, 0x41, 0x00c3}, {
581 0x22, 0x41, 0x00c4}, {
582 0x2a, 0x41, 0x00c5}, {
583 0x41, 0x45, 0x00c6}, {
584 0x2c, 0x43, 0x00c7}, {
585 0x60, 0x45, 0x00c8}, {
586 0x27, 0x45, 0x00c9}, {
587 0x5e, 0x45, 0x00ca}, {
588 0x22, 0x45, 0x00cb}, {
589 0x60, 0x49, 0x00cc}, {
590 0x27, 0x49, 0x00cd}, {
591 0x5e, 0x49, 0x00ce}, {
592 0x22, 0x49, 0x00cf}, {
593 0x2d, 0x44, 0x00d0}, {
594 0x7e, 0x4e, 0x00d1}, {
595 0x60, 0x4f, 0x00d2}, {
596 0x27, 0x4f, 0x00d3}, {
597 0x5e, 0x4f, 0x00d4}, {
598 0x7e, 0x4f, 0x00d5}, {
599 0x22, 0x4f, 0x00d6}, {
600 0x58, 0x58, 0x00d7}, {
601 0x2f, 0x4f, 0x00d8}, {
602 0x60, 0x55, 0x00d9}, {
603 0x27, 0x55, 0x00da}, {
604 0x5e, 0x55, 0x00db}, {
605 0x22, 0x55, 0x00dc}, {
606 0x27, 0x59, 0x00dd}, {
607 0x48, 0x54, 0x00de}, {
608 0x73, 0x73, 0x00df}, {
609 0x60, 0x61, 0x00e0}, {
610 0x27, 0x61, 0x00e1}, {
611 0x5e, 0x61, 0x00e2}, {
612 0x7e, 0x61, 0x00e3}, {
613 0x22, 0x61, 0x00e4}, {
614 0x2a, 0x61, 0x00e5}, {
615 0x61, 0x65, 0x00e6}, {
616 0x2c, 0x63, 0x00e7}, {
617 0x60, 0x65, 0x00e8}, {
618 0x27, 0x65, 0x00e9}, {
619 0x5e, 0x65, 0x00ea}, {
620 0x22, 0x65, 0x00eb}, {
621 0x60, 0x69, 0x00ec}, {
622 0x27, 0x69, 0x00ed}, {
623 0x5e, 0x69, 0x00ee}, {
624 0x22, 0x69, 0x00ef}, {
625 0x2d, 0x64, 0x00f0}, {
626 0x7e, 0x6e, 0x00f1}, {
627 0x60, 0x6f, 0x00f2}, {
628 0x27, 0x6f, 0x00f3}, {
629 0x5e, 0x6f, 0x00f4}, {
630 0x7e, 0x6f, 0x00f5}, {
631 0x22, 0x6f, 0x00f6}, {
632 0x3a, 0x2d, 0x00f7}, {
633 0x6f, 0x2f, 0x00f8}, {
634 0x60, 0x75, 0x00f9}, {
635 0x27, 0x75, 0x00fa}, {
636 0x5e, 0x75, 0x00fb}, {
637 0x22, 0x75, 0x00fc}, {
638 0x27, 0x79, 0x00fd}, {
639 0x68, 0x74, 0x00fe}, {
640 0x22, 0x79, 0x00ff},
641 /* Unicode extras. */
642 {
643 0x6f, 0x65, 0x0153}, {
644 0x4f, 0x45, 0x0152},
645 /* Compose pairs from UCS */
646 {
647 0x41, 0x2D, 0x0100}, {
648 0x61, 0x2D, 0x0101}, {
649 0x43, 0x27, 0x0106}, {
650 0x63, 0x27, 0x0107}, {
651 0x43, 0x5E, 0x0108}, {
652 0x63, 0x5E, 0x0109}, {
653 0x45, 0x2D, 0x0112}, {
654 0x65, 0x2D, 0x0113}, {
655 0x47, 0x5E, 0x011C}, {
656 0x67, 0x5E, 0x011D}, {
657 0x47, 0x2C, 0x0122}, {
658 0x67, 0x2C, 0x0123}, {
659 0x48, 0x5E, 0x0124}, {
660 0x68, 0x5E, 0x0125}, {
661 0x49, 0x7E, 0x0128}, {
662 0x69, 0x7E, 0x0129}, {
663 0x49, 0x2D, 0x012A}, {
664 0x69, 0x2D, 0x012B}, {
665 0x4A, 0x5E, 0x0134}, {
666 0x6A, 0x5E, 0x0135}, {
667 0x4B, 0x2C, 0x0136}, {
668 0x6B, 0x2C, 0x0137}, {
669 0x4C, 0x27, 0x0139}, {
670 0x6C, 0x27, 0x013A}, {
671 0x4C, 0x2C, 0x013B}, {
672 0x6C, 0x2C, 0x013C}, {
673 0x4E, 0x27, 0x0143}, {
674 0x6E, 0x27, 0x0144}, {
675 0x4E, 0x2C, 0x0145}, {
676 0x6E, 0x2C, 0x0146}, {
677 0x4F, 0x2D, 0x014C}, {
678 0x6F, 0x2D, 0x014D}, {
679 0x52, 0x27, 0x0154}, {
680 0x72, 0x27, 0x0155}, {
681 0x52, 0x2C, 0x0156}, {
682 0x72, 0x2C, 0x0157}, {
683 0x53, 0x27, 0x015A}, {
684 0x73, 0x27, 0x015B}, {
685 0x53, 0x5E, 0x015C}, {
686 0x73, 0x5E, 0x015D}, {
687 0x53, 0x2C, 0x015E}, {
688 0x73, 0x2C, 0x015F}, {
689 0x54, 0x2C, 0x0162}, {
690 0x74, 0x2C, 0x0163}, {
691 0x55, 0x7E, 0x0168}, {
692 0x75, 0x7E, 0x0169}, {
693 0x55, 0x2D, 0x016A}, {
694 0x75, 0x2D, 0x016B}, {
695 0x55, 0x2A, 0x016E}, {
696 0x75, 0x2A, 0x016F}, {
697 0x57, 0x5E, 0x0174}, {
698 0x77, 0x5E, 0x0175}, {
699 0x59, 0x5E, 0x0176}, {
700 0x79, 0x5E, 0x0177}, {
701 0x59, 0x22, 0x0178}, {
702 0x5A, 0x27, 0x0179}, {
703 0x7A, 0x27, 0x017A}, {
704 0x47, 0x27, 0x01F4}, {
705 0x67, 0x27, 0x01F5}, {
706 0x4E, 0x60, 0x01F8}, {
707 0x6E, 0x60, 0x01F9}, {
708 0x45, 0x2C, 0x0228}, {
709 0x65, 0x2C, 0x0229}, {
710 0x59, 0x2D, 0x0232}, {
711 0x79, 0x2D, 0x0233}, {
712 0x44, 0x2C, 0x1E10}, {
713 0x64, 0x2C, 0x1E11}, {
714 0x47, 0x2D, 0x1E20}, {
715 0x67, 0x2D, 0x1E21}, {
716 0x48, 0x22, 0x1E26}, {
717 0x68, 0x22, 0x1E27}, {
718 0x48, 0x2C, 0x1E28}, {
719 0x68, 0x2C, 0x1E29}, {
720 0x4B, 0x27, 0x1E30}, {
721 0x6B, 0x27, 0x1E31}, {
722 0x4D, 0x27, 0x1E3E}, {
723 0x6D, 0x27, 0x1E3F}, {
724 0x50, 0x27, 0x1E54}, {
725 0x70, 0x27, 0x1E55}, {
726 0x56, 0x7E, 0x1E7C}, {
727 0x76, 0x7E, 0x1E7D}, {
728 0x57, 0x60, 0x1E80}, {
729 0x77, 0x60, 0x1E81}, {
730 0x57, 0x27, 0x1E82}, {
731 0x77, 0x27, 0x1E83}, {
732 0x57, 0x22, 0x1E84}, {
733 0x77, 0x22, 0x1E85}, {
734 0x58, 0x22, 0x1E8C}, {
735 0x78, 0x22, 0x1E8D}, {
736 0x5A, 0x5E, 0x1E90}, {
737 0x7A, 0x5E, 0x1E91}, {
738 0x74, 0x22, 0x1E97}, {
739 0x77, 0x2A, 0x1E98}, {
740 0x79, 0x2A, 0x1E99}, {
741 0x45, 0x7E, 0x1EBC}, {
742 0x65, 0x7E, 0x1EBD}, {
743 0x59, 0x60, 0x1EF2}, {
744 0x79, 0x60, 0x1EF3}, {
745 0x59, 0x7E, 0x1EF8}, {
746 0x79, 0x7E, 0x1EF9},
747 /* Compatible/possibles from UCS */
748 {
749 0x49, 0x4A, 0x0132}, {
750 0x69, 0x6A, 0x0133}, {
751 0x4C, 0x4A, 0x01C7}, {
752 0x4C, 0x6A, 0x01C8}, {
753 0x6C, 0x6A, 0x01C9}, {
754 0x4E, 0x4A, 0x01CA}, {
755 0x4E, 0x6A, 0x01CB}, {
756 0x6E, 0x6A, 0x01CC}, {
757 0x44, 0x5A, 0x01F1}, {
758 0x44, 0x7A, 0x01F2}, {
759 0x64, 0x7A, 0x01F3}, {
760 0x2E, 0x2E, 0x2025}, {
761 0x21, 0x21, 0x203C}, {
762 0x3F, 0x21, 0x2048}, {
763 0x21, 0x3F, 0x2049}, {
764 0x52, 0x73, 0x20A8}, {
765 0x4E, 0x6F, 0x2116}, {
766 0x53, 0x4D, 0x2120}, {
767 0x54, 0x4D, 0x2122}, {
768 0x49, 0x49, 0x2161}, {
769 0x49, 0x56, 0x2163}, {
770 0x56, 0x49, 0x2165}, {
771 0x49, 0x58, 0x2168}, {
772 0x58, 0x49, 0x216A}, {
773 0x69, 0x69, 0x2171}, {
774 0x69, 0x76, 0x2173}, {
775 0x76, 0x69, 0x2175}, {
776 0x69, 0x78, 0x2178}, {
777 0x78, 0x69, 0x217A}, {
778 0x31, 0x30, 0x2469}, {
779 0x31, 0x31, 0x246A}, {
780 0x31, 0x32, 0x246B}, {
781 0x31, 0x33, 0x246C}, {
782 0x31, 0x34, 0x246D}, {
783 0x31, 0x35, 0x246E}, {
784 0x31, 0x36, 0x246F}, {
785 0x31, 0x37, 0x2470}, {
786 0x31, 0x38, 0x2471}, {
787 0x31, 0x39, 0x2472}, {
788 0x32, 0x30, 0x2473}, {
789 0x31, 0x2E, 0x2488}, {
790 0x32, 0x2E, 0x2489}, {
791 0x33, 0x2E, 0x248A}, {
792 0x34, 0x2E, 0x248B}, {
793 0x35, 0x2E, 0x248C}, {
794 0x36, 0x2E, 0x248D}, {
795 0x37, 0x2E, 0x248E}, {
796 0x38, 0x2E, 0x248F}, {
797 0x39, 0x2E, 0x2490}, {
798 0x64, 0x61, 0x3372}, {
799 0x41, 0x55, 0x3373}, {
800 0x6F, 0x56, 0x3375}, {
801 0x70, 0x63, 0x3376}, {
802 0x70, 0x41, 0x3380}, {
803 0x6E, 0x41, 0x3381}, {
804 0x6D, 0x41, 0x3383}, {
805 0x6B, 0x41, 0x3384}, {
806 0x4B, 0x42, 0x3385}, {
807 0x4D, 0x42, 0x3386}, {
808 0x47, 0x42, 0x3387}, {
809 0x70, 0x46, 0x338A}, {
810 0x6E, 0x46, 0x338B}, {
811 0x6D, 0x67, 0x338E}, {
812 0x6B, 0x67, 0x338F}, {
813 0x48, 0x7A, 0x3390}, {
814 0x66, 0x6D, 0x3399}, {
815 0x6E, 0x6D, 0x339A}, {
816 0x6D, 0x6D, 0x339C}, {
817 0x63, 0x6D, 0x339D}, {
818 0x6B, 0x6D, 0x339E}, {
819 0x50, 0x61, 0x33A9}, {
820 0x70, 0x73, 0x33B0}, {
821 0x6E, 0x73, 0x33B1}, {
822 0x6D, 0x73, 0x33B3}, {
823 0x70, 0x56, 0x33B4}, {
824 0x6E, 0x56, 0x33B5}, {
825 0x6D, 0x56, 0x33B7}, {
826 0x6B, 0x56, 0x33B8}, {
827 0x4D, 0x56, 0x33B9}, {
828 0x70, 0x57, 0x33BA}, {
829 0x6E, 0x57, 0x33BB}, {
830 0x6D, 0x57, 0x33BD}, {
831 0x6B, 0x57, 0x33BE}, {
832 0x4D, 0x57, 0x33BF}, {
833 0x42, 0x71, 0x33C3}, {
834 0x63, 0x63, 0x33C4}, {
835 0x63, 0x64, 0x33C5}, {
836 0x64, 0x42, 0x33C8}, {
837 0x47, 0x79, 0x33C9}, {
838 0x68, 0x61, 0x33CA}, {
839 0x48, 0x50, 0x33CB}, {
840 0x69, 0x6E, 0x33CC}, {
841 0x4B, 0x4B, 0x33CD}, {
842 0x4B, 0x4D, 0x33CE}, {
843 0x6B, 0x74, 0x33CF}, {
844 0x6C, 0x6D, 0x33D0}, {
845 0x6C, 0x6E, 0x33D1}, {
846 0x6C, 0x78, 0x33D3}, {
847 0x6D, 0x62, 0x33D4}, {
848 0x50, 0x48, 0x33D7}, {
849 0x50, 0x52, 0x33DA}, {
850 0x73, 0x72, 0x33DB}, {
851 0x53, 0x76, 0x33DC}, {
852 0x57, 0x62, 0x33DD}, {
853 0x66, 0x66, 0xFB00}, {
854 0x66, 0x69, 0xFB01}, {
855 0x66, 0x6C, 0xFB02}, {
856 0x73, 0x74, 0xFB06}, {
857 0, 0, 0}
858 }, *c;
859
860 static int recurse = 0;
861 int nc = -1;
862
863 for (c = composetbl; c->first; c++) {
864 if (c->first == first && c->second == second)
865 return c->composed;
866 }
867
868 if (recurse == 0) {
869 recurse = 1;
870 nc = check_compose(second, first);
871 if (nc == -1)
872 nc = check_compose(toupper(first), toupper(second));
873 if (nc == -1)
874 nc = check_compose(toupper(second), toupper(first));
875 recurse = 0;
876 }
877 return nc;
878}
879
880int decode_codepage(char *cp_name)
881{
882 char *s, *d;
883 struct cp_list_item *cpi;
884 int codepage = -1;
4eeb7d09 885 CPINFO cpinfo;
886
887 if (cp_name && *cp_name)
888 for (cpi = cp_list; cpi->name; cpi++) {
889 s = cp_name;
890 d = cpi->name;
891 for (;;) {
892 while (*s && !isalnum(*s) && *s != ':')
893 s++;
894 while (*d && !isalnum(*d) && *d != ':')
895 d++;
896 if (*s == 0) {
897 codepage = cpi->codepage;
898 if (codepage == CP_UTF8)
899 goto break_break;
900 if (codepage == 0) {
901 codepage = 65536 + (cpi - cp_list);
902 goto break_break;
903 }
904
905 if (GetCPInfo(codepage, &cpinfo) != 0)
906 goto break_break;
907 }
274a5b41 908 if (tolower(*s++) != tolower(*d++))
4eeb7d09 909 break;
910 }
911 }
912
913 if (cp_name && *cp_name) {
914 d = cp_name;
2d466ffd 915 if (tolower(d[0]) == 'c' && tolower(d[1]) == 'p')
4eeb7d09 916 d += 2;
2d466ffd 917 if (tolower(d[0]) == 'i' && tolower(d[1]) == 'b'
918 && tolower(d[1]) == 'm')
4eeb7d09 919 d += 3;
920 for (s = d; *s >= '0' && *s <= '9'; s++);
921 if (*s == 0 && s != d)
922 codepage = atoi(d); /* CP999 or IBM999 */
923
924 if (codepage == CP_ACP)
925 codepage = GetACP();
926 if (codepage == CP_OEMCP)
927 codepage = GetOEMCP();
928 if (codepage > 65535)
929 codepage = -2;
930 }
931
932 break_break:;
933 if (codepage != -1) {
934 if (codepage != CP_UTF8 && codepage < 65536) {
935 if (GetCPInfo(codepage, &cpinfo) == 0) {
936 codepage = -2;
937 } else if (cpinfo.MaxCharSize > 1)
938 codepage = -3;
939 }
940 }
941 if (codepage == -1 && *cp_name)
942 codepage = -2;
943 return codepage;
944}
945
946char *cp_name(int codepage)
947{
948 struct cp_list_item *cpi, *cpno;
949 static char buf[32];
950 if (codepage > 0 && codepage < 65536)
951 sprintf(buf, "CP%03d", codepage);
952 else
953 *buf = 0;
954
955 if (codepage >= 65536) {
956 cpno = 0;
957 for (cpi = cp_list; cpi->name; cpi++)
958 if (cpi == cp_list + (codepage - 65536)) {
959 cpno = cpi;
960 break;
961 }
962 if (cpno)
963 for (cpi = cp_list; cpi->name; cpi++) {
964 if (cpno->cp_table == cpi->cp_table)
965 return cpi->name;
966 }
967 } else {
968 for (cpi = cp_list; cpi->name; cpi++) {
969 if (codepage == cpi->codepage)
970 return cpi->name;
971 }
972 }
973 return buf;
974}
975
875b193f 976/*
977 * Return the nth code page in the list, for use in the GUI
978 * configurer.
979 */
980char *cp_enumerate(int index)
981{
982 if (index < 0 || index >= lenof(cp_list))
983 return NULL;
984 return cp_list[index].name;
985}
986
4eeb7d09 987static void get_unitab(int codepage, wchar_t * unitab, int ftype)
988{
989 char tbuf[4];
990 int i, max = 256, flg = MB_ERR_INVALID_CHARS;
991
992 if (ftype)
993 flg |= MB_USEGLYPHCHARS;
994 if (ftype == 2)
995 max = 128;
996
997 if (codepage == CP_UTF8)
998 codepage = 28591;
999 else if (codepage == CP_ACP)
1000 codepage = GetACP();
1001 else if (codepage == CP_OEMCP)
1002 codepage = GetOEMCP();
1003
1004 if (codepage > 0 && codepage < 65536) {
1005 for (i = 0; i < max; i++) {
1006 tbuf[0] = i;
1007
1008 if (MultiByteToWideChar(codepage, flg, tbuf, 1, unitab + i, 1)
1009 != 1)
1010 unitab[i] = 0xFFFD;
1011 }
1012 } else {
1013 int j = 256 - cp_list[codepage & 0xFFFF].cp_size;
1014 for (i = 0; i < max; i++)
1015 unitab[i] = i;
1016 for (i = j; i < max; i++)
1017 unitab[i] = cp_list[codepage & 0xFFFF].cp_table[i - j];
1018 }
1019}