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