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