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