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