1/* 2 * "streamable kanji code filter and converter" 3 * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved. 4 * 5 * LICENSE NOTICES 6 * 7 * This file is part of "streamable kanji code filter and converter", 8 * which is distributed under the terms of GNU Lesser General Public 9 * License (version 2) as published by the Free Software Foundation. 10 * 11 * This software is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with "streamable kanji code filter and converter"; 18 * if not, write to the Free Software Foundation, Inc., 59 Temple Place, 19 * Suite 330, Boston, MA 02111-1307 USA 20 * 21 * The author of this file: Moriyoshi Koizumi <koizumi@gree.co.jp> 22 * 23 */ 24 25#ifdef HAVE_CONFIG_H 26#include "config.h" 27#endif 28 29#include "mbfilter.h" 30#include "mbfilter_cp5022x.h" 31#include "mbfilter_jis.h" 32#include "mbfilter_tl_jisx0201_jisx0208.h" 33 34#include "unicode_table_cp932_ext.h" 35#include "unicode_table_jis.h" 36#include "cp932_table.h" 37 38typedef struct _mbfl_filt_conv_wchar_cp50220_ctx { 39 mbfl_filt_tl_jisx0201_jisx0208_param tl_param; 40 mbfl_convert_filter last; 41} mbfl_filt_conv_wchar_cp50220_ctx; 42 43static int mbfl_filt_ident_jis_ms(int c, mbfl_identify_filter *filter); 44static int mbfl_filt_ident_cp50220(int c, mbfl_identify_filter *filter); 45static int mbfl_filt_ident_cp50221(int c, mbfl_identify_filter *filter); 46static int mbfl_filt_ident_cp50222(int c, mbfl_identify_filter *filter); 47static void mbfl_filt_conv_wchar_cp50220_ctor(mbfl_convert_filter *filt); 48static void mbfl_filt_conv_wchar_cp50220_dtor(mbfl_convert_filter *filt); 49static void mbfl_filt_conv_wchar_cp50220_copy(mbfl_convert_filter *src, mbfl_convert_filter *dest); 50 51const mbfl_encoding mbfl_encoding_jis_ms = { 52 mbfl_no_encoding_jis_ms, 53 "JIS-ms", 54 "ISO-2022-JP", 55 NULL, 56 NULL, 57 MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE 58}; 59 60const mbfl_encoding mbfl_encoding_cp50220 = { 61 mbfl_no_encoding_cp50220, 62 "CP50220", 63 "ISO-2022-JP", 64 (const char *(*)[])NULL, 65 NULL, 66 MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE 67}; 68 69const mbfl_encoding mbfl_encoding_cp50220raw = { 70 mbfl_no_encoding_cp50220raw, 71 "CP50220raw", 72 "ISO-2022-JP", 73 (const char *(*)[])NULL, 74 NULL, 75 MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE 76}; 77 78const mbfl_encoding mbfl_encoding_cp50221 = { 79 mbfl_no_encoding_cp50221, 80 "CP50221", 81 "ISO-2022-JP", 82 NULL, 83 NULL, 84 MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE 85}; 86 87const mbfl_encoding mbfl_encoding_cp50222 = { 88 mbfl_no_encoding_cp50222, 89 "CP50222", 90 "ISO-2022-JP", 91 NULL, 92 NULL, 93 MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE 94}; 95 96const struct mbfl_identify_vtbl vtbl_identify_jis_ms = { 97 mbfl_no_encoding_jis_ms, 98 mbfl_filt_ident_common_ctor, 99 mbfl_filt_ident_common_dtor, 100 mbfl_filt_ident_jis_ms 101}; 102 103const struct mbfl_identify_vtbl vtbl_identify_cp50220 = { 104 mbfl_no_encoding_cp50220, 105 mbfl_filt_ident_common_ctor, 106 mbfl_filt_ident_common_dtor, 107 mbfl_filt_ident_cp50220 108}; 109 110const struct mbfl_identify_vtbl vtbl_identify_cp50220raw = { 111 mbfl_no_encoding_cp50220raw, 112 mbfl_filt_ident_common_ctor, 113 mbfl_filt_ident_common_dtor, 114 mbfl_filt_ident_cp50220 115}; 116 117const struct mbfl_identify_vtbl vtbl_identify_cp50221 = { 118 mbfl_no_encoding_cp50221, 119 mbfl_filt_ident_common_ctor, 120 mbfl_filt_ident_common_dtor, 121 mbfl_filt_ident_cp50221 122}; 123 124const struct mbfl_identify_vtbl vtbl_identify_cp50222 = { 125 mbfl_no_encoding_cp50222, 126 mbfl_filt_ident_common_ctor, 127 mbfl_filt_ident_common_dtor, 128 mbfl_filt_ident_cp50222 129}; 130 131const struct mbfl_convert_vtbl vtbl_jis_ms_wchar = { 132 mbfl_no_encoding_jis_ms, 133 mbfl_no_encoding_wchar, 134 mbfl_filt_conv_common_ctor, 135 mbfl_filt_conv_common_dtor, 136 mbfl_filt_conv_jis_ms_wchar, 137 mbfl_filt_conv_common_flush, 138}; 139 140const struct mbfl_convert_vtbl vtbl_wchar_jis_ms = { 141 mbfl_no_encoding_wchar, 142 mbfl_no_encoding_jis_ms, 143 mbfl_filt_conv_common_ctor, 144 mbfl_filt_conv_common_dtor, 145 mbfl_filt_conv_wchar_jis_ms, 146 mbfl_filt_conv_any_jis_flush 147}; 148 149const struct mbfl_convert_vtbl vtbl_cp50220_wchar = { 150 mbfl_no_encoding_cp50220, 151 mbfl_no_encoding_wchar, 152 mbfl_filt_conv_common_ctor, 153 mbfl_filt_conv_common_dtor, 154 mbfl_filt_conv_jis_ms_wchar, 155 mbfl_filt_conv_common_flush 156}; 157 158const struct mbfl_convert_vtbl vtbl_wchar_cp50220 = { 159 mbfl_no_encoding_wchar, 160 mbfl_no_encoding_cp50220, 161 mbfl_filt_conv_wchar_cp50220_ctor, 162 mbfl_filt_conv_wchar_cp50220_dtor, 163 mbfl_filt_conv_wchar_cp50221, 164 mbfl_filt_conv_any_jis_flush, 165 mbfl_filt_conv_wchar_cp50220_copy 166}; 167 168const struct mbfl_convert_vtbl vtbl_cp50220raw_wchar = { 169 mbfl_no_encoding_cp50220raw, 170 mbfl_no_encoding_wchar, 171 mbfl_filt_conv_common_ctor, 172 mbfl_filt_conv_common_dtor, 173 mbfl_filt_conv_jis_ms_wchar, 174 mbfl_filt_conv_common_flush 175}; 176 177const struct mbfl_convert_vtbl vtbl_wchar_cp50220raw = { 178 mbfl_no_encoding_wchar, 179 mbfl_no_encoding_cp50220raw, 180 mbfl_filt_conv_wchar_cp50220_ctor, 181 mbfl_filt_conv_wchar_cp50220_dtor, 182 mbfl_filt_conv_wchar_cp50220raw, 183 mbfl_filt_conv_any_jis_flush, 184 mbfl_filt_conv_wchar_cp50220_copy 185}; 186 187const struct mbfl_convert_vtbl vtbl_cp50221_wchar = { 188 mbfl_no_encoding_cp50221, 189 mbfl_no_encoding_wchar, 190 mbfl_filt_conv_common_ctor, 191 mbfl_filt_conv_common_dtor, 192 mbfl_filt_conv_jis_ms_wchar, 193 mbfl_filt_conv_common_flush 194}; 195 196const struct mbfl_convert_vtbl vtbl_wchar_cp50221 = { 197 mbfl_no_encoding_wchar, 198 mbfl_no_encoding_cp50221, 199 mbfl_filt_conv_common_ctor, 200 mbfl_filt_conv_common_dtor, 201 mbfl_filt_conv_wchar_cp50221, 202 mbfl_filt_conv_any_jis_flush 203}; 204 205const struct mbfl_convert_vtbl vtbl_cp50222_wchar = { 206 mbfl_no_encoding_cp50222, 207 mbfl_no_encoding_wchar, 208 mbfl_filt_conv_common_ctor, 209 mbfl_filt_conv_common_dtor, 210 mbfl_filt_conv_jis_ms_wchar, 211 mbfl_filt_conv_common_flush 212}; 213 214const struct mbfl_convert_vtbl vtbl_wchar_cp50222 = { 215 mbfl_no_encoding_wchar, 216 mbfl_no_encoding_cp50222, 217 mbfl_filt_conv_common_ctor, 218 mbfl_filt_conv_common_dtor, 219 mbfl_filt_conv_wchar_cp50222, 220 mbfl_filt_conv_wchar_cp50222_flush 221}; 222 223#define CK(statement) do { if ((statement) < 0) return (-1); } while (0) 224 225/* 226 * JIS-ms => wchar 227 */ 228int 229mbfl_filt_conv_jis_ms_wchar(int c, mbfl_convert_filter *filter) 230{ 231 int c1, s, w; 232 233retry: 234 switch (filter->status & 0xf) { 235/* case 0x00: ASCII */ 236/* case 0x10: X 0201 latin */ 237/* case 0x20: X 0201 kana */ 238/* case 0x80: X 0208 */ 239/* case 0x90: X 0212 */ 240 case 0: 241 if (c == 0x1b) { 242 filter->status += 2; 243 } else if (c == 0x0e) { /* "kana in" */ 244 filter->status = 0x20; 245 } else if (c == 0x0f) { /* "kana out" */ 246 filter->status = 0; 247 } else if (filter->status == 0x10 && c == 0x5c) { /* YEN SIGN */ 248 CK((*filter->output_function)(0xa5, filter->data)); 249 } else if (filter->status == 0x10 && c == 0x7e) { /* OVER LINE */ 250 CK((*filter->output_function)(0x203e, filter->data)); 251 } else if (filter->status == 0x20 && c > 0x20 && c < 0x60) { /* kana */ 252 CK((*filter->output_function)(0xff40 + c, filter->data)); 253 } else if ((filter->status == 0x80 || filter->status == 0x90) && c > 0x20 && c < 0x7f) { /* kanji first char */ 254 filter->cache = c; 255 filter->status += 1; 256 } else if (c >= 0 && c < 0x80) { /* latin, CTLs */ 257 CK((*filter->output_function)(c, filter->data)); 258 } else if (c > 0xa0 && c < 0xe0) { /* GR kana */ 259 CK((*filter->output_function)(0xfec0 + c, filter->data)); 260 } else { 261 w = c & MBFL_WCSGROUP_MASK; 262 w |= MBFL_WCSGROUP_THROUGH; 263 CK((*filter->output_function)(w, filter->data)); 264 } 265 break; 266 267/* case 0x81: X 0208 second char */ 268/* case 0x91: X 0212 second char */ 269 case 1: 270 filter->status &= ~0xf; 271 c1 = filter->cache; 272 if (c > 0x20 && c < 0x7f) { 273 s = (c1 - 0x21)*94 + c - 0x21; 274 if (filter->status == 0x80) { 275 if (s >= 0 && s < jisx0208_ucs_table_size) { 276 w = jisx0208_ucs_table[s]; 277 } else if (s >= cp932ext1_ucs_table_min && s < cp932ext1_ucs_table_max) { 278 w = cp932ext1_ucs_table[s - cp932ext1_ucs_table_min]; 279 } else if (s >= cp932ext2_ucs_table_min && s < cp932ext2_ucs_table_max) { 280 w = cp932ext2_ucs_table[s - cp932ext2_ucs_table_min]; 281 } else if (s >= cp932ext3_ucs_table_min && s < cp932ext2_ucs_table_max) { 282 w = cp932ext3_ucs_table[s - cp932ext3_ucs_table_min]; 283 } else if (s >= 94 * 94 && s < 114 * 94) { 284 /* user-defined => PUA (Microsoft extended) */ 285 w = (s & 0xff) + ((s >> 8) - 94) * 94 + 0xe000; 286 } else if (s >= 212 * 94 && s < 222 * 94) { 287 /* user-defined => PUA (G3 85 - 94 Ku) */ 288 w = (s & 0xff) + ((s >> 8) - 212) * 94 + 0xe000 + 10 * 94; 289 } else { 290 w = 0; 291 } 292 if (w <= 0) { 293 w = (c1 << 8) | c; 294 w &= MBFL_WCSPLANE_MASK; 295 w |= MBFL_WCSPLANE_JIS0208; 296 } 297 } else { 298 if (s >= 0 && s < jisx0212_ucs_table_size) { 299 w = jisx0212_ucs_table[s]; 300 } else { 301 w = 0; 302 } 303 if (w <= 0) { 304 w = (c1 << 8) | c; 305 w &= MBFL_WCSPLANE_MASK; 306 w |= MBFL_WCSPLANE_JIS0212; 307 } 308 } 309 CK((*filter->output_function)(w, filter->data)); 310 } else if (c == 0x1b) { 311 filter->status += 2; 312 } else if ((c >= 0 && c < 0x21) || c == 0x7f) { /* CTLs */ 313 CK((*filter->output_function)(c, filter->data)); 314 } else { 315 w = (c1 << 8) | c; 316 w &= MBFL_WCSGROUP_MASK; 317 w |= MBFL_WCSGROUP_THROUGH; 318 CK((*filter->output_function)(w, filter->data)); 319 } 320 break; 321 322 /* ESC */ 323/* case 0x02: */ 324/* case 0x12: */ 325/* case 0x22: */ 326/* case 0x82: */ 327/* case 0x92: */ 328 case 2: 329 if (c == 0x24) { /* '$' */ 330 filter->status++; 331 } else if (c == 0x28) { /* '(' */ 332 filter->status += 3; 333 } else { 334 filter->status &= ~0xf; 335 CK((*filter->output_function)(0x1b, filter->data)); 336 goto retry; 337 } 338 break; 339 340 /* ESC $ */ 341/* case 0x03: */ 342/* case 0x13: */ 343/* case 0x23: */ 344/* case 0x83: */ 345/* case 0x93: */ 346 case 3: 347 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */ 348 filter->status = 0x80; 349 } else if (c == 0x28) { /* '(' */ 350 filter->status++; 351 } else { 352 filter->status &= ~0xf; 353 CK((*filter->output_function)(0x1b, filter->data)); 354 CK((*filter->output_function)(0x24, filter->data)); 355 goto retry; 356 } 357 break; 358 359 /* ESC $ ( */ 360/* case 0x04: */ 361/* case 0x14: */ 362/* case 0x24: */ 363/* case 0x84: */ 364/* case 0x94: */ 365 case 4: 366 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */ 367 filter->status = 0x80; 368 } else if (c == 0x44) { /* 'D' */ 369 filter->status = 0x90; 370 } else { 371 filter->status &= ~0xf; 372 CK((*filter->output_function)(0x1b, filter->data)); 373 CK((*filter->output_function)(0x24, filter->data)); 374 CK((*filter->output_function)(0x28, filter->data)); 375 goto retry; 376 } 377 break; 378 379 /* ESC ( */ 380/* case 0x05: */ 381/* case 0x15: */ 382/* case 0x25: */ 383/* case 0x85: */ 384/* case 0x95: */ 385 case 5: 386 if (c == 0x42 || c == 0x48) { /* 'B' or 'H' */ 387 filter->status = 0; 388 } else if (c == 0x4a) { /* 'J' */ 389 filter->status = 0x10; 390 } else if (c == 0x49) { /* 'I' */ 391 filter->status = 0x20; 392 } else { 393 filter->status &= ~0xf; 394 CK((*filter->output_function)(0x1b, filter->data)); 395 CK((*filter->output_function)(0x28, filter->data)); 396 goto retry; 397 } 398 break; 399 400 default: 401 filter->status = 0; 402 break; 403 } 404 405 return c; 406} 407 408/* 409 * wchar => JIS 410 */ 411int 412mbfl_filt_conv_wchar_jis_ms(int c, mbfl_convert_filter *filter) 413{ 414 int c1, s; 415 416 s = 0; 417 if (c >= ucs_a1_jis_table_min && c < ucs_a1_jis_table_max) { 418 s = ucs_a1_jis_table[c - ucs_a1_jis_table_min]; 419 } else if (c >= ucs_a2_jis_table_min && c < ucs_a2_jis_table_max) { 420 s = ucs_a2_jis_table[c - ucs_a2_jis_table_min]; 421 } else if (c >= ucs_i_jis_table_min && c < ucs_i_jis_table_max) { 422 s = ucs_i_jis_table[c - ucs_i_jis_table_min]; 423 } else if (c >= ucs_r_jis_table_min && c < ucs_r_jis_table_max) { 424 s = ucs_r_jis_table[c - ucs_r_jis_table_min]; 425 } else if (c >= 0xe000 && c < (0xe000 + 10 * 94)) { 426 /* PUE => Microsoft extended (pseudo 95ku - 114ku) */ 427 /* See http://www.opengroup.or.jp/jvc/cde/ucs-conv.html#ch4_2 */ 428 s = c - 0xe000; 429 s = (s / 94 + 0x75) << 8 | (s % 94 + 0x21); 430 } else if (c >= (0xe000 + 10 * 94) && c <= (0xe000 + 20 * 94)) { 431 /* PUE => JISX0212 user-defined (G3 85ku - 94ku) */ 432 /* See http://www.opengroup.or.jp/jvc/cde/ucs-conv.html#ch4_2 */ 433 s = c - (0xe000 + 10 * 94); 434 s = (s / 94 + 0xf5) << 8 | (s % 94 + 0xa1); 435 } 436 437 /* do some transliteration */ 438 if (s <= 0) { 439 c1 = c & ~MBFL_WCSPLANE_MASK; 440 if (c1 == MBFL_WCSPLANE_JIS0208) { 441 s = c & MBFL_WCSPLANE_MASK; 442 } else if (c1 == MBFL_WCSPLANE_JIS0212) { 443 s = c & MBFL_WCSPLANE_MASK; 444 s |= 0x8080; 445 } else if (c == 0xa5) { /* YEN SIGN */ 446 s = 0x1005c; 447 } else if (c == 0x203e) { /* OVER LINE */ 448 s = 0x1007e; 449 } else if (c == 0xff3c) { /* FULLWIDTH REVERSE SOLIDUS */ 450 s = 0x2140; 451 } else if (c == 0xff5e) { /* FULLWIDTH TILDE */ 452 s = 0x2141; 453 } else if (c == 0x2225) { /* PARALLEL TO */ 454 s = 0x2142; 455 } else if (c == 0xff0d) { /* FULLWIDTH HYPHEN-MINUS */ 456 s = 0x215d; 457 } else if (c == 0xffe0) { /* FULLWIDTH CENT SIGN */ 458 s = 0x2171; 459 } else if (c == 0xffe1) { /* FULLWIDTH POUND SIGN */ 460 s = 0x2172; 461 } else if (c == 0xffe2) { /* FULLWIDTH NOT SIGN */ 462 s = 0x224c; 463 } 464 } 465 if (s <= 0 || s >= 0x8080 && s < 0x10000) { 466 int i; 467 s = -1; 468 469 for (i = 0; 470 i < cp932ext1_ucs_table_max - cp932ext1_ucs_table_min; i++) { 471 const int oh = cp932ext1_ucs_table_min / 94; 472 473 if (c == cp932ext1_ucs_table[i]) { 474 s = ((i / 94 + oh + 0x21) << 8) + (i % 94 + 0x21); 475 break; 476 } 477 } 478 479 if (s < 0) { 480 const int oh = cp932ext2_ucs_table_min / 94; 481 const int cp932ext2_ucs_table_size = 482 cp932ext2_ucs_table_max - cp932ext2_ucs_table_min; 483 for (i = 0; i < cp932ext2_ucs_table_size; i++) { 484 if (c == cp932ext2_ucs_table[i]) { 485 s = ((i / 94 + oh + 0x21) << 8) + (i % 94 + 0x21); 486 break; 487 } 488 } 489 } 490 491 if (s < 0) { 492 const int cp932ext3_ucs_table_size = 493 cp932ext3_ucs_table_max - cp932ext3_ucs_table_min; 494 const int limit = cp932ext3_ucs_table_size > 495 cp932ext3_eucjp_table_size ? 496 cp932ext3_eucjp_table_size: 497 cp932ext3_ucs_table_size; 498 for (i = 0; i < limit; i++) { 499 if (c == cp932ext3_ucs_table[i]) { 500 s = cp932ext3_eucjp_table[i]; 501 break; 502 } 503 } 504 } 505 506 if (c == 0) { 507 s = 0; 508 } else if (s <= 0) { 509 s = -1; 510 } 511 } 512 513 if (s >= 0) { 514 if (s < 0x80) { /* ASCII */ 515 if ((filter->status & 0xff00) != 0) { 516 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */ 517 CK((*filter->output_function)(0x28, filter->data)); /* '(' */ 518 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */ 519 } 520 filter->status = 0; 521 CK((*filter->output_function)(s, filter->data)); 522 } else if (s < 0x100) { /* kana */ 523 if ((filter->status & 0xff00) != 0x100) { 524 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */ 525 CK((*filter->output_function)(0x28, filter->data)); /* '(' */ 526 CK((*filter->output_function)(0x49, filter->data)); /* 'I' */ 527 } 528 filter->status = 0x100; 529 CK((*filter->output_function)(s & 0x7f, filter->data)); 530 } else if (s < 0x8080) { /* X 0208 */ 531 if ((filter->status & 0xff00) != 0x200) { 532 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */ 533 CK((*filter->output_function)(0x24, filter->data)); /* '$' */ 534 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */ 535 } 536 filter->status = 0x200; 537 CK((*filter->output_function)((s >> 8) & 0x7f, filter->data)); 538 CK((*filter->output_function)(s & 0x7f, filter->data)); 539 } else if (s < 0x10000) { /* X 0212 */ 540 if ((filter->status & 0xff00) != 0x300) { 541 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */ 542 CK((*filter->output_function)(0x24, filter->data)); /* '$' */ 543 CK((*filter->output_function)(0x28, filter->data)); /* '(' */ 544 CK((*filter->output_function)(0x44, filter->data)); /* 'D' */ 545 } 546 filter->status = 0x300; 547 CK((*filter->output_function)((s >> 8) & 0x7f, filter->data)); 548 CK((*filter->output_function)(s & 0x7f, filter->data)); 549 } else { /* X 0201 latin */ 550 if ((filter->status & 0xff00) != 0x400) { 551 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */ 552 CK((*filter->output_function)(0x28, filter->data)); /* '(' */ 553 CK((*filter->output_function)(0x4a, filter->data)); /* 'J' */ 554 } 555 filter->status = 0x400; 556 CK((*filter->output_function)(s & 0x7f, filter->data)); 557 } 558 } else { 559 if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) { 560 CK(mbfl_filt_conv_illegal_output(c, filter)); 561 } 562 } 563 564 return c; 565} 566 567/* 568 * wchar => CP50220 569 */ 570static void 571mbfl_filt_conv_wchar_cp50220_ctor(mbfl_convert_filter *filt) 572{ 573 mbfl_filt_conv_wchar_cp50220_ctx *ctx; 574 575 mbfl_filt_conv_common_ctor(filt); 576 577 ctx = mbfl_malloc(sizeof(mbfl_filt_conv_wchar_cp50220_ctx)); 578 if (ctx == NULL) { 579 mbfl_filt_conv_common_dtor(filt); 580 return; 581 } 582 583 ctx->tl_param.mode = MBFL_FILT_TL_HAN2ZEN_KATAKANA | MBFL_FILT_TL_HAN2ZEN_GLUE; 584 585 ctx->last = *filt; 586 ctx->last.opaque = ctx; 587 ctx->last.data = filt->data; 588 filt->filter_function = vtbl_tl_jisx0201_jisx0208.filter_function; 589 filt->filter_flush = vtbl_tl_jisx0201_jisx0208.filter_flush; 590 filt->output_function = (int(*)(int, void *))ctx->last.filter_function; 591 filt->flush_function = (int(*)(void *))ctx->last.filter_flush; 592 filt->data = &ctx->last; 593 filt->opaque = ctx; 594 vtbl_tl_jisx0201_jisx0208.filter_ctor(filt); 595} 596 597static void 598mbfl_filt_conv_wchar_cp50220_copy(mbfl_convert_filter *src, mbfl_convert_filter *dest) 599{ 600 mbfl_filt_conv_wchar_cp50220_ctx *ctx; 601 602 *dest = *src; 603 ctx = mbfl_malloc(sizeof(mbfl_filt_conv_wchar_cp50220_ctx)); 604 if (ctx != NULL) { 605 *ctx = *(mbfl_filt_conv_wchar_cp50220_ctx*)src->opaque; 606 } 607 608 dest->opaque = ctx; 609 dest->data = &ctx->last; 610} 611 612static void 613mbfl_filt_conv_wchar_cp50220_dtor(mbfl_convert_filter *filt) 614{ 615 vtbl_tl_jisx0201_jisx0208.filter_dtor(filt); 616 617 if (filt->opaque != NULL) { 618 mbfl_free(filt->opaque); 619 } 620 621 mbfl_filt_conv_common_dtor(filt); 622} 623 624/* 625 * wchar => cp50220raw 626 */ 627int 628mbfl_filt_conv_wchar_cp50220raw(int c, mbfl_convert_filter *filter) 629{ 630 if (c & MBFL_WCSPLANE_JIS0208) { 631 const int s = c & MBFL_WCSPLANE_MASK; 632 633 if ((filter->status & 0xff00) != 0x200) { 634 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */ 635 CK((*filter->output_function)(0x24, filter->data)); /* '$' */ 636 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */ 637 filter->status = 0x200; 638 } 639 CK((*filter->output_function)((s >> 8) & 0x7f, filter->data)); 640 CK((*filter->output_function)(s & 0x7f, filter->data)); 641 return c; 642 } else { 643 return mbfl_filt_conv_wchar_cp50221(c, filter); 644 } 645} 646 647/* 648 * wchar => CP50221 649 */ 650int 651mbfl_filt_conv_wchar_cp50221(int c, mbfl_convert_filter *filter) 652{ 653 int s = 0; 654 655 if (c >= ucs_a1_jis_table_min && c < ucs_a1_jis_table_max) { 656 s = ucs_a1_jis_table[c - ucs_a1_jis_table_min]; 657 } else if (c >= ucs_a2_jis_table_min && c < ucs_a2_jis_table_max) { 658 s = ucs_a2_jis_table[c - ucs_a2_jis_table_min]; 659 } else if (c >= ucs_i_jis_table_min && c < ucs_i_jis_table_max) { 660 s = ucs_i_jis_table[c - ucs_i_jis_table_min]; 661 } else if (c >= ucs_r_jis_table_min && c < ucs_r_jis_table_max) { 662 s = ucs_r_jis_table[c - ucs_r_jis_table_min]; 663 } else if (c >= 0xe000 && c < (0xe000 + 10 * 94)) { 664 /* PUE => Microsoft extended */ 665 /* See http://www.opengroup.or.jp/jvc/cde/ucs-conv.html#ch4_2 */ 666 s = c - 0xe000; 667 s = (s / 94 + 0x75) << 8 | (s % 94 + 0x21); 668 } else if (c >= (0xe000 + 10 * 94) && c <= (0xe000 + 20 * 94)) { 669 /* PUE => JISX0212 user-defined (G3 85ku - 94ku) */ 670 /* See http://www.opengroup.or.jp/jvc/cde/ucs-conv.html#ch4_2 */ 671 s = c - (0xe000 + 10 * 94); 672 s = (s / 94 + 0xf5) << 8 | (s % 94 + 0xa1); 673 } 674 675 if (s <= 0) { 676 if (c == 0xa5) { /* YEN SIGN */ 677 s = 0x1005c; 678 } else if (c == 0x203e) { /* OVER LINE */ 679 s = 0x1007e; 680 } else if (c == 0xff3c) { /* FULLWIDTH REVERSE SOLIDUS */ 681 s = 0x2140; 682 } else if (c == 0xff5e) { /* FULLWIDTH TILDE */ 683 s = 0x2141; 684 } else if (c == 0x2225) { /* PARALLEL TO */ 685 s = 0x2142; 686 } else if (c == 0xff0d) { /* FULLWIDTH HYPHEN-MINUS */ 687 s = 0x215d; 688 } else if (c == 0xffe0) { /* FULLWIDTH CENT SIGN */ 689 s = 0x2171; 690 } else if (c == 0xffe1) { /* FULLWIDTH POUND SIGN */ 691 s = 0x2172; 692 } else if (c == 0xffe2) { /* FULLWIDTH NOT SIGN */ 693 s = 0x224c; 694 } 695 } 696 if (s <= 0 || s >= 0x8080 && s < 0x10000) { 697 int i; 698 s = -1; 699 700 for (i = 0; 701 i < cp932ext1_ucs_table_max - cp932ext1_ucs_table_min; 702 i++) { 703 const int oh = cp932ext1_ucs_table_min / 94; 704 705 if (c == cp932ext1_ucs_table[i]) { 706 s = ((i / 94 + oh + 0x21) << 8) + (i % 94 + 0x21); 707 break; 708 } 709 } 710 711 if (s < 0) { 712 const int oh = cp932ext2_ucs_table_min / 94; 713 const int cp932ext2_ucs_table_size = 714 cp932ext2_ucs_table_max - cp932ext2_ucs_table_min; 715 for (i = 0; i < cp932ext2_ucs_table_size; i++) { 716 if (c == cp932ext2_ucs_table[i]) { 717 s = ((i / 94 + oh + 0x21) << 8) + (i % 94 + 0x21); 718 break; 719 } 720 } 721 } 722 723 if (s < 0) { 724 const int cp932ext3_ucs_table_size = 725 cp932ext3_ucs_table_max - cp932ext3_ucs_table_min; 726 const int limit = cp932ext3_ucs_table_size > 727 cp932ext3_eucjp_table_size ? 728 cp932ext3_eucjp_table_size: 729 cp932ext3_ucs_table_size; 730 for (i = 0; i < limit; i++) { 731 if (c == cp932ext3_ucs_table[i]) { 732 s = cp932ext3_eucjp_table[i]; 733 break; 734 } 735 } 736 } 737 738 if (c == 0) { 739 s = 0; 740 } else if (s <= 0) { 741 s = -1; 742 } 743 } 744 745 if (s >= 0) { 746 if (s < 0x80) { /* ASCII */ 747 if ((filter->status & 0xff00) != 0) { 748 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */ 749 CK((*filter->output_function)(0x28, filter->data)); /* '(' */ 750 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */ 751 filter->status = 0; 752 } 753 CK((*filter->output_function)(s, filter->data)); 754 } else if (s >= 0xa0 && s < 0xe0) { /* X 0201 kana */ 755 if ((filter->status & 0xff00) != 0x500) { 756 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */ 757 CK((*filter->output_function)(0x28, filter->data)); /* '(' */ 758 CK((*filter->output_function)(0x49, filter->data)); /* 'I' */ 759 filter->status = 0x500; 760 } 761 CK((*filter->output_function)(s - 0x80, filter->data)); 762 } else if (s < 0x8080) { /* X 0208 */ 763 if ((filter->status & 0xff00) != 0x200) { 764 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */ 765 CK((*filter->output_function)(0x24, filter->data)); /* '$' */ 766 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */ 767 filter->status = 0x200; 768 } 769 CK((*filter->output_function)((s >> 8) & 0x7f, filter->data)); 770 CK((*filter->output_function)(s & 0x7f, filter->data)); 771 } else if (s < 0x10000) { /* X0212 */ 772 if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) { 773 CK(mbfl_filt_conv_illegal_output(c, filter)); 774 } 775 } else { /* X 0201 latin */ 776 if ((filter->status & 0xff00) != 0x400) { 777 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */ 778 CK((*filter->output_function)(0x28, filter->data)); /* '(' */ 779 CK((*filter->output_function)(0x4a, filter->data)); /* 'J' */ 780 } 781 filter->status = 0x400; 782 CK((*filter->output_function)(s & 0x7f, filter->data)); 783 } 784 } else { 785 if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) { 786 CK(mbfl_filt_conv_illegal_output(c, filter)); 787 } 788 } 789 790 return c; 791} 792 793/* 794 * wchar => CP50222 795 */ 796int 797mbfl_filt_conv_wchar_cp50222(int c, mbfl_convert_filter *filter) 798{ 799 int s; 800 801 s = 0; 802 803 if (c >= ucs_a1_jis_table_min && c < ucs_a1_jis_table_max) { 804 s = ucs_a1_jis_table[c - ucs_a1_jis_table_min]; 805 } else if (c >= ucs_a2_jis_table_min && c < ucs_a2_jis_table_max) { 806 s = ucs_a2_jis_table[c - ucs_a2_jis_table_min]; 807 } else if (c >= ucs_i_jis_table_min && c < ucs_i_jis_table_max) { 808 s = ucs_i_jis_table[c - ucs_i_jis_table_min]; 809 } else if (c >= ucs_r_jis_table_min && c < ucs_r_jis_table_max) { 810 s = ucs_r_jis_table[c - ucs_r_jis_table_min]; 811 } else if (c >= 0xe000 && c < (0xe000 + 10 * 94)) { 812 /* PUE => Microsoft extended */ 813 /* See http://www.opengroup.or.jp/jvc/cde/ucs-conv.html#ch4_2 */ 814 s = c - 0xe000; 815 s = (s / 94 + 0x75) << 8 | (s % 94 + 0x21); 816 } else if (c >= (0xe000 + 10 * 94) && c <= (0xe000 + 20 * 94)) { 817 /* PUE => JISX0212 user-defined (G3 85ku - 94ku) */ 818 /* See http://www.opengroup.or.jp/jvc/cde/ucs-conv.html#ch4_2 */ 819 s = c - (0xe000 + 10 * 94); 820 s = (s / 94 + 0xf5) << 8 | (s % 94 + 0xa1); 821 } 822 823 if (s <= 0) { 824 if (c == 0xa5) { /* YEN SIGN */ 825 s = 0x1005c; 826 } else if (c == 0x203e) { /* OVER LINE */ 827 s = 0x1007e; 828 } else if (c == 0xff3c) { /* FULLWIDTH REVERSE SOLIDUS */ 829 s = 0x2140; 830 } else if (c == 0xff5e) { /* FULLWIDTH TILDE */ 831 s = 0x2141; 832 } else if (c == 0x2225) { /* PARALLEL TO */ 833 s = 0x2142; 834 } else if (c == 0xff0d) { /* FULLWIDTH HYPHEN-MINUS */ 835 s = 0x215d; 836 } else if (c == 0xffe0) { /* FULLWIDTH CENT SIGN */ 837 s = 0x2171; 838 } else if (c == 0xffe1) { /* FULLWIDTH POUND SIGN */ 839 s = 0x2172; 840 } else if (c == 0xffe2) { /* FULLWIDTH NOT SIGN */ 841 s = 0x224c; 842 } 843 } 844 if (s <= 0 || s >= 0x8080 && s < 0x10000) { 845 int i; 846 s = -1; 847 848 for (i = 0; 849 i < cp932ext1_ucs_table_max - cp932ext1_ucs_table_min; i++) { 850 const int oh = cp932ext1_ucs_table_min / 94; 851 852 if (c == cp932ext1_ucs_table[i]) { 853 s = ((i / 94 + oh + 0x21) << 8) + (i % 94 + 0x21); 854 break; 855 } 856 } 857 858 if (s <= 0) { 859 const int oh = cp932ext2_ucs_table_min / 94; 860 const int cp932ext2_ucs_table_size = 861 cp932ext2_ucs_table_max - cp932ext2_ucs_table_min; 862 for (i = 0; i < cp932ext2_ucs_table_size; i++) { 863 if (c == cp932ext2_ucs_table[i]) { 864 s = ((i / 94 + oh + 0x21) << 8) + (i % 94 + 0x21); 865 break; 866 } 867 } 868 } 869 870 if (s <= 0) { 871 const int cp932ext3_ucs_table_size = 872 cp932ext3_ucs_table_max - cp932ext3_ucs_table_min; 873 const int limit = cp932ext3_ucs_table_size > 874 cp932ext3_eucjp_table_size ? 875 cp932ext3_eucjp_table_size: 876 cp932ext3_ucs_table_size; 877 for (i = 0; i < limit; i++) { 878 if (c == cp932ext3_ucs_table[i]) { 879 s = cp932ext3_eucjp_table[i]; 880 break; 881 } 882 } 883 } 884 885 if (c == 0) { 886 s = 0; 887 } else if (s <= 0) { 888 s = -1; 889 } 890 } 891 892 if (s >= 0) { 893 if (s < 0x80) { /* ASCII */ 894 if ((filter->status & 0xff00) == 0x500) { 895 CK((*filter->output_function)(0x0f, filter->data)); /* SO */ 896 filter->status = 0; 897 } else if ((filter->status & 0xff00) != 0) { 898 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */ 899 CK((*filter->output_function)(0x28, filter->data)); /* '(' */ 900 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */ 901 filter->status = 0; 902 } 903 CK((*filter->output_function)(s, filter->data)); 904 } else if (s >= 0xa0 && s < 0xe0) { /* X 0201 kana */ 905 if ((filter->status & 0xff00) != 0x500) { 906 CK((*filter->output_function)(0x0e, filter->data)); /* SI */ 907 filter->status = 0x500; 908 } 909 CK((*filter->output_function)(s - 0x80, filter->data)); 910 } else if (s < 0x8080) { /* X 0208 */ 911 if ((filter->status & 0xff00) == 0x500) { 912 CK((*filter->output_function)(0x0f, filter->data)); /* SO */ 913 filter->status = 0; 914 } 915 if ((filter->status & 0xff00) != 0x200) { 916 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */ 917 CK((*filter->output_function)(0x24, filter->data)); /* '$' */ 918 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */ 919 filter->status = 0x200; 920 } 921 CK((*filter->output_function)((s >> 8) & 0x7f, filter->data)); 922 CK((*filter->output_function)(s & 0x7f, filter->data)); 923 } else if (s < 0x10000) { /* X0212 */ 924 if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) { 925 CK(mbfl_filt_conv_illegal_output(c, filter)); 926 } 927 } else { /* X 0201 latin */ 928 if ((filter->status & 0xff00) == 0x500) { 929 CK((*filter->output_function)(0x0f, filter->data)); /* SO */ 930 filter->status = 0; 931 } 932 if ((filter->status & 0xff00) != 0x400) { 933 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */ 934 CK((*filter->output_function)(0x28, filter->data)); /* '(' */ 935 CK((*filter->output_function)(0x4a, filter->data)); /* 'J' */ 936 } 937 filter->status = 0x400; 938 CK((*filter->output_function)(s & 0x7f, filter->data)); 939 } 940 } else { 941 if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) { 942 CK(mbfl_filt_conv_illegal_output(c, filter)); 943 } 944 } 945 946 return c; 947} 948 949int 950mbfl_filt_conv_wchar_cp50222_flush(mbfl_convert_filter *filter) 951{ 952 /* back to latin */ 953 if ((filter->status & 0xff00) == 0x500) { 954 CK((*filter->output_function)(0x0f, filter->data)); /* SO */ 955 } else if ((filter->status & 0xff00) != 0) { 956 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */ 957 CK((*filter->output_function)(0x28, filter->data)); /* '(' */ 958 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */ 959 } 960 filter->status &= 0xff; 961 962 if (filter->flush_function != NULL) { 963 return (*filter->flush_function)(filter->data); 964 } 965 966 return 0; 967} 968 969 970static int mbfl_filt_ident_jis_ms(int c, mbfl_identify_filter *filter) 971{ 972retry: 973 switch (filter->status & 0xf) { 974/* case 0x00: ASCII */ 975/* case 0x10: X 0201 latin */ 976/* case 0x20: X 0201 kana */ 977/* case 0x80: X 0208 */ 978/* case 0x90: X 0212 */ 979 case 0: 980 if (c == 0x1b) { 981 filter->status += 2; 982 } else if (c == 0x0e) { /* "kana in" */ 983 filter->status = 0x20; 984 } else if (c == 0x0f) { /* "kana out" */ 985 filter->status = 0; 986 } else if ((filter->status == 0x80 || filter->status == 0x90) && c > 0x20 && c < 0x7f) { /* kanji first char */ 987 filter->status += 1; 988 } else if (c >= 0 && c < 0x80) { /* latin, CTLs */ 989 ; 990 } else { 991 filter->flag = 1; /* bad */ 992 } 993 break; 994 995/* case 0x81: X 0208 second char */ 996/* case 0x91: X 0212 second char */ 997 case 1: 998 filter->status &= ~0xf; 999 if (c == 0x1b) { 1000 goto retry; 1001 } else if (c < 0x21 || c > 0x7e) { /* bad */ 1002 filter->flag = 1; 1003 } 1004 break; 1005 1006 /* ESC */ 1007 case 2: 1008 if (c == 0x24) { /* '$' */ 1009 filter->status++; 1010 } else if (c == 0x28) { /* '(' */ 1011 filter->status += 3; 1012 } else { 1013 filter->flag = 1; /* bad */ 1014 filter->status &= ~0xf; 1015 goto retry; 1016 } 1017 break; 1018 1019 /* ESC $ */ 1020 case 3: 1021 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */ 1022 filter->status = 0x80; 1023 } else if (c == 0x28) { /* '(' */ 1024 filter->status++; 1025 } else { 1026 filter->flag = 1; /* bad */ 1027 filter->status &= ~0xf; 1028 goto retry; 1029 } 1030 break; 1031 1032 /* ESC $ ( */ 1033 case 4: 1034 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */ 1035 filter->status = 0x80; 1036 } else if (c == 0x44) { /* 'D' */ 1037 filter->status = 0x90; 1038 } else { 1039 filter->flag = 1; /* bad */ 1040 filter->status &= ~0xf; 1041 goto retry; 1042 } 1043 break; 1044 1045 /* ESC ( */ 1046 case 5: 1047 if (c == 0x42 || c == 0x48) { /* 'B' or 'H' */ 1048 filter->status = 0; 1049 } else if (c == 0x4a) { /* 'J' */ 1050 filter->status = 0x10; 1051 } else if (c == 0x49) { /* 'I' */ 1052 filter->status = 0x20; 1053 } else { 1054 filter->flag = 1; /* bad */ 1055 filter->status &= ~0xf; 1056 goto retry; 1057 } 1058 break; 1059 1060 default: 1061 filter->status = 0; 1062 break; 1063 } 1064 1065 return c; 1066} 1067 1068static int mbfl_filt_ident_cp50220(int c, mbfl_identify_filter *filter) 1069{ 1070retry: 1071 switch (filter->status & 0xf) { 1072/* case 0x00: ASCII */ 1073/* case 0x10: X 0201 latin */ 1074/* case 0x80: X 0208 */ 1075 case 0: 1076 if (c == 0x1b) { 1077 filter->status += 2; 1078 } else if (filter->status == 0x80 && c > 0x20 && c < 0x7f) { /* kanji first char */ 1079 filter->status += 1; 1080 } else if (c >= 0 && c < 0x80) { /* latin, CTLs */ 1081 ; 1082 } else { 1083 filter->flag = 1; /* bad */ 1084 } 1085 break; 1086 1087/* case 0x81: X 0208 second char */ 1088 case 1: 1089 if (c == 0x1b) { 1090 filter->status++; 1091 } else { 1092 filter->status &= ~0xf; 1093 if (c < 0x21 || c > 0x7e) { /* bad */ 1094 filter->flag = 1; 1095 } 1096 } 1097 break; 1098 1099 /* ESC */ 1100 case 2: 1101 if (c == 0x24) { /* '$' */ 1102 filter->status++; 1103 } else if (c == 0x28) { /* '(' */ 1104 filter->status += 3; 1105 } else { 1106 filter->flag = 1; /* bad */ 1107 filter->status &= ~0xf; 1108 goto retry; 1109 } 1110 break; 1111 1112 /* ESC $ */ 1113 case 3: 1114 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */ 1115 filter->status = 0x80; 1116 } else { 1117 filter->flag = 1; /* bad */ 1118 filter->status &= ~0xf; 1119 goto retry; 1120 } 1121 break; 1122 1123 /* ESC ( */ 1124 case 5: 1125 if (c == 0x42) { /* 'B' */ 1126 filter->status = 0; 1127 } else if (c == 0x4a) { /* 'J' */ 1128 filter->status = 0x10; 1129 } else { 1130 filter->flag = 1; /* bad */ 1131 filter->status &= ~0xf; 1132 goto retry; 1133 } 1134 break; 1135 1136 default: 1137 filter->status = 0; 1138 break; 1139 } 1140 1141 return c; 1142} 1143 1144static int mbfl_filt_ident_cp50221(int c, mbfl_identify_filter *filter) 1145{ 1146retry: 1147 switch (filter->status & 0xf) { 1148/* case 0x00: ASCII */ 1149/* case 0x10: X 0201 latin */ 1150/* case 0x80: X 0208 */ 1151 case 0: 1152 if (c == 0x1b) { 1153 filter->status += 2; 1154 } else if (filter->status == 0x80 && c > 0x20 && c < 0x7f) { /* kanji first char */ 1155 filter->status += 1; 1156 } else if (c >= 0 && c < 0x80) { /* latin, CTLs */ 1157 ; 1158 } else { 1159 filter->flag = 1; /* bad */ 1160 } 1161 break; 1162 1163/* case 0x81: X 0208 second char */ 1164 case 1: 1165 if (c == 0x1b) { 1166 filter->status++; 1167 } else { 1168 filter->status &= ~0xf; 1169 if (c < 0x21 || c > 0x7e) { /* bad */ 1170 filter->flag = 1; 1171 } 1172 } 1173 break; 1174 1175 /* ESC */ 1176 case 2: 1177 if (c == 0x24) { /* '$' */ 1178 filter->status++; 1179 } else if (c == 0x28) { /* '(' */ 1180 filter->status += 3; 1181 } else { 1182 filter->flag = 1; /* bad */ 1183 filter->status &= ~0xf; 1184 goto retry; 1185 } 1186 break; 1187 1188 /* ESC $ */ 1189 case 3: 1190 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */ 1191 filter->status = 0x80; 1192 } else { 1193 filter->flag = 1; /* bad */ 1194 filter->status &= ~0xf; 1195 goto retry; 1196 } 1197 break; 1198 1199 /* ESC ( */ 1200 case 5: 1201 if (c == 0x42) { /* 'B' */ 1202 filter->status = 0; 1203 } else if (c == 0x4a) { /* 'J' */ 1204 filter->status = 0x10; 1205 } else if (c == 0x49) { /* 'I' */ 1206 filter->status = 0x20; 1207 } else { 1208 filter->flag = 1; /* bad */ 1209 filter->status &= ~0xf; 1210 goto retry; 1211 } 1212 break; 1213 1214 default: 1215 filter->status = 0; 1216 break; 1217 } 1218 1219 return c; 1220} 1221 1222static int mbfl_filt_ident_cp50222(int c, mbfl_identify_filter *filter) 1223{ 1224retry: 1225 switch (filter->status & 0xf) { 1226/* case 0x00: ASCII */ 1227/* case 0x10: X 0201 latin */ 1228/* case 0x80: X 0208 */ 1229 case 0: 1230 if (c == 0x1b) { 1231 filter->status += 2; 1232 } else if (filter->status == 0x80 && c > 0x20 && c < 0x7f) { /* kanji first char */ 1233 filter->status += 1; 1234 } else if (c >= 0 && c < 0x80) { /* latin, CTLs */ 1235 ; 1236 } else { 1237 filter->flag = 1; /* bad */ 1238 } 1239 break; 1240 1241/* case 0x81: X 0208 second char */ 1242 case 1: 1243 if (c == 0x1b) { 1244 filter->status++; 1245 } else { 1246 filter->status &= ~0xf; 1247 if (c < 0x21 || c > 0x7e) { /* bad */ 1248 filter->flag = 1; 1249 } 1250 } 1251 break; 1252 1253 /* ESC */ 1254 case 2: 1255 if (c == 0x24) { /* '$' */ 1256 filter->status++; 1257 } else if (c == 0x28) { /* '(' */ 1258 filter->status += 3; 1259 } else { 1260 filter->flag = 1; /* bad */ 1261 filter->status &= ~0xf; 1262 goto retry; 1263 } 1264 break; 1265 1266 /* ESC $ */ 1267 case 3: 1268 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */ 1269 filter->status = 0x80; 1270 } else { 1271 filter->flag = 1; /* bad */ 1272 filter->status &= ~0xf; 1273 goto retry; 1274 } 1275 break; 1276 1277 /* ESC ( */ 1278 case 5: 1279 if (c == 0x42) { /* 'B' */ 1280 filter->status = 0; 1281 } else if (c == 0x4a) { /* 'J' */ 1282 filter->status = 0x10; 1283 } else { 1284 filter->flag = 1; /* bad */ 1285 filter->status &= ~0xf; 1286 goto retry; 1287 } 1288 break; 1289 1290 default: 1291 filter->status = 0; 1292 break; 1293 } 1294 1295 return c; 1296} 1297 1298 1299 1300