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