Fix the licence again. (Despite the copyright holders being more
[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
dc3c8261 19 * equivalents mapped to their unicode 3.0 locations.
4eeb7d09 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];
dc3c8261 270
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
5a73255e 396 if (dbcs_screenfont && font_codepage != line_codepage) {
397 /* F***ing Microsoft fonts, Japanese and Korean codepage fonts
398 * have a currency symbol at 0x5C but their unicode value is
399 * still given as U+005C not the correct U+00A5. */
400 unitab_line['\\'] = ATTR_OEMCP + '\\';
401 }
402
4eeb7d09 403 /* Last chance, if !unicode then try poorman links. */
404 if (cfg.vtmode != VT_UNICODE) {
d3cb5465 405 static char poorman_scoacs[] =
406 "CueaaaaceeeiiiAAE**ooouuyOUc$YPsaiounNao?++**!<>###||||++||++++++--|-+||++--|-+----++++++++##||#aBTPEsyt******EN=+><++-=... n2* ";
4eeb7d09 407 static char poorman_latin1[] =
408 " !cL.Y|S\"Ca<--R~o+23'u|.,1o>///?AAAAAAACEEEEIIIIDNOOOOOxOUUUUYPBaaaaaaaceeeeiiiionooooo/ouuuuypy";
409 static char poorman_vt100[] = "*#****o~**+++++-----++++|****L.";
410
411 for (i = 160; i < 256; i++)
412 if (!DIRECT_FONT(unitab_line[i]) &&
413 unitab_line[i] >= 160 && unitab_line[i] < 256)
414 unitab_line[i] = (WCHAR) (ATTR_ACP
415 + poorman_latin1[unitab_line[i] -
416 160]);
417 for (i = 96; i < 127; i++)
418 if (!DIRECT_FONT(unitab_xterm[i]))
419 unitab_xterm[i] =
420 (WCHAR) (ATTR_ACP + poorman_vt100[i - 96]);
d3cb5465 421 for(i=128;i<256;i++)
422 if (!DIRECT_FONT(unitab_scoacs[i]))
423 unitab_scoacs[i] =
424 (WCHAR) (ATTR_ACP + poorman_scoacs[i - 128]);
4eeb7d09 425 }
426}
427
428static void link_font(WCHAR * line_tbl, WCHAR * font_tbl, WCHAR attr)
429{
614e8f54 430 int font_index, line_index, i;
431 for (line_index = 0; line_index < 256; line_index++) {
432 if (DIRECT_FONT(line_tbl[line_index]))
4eeb7d09 433 continue;
614e8f54 434 for(i = 0; i < 256; i++) {
435 font_index = ((32 + i) & 0xFF);
436 if (line_tbl[line_index] == font_tbl[font_index]) {
437 line_tbl[line_index] = (WCHAR) (attr + font_index);
4eeb7d09 438 break;
439 }
440 }
441 }
442}
443
444void lpage_send(int codepage, char *buf, int len)
445{
446 static wchar_t *widebuffer = 0;
447 static int widesize = 0;
448 int wclen;
449
450 if (codepage < 0) {
451 ldisc_send(buf, len);
452 return;
453 }
454
455 if (len > widesize) {
456 sfree(widebuffer);
457 widebuffer = smalloc(len * 2 * sizeof(wchar_t));
458 widesize = len * 2;
459 }
460
461 wclen =
462 MultiByteToWideChar(codepage, 0, buf, len, widebuffer, widesize);
463 luni_send(widebuffer, wclen);
464}
465
466void luni_send(wchar_t * widebuf, int len)
467{
468 static char *linebuffer = 0;
469 static int linesize = 0;
8f22582c 470 int ratio = (in_utf)?3:1;
4eeb7d09 471 int i;
472 char *p;
473
474 if (len * ratio > linesize) {
475 sfree(linebuffer);
476 linebuffer = smalloc(len * ratio * 2 * sizeof(wchar_t));
477 linesize = len * ratio * 2;
478 }
479
8f22582c 480 if (in_utf) {
4eeb7d09 481 /* UTF is a simple algorithm */
482 for (p = linebuffer, i = 0; i < len; i++) {
483 wchar_t ch = widebuf[i];
05054a30 484 /* Windows wchar_t is UTF-16 */
485 if ((ch&0xF800) == 0xD800) ch = '.';
486
4eeb7d09 487 if (ch < 0x80) {
488 *p++ = (char) (ch);
489 } else if (ch < 0x800) {
490 *p++ = (0xC0 | (ch >> 6));
491 *p++ = (0x80 | (ch & 0x3F));
492 } else {
493 *p++ = (0xE0 | (ch >> 12));
494 *p++ = (0x80 | ((ch >> 6) & 0x3F));
495 *p++ = (0x80 | (ch & 0x3F));
496 }
497 }
498 } else if (!uni_tbl) {
499 int rv;
500 rv = WideCharToMultiByte(line_codepage, 0, widebuf, len,
501 linebuffer, linesize, NULL, NULL);
502 if (rv >= 0)
503 p = linebuffer + rv;
504 else
505 p = linebuffer;
506 } else {
507 /* Others are a lookup in an array */
508 for (p = linebuffer, i = 0; i < len; i++) {
509 wchar_t ch = widebuf[i];
510 int by;
511 char *p1;
512 if (uni_tbl && (p1 = uni_tbl[(ch >> 8) & 0xFF])
513 && (by = p1[ch & 0xFF]))
514 *p++ = by;
515 else if (ch < 0x80)
516 *p++ = (char) ch;
517#if 1
518 else
519 *p++ = '.';
520#endif
521 }
522 }
523 if (p > linebuffer)
524 ldisc_send(linebuffer, p - linebuffer);
525}
526
527int check_compose(int first, int second)
528{
529
530 static struct {
531 char first, second;
532 wchar_t composed;
533 } composetbl[] = {
534 {
535 0x2b, 0x2b, 0x0023}, {
536 0x41, 0x41, 0x0040}, {
537 0x28, 0x28, 0x005b}, {
538 0x2f, 0x2f, 0x005c}, {
539 0x29, 0x29, 0x005d}, {
540 0x28, 0x2d, 0x007b}, {
541 0x2d, 0x29, 0x007d}, {
542 0x2f, 0x5e, 0x007c}, {
543 0x21, 0x21, 0x00a1}, {
544 0x43, 0x2f, 0x00a2}, {
545 0x43, 0x7c, 0x00a2}, {
546 0x4c, 0x2d, 0x00a3}, {
5a73255e 547 0x4c, 0x3d, 0x20a4}, {
4eeb7d09 548 0x58, 0x4f, 0x00a4}, {
549 0x58, 0x30, 0x00a4}, {
550 0x59, 0x2d, 0x00a5}, {
551 0x59, 0x3d, 0x00a5}, {
552 0x7c, 0x7c, 0x00a6}, {
553 0x53, 0x4f, 0x00a7}, {
554 0x53, 0x21, 0x00a7}, {
555 0x53, 0x30, 0x00a7}, {
556 0x22, 0x22, 0x00a8}, {
557 0x43, 0x4f, 0x00a9}, {
558 0x43, 0x30, 0x00a9}, {
559 0x41, 0x5f, 0x00aa}, {
560 0x3c, 0x3c, 0x00ab}, {
561 0x2c, 0x2d, 0x00ac}, {
562 0x2d, 0x2d, 0x00ad}, {
563 0x52, 0x4f, 0x00ae}, {
564 0x2d, 0x5e, 0x00af}, {
565 0x30, 0x5e, 0x00b0}, {
566 0x2b, 0x2d, 0x00b1}, {
567 0x32, 0x5e, 0x00b2}, {
568 0x33, 0x5e, 0x00b3}, {
569 0x27, 0x27, 0x00b4}, {
570 0x2f, 0x55, 0x00b5}, {
571 0x50, 0x21, 0x00b6}, {
572 0x2e, 0x5e, 0x00b7}, {
573 0x2c, 0x2c, 0x00b8}, {
574 0x31, 0x5e, 0x00b9}, {
575 0x4f, 0x5f, 0x00ba}, {
576 0x3e, 0x3e, 0x00bb}, {
577 0x31, 0x34, 0x00bc}, {
578 0x31, 0x32, 0x00bd}, {
579 0x33, 0x34, 0x00be}, {
580 0x3f, 0x3f, 0x00bf}, {
581 0x60, 0x41, 0x00c0}, {
582 0x27, 0x41, 0x00c1}, {
583 0x5e, 0x41, 0x00c2}, {
584 0x7e, 0x41, 0x00c3}, {
585 0x22, 0x41, 0x00c4}, {
586 0x2a, 0x41, 0x00c5}, {
587 0x41, 0x45, 0x00c6}, {
588 0x2c, 0x43, 0x00c7}, {
589 0x60, 0x45, 0x00c8}, {
590 0x27, 0x45, 0x00c9}, {
591 0x5e, 0x45, 0x00ca}, {
592 0x22, 0x45, 0x00cb}, {
593 0x60, 0x49, 0x00cc}, {
594 0x27, 0x49, 0x00cd}, {
595 0x5e, 0x49, 0x00ce}, {
596 0x22, 0x49, 0x00cf}, {
597 0x2d, 0x44, 0x00d0}, {
598 0x7e, 0x4e, 0x00d1}, {
599 0x60, 0x4f, 0x00d2}, {
600 0x27, 0x4f, 0x00d3}, {
601 0x5e, 0x4f, 0x00d4}, {
602 0x7e, 0x4f, 0x00d5}, {
603 0x22, 0x4f, 0x00d6}, {
604 0x58, 0x58, 0x00d7}, {
605 0x2f, 0x4f, 0x00d8}, {
606 0x60, 0x55, 0x00d9}, {
607 0x27, 0x55, 0x00da}, {
608 0x5e, 0x55, 0x00db}, {
609 0x22, 0x55, 0x00dc}, {
610 0x27, 0x59, 0x00dd}, {
611 0x48, 0x54, 0x00de}, {
612 0x73, 0x73, 0x00df}, {
613 0x60, 0x61, 0x00e0}, {
614 0x27, 0x61, 0x00e1}, {
615 0x5e, 0x61, 0x00e2}, {
616 0x7e, 0x61, 0x00e3}, {
617 0x22, 0x61, 0x00e4}, {
618 0x2a, 0x61, 0x00e5}, {
619 0x61, 0x65, 0x00e6}, {
620 0x2c, 0x63, 0x00e7}, {
621 0x60, 0x65, 0x00e8}, {
622 0x27, 0x65, 0x00e9}, {
623 0x5e, 0x65, 0x00ea}, {
624 0x22, 0x65, 0x00eb}, {
625 0x60, 0x69, 0x00ec}, {
626 0x27, 0x69, 0x00ed}, {
627 0x5e, 0x69, 0x00ee}, {
628 0x22, 0x69, 0x00ef}, {
629 0x2d, 0x64, 0x00f0}, {
630 0x7e, 0x6e, 0x00f1}, {
631 0x60, 0x6f, 0x00f2}, {
632 0x27, 0x6f, 0x00f3}, {
633 0x5e, 0x6f, 0x00f4}, {
634 0x7e, 0x6f, 0x00f5}, {
635 0x22, 0x6f, 0x00f6}, {
636 0x3a, 0x2d, 0x00f7}, {
637 0x6f, 0x2f, 0x00f8}, {
638 0x60, 0x75, 0x00f9}, {
639 0x27, 0x75, 0x00fa}, {
640 0x5e, 0x75, 0x00fb}, {
641 0x22, 0x75, 0x00fc}, {
642 0x27, 0x79, 0x00fd}, {
643 0x68, 0x74, 0x00fe}, {
644 0x22, 0x79, 0x00ff},
645 /* Unicode extras. */
646 {
647 0x6f, 0x65, 0x0153}, {
648 0x4f, 0x45, 0x0152},
649 /* Compose pairs from UCS */
650 {
651 0x41, 0x2D, 0x0100}, {
652 0x61, 0x2D, 0x0101}, {
653 0x43, 0x27, 0x0106}, {
654 0x63, 0x27, 0x0107}, {
655 0x43, 0x5E, 0x0108}, {
656 0x63, 0x5E, 0x0109}, {
657 0x45, 0x2D, 0x0112}, {
658 0x65, 0x2D, 0x0113}, {
659 0x47, 0x5E, 0x011C}, {
660 0x67, 0x5E, 0x011D}, {
661 0x47, 0x2C, 0x0122}, {
662 0x67, 0x2C, 0x0123}, {
663 0x48, 0x5E, 0x0124}, {
664 0x68, 0x5E, 0x0125}, {
665 0x49, 0x7E, 0x0128}, {
666 0x69, 0x7E, 0x0129}, {
667 0x49, 0x2D, 0x012A}, {
668 0x69, 0x2D, 0x012B}, {
669 0x4A, 0x5E, 0x0134}, {
670 0x6A, 0x5E, 0x0135}, {
671 0x4B, 0x2C, 0x0136}, {
672 0x6B, 0x2C, 0x0137}, {
673 0x4C, 0x27, 0x0139}, {
674 0x6C, 0x27, 0x013A}, {
675 0x4C, 0x2C, 0x013B}, {
676 0x6C, 0x2C, 0x013C}, {
677 0x4E, 0x27, 0x0143}, {
678 0x6E, 0x27, 0x0144}, {
679 0x4E, 0x2C, 0x0145}, {
680 0x6E, 0x2C, 0x0146}, {
681 0x4F, 0x2D, 0x014C}, {
682 0x6F, 0x2D, 0x014D}, {
683 0x52, 0x27, 0x0154}, {
684 0x72, 0x27, 0x0155}, {
685 0x52, 0x2C, 0x0156}, {
686 0x72, 0x2C, 0x0157}, {
687 0x53, 0x27, 0x015A}, {
688 0x73, 0x27, 0x015B}, {
689 0x53, 0x5E, 0x015C}, {
690 0x73, 0x5E, 0x015D}, {
691 0x53, 0x2C, 0x015E}, {
692 0x73, 0x2C, 0x015F}, {
693 0x54, 0x2C, 0x0162}, {
694 0x74, 0x2C, 0x0163}, {
695 0x55, 0x7E, 0x0168}, {
696 0x75, 0x7E, 0x0169}, {
697 0x55, 0x2D, 0x016A}, {
698 0x75, 0x2D, 0x016B}, {
699 0x55, 0x2A, 0x016E}, {
700 0x75, 0x2A, 0x016F}, {
701 0x57, 0x5E, 0x0174}, {
702 0x77, 0x5E, 0x0175}, {
703 0x59, 0x5E, 0x0176}, {
704 0x79, 0x5E, 0x0177}, {
705 0x59, 0x22, 0x0178}, {
706 0x5A, 0x27, 0x0179}, {
707 0x7A, 0x27, 0x017A}, {
708 0x47, 0x27, 0x01F4}, {
709 0x67, 0x27, 0x01F5}, {
710 0x4E, 0x60, 0x01F8}, {
711 0x6E, 0x60, 0x01F9}, {
712 0x45, 0x2C, 0x0228}, {
713 0x65, 0x2C, 0x0229}, {
714 0x59, 0x2D, 0x0232}, {
715 0x79, 0x2D, 0x0233}, {
716 0x44, 0x2C, 0x1E10}, {
717 0x64, 0x2C, 0x1E11}, {
718 0x47, 0x2D, 0x1E20}, {
719 0x67, 0x2D, 0x1E21}, {
720 0x48, 0x22, 0x1E26}, {
721 0x68, 0x22, 0x1E27}, {
722 0x48, 0x2C, 0x1E28}, {
723 0x68, 0x2C, 0x1E29}, {
724 0x4B, 0x27, 0x1E30}, {
725 0x6B, 0x27, 0x1E31}, {
726 0x4D, 0x27, 0x1E3E}, {
727 0x6D, 0x27, 0x1E3F}, {
728 0x50, 0x27, 0x1E54}, {
729 0x70, 0x27, 0x1E55}, {
730 0x56, 0x7E, 0x1E7C}, {
731 0x76, 0x7E, 0x1E7D}, {
732 0x57, 0x60, 0x1E80}, {
733 0x77, 0x60, 0x1E81}, {
734 0x57, 0x27, 0x1E82}, {
735 0x77, 0x27, 0x1E83}, {
736 0x57, 0x22, 0x1E84}, {
737 0x77, 0x22, 0x1E85}, {
738 0x58, 0x22, 0x1E8C}, {
739 0x78, 0x22, 0x1E8D}, {
740 0x5A, 0x5E, 0x1E90}, {
741 0x7A, 0x5E, 0x1E91}, {
742 0x74, 0x22, 0x1E97}, {
743 0x77, 0x2A, 0x1E98}, {
744 0x79, 0x2A, 0x1E99}, {
745 0x45, 0x7E, 0x1EBC}, {
746 0x65, 0x7E, 0x1EBD}, {
747 0x59, 0x60, 0x1EF2}, {
748 0x79, 0x60, 0x1EF3}, {
749 0x59, 0x7E, 0x1EF8}, {
750 0x79, 0x7E, 0x1EF9},
751 /* Compatible/possibles from UCS */
752 {
753 0x49, 0x4A, 0x0132}, {
754 0x69, 0x6A, 0x0133}, {
755 0x4C, 0x4A, 0x01C7}, {
756 0x4C, 0x6A, 0x01C8}, {
757 0x6C, 0x6A, 0x01C9}, {
758 0x4E, 0x4A, 0x01CA}, {
759 0x4E, 0x6A, 0x01CB}, {
760 0x6E, 0x6A, 0x01CC}, {
761 0x44, 0x5A, 0x01F1}, {
762 0x44, 0x7A, 0x01F2}, {
763 0x64, 0x7A, 0x01F3}, {
764 0x2E, 0x2E, 0x2025}, {
765 0x21, 0x21, 0x203C}, {
766 0x3F, 0x21, 0x2048}, {
767 0x21, 0x3F, 0x2049}, {
768 0x52, 0x73, 0x20A8}, {
769 0x4E, 0x6F, 0x2116}, {
770 0x53, 0x4D, 0x2120}, {
771 0x54, 0x4D, 0x2122}, {
772 0x49, 0x49, 0x2161}, {
773 0x49, 0x56, 0x2163}, {
774 0x56, 0x49, 0x2165}, {
775 0x49, 0x58, 0x2168}, {
776 0x58, 0x49, 0x216A}, {
777 0x69, 0x69, 0x2171}, {
778 0x69, 0x76, 0x2173}, {
779 0x76, 0x69, 0x2175}, {
780 0x69, 0x78, 0x2178}, {
781 0x78, 0x69, 0x217A}, {
782 0x31, 0x30, 0x2469}, {
783 0x31, 0x31, 0x246A}, {
784 0x31, 0x32, 0x246B}, {
785 0x31, 0x33, 0x246C}, {
786 0x31, 0x34, 0x246D}, {
787 0x31, 0x35, 0x246E}, {
788 0x31, 0x36, 0x246F}, {
789 0x31, 0x37, 0x2470}, {
790 0x31, 0x38, 0x2471}, {
791 0x31, 0x39, 0x2472}, {
792 0x32, 0x30, 0x2473}, {
793 0x31, 0x2E, 0x2488}, {
794 0x32, 0x2E, 0x2489}, {
795 0x33, 0x2E, 0x248A}, {
796 0x34, 0x2E, 0x248B}, {
797 0x35, 0x2E, 0x248C}, {
798 0x36, 0x2E, 0x248D}, {
799 0x37, 0x2E, 0x248E}, {
800 0x38, 0x2E, 0x248F}, {
801 0x39, 0x2E, 0x2490}, {
802 0x64, 0x61, 0x3372}, {
803 0x41, 0x55, 0x3373}, {
804 0x6F, 0x56, 0x3375}, {
805 0x70, 0x63, 0x3376}, {
806 0x70, 0x41, 0x3380}, {
807 0x6E, 0x41, 0x3381}, {
808 0x6D, 0x41, 0x3383}, {
809 0x6B, 0x41, 0x3384}, {
810 0x4B, 0x42, 0x3385}, {
811 0x4D, 0x42, 0x3386}, {
812 0x47, 0x42, 0x3387}, {
813 0x70, 0x46, 0x338A}, {
814 0x6E, 0x46, 0x338B}, {
815 0x6D, 0x67, 0x338E}, {
816 0x6B, 0x67, 0x338F}, {
817 0x48, 0x7A, 0x3390}, {
818 0x66, 0x6D, 0x3399}, {
819 0x6E, 0x6D, 0x339A}, {
820 0x6D, 0x6D, 0x339C}, {
821 0x63, 0x6D, 0x339D}, {
822 0x6B, 0x6D, 0x339E}, {
823 0x50, 0x61, 0x33A9}, {
824 0x70, 0x73, 0x33B0}, {
825 0x6E, 0x73, 0x33B1}, {
826 0x6D, 0x73, 0x33B3}, {
827 0x70, 0x56, 0x33B4}, {
828 0x6E, 0x56, 0x33B5}, {
829 0x6D, 0x56, 0x33B7}, {
830 0x6B, 0x56, 0x33B8}, {
831 0x4D, 0x56, 0x33B9}, {
832 0x70, 0x57, 0x33BA}, {
833 0x6E, 0x57, 0x33BB}, {
834 0x6D, 0x57, 0x33BD}, {
835 0x6B, 0x57, 0x33BE}, {
836 0x4D, 0x57, 0x33BF}, {
837 0x42, 0x71, 0x33C3}, {
838 0x63, 0x63, 0x33C4}, {
839 0x63, 0x64, 0x33C5}, {
840 0x64, 0x42, 0x33C8}, {
841 0x47, 0x79, 0x33C9}, {
842 0x68, 0x61, 0x33CA}, {
843 0x48, 0x50, 0x33CB}, {
844 0x69, 0x6E, 0x33CC}, {
845 0x4B, 0x4B, 0x33CD}, {
846 0x4B, 0x4D, 0x33CE}, {
847 0x6B, 0x74, 0x33CF}, {
848 0x6C, 0x6D, 0x33D0}, {
849 0x6C, 0x6E, 0x33D1}, {
850 0x6C, 0x78, 0x33D3}, {
851 0x6D, 0x62, 0x33D4}, {
852 0x50, 0x48, 0x33D7}, {
853 0x50, 0x52, 0x33DA}, {
854 0x73, 0x72, 0x33DB}, {
855 0x53, 0x76, 0x33DC}, {
856 0x57, 0x62, 0x33DD}, {
857 0x66, 0x66, 0xFB00}, {
858 0x66, 0x69, 0xFB01}, {
859 0x66, 0x6C, 0xFB02}, {
860 0x73, 0x74, 0xFB06}, {
861 0, 0, 0}
862 }, *c;
863
864 static int recurse = 0;
865 int nc = -1;
866
867 for (c = composetbl; c->first; c++) {
868 if (c->first == first && c->second == second)
869 return c->composed;
870 }
871
872 if (recurse == 0) {
873 recurse = 1;
874 nc = check_compose(second, first);
875 if (nc == -1)
876 nc = check_compose(toupper(first), toupper(second));
877 if (nc == -1)
878 nc = check_compose(toupper(second), toupper(first));
879 recurse = 0;
880 }
881 return nc;
882}
883
884int decode_codepage(char *cp_name)
885{
886 char *s, *d;
887 struct cp_list_item *cpi;
888 int codepage = -1;
4eeb7d09 889 CPINFO cpinfo;
890
b8ae1f0f 891 if (!*cp_name) {
892 /*
893 * Here we select a plausible default code page based on
894 * the locale the user is in. We wish to select an ISO code
895 * page or appropriate local default _rather_ than go with
896 * the Win125* series, because it's more important to have
897 * CSI and friends enabled by default than the ghastly
898 * Windows extra quote characters, and because it's more
899 * likely the user is connecting to a remote server that
900 * does something Unixy or VMSy and hence standards-
901 * compliant than that they're connecting back to a Windows
902 * box using horrible nonstandard charsets.
903 *
904 * Accordingly, Robert de Bath suggests a method for
905 * picking a default character set that runs as follows:
906 * first call GetACP to get the system's ANSI code page
907 * identifier, and translate as follows:
908 *
909 * 1250 -> ISO 8859-2
910 * 1251 -> KOI8-U
911 * 1252 -> ISO 8859-1
912 * 1253 -> ISO 8859-7
913 * 1254 -> ISO 8859-9
914 * 1255 -> ISO 8859-8
915 * 1256 -> ISO 8859-6
916 * 1257 -> ISO 8859-4
917 *
918 * and for anything else, choose direct-to-font.
919 */
920 int cp = GetACP();
921 switch (cp) {
922 case 1250: cp_name = "ISO-8859-2"; break;
923 case 1251: cp_name = "KOI8-U"; break;
924 case 1252: cp_name = "ISO-8859-1"; break;
925 case 1253: cp_name = "ISO-8859-7"; break;
926 case 1254: cp_name = "ISO-8859-9"; break;
927 case 1255: cp_name = "ISO-8859-8"; break;
928 case 1256: cp_name = "ISO-8859-6"; break;
929 case 1257: cp_name = "ISO-8859-4"; break;
930 /* default: leave it blank, which will select -1, direct->font */
931 }
932 }
933
4eeb7d09 934 if (cp_name && *cp_name)
935 for (cpi = cp_list; cpi->name; cpi++) {
936 s = cp_name;
937 d = cpi->name;
938 for (;;) {
939 while (*s && !isalnum(*s) && *s != ':')
940 s++;
941 while (*d && !isalnum(*d) && *d != ':')
942 d++;
943 if (*s == 0) {
944 codepage = cpi->codepage;
945 if (codepage == CP_UTF8)
946 goto break_break;
947 if (codepage == 0) {
948 codepage = 65536 + (cpi - cp_list);
949 goto break_break;
950 }
951
952 if (GetCPInfo(codepage, &cpinfo) != 0)
953 goto break_break;
954 }
274a5b41 955 if (tolower(*s++) != tolower(*d++))
4eeb7d09 956 break;
957 }
958 }
959
960 if (cp_name && *cp_name) {
961 d = cp_name;
2d466ffd 962 if (tolower(d[0]) == 'c' && tolower(d[1]) == 'p')
4eeb7d09 963 d += 2;
2d466ffd 964 if (tolower(d[0]) == 'i' && tolower(d[1]) == 'b'
965 && tolower(d[1]) == 'm')
4eeb7d09 966 d += 3;
967 for (s = d; *s >= '0' && *s <= '9'; s++);
968 if (*s == 0 && s != d)
969 codepage = atoi(d); /* CP999 or IBM999 */
970
971 if (codepage == CP_ACP)
972 codepage = GetACP();
973 if (codepage == CP_OEMCP)
974 codepage = GetOEMCP();
975 if (codepage > 65535)
976 codepage = -2;
977 }
978
979 break_break:;
980 if (codepage != -1) {
981 if (codepage != CP_UTF8 && codepage < 65536) {
982 if (GetCPInfo(codepage, &cpinfo) == 0) {
983 codepage = -2;
984 } else if (cpinfo.MaxCharSize > 1)
985 codepage = -3;
986 }
987 }
988 if (codepage == -1 && *cp_name)
989 codepage = -2;
990 return codepage;
991}
992
993char *cp_name(int codepage)
994{
995 struct cp_list_item *cpi, *cpno;
996 static char buf[32];
b8ae1f0f 997
998 if (codepage == -1) {
999 sprintf(buf, "Use font encoding");
1000 return buf;
1001 }
1002
4eeb7d09 1003 if (codepage > 0 && codepage < 65536)
1004 sprintf(buf, "CP%03d", codepage);
1005 else
1006 *buf = 0;
1007
1008 if (codepage >= 65536) {
1009 cpno = 0;
1010 for (cpi = cp_list; cpi->name; cpi++)
1011 if (cpi == cp_list + (codepage - 65536)) {
1012 cpno = cpi;
1013 break;
1014 }
1015 if (cpno)
1016 for (cpi = cp_list; cpi->name; cpi++) {
1017 if (cpno->cp_table == cpi->cp_table)
1018 return cpi->name;
1019 }
1020 } else {
1021 for (cpi = cp_list; cpi->name; cpi++) {
1022 if (codepage == cpi->codepage)
1023 return cpi->name;
1024 }
1025 }
1026 return buf;
1027}
1028
875b193f 1029/*
1030 * Return the nth code page in the list, for use in the GUI
1031 * configurer.
1032 */
1033char *cp_enumerate(int index)
1034{
1035 if (index < 0 || index >= lenof(cp_list))
1036 return NULL;
1037 return cp_list[index].name;
1038}
1039
4eeb7d09 1040static void get_unitab(int codepage, wchar_t * unitab, int ftype)
1041{
1042 char tbuf[4];
1043 int i, max = 256, flg = MB_ERR_INVALID_CHARS;
1044
1045 if (ftype)
1046 flg |= MB_USEGLYPHCHARS;
1047 if (ftype == 2)
1048 max = 128;
1049
1050 if (codepage == CP_UTF8)
1051 codepage = 28591;
1052 else if (codepage == CP_ACP)
1053 codepage = GetACP();
1054 else if (codepage == CP_OEMCP)
1055 codepage = GetOEMCP();
1056
1057 if (codepage > 0 && codepage < 65536) {
1058 for (i = 0; i < max; i++) {
1059 tbuf[0] = i;
1060
1061 if (MultiByteToWideChar(codepage, flg, tbuf, 1, unitab + i, 1)
1062 != 1)
1063 unitab[i] = 0xFFFD;
1064 }
1065 } else {
1066 int j = 256 - cp_list[codepage & 0xFFFF].cp_size;
1067 for (i = 0; i < max; i++)
1068 unitab[i] = i;
1069 for (i = j; i < max; i++)
1070 unitab[i] = cp_list[codepage & 0xFFFF].cp_table[i - j];
1071 }
1072}