1 /* 2 * Copyright (C) 1999-2001, 2005 Free Software Foundation, Inc. 3 * This file is part of the GNU LIBICONV Library. 4 * 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. 9 * 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. 14 * 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., 51 Franklin Street, 18 * Fifth Floor, Boston, MA 02110-1301, USA. 19 */ 20 21 /* 22 * BIG5-2003 23 */ 24 25 /* 26 * BIG5-2003 is a slightly extended and slightly modified version of BIG5. 27 * It is actually nearer to Microsoft CP950 than to BIG5. The differences 28 * between EASTASIA/OTHER/BIG5.TXT found on ftp.unicode.org and BIG5-2003.TXT 29 * are as follows: 30 * 31 * 1. Some characters in the symbols area (0xA140..0xA2CE) are defined 32 * differently: 33 * 34 * code BIG5.TXT BIG5-2003.TXT 35 * 0xA145 0x2022 # BULLET 0x2027 # HYPHENATION POINT 36 * 0xA14E 0xFF64 # HALFWIDTH IDEOGRAPHIC COMMA 37 * 0xFE51 # SMALL IDEOGRAPHIC COMMA 38 * 0xA156 0x2013 # EN DASH 0x2015 # HORIZONTAL BAR 39 * 0xA15A --- 0x2574 # BOX DRAWINGS LIGHT LEFT 40 * 0xA1C3 --- 0xFFE3 # FULLWIDTH MACRON 41 * 0xA1C5 --- 0x02CD # MODIFIER LETTER LOW MACRON 42 * 0xA1E3 0x223C # TILDE OPERATOR 0xFF5E # FULLWIDTH TILDE 43 * 0xA1F2 0x2641 # EARTH 0x2295 # CIRCLED PLUS 44 * 0xA1F3 0x2609 # SUN 0x2299 # CIRCLED DOT OPERATOR 45 * 0xA1FE --- 0xFF0F # FULLWIDTH SOLIDUS 46 * 0xA240 --- 0xFF3C # FULLWIDTH REVERSE SOLIDUS 47 * 0xA241 0xFF0F # FULLWIDTH SOLIDUS 0x2215 # DIVISION SLASH 48 * 0xA242 0xFF3C # FULLWIDTH REVERSE SOLIDUS 49 * 0xFE68 # SMALL REVERSE SOLIDUS 50 * 0xA244 0x00A5 # YEN SIGN 0xFFE5 # FULLWIDTH YEN SIGN 51 * 0xA246 0x00A2 # CENT SIGN 0xFFE0 # FULLWIDTH CENT SIGN 52 * 0xA247 0x00A3 # POUND SIGN 0xFFE1 # FULLWIDTH POUND SIGN 53 * 0xA2A4 0x2550 # BOX DRAWINGS DOUBLE HORIZONTAL 54 * 0x2501 # BOX DRAWINGS HEAVY HORIZONTAL 55 * 0xA2A5 0x255E # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE 56 * 0x251D # BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY 57 * 0xA2A6 0x256A # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE 58 * 0x253F # BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY 59 * 0xA2A7 0x2561 # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE 60 * 0x2525 # BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY 61 * 0xA2CC --- 0x3038 # HANGZHOU NUMERAL TEN 62 * 0xA2CD 0x5344 0x3039 # HANGZHOU NUMERAL TWENTY 63 * 0xA2CE --- 0x303A # HANGZHOU NUMERAL THIRTY 64 * 65 * 2. A control symbols area is added: 66 * 67 * code 68 * 0xA3C0..0xA3E0 U+2400..U+2421 69 * 70 * 3. The Euro sign is added: 71 * 72 * code 73 * 0xA3E1 0x20AC # EURO SIGN 74 * 75 * 4. Some characters in the main area are defined differently: 76 * 77 * code BIG5.TXT BIG5-2003.TXT 78 * 0xC255 0x5F5D 0x5F5E 79 * 80 * 5. The area 0xC6A1..0xC7FE is organized differently: 81 * 82 * code 83 * 0xC6A1..0xC6BE numerals (was in BIG5.TXT at 0xC7E9..0xC7FC) 84 * 0xC6BF..0xC6D7 radicals 85 * 0xC6D8..0xC6E6 rarely used symbols 86 * 0xC6E7..0xC77A hiragana (U+3041..U+3093, was in BIG5.TXT at 0xC6A5..0xC6F7) 87 * 0xC77B..0xC7F2 katakana (U+30A1..U+30F6, was in BIG5.TXT at 0xC6F8..0xC7B0) 88 * 89 * 6. Some characters are added at 0xF9D6..0xF9DC. 90 * 91 * 7. Box drawing characters are added at 0xF9DD..0xF9FE. 92 * 93 * Note: 4 of these characters are mapped in a non-inversible way, because 94 * Unicode does not yet include the corresponding characters: 95 * 96 * code Unicode approximation 97 * 0xF9FA BOX DRAWINGS DOUBLE ARC DOWN AND RIGHT 0x2554 98 * 0xF9FB BOX DRAWINGS DOUBLE ARC DOWN AND LEFT 0x2557 99 * 0xF9FC BOX DRAWINGS DOUBLE ARC UP AND RIGHT 0x255A 100 * 0xF9FD BOX DRAWINGS DOUBLE ARC UP AND LEFT 0x255D 101 * 102 * 8. Private area mappings are added: 103 * 104 * code Unicode 105 * 0x{81..8D}{40..7E,A1..FE} U+EEB8..U+F6B0 106 * 0x{8E..A0}{40..7E,A1..FE} U+E311..U+EEB7 107 * 0x{FA..FE}{40..7E,A1..FE} U+E000..U+E310 108 * 109 * These mappings are not contained in the BSMI Big5-2003 standard. However, 110 * they were contained in a draft of it. 111 */ 112 113 static const unsigned short big5_2003_2uni_pagea1[314] = { 114 /* 0xa1 */ 115 0x3000, 0xff0c, 0x3001, 0x3002, 0xff0e, 0x2027, 0xff1b, 0xff1a, 116 0xff1f, 0xff01, 0xfe30, 0x2026, 0x2025, 0xfe50, 0xfe51, 0xfe52, 117 0x00b7, 0xfe54, 0xfe55, 0xfe56, 0xfe57, 0xff5c, 0x2015, 0xfe31, 118 0x2014, 0xfe33, 0x2574, 0xfe34, 0xfe4f, 0xff08, 0xff09, 0xfe35, 119 0xfe36, 0xff5b, 0xff5d, 0xfe37, 0xfe38, 0x3014, 0x3015, 0xfe39, 120 0xfe3a, 0x3010, 0x3011, 0xfe3b, 0xfe3c, 0x300a, 0x300b, 0xfe3d, 121 0xfe3e, 0x3008, 0x3009, 0xfe3f, 0xfe40, 0x300c, 0x300d, 0xfe41, 122 0xfe42, 0x300e, 0x300f, 0xfe43, 0xfe44, 0xfe59, 0xfe5a, 0xfe5b, 123 0xfe5c, 0xfe5d, 0xfe5e, 0x2018, 0x2019, 0x201c, 0x201d, 0x301d, 124 0x301e, 0x2035, 0x2032, 0xff03, 0xff06, 0xff0a, 0x203b, 0x00a7, 125 0x3003, 0x25cb, 0x25cf, 0x25b3, 0x25b2, 0x25ce, 0x2606, 0x2605, 126 0x25c7, 0x25c6, 0x25a1, 0x25a0, 0x25bd, 0x25bc, 0x32a3, 0x2105, 127 0x203e, 0xffe3, 0xff3f, 0x02cd, 0xfe49, 0xfe4a, 0xfe4d, 0xfe4e, 128 0xfe4b, 0xfe4c, 0xfe5f, 0xfe60, 0xfe61, 0xff0b, 0xff0d, 0x00d7, 129 0x00f7, 0x00b1, 0x221a, 0xff1c, 0xff1e, 0xff1d, 0x2266, 0x2267, 130 0x2260, 0x221e, 0x2252, 0x2261, 0xfe62, 0xfe63, 0xfe64, 0xfe65, 131 0xfe66, 0xff5e, 0x2229, 0x222a, 0x22a5, 0x2220, 0x221f, 0x22bf, 132 0x33d2, 0x33d1, 0x222b, 0x222e, 0x2235, 0x2234, 0x2640, 0x2642, 133 0x2295, 0x2299, 0x2191, 0x2193, 0x2190, 0x2192, 0x2196, 0x2197, 134 0x2199, 0x2198, 0x2225, 0x2223, 0xff0f, 135 /* 0xa2 */ 136 0xff3c, 0x2215, 0xfe68, 0xff04, 0xffe5, 0x3012, 0xffe0, 0xffe1, 137 0xff05, 0xff20, 0x2103, 0x2109, 0xfe69, 0xfe6a, 0xfe6b, 0x33d5, 138 0x339c, 0x339d, 0x339e, 0x33ce, 0x33a1, 0x338e, 0x338f, 0x33c4, 139 0x00b0, 0x5159, 0x515b, 0x515e, 0x515d, 0x5161, 0x5163, 0x55e7, 140 0x74e9, 0x7cce, 0x2581, 0x2582, 0x2583, 0x2584, 0x2585, 0x2586, 141 0x2587, 0x2588, 0x258f, 0x258e, 0x258d, 0x258c, 0x258b, 0x258a, 142 0x2589, 0x253c, 0x2534, 0x252c, 0x2524, 0x251c, 0x2594, 0x2500, 143 0x2502, 0x2595, 0x250c, 0x2510, 0x2514, 0x2518, 0x256d, 0x256e, 144 0x2570, 0x256f, 0x2501, 0x251d, 0x253f, 0x2525, 0x25e2, 0x25e3, 145 0x25e5, 0x25e4, 0x2571, 0x2572, 0x2573, 0xff10, 0xff11, 0xff12, 146 0xff13, 0xff14, 0xff15, 0xff16, 0xff17, 0xff18, 0xff19, 0x2160, 147 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 148 0x2169, 0x3021, 0x3022, 0x3023, 0x3024, 0x3025, 0x3026, 0x3027, 149 0x3028, 0x3029, 0x3038, 0x3039, 0x303a, 0xff21, 0xff22, 0xff23, 150 0xff24, 0xff25, 0xff26, 0xff27, 0xff28, 0xff29, 0xff2a, 0xff2b, 151 0xff2c, 0xff2d, 0xff2e, 0xff2f, 0xff30, 0xff31, 0xff32, 0xff33, 152 0xff34, 0xff35, 0xff36, 0xff37, 0xff38, 0xff39, 0xff3a, 0xff41, 153 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47, 0xff48, 0xff49, 154 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0xff4f, 0xff50, 0xff51, 155 0xff52, 0xff53, 0xff54, 0xff55, 0xff56, 156 }; 157 158 static const unsigned short big5_2003_2uni_pagec6[70] = { 159 /* 0xc6a1 */ 160 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, 161 0x2468, 0x2469, 0x2474, 0x2475, 0x2476, 0x2477, 0x2478, 0x2479, 162 0x247a, 0x247b, 0x247c, 0x247d, 0x2170, 0x2171, 0x2172, 0x2173, 163 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x2f02, 0x2f03, 164 0x2f05, 0x2f07, 0x2f0c, 0x2f0d, 0x2f0e, 0x2f13, 0x2f16, 0x2f19, 165 0x2f1b, 0x2f22, 0x2f27, 0x2f2e, 0x2f33, 0x2f34, 0x2f35, 0x2f39, 166 0x2f3a, 0x2f41, 0x2f46, 0x2f67, 0x2f68, 0x2fa1, 0x2faa, 0x00a8, 167 0xff3e, 0x30fd, 0x30fe, 0x309d, 0x309e, 0xfffd, 0xfffd, 0x3005, 168 0x3006, 0x3007, 0x30fc, 0xff3b, 0xff3d, 0x273d, 169 }; 170 171 static const unsigned short big5_2003_2uni_pagef9[41] = { 172 /* 0xf9d6 */ 173 0x7881, 0x92b9, 0x88cf, 0x58bb, 0x6052, 0x7ca7, 0x5afa, 174 /* 0xf9dd */ 175 0x2554, 0x2566, 0x2557, 0x2560, 0x256c, 0x2563, 0x255a, 0x2569, 176 0x255d, 0x2552, 0x2564, 0x2555, 0x255e, 0x256a, 0x2561, 0x2558, 177 0x2567, 0x255b, 0x2553, 0x2565, 0x2556, 0x255f, 0x256b, 0x2562, 178 0x2559, 0x2568, 0x255c, 0x2551, 0x2550, 179 0x2554, 0x2557, 0x255a, 0x255d, /* not invertible */ 180 0x2593, 181 }; 182 183 static int 184 big5_2003_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) 185 { 186 unsigned char c = *s; 187 /* Code set 0 (ASCII) */ 188 if (c < 0x80) 189 return ascii_mbtowc(conv,pwc,s,n); 190 /* Code set 1 (BIG5 extended) */ 191 if (c >= 0x81 && c < 0xff) { 192 if (n < 2) 193 return RET_TOOFEW(0); 194 { 195 unsigned char c2 = s[1]; 196 if ((c2 >= 0x40 && c2 < 0x7f) || (c2 >= 0xa1 && c2 < 0xff)) { 197 if (c >= 0xa1) { 198 if (c < 0xa3) { 199 unsigned int i = 157 * (c - 0xa1) + (c2 - (c2 >= 0xa1 ? 0x62 : 0x40)); 200 unsigned short wc = big5_2003_2uni_pagea1[i]; 201 if (wc != 0xfffd) { 202 *pwc = (ucs4_t) wc; 203 return 2; 204 } 205 } 206 if (!((c == 0xc6 && c2 >= 0xa1) || c == 0xc7)) { 207 if (!(c == 0xc2 && c2 == 0x55)) { 208 int ret = big5_mbtowc(conv,pwc,s,2); 209 if (ret != RET_ILSEQ) 210 return ret; 211 if (c == 0xa3) { 212 if (c2 >= 0xc0 && c2 <= 0xe1) { 213 *pwc = (c2 == 0xe1 ? 0x20ac : c2 == 0xe0 ? 0x2421 : 0x2340 + c2); 214 return 2; 215 } 216 } else if (c == 0xf9) { 217 if (c2 >= 0xd6) { 218 *pwc = big5_2003_2uni_pagef9[c2-0xd6]; 219 return 2; 220 } 221 } else if (c >= 0xfa) { 222 *pwc = 0xe000 + 157 * (c - 0xfa) + (c2 - (c2 >= 0xa1 ? 0x62 : 0x40)); 223 return 2; 224 } 225 } else { 226 /* c == 0xc2 && c2 == 0x55. */ 227 *pwc = 0x5f5e; 228 return 2; 229 } 230 } else { 231 /* (c == 0xc6 && c2 >= 0xa1) || c == 0xc7. */ 232 unsigned int i = 157 * (c - 0xc6) + (c2 - (c2 >= 0xa1 ? 0x62 : 0x40)); 233 if (i < 133) { 234 /* 63 <= i < 133. */ 235 unsigned short wc = big5_2003_2uni_pagec6[i-63]; 236 if (wc != 0xfffd) { 237 *pwc = (ucs4_t) wc; 238 return 2; 239 } 240 } else if (i < 216) { 241 /* 133 <= i < 216. Hiragana. */ 242 *pwc = 0x3041 - 133 + i; 243 return 2; 244 } else if (i < 302) { 245 /* 216 <= i < 302. Katakana. */ 246 *pwc = 0x30a1 - 216 + i; 247 return 2; 248 } 249 } 250 } else { 251 /* 0x81 <= c < 0xa1. */ 252 *pwc = (c >= 0x8e ? 0xdb18 : 0xeeb8) + 157 * (c - 0x81) 253 + (c2 - (c2 >= 0xa1 ? 0x62 : 0x40)); 254 return 2; 255 } 256 } 257 } 258 } 259 return RET_ILSEQ; 260 } 261 262 static const unsigned char big5_2003_2charset_page25[29] = { 263 /* 0x2550 */ 264 0xf9, 0xf8, 0xe6, 0xef, 0xdd, 0xe8, 0xf1, 0xdf, 265 0xec, 0xf5, 0xe3, 0xee, 0xf7, 0xe5, 0xe9, 0xf2, 266 0xe0, 0xeb, 0xf4, 0xe2, 0xe7, 0xf0, 0xde, 0xed, 267 0xf6, 0xe4, 0xea, 0xf3, 0xe1, 268 }; 269 270 static int 271 big5_2003_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) 272 { 273 unsigned char buf[2]; 274 int ret; 275 276 /* Code set 0 (ASCII) */ 277 ret = ascii_wctomb(conv,r,wc,n); 278 if (ret != RET_ILUNI) 279 return ret; 280 281 /* Code set 1 (BIG5 extended) */ 282 switch (wc >> 8) { 283 case 0x00: 284 if (wc == 0x00a8) { buf[0] = 0xc6; buf[1] = 0xd8; ret = 2; break; } 285 if (wc == 0x00a2 || wc == 0x00a3 || wc == 0x00a5) 286 return RET_ILUNI; 287 break; 288 case 0x02: 289 if (wc == 0x02cd) { buf[0] = 0xa1; buf[1] = 0xc5; ret = 2; break; } 290 break; 291 case 0x04: 292 return RET_ILUNI; 293 case 0x20: 294 if (wc == 0x2015) { buf[0] = 0xa1; buf[1] = 0x56; ret = 2; break; } 295 if (wc == 0x2027) { buf[0] = 0xa1; buf[1] = 0x45; ret = 2; break; } 296 if (wc == 0x20ac) { buf[0] = 0xa3; buf[1] = 0xe1; ret = 2; break; } 297 if (wc == 0x2013 || wc == 0x2022) 298 return RET_ILUNI; 299 break; 300 case 0x21: 301 if (wc >= 0x2170 && wc <= 0x2179) { 302 buf[0] = 0xc6; buf[1] = wc - 0x20bb; ret = 2; 303 break; 304 } 305 break; 306 case 0x22: 307 if (wc == 0x2215) { buf[0] = 0xa2; buf[1] = 0x41; ret = 2; break; } 308 if (wc == 0x2295) { buf[0] = 0xa1; buf[1] = 0xf2; ret = 2; break; } 309 if (wc == 0x2299) { buf[0] = 0xa1; buf[1] = 0xf3; ret = 2; break; } 310 if (wc == 0x223c) 311 return RET_ILUNI; 312 break; 313 case 0x24: 314 if (wc <= 0x241f) { buf[0] = 0xa3; buf[1] = wc - 0x2340; ret = 2; break; } 315 if (wc == 0x2421) { buf[0] = 0xa3; buf[1] = 0xe0; ret = 2; break; } 316 if (wc >= 0x2460 && wc <= 0x2469) { 317 buf[0] = 0xc6; buf[1] = wc - 0x23bf; ret = 2; 318 break; 319 } 320 if (wc >= 0x2474 && wc <= 0x247d) { 321 buf[0] = 0xc6; buf[1] = wc - 0x23c9; ret = 2; 322 break; 323 } 324 break; 325 case 0x25: 326 if (wc == 0x2501) { buf[0] = 0xa2; buf[1] = 0xa4; ret = 2; break; } 327 if (wc == 0x251d) { buf[0] = 0xa2; buf[1] = 0xa5; ret = 2; break; } 328 if (wc == 0x2525) { buf[0] = 0xa2; buf[1] = 0xa7; ret = 2; break; } 329 if (wc == 0x253f) { buf[0] = 0xa2; buf[1] = 0xa6; ret = 2; break; } 330 if (wc >= 0x2550 && wc <= 0x256c) { 331 buf[0] = 0xf9; buf[1] = big5_2003_2charset_page25[wc-0x2550]; ret = 2; 332 break; 333 } 334 if (wc == 0x2574) { buf[0] = 0xa1; buf[1] = 0x5a; ret = 2; break; } 335 if (wc == 0x2593) { buf[0] = 0xf9; buf[1] = 0xfe; ret = 2; break; } 336 break; 337 case 0x26: 338 if (wc == 0x2609 || wc == 0x2641) 339 return RET_ILUNI; 340 break; 341 case 0x27: 342 if (wc == 0x273d) { buf[0] = 0xc6; buf[1] = 0xe6; ret = 2; break; } 343 break; 344 case 0x2f: 345 if (wc == 0x2f02) { buf[0] = 0xc6; buf[1] = 0xbf; ret = 2; break; } 346 if (wc == 0x2f03) { buf[0] = 0xc6; buf[1] = 0xc0; ret = 2; break; } 347 if (wc == 0x2f05) { buf[0] = 0xc6; buf[1] = 0xc1; ret = 2; break; } 348 if (wc == 0x2f07) { buf[0] = 0xc6; buf[1] = 0xc2; ret = 2; break; } 349 if (wc == 0x2f0c) { buf[0] = 0xc6; buf[1] = 0xc3; ret = 2; break; } 350 if (wc == 0x2f0d) { buf[0] = 0xc6; buf[1] = 0xc4; ret = 2; break; } 351 if (wc == 0x2f0e) { buf[0] = 0xc6; buf[1] = 0xc5; ret = 2; break; } 352 if (wc == 0x2f13) { buf[0] = 0xc6; buf[1] = 0xc6; ret = 2; break; } 353 if (wc == 0x2f16) { buf[0] = 0xc6; buf[1] = 0xc7; ret = 2; break; } 354 if (wc == 0x2f19) { buf[0] = 0xc6; buf[1] = 0xc8; ret = 2; break; } 355 if (wc == 0x2f1b) { buf[0] = 0xc6; buf[1] = 0xc9; ret = 2; break; } 356 if (wc == 0x2f22) { buf[0] = 0xc6; buf[1] = 0xca; ret = 2; break; } 357 if (wc == 0x2f27) { buf[0] = 0xc6; buf[1] = 0xcb; ret = 2; break; } 358 if (wc == 0x2f2e) { buf[0] = 0xc6; buf[1] = 0xcc; ret = 2; break; } 359 if (wc == 0x2f33) { buf[0] = 0xc6; buf[1] = 0xcd; ret = 2; break; } 360 if (wc == 0x2f34) { buf[0] = 0xc6; buf[1] = 0xce; ret = 2; break; } 361 if (wc == 0x2f35) { buf[0] = 0xc6; buf[1] = 0xcf; ret = 2; break; } 362 if (wc == 0x2f39) { buf[0] = 0xc6; buf[1] = 0xd0; ret = 2; break; } 363 if (wc == 0x2f3a) { buf[0] = 0xc6; buf[1] = 0xd1; ret = 2; break; } 364 if (wc == 0x2f41) { buf[0] = 0xc6; buf[1] = 0xd2; ret = 2; break; } 365 if (wc == 0x2f46) { buf[0] = 0xc6; buf[1] = 0xd3; ret = 2; break; } 366 if (wc == 0x2f67) { buf[0] = 0xc6; buf[1] = 0xd4; ret = 2; break; } 367 if (wc == 0x2f68) { buf[0] = 0xc6; buf[1] = 0xd5; ret = 2; break; } 368 if (wc == 0x2fa1) { buf[0] = 0xc6; buf[1] = 0xd6; ret = 2; break; } 369 if (wc == 0x2faa) { buf[0] = 0xc6; buf[1] = 0xd7; ret = 2; break; } 370 break; 371 case 0x30: 372 if (wc >= 0x3005 && wc <= 0x3007) { 373 buf[0] = 0xc6; buf[1] = wc - 0x2f25; ret = 2; 374 break; 375 } 376 if (wc >= 0x3038 && wc <= 0x303a) { 377 buf[0] = 0xa2; buf[1] = wc - 0x2f6c; ret = 2; 378 break; 379 } 380 if (wc >= 0x3041 && wc <= 0x3093) { 381 if (wc < 0x3059) { 382 buf[0] = 0xc6; buf[1] = wc - 0x2f5a; 383 } else { 384 buf[0] = 0xc7; buf[1] = wc - 0x3019; 385 } 386 ret = 2; 387 break; 388 } 389 if (wc == 0x309d) { buf[0] = 0xc6; buf[1] = 0xdc; ret = 2; break; } 390 if (wc == 0x309e) { buf[0] = 0xc6; buf[1] = 0xdd; ret = 2; break; } 391 if (wc >= 0x30a1 && wc <= 0x30f6) { 392 buf[0] = 0xc7; buf[1] = wc - (wc < 0x30a5 ? 0x3026 : 0x3004); ret = 2; 393 break; 394 } 395 if (wc == 0x30fc) { buf[0] = 0xc6; buf[1] = 0xe3; ret = 2; break; } 396 if (wc == 0x30fd) { buf[0] = 0xc6; buf[1] = 0xda; ret = 2; break; } 397 if (wc == 0x30fe) { buf[0] = 0xc6; buf[1] = 0xdb; ret = 2; break; } 398 break; 399 case 0x53: 400 if (wc == 0x5344) 401 return RET_ILUNI; 402 break; 403 case 0x58: 404 if (wc == 0x58bb) { buf[0] = 0xf9; buf[1] = 0xd9; ret = 2; break; } 405 break; 406 case 0x5a: 407 if (wc == 0x5afa) { buf[0] = 0xf9; buf[1] = 0xdc; ret = 2; break; } 408 break; 409 case 0x5f: 410 if (wc == 0x5f5e) { buf[0] = 0xc2; buf[1] = 0x55; ret = 2; break; } 411 if (wc == 0x5f5d) 412 return RET_ILUNI; 413 break; 414 case 0x60: 415 if (wc == 0x6052) { buf[0] = 0xf9; buf[1] = 0xda; ret = 2; break; } 416 break; 417 case 0x78: 418 if (wc == 0x7881) { buf[0] = 0xf9; buf[1] = 0xd6; ret = 2; break; } 419 break; 420 case 0x7c: 421 if (wc == 0x7ca7) { buf[0] = 0xf9; buf[1] = 0xdb; ret = 2; break; } 422 break; 423 case 0x88: 424 if (wc == 0x88cf) { buf[0] = 0xf9; buf[1] = 0xd8; ret = 2; break; } 425 break; 426 case 0x92: 427 if (wc == 0x92b9) { buf[0] = 0xf9; buf[1] = 0xd7; ret = 2; break; } 428 break; 429 case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: 430 case 0xe6: case 0xe7: case 0xe8: case 0xe9: case 0xea: case 0xeb: 431 case 0xec: case 0xed: case 0xee: case 0xef: case 0xf0: case 0xf1: 432 case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: 433 { 434 unsigned int i = wc - 0xe000; 435 if (i < 5809) { 436 unsigned int c1 = i / 157; 437 unsigned int c2 = i % 157; 438 buf[0] = c1 + (c1 < 5 ? 0xfa : c1 < 24 ? 0x89 : 0x69); 439 buf[1] = c2 + (c2 < 0x3f ? 0x40 : 0x62); 440 ret = 2; 441 break; 442 } 443 } 444 break; 445 case 0xfe: 446 if (wc == 0xfe51) { buf[0] = 0xa1; buf[1] = 0x4e; ret = 2; break; } 447 if (wc == 0xfe68) { buf[0] = 0xa2; buf[1] = 0x42; ret = 2; break; } 448 break; 449 case 0xff: 450 if (wc == 0xff0f) { buf[0] = 0xa1; buf[1] = 0xfe; ret = 2; break; } 451 if (wc == 0xff3b) { buf[0] = 0xc6; buf[1] = 0xe4; ret = 2; break; } 452 if (wc == 0xff3c) { buf[0] = 0xa2; buf[1] = 0x40; ret = 2; break; } 453 if (wc == 0xff3d) { buf[0] = 0xc6; buf[1] = 0xe5; ret = 2; break; } 454 if (wc == 0xff3e) { buf[0] = 0xc6; buf[1] = 0xd9; ret = 2; break; } 455 if (wc == 0xff5e) { buf[0] = 0xa1; buf[1] = 0xe3; ret = 2; break; } 456 if (wc == 0xffe0) { buf[0] = 0xa2; buf[1] = 0x46; ret = 2; break; } 457 if (wc == 0xffe1) { buf[0] = 0xa2; buf[1] = 0x47; ret = 2; break; } 458 if (wc == 0xffe3) { buf[0] = 0xa1; buf[1] = 0xc3; ret = 2; break; } 459 if (wc == 0xffe5) { buf[0] = 0xa2; buf[1] = 0x44; ret = 2; break; } 460 if (wc == 0xff64) 461 return RET_ILUNI; 462 break; 463 } 464 if (ret == RET_ILUNI) 465 ret = big5_wctomb(conv,buf,wc,2); 466 if (ret != RET_ILUNI) { 467 if (ret != 2) abort(); 468 if (n < 2) 469 return RET_TOOSMALL; 470 r[0] = buf[0]; 471 r[1] = buf[1]; 472 return 2; 473 } 474 475 return RET_ILUNI; 476 } 477