Update after gnulib changed.
[libiconv.git] / lib / cp950.h
blobf7452a81d5ecbb7b3346a04f37163022e7d47663
1 /*
2 * Copyright (C) 1999-2001, 2005, 2016 Free Software Foundation, Inc.
3 * This file is part of the GNU LIBICONV Library.
5 * The GNU LIBICONV Library is free software; you can redistribute it
6 * and/or modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either version 2.1
8 * of the License, or (at your option) any later version.
10 * The GNU LIBICONV Library is distributed in the hope that it will be
11 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with the GNU LIBICONV Library; see the file COPYING.LIB.
17 * If not, see <https://www.gnu.org/licenses/>.
21 * CP950
25 * Microsoft CP950 is a slightly extended and slightly modified version of
26 * BIG5. The differences between the EASTASIA/OTHER/BIG5.TXT and
27 * VENDORS/MICSFT/WINDOWS/CP950.TXT tables found on ftp.unicode.org are
28 * as follows:
30 * 1. Some characters in the BIG5 range are defined differently:
32 * code BIG5.TXT CP950.TXT
33 * 0xA145 0x2022 # BULLET 0x2027 # HYPHENATION POINT
34 * 0xA14E 0xFF64 # HALFWIDTH IDEOGRAPHIC COMMA
35 * 0xFE51 # SMALL IDEOGRAPHIC COMMA
36 * 0xA15A --- 0x2574 # BOX DRAWINGS LIGHT LEFT
37 * 0xA1C2 0x203E # OVERLINE 0x00AF # MACRON
38 * 0xA1C3 --- 0xFFE3 # FULLWIDTH MACRON
39 * 0xA1C5 --- 0x02CD # MODIFIER LETTER LOW MACRON
40 * 0xA1E3 0x223C # TILDE OPERATOR 0xFF5E # FULLWIDTH TILDE
41 * 0xA1F2 0x2641 # EARTH 0x2295 # CIRCLED PLUS
42 * 0xA1F3 0x2609 # SUN 0x2299 # CIRCLED DOT OPERATOR
43 * 0xA1FE --- 0xFF0F # FULLWIDTH SOLIDUS
44 * 0xA240 --- 0xFF3C # FULLWIDTH REVERSE SOLIDUS
45 * 0xA241 0xFF0F # FULLWIDTH SOLIDUS 0x2215 # DIVISION SLASH
46 * 0xA242 0xFF3C # FULLWIDTH REVERSE SOLIDUS
47 * 0xFE68 # SMALL REVERSE SOLIDUS
48 * 0xA244 0x00A5 # YEN SIGN 0xFFE5 # FULLWIDTH YEN SIGN
49 * 0xA246 0x00A2 # CENT SIGN 0xFFE0 # FULLWIDTH CENT SIGN
50 * 0xA247 0x00A3 # POUND SIGN 0xFFE1 # FULLWIDTH POUND SIGN
51 * 0xA2CC --- 0x5341
52 * 0xA2CE --- 0x5345
54 * 2. A small new row. See cp950ext.h.
56 * 3. CP950.TXT is lacking the range 0xC6A1..0xC7FC (Hiragana, Katakana,
57 * Cyrillic, circled digits, parenthesized digits).
59 * We implement this omission, because said range is marked "uncertain"
60 * in the unicode.org BIG5 table.
62 * The table found on Microsoft's website furthermore adds:
64 * 4. A single character:
66 * code CP950.TXT
67 * 0xA3E1 0x20AC # EURO SIGN
69 * Many variants of BIG5 or CP950 (in JDK, Solaris, OSF/1, Windows-2000, ICU,
70 * as well as our BIG5-2003 converter) also add:
72 * 5. Private area mappings:
74 * code Unicode
75 * 0x{81..8D}{40..7E,A1..FE} U+EEB8..U+F6B0
76 * 0x{8E..A0}{40..7E,A1..FE} U+E311..U+EEB7
77 * 0x{FA..FE}{40..7E,A1..FE} U+E000..U+E310
79 * We add them too because, although there are backward compatibility problems
80 * when a character from a private area is moved to an official Unicode code
81 * point, they are useful for some people in practice.
84 static const unsigned short cp950_2uni_pagea1[314] = {
85 /* 0xa1 */
86 0x3000, 0xff0c, 0x3001, 0x3002, 0xff0e, 0x2027, 0xff1b, 0xff1a,
87 0xff1f, 0xff01, 0xfe30, 0x2026, 0x2025, 0xfe50, 0xfe51, 0xfe52,
88 0x00b7, 0xfe54, 0xfe55, 0xfe56, 0xfe57, 0xff5c, 0x2013, 0xfe31,
89 0x2014, 0xfe33, 0x2574, 0xfe34, 0xfe4f, 0xff08, 0xff09, 0xfe35,
90 0xfe36, 0xff5b, 0xff5d, 0xfe37, 0xfe38, 0x3014, 0x3015, 0xfe39,
91 0xfe3a, 0x3010, 0x3011, 0xfe3b, 0xfe3c, 0x300a, 0x300b, 0xfe3d,
92 0xfe3e, 0x3008, 0x3009, 0xfe3f, 0xfe40, 0x300c, 0x300d, 0xfe41,
93 0xfe42, 0x300e, 0x300f, 0xfe43, 0xfe44, 0xfe59, 0xfe5a, 0xfe5b,
94 0xfe5c, 0xfe5d, 0xfe5e, 0x2018, 0x2019, 0x201c, 0x201d, 0x301d,
95 0x301e, 0x2035, 0x2032, 0xff03, 0xff06, 0xff0a, 0x203b, 0x00a7,
96 0x3003, 0x25cb, 0x25cf, 0x25b3, 0x25b2, 0x25ce, 0x2606, 0x2605,
97 0x25c7, 0x25c6, 0x25a1, 0x25a0, 0x25bd, 0x25bc, 0x32a3, 0x2105,
98 0x00af, 0xffe3, 0xff3f, 0x02cd, 0xfe49, 0xfe4a, 0xfe4d, 0xfe4e,
99 0xfe4b, 0xfe4c, 0xfe5f, 0xfe60, 0xfe61, 0xff0b, 0xff0d, 0x00d7,
100 0x00f7, 0x00b1, 0x221a, 0xff1c, 0xff1e, 0xff1d, 0x2266, 0x2267,
101 0x2260, 0x221e, 0x2252, 0x2261, 0xfe62, 0xfe63, 0xfe64, 0xfe65,
102 0xfe66, 0xff5e, 0x2229, 0x222a, 0x22a5, 0x2220, 0x221f, 0x22bf,
103 0x33d2, 0x33d1, 0x222b, 0x222e, 0x2235, 0x2234, 0x2640, 0x2642,
104 0x2295, 0x2299, 0x2191, 0x2193, 0x2190, 0x2192, 0x2196, 0x2197,
105 0x2199, 0x2198, 0x2225, 0x2223, 0xff0f,
106 /* 0xa2 */
107 0xff3c, 0x2215, 0xfe68, 0xff04, 0xffe5, 0x3012, 0xffe0, 0xffe1,
108 0xff05, 0xff20, 0x2103, 0x2109, 0xfe69, 0xfe6a, 0xfe6b, 0x33d5,
109 0x339c, 0x339d, 0x339e, 0x33ce, 0x33a1, 0x338e, 0x338f, 0x33c4,
110 0x00b0, 0x5159, 0x515b, 0x515e, 0x515d, 0x5161, 0x5163, 0x55e7,
111 0x74e9, 0x7cce, 0x2581, 0x2582, 0x2583, 0x2584, 0x2585, 0x2586,
112 0x2587, 0x2588, 0x258f, 0x258e, 0x258d, 0x258c, 0x258b, 0x258a,
113 0x2589, 0x253c, 0x2534, 0x252c, 0x2524, 0x251c, 0x2594, 0x2500,
114 0x2502, 0x2595, 0x250c, 0x2510, 0x2514, 0x2518, 0x256d, 0x256e,
115 0x2570, 0x256f, 0x2550, 0x255e, 0x256a, 0x2561, 0x25e2, 0x25e3,
116 0x25e5, 0x25e4, 0x2571, 0x2572, 0x2573, 0xff10, 0xff11, 0xff12,
117 0xff13, 0xff14, 0xff15, 0xff16, 0xff17, 0xff18, 0xff19, 0x2160,
118 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168,
119 0x2169, 0x3021, 0x3022, 0x3023, 0x3024, 0x3025, 0x3026, 0x3027,
120 0x3028, 0x3029, 0x5341, 0x5344, 0x5345, 0xff21, 0xff22, 0xff23,
121 0xff24, 0xff25, 0xff26, 0xff27, 0xff28, 0xff29, 0xff2a, 0xff2b,
122 0xff2c, 0xff2d, 0xff2e, 0xff2f, 0xff30, 0xff31, 0xff32, 0xff33,
123 0xff34, 0xff35, 0xff36, 0xff37, 0xff38, 0xff39, 0xff3a, 0xff41,
124 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47, 0xff48, 0xff49,
125 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0xff4f, 0xff50, 0xff51,
126 0xff52, 0xff53, 0xff54, 0xff55, 0xff56,
129 #include "cp950ext.h"
131 static int
132 cp950_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, size_t n)
134 unsigned char c = *s;
135 /* Code set 0 (ASCII) */
136 if (c < 0x80)
137 return ascii_mbtowc(conv,pwc,s,n);
138 /* Code set 1 (BIG5 extended) */
139 if (c >= 0x81 && c < 0xff) {
140 if (n < 2)
141 return RET_TOOFEW(0);
143 unsigned char c2 = s[1];
144 if ((c2 >= 0x40 && c2 < 0x7f) || (c2 >= 0xa1 && c2 < 0xff)) {
145 if (c >= 0xa1) {
146 if (c < 0xa3) {
147 unsigned int i = 157 * (c - 0xa1) + (c2 - (c2 >= 0xa1 ? 0x62 : 0x40));
148 unsigned short wc = cp950_2uni_pagea1[i];
149 if (wc != 0xfffd) {
150 *pwc = (ucs4_t) wc;
151 return 2;
154 if (!((c == 0xc6 && c2 >= 0xa1) || c == 0xc7)) {
155 int ret = big5_mbtowc(conv,pwc,s,2);
156 if (ret != RET_ILSEQ)
157 return ret;
159 if (c == 0xa3 && c2 == 0xe1) {
160 *pwc = 0x20ac;
161 return 2;
163 if (c >= 0xfa) {
164 /* User-defined characters */
165 *pwc = 0xe000 + 157 * (c - 0xfa) + (c2 - (c2 >= 0xa1 ? 0x62 : 0x40));
166 return 2;
168 } else {
169 /* 0x81 <= c < 0xa1. */
170 /* User-defined characters */
171 *pwc = (c >= 0x8e ? 0xdb18 : 0xeeb8) + 157 * (c - 0x81)
172 + (c2 - (c2 >= 0xa1 ? 0x62 : 0x40));
173 return 2;
177 if (c == 0xf9) {
178 int ret = cp950ext_mbtowc(conv,pwc,s,2);
179 if (ret != RET_ILSEQ)
180 return ret;
183 return RET_ILSEQ;
186 static int
187 cp950_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, size_t n)
189 unsigned char buf[2];
190 int ret;
192 /* Code set 0 (ASCII) */
193 ret = ascii_wctomb(conv,r,wc,n);
194 if (ret != RET_ILUNI)
195 return ret;
197 /* Code set 1 (BIG5 extended) */
198 switch (wc >> 8) {
199 case 0x00:
200 if (wc == 0x00af) { buf[0] = 0xa1; buf[1] = 0xc2; ret = 2; break; }
201 if (wc == 0x00a2 || wc == 0x00a3 || wc == 0x00a4)
202 return RET_ILUNI;
203 break;
204 case 0x02:
205 if (wc == 0x02cd) { buf[0] = 0xa1; buf[1] = 0xc5; ret = 2; break; }
206 break;
207 case 0x20:
208 if (wc == 0x2027) { buf[0] = 0xa1; buf[1] = 0x45; ret = 2; break; }
209 if (wc == 0x20ac) { buf[0] = 0xa3; buf[1] = 0xe1; ret = 2; break; }
210 if (wc == 0x2022 || wc == 0x203e)
211 return RET_ILUNI;
212 break;
213 case 0x22:
214 if (wc == 0x2215) { buf[0] = 0xa2; buf[1] = 0x41; ret = 2; break; }
215 if (wc == 0x2295) { buf[0] = 0xa1; buf[1] = 0xf2; ret = 2; break; }
216 if (wc == 0x2299) { buf[0] = 0xa1; buf[1] = 0xf3; ret = 2; break; }
217 if (wc == 0x223c)
218 return RET_ILUNI;
219 break;
220 case 0x25:
221 if (wc == 0x2574) { buf[0] = 0xa1; buf[1] = 0x5a; ret = 2; break; }
222 break;
223 case 0x26:
224 if (wc == 0x2609 || wc == 0x2641)
225 return RET_ILUNI;
226 break;
227 case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5:
228 case 0xe6: case 0xe7: case 0xe8: case 0xe9: case 0xea: case 0xeb:
229 case 0xec: case 0xed: case 0xee: case 0xef: case 0xf0: case 0xf1:
230 case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6:
232 /* User-defined characters */
233 unsigned int i = wc - 0xe000;
234 if (i < 5809) {
235 unsigned int c1 = i / 157;
236 unsigned int c2 = i % 157;
237 buf[0] = c1 + (c1 < 5 ? 0xfa : c1 < 24 ? 0x89 : 0x69);
238 buf[1] = c2 + (c2 < 0x3f ? 0x40 : 0x62);
239 ret = 2;
240 break;
243 break;
244 case 0xfe:
245 if (wc == 0xfe51) { buf[0] = 0xa1; buf[1] = 0x4e; ret = 2; break; }
246 if (wc == 0xfe68) { buf[0] = 0xa2; buf[1] = 0x42; ret = 2; break; }
247 break;
248 case 0xff:
249 if (wc == 0xff0f) { buf[0] = 0xa1; buf[1] = 0xfe; ret = 2; break; }
250 if (wc == 0xff3c) { buf[0] = 0xa2; buf[1] = 0x40; ret = 2; break; }
251 if (wc == 0xff5e) { buf[0] = 0xa1; buf[1] = 0xe3; ret = 2; break; }
252 if (wc == 0xffe0) { buf[0] = 0xa2; buf[1] = 0x46; ret = 2; break; }
253 if (wc == 0xffe1) { buf[0] = 0xa2; buf[1] = 0x47; ret = 2; break; }
254 if (wc == 0xffe3) { buf[0] = 0xa1; buf[1] = 0xc3; ret = 2; break; }
255 if (wc == 0xffe5) { buf[0] = 0xa2; buf[1] = 0x44; ret = 2; break; }
256 if (wc == 0xff64)
257 return RET_ILUNI;
258 break;
260 if (ret == RET_ILUNI)
261 ret = big5_wctomb(conv,buf,wc,2);
262 if (ret != RET_ILUNI) {
263 if (ret != 2) abort();
264 if (!((buf[0] == 0xc6 && buf[1] >= 0xa1) || buf[0] == 0xc7)) {
265 if (n < 2)
266 return RET_TOOSMALL;
267 r[0] = buf[0];
268 r[1] = buf[1];
269 return 2;
272 ret = cp950ext_wctomb(conv,buf,wc,2);
273 if (ret != RET_ILUNI) {
274 if (ret != 2) abort();
275 if (n < 2)
276 return RET_TOOSMALL;
277 r[0] = buf[0];
278 r[1] = buf[1];
279 return 2;
282 return RET_ILUNI;