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