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