2 * Copyright (C) 1999-2001 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 Library General Public
7 * License as published by the Free Software Foundation; either version 2
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 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with the GNU LIBICONV Library; see the file COPYING.LIB.
17 * If not, write to the Free Software Foundation, Inc., 59 Temple Place -
18 * Suite 330, Boston, MA 02111-1307, USA.
26 * Microsoft CP950 is a slightly extended and slightly modified version of
27 * BIG5. The differences between the EASTASIA/OTHER/BIG5.TXT and
28 * VENDORS/MICSFT/WINDOWS/CP950.TXT tables found on ftp.unicode.org are
31 * 1. Some characters in the BIG5 range are defined differently:
33 * code BIG5.TXT CP950.TXT
34 * 0xA145 0x2022 # BULLET 0x2027 # HYPHENATION POINT
35 * 0xA14E 0xFF64 # HALFWIDTH IDEOGRAPHIC COMMA
36 * 0xFE51 # SMALL IDEOGRAPHIC COMMA
37 * 0xA15A --- 0x2574 # BOX DRAWINGS LIGHT LEFT
38 * 0xA1C2 0x203E # OVERLINE 0x00AF # MACRON
39 * 0xA1C3 --- 0xFFE3 # FULLWIDTH MACRON
40 * 0xA1C5 --- 0x02CD # MODIFIER LETTER LOW MACRON
41 * 0xA1E3 0x223C # TILDE OPERATOR 0xFF5E # FULLWIDTH TILDE
42 * 0xA1F2 0x2641 # EARTH 0x2295 # CIRCLED PLUS
43 * 0xA1F3 0x2609 # SUN 0x2299 # CIRCLED DOT OPERATOR
44 * 0xA1FE --- 0xFF0F # FULLWIDTH SOLIDUS
45 * 0xA240 --- 0xFF3C # FULLWIDTH REVERSE SOLIDUS
46 * 0xA241 0xFF0F # FULLWIDTH SOLIDUS 0x2215 # DIVISION SLASH
47 * 0xA242 0xFF3C # FULLWIDTH REVERSE SOLIDUS
48 * 0xFE68 # SMALL REVERSE SOLIDUS
49 * 0xA244 0x00A5 # YEN SIGN 0xFFE5 # FULLWIDTH YEN SIGN
50 * 0xA246 0x00A2 # CENT SIGN 0xFFE0 # FULLWIDTH CENT SIGN
51 * 0xA247 0x00A3 # POUND SIGN 0xFFE1 # FULLWIDTH POUND SIGN
55 * 2. A small new row. See cp950ext.h.
57 * 3. CP950.TXT is lacking the range 0xC6A1..0xC7FC (Hiragana, Katakana,
58 * Cyrillic, circled digits, parenthesized digits).
60 * We implement this omission, because said range is marked "uncertain"
61 * in the unicode.org BIG5 table.
64 static const unsigned short cp950_2uni_pagea1
[314] = {
66 0x3000, 0xff0c, 0x3001, 0x3002, 0xff0e, 0x2027, 0xff1b, 0xff1a,
67 0xff1f, 0xff01, 0xfe30, 0x2026, 0x2025, 0xfe50, 0xfe51, 0xfe52,
68 0x00b7, 0xfe54, 0xfe55, 0xfe56, 0xfe57, 0xff5c, 0x2013, 0xfe31,
69 0x2014, 0xfe33, 0x2574, 0xfe34, 0xfe4f, 0xff08, 0xff09, 0xfe35,
70 0xfe36, 0xff5b, 0xff5d, 0xfe37, 0xfe38, 0x3014, 0x3015, 0xfe39,
71 0xfe3a, 0x3010, 0x3011, 0xfe3b, 0xfe3c, 0x300a, 0x300b, 0xfe3d,
72 0xfe3e, 0x3008, 0x3009, 0xfe3f, 0xfe40, 0x300c, 0x300d, 0xfe41,
73 0xfe42, 0x300e, 0x300f, 0xfe43, 0xfe44, 0xfe59, 0xfe5a, 0xfe5b,
74 0xfe5c, 0xfe5d, 0xfe5e, 0x2018, 0x2019, 0x201c, 0x201d, 0x301d,
75 0x301e, 0x2035, 0x2032, 0xff03, 0xff06, 0xff0a, 0x203b, 0x00a7,
76 0x3003, 0x25cb, 0x25cf, 0x25b3, 0x25b2, 0x25ce, 0x2606, 0x2605,
77 0x25c7, 0x25c6, 0x25a1, 0x25a0, 0x25bd, 0x25bc, 0x32a3, 0x2105,
78 0x00af, 0xffe3, 0xff3f, 0x02cd, 0xfe49, 0xfe4a, 0xfe4d, 0xfe4e,
79 0xfe4b, 0xfe4c, 0xfe5f, 0xfe60, 0xfe61, 0xff0b, 0xff0d, 0x00d7,
80 0x00f7, 0x00b1, 0x221a, 0xff1c, 0xff1e, 0xff1d, 0x2266, 0x2267,
81 0x2260, 0x221e, 0x2252, 0x2261, 0xfe62, 0xfe63, 0xfe64, 0xfe65,
82 0xfe66, 0xff5e, 0x2229, 0x222a, 0x22a5, 0x2220, 0x221f, 0x22bf,
83 0x33d2, 0x33d1, 0x222b, 0x222e, 0x2235, 0x2234, 0x2640, 0x2642,
84 0x2295, 0x2299, 0x2191, 0x2193, 0x2190, 0x2192, 0x2196, 0x2197,
85 0x2199, 0x2198, 0x2225, 0x2223, 0xff0f,
87 0xff3c, 0x2215, 0xfe68, 0xff04, 0xffe5, 0x3012, 0xffe0, 0xffe1,
88 0xff05, 0xff20, 0x2103, 0x2109, 0xfe69, 0xfe6a, 0xfe6b, 0x33d5,
89 0x339c, 0x339d, 0x339e, 0x33ce, 0x33a1, 0x338e, 0x338f, 0x33c4,
90 0x00b0, 0x5159, 0x515b, 0x515e, 0x515d, 0x5161, 0x5163, 0x55e7,
91 0x74e9, 0x7cce, 0x2581, 0x2582, 0x2583, 0x2584, 0x2585, 0x2586,
92 0x2587, 0x2588, 0x258f, 0x258e, 0x258d, 0x258c, 0x258b, 0x258a,
93 0x2589, 0x253c, 0x2534, 0x252c, 0x2524, 0x251c, 0x2594, 0x2500,
94 0x2502, 0x2595, 0x250c, 0x2510, 0x2514, 0x2518, 0x256d, 0x256e,
95 0x2570, 0x256f, 0x2550, 0x255e, 0x256a, 0x2561, 0x25e2, 0x25e3,
96 0x25e5, 0x25e4, 0x2571, 0x2572, 0x2573, 0xff10, 0xff11, 0xff12,
97 0xff13, 0xff14, 0xff15, 0xff16, 0xff17, 0xff18, 0xff19, 0x2160,
98 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168,
99 0x2169, 0x3021, 0x3022, 0x3023, 0x3024, 0x3025, 0x3026, 0x3027,
100 0x3028, 0x3029, 0x5341, 0x5344, 0x5345, 0xff21, 0xff22, 0xff23,
101 0xff24, 0xff25, 0xff26, 0xff27, 0xff28, 0xff29, 0xff2a, 0xff2b,
102 0xff2c, 0xff2d, 0xff2e, 0xff2f, 0xff30, 0xff31, 0xff32, 0xff33,
103 0xff34, 0xff35, 0xff36, 0xff37, 0xff38, 0xff39, 0xff3a, 0xff41,
104 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47, 0xff48, 0xff49,
105 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0xff4f, 0xff50, 0xff51,
106 0xff52, 0xff53, 0xff54, 0xff55, 0xff56,
109 #include "cp950ext.h"
112 cp950_mbtowc (conv_t conv
, ucs4_t
*pwc
, const unsigned char *s
, int n
)
114 unsigned char c
= *s
;
115 /* Code set 0 (ASCII) */
117 return ascii_mbtowc(conv
,pwc
,s
,n
);
118 /* Code set 1 (BIG5 extended) */
119 if (c
>= 0xa1 && c
< 0xff) {
121 return RET_TOOFEW(0);
123 unsigned char c2
= s
[1];
124 if ((c2
>= 0x40 && c2
< 0x7f) || (c2
>= 0xa1 && c2
< 0xff)) {
126 unsigned int i
= 157 * (c
- 0xa1) + (c2
- (c2
>= 0xa1 ? 0x62 : 0x40));
127 unsigned short wc
= cp950_2uni_pagea1
[i
];
133 if (!((c
== 0xc6 && c2
>= 0xa1) || c
== 0xc7)) {
134 int ret
= big5_mbtowc(conv
,pwc
,s
,2);
135 if (ret
!= RET_ILSEQ
)
141 int ret
= cp950ext_mbtowc(conv
,pwc
,s
,2);
142 if (ret
!= RET_ILSEQ
)
150 cp950_wctomb (conv_t conv
, unsigned char *r
, ucs4_t wc
, int n
)
152 unsigned char buf
[2];
155 /* Code set 0 (ASCII) */
156 ret
= ascii_wctomb(conv
,r
,wc
,n
);
157 if (ret
!= RET_ILUNI
)
160 /* Code set 1 (BIG5 extended) */
163 if (wc
== 0x00af) { buf
[0] = 0xa1; buf
[1] = 0xc2; ret
= 2; break; }
164 if (wc
== 0x00a2 || wc
== 0x00a3 || wc
== 0x00a4)
168 if (wc
== 0x02cd) { buf
[0] = 0xa1; buf
[1] = 0xc5; ret
= 2; break; }
171 if (wc
== 0x2027) { buf
[0] = 0xa1; buf
[1] = 0x45; ret
= 2; break; }
172 if (wc
== 0x2022 || wc
== 0x203e)
176 if (wc
== 0x2215) { buf
[0] = 0xa2; buf
[1] = 0x41; ret
= 2; break; }
177 if (wc
== 0x2295) { buf
[0] = 0xa1; buf
[1] = 0xf2; ret
= 2; break; }
178 if (wc
== 0x2299) { buf
[0] = 0xa1; buf
[1] = 0xf3; ret
= 2; break; }
183 if (wc
== 0x2574) { buf
[0] = 0xa1; buf
[1] = 0x5a; ret
= 2; break; }
186 if (wc
== 0x2609 || wc
== 0x2641)
190 if (wc
== 0xfe51) { buf
[0] = 0xa1; buf
[1] = 0x4e; ret
= 2; break; }
191 if (wc
== 0xfe68) { buf
[0] = 0xa2; buf
[1] = 0x42; ret
= 2; break; }
194 if (wc
== 0xff0f) { buf
[0] = 0xa1; buf
[1] = 0xfe; ret
= 2; break; }
195 if (wc
== 0xff3c) { buf
[0] = 0xa2; buf
[1] = 0x40; ret
= 2; break; }
196 if (wc
== 0xff5e) { buf
[0] = 0xa1; buf
[1] = 0xe3; ret
= 2; break; }
197 if (wc
== 0xffe0) { buf
[0] = 0xa2; buf
[1] = 0x46; ret
= 2; break; }
198 if (wc
== 0xffe1) { buf
[0] = 0xa2; buf
[1] = 0x47; ret
= 2; break; }
199 if (wc
== 0xffe3) { buf
[0] = 0xa1; buf
[1] = 0xc3; ret
= 2; break; }
200 if (wc
== 0xffe5) { buf
[0] = 0xa2; buf
[1] = 0x44; ret
= 2; break; }
205 if (ret
== RET_ILUNI
)
206 ret
= big5_wctomb(conv
,buf
,wc
,2);
207 if (ret
!= RET_ILUNI
) {
208 if (ret
!= 2) abort();
209 if (!((buf
[0] == 0xc6 && buf
[1] >= 0xa1) || buf
[0] == 0xc7)) {
217 ret
= cp950ext_wctomb(conv
,buf
,wc
,2);
218 if (ret
!= RET_ILUNI
) {
219 if (ret
!= 2) abort();