Back to index

php5  5.3.10
mbfilter_cp5022x.c
Go to the documentation of this file.
00001 /*
00002  * "streamable kanji code filter and converter"
00003  * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
00004  *
00005  * LICENSE NOTICES
00006  *
00007  * This file is part of "streamable kanji code filter and converter",
00008  * which is distributed under the terms of GNU Lesser General Public 
00009  * License (version 2) as published by the Free Software Foundation.
00010  *
00011  * This software is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with "streamable kanji code filter and converter";
00018  * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
00019  * Suite 330, Boston, MA  02111-1307  USA
00020  *
00021  * The author of this file: Moriyoshi Koizumi <koizumi@gree.co.jp>
00022  *
00023  */
00024 
00025 #ifdef HAVE_CONFIG_H
00026 #include "config.h"
00027 #endif
00028 
00029 #include "mbfilter.h"
00030 #include "mbfilter_cp5022x.h"
00031 #include "mbfilter_jis.h"
00032 #include "mbfilter_tl_jisx0201_jisx0208.h"
00033 
00034 #include "unicode_table_cp932_ext.h"
00035 #include "unicode_table_jis.h"
00036 #include "cp932_table.h"
00037 
00038 typedef struct _mbfl_filt_conv_wchar_cp50220_ctx {
00039        mbfl_filt_tl_jisx0201_jisx0208_param tl_param;
00040        mbfl_convert_filter last;
00041 } mbfl_filt_conv_wchar_cp50220_ctx;
00042 
00043 static int mbfl_filt_ident_jis_ms(int c, mbfl_identify_filter *filter);
00044 static int mbfl_filt_ident_cp50220(int c, mbfl_identify_filter *filter);
00045 static int mbfl_filt_ident_cp50221(int c, mbfl_identify_filter *filter);
00046 static int mbfl_filt_ident_cp50222(int c, mbfl_identify_filter *filter);
00047 static void mbfl_filt_conv_wchar_cp50220_ctor(mbfl_convert_filter *filt);
00048 static void mbfl_filt_conv_wchar_cp50220_dtor(mbfl_convert_filter *filt);
00049 static void mbfl_filt_conv_wchar_cp50220_copy(mbfl_convert_filter *src, mbfl_convert_filter *dest);
00050 
00051 const mbfl_encoding mbfl_encoding_jis_ms = {
00052        mbfl_no_encoding_jis_ms,
00053        "JIS-ms",
00054        "ISO-2022-JP",
00055        NULL,
00056        NULL,
00057        MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE
00058 };
00059 
00060 const mbfl_encoding mbfl_encoding_cp50220 = {
00061        mbfl_no_encoding_cp50220,
00062        "CP50220",
00063        "ISO-2022-JP",
00064        (const char *(*)[])NULL,
00065        NULL,
00066        MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE
00067 };
00068 
00069 const mbfl_encoding mbfl_encoding_cp50220raw = {
00070        mbfl_no_encoding_cp50220raw,
00071        "CP50220raw",
00072        "ISO-2022-JP",
00073        (const char *(*)[])NULL,
00074        NULL,
00075        MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE
00076 };
00077 
00078 const mbfl_encoding mbfl_encoding_cp50221 = {
00079        mbfl_no_encoding_cp50221,
00080        "CP50221",
00081        "ISO-2022-JP",
00082        NULL,
00083        NULL,
00084        MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE
00085 };
00086 
00087 const mbfl_encoding mbfl_encoding_cp50222 = {
00088        mbfl_no_encoding_cp50222,
00089        "CP50222",
00090        "ISO-2022-JP",
00091        NULL,
00092        NULL,
00093        MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE
00094 };
00095 
00096 const struct mbfl_identify_vtbl vtbl_identify_jis_ms = {
00097        mbfl_no_encoding_jis_ms,
00098        mbfl_filt_ident_common_ctor,
00099        mbfl_filt_ident_common_dtor,
00100        mbfl_filt_ident_jis_ms
00101 };
00102 
00103 const struct mbfl_identify_vtbl vtbl_identify_cp50220 = {
00104        mbfl_no_encoding_cp50220,
00105        mbfl_filt_ident_common_ctor,
00106        mbfl_filt_ident_common_dtor,
00107        mbfl_filt_ident_cp50220
00108 };
00109 
00110 const struct mbfl_identify_vtbl vtbl_identify_cp50220raw = {
00111        mbfl_no_encoding_cp50220raw,
00112        mbfl_filt_ident_common_ctor,
00113        mbfl_filt_ident_common_dtor,
00114        mbfl_filt_ident_cp50220
00115 };
00116 
00117 const struct mbfl_identify_vtbl vtbl_identify_cp50221 = {
00118        mbfl_no_encoding_cp50221,
00119        mbfl_filt_ident_common_ctor,
00120        mbfl_filt_ident_common_dtor,
00121        mbfl_filt_ident_cp50221
00122 };
00123 
00124 const struct mbfl_identify_vtbl vtbl_identify_cp50222 = {
00125        mbfl_no_encoding_cp50222,
00126        mbfl_filt_ident_common_ctor,
00127        mbfl_filt_ident_common_dtor,
00128        mbfl_filt_ident_cp50222
00129 };
00130 
00131 const struct mbfl_convert_vtbl vtbl_jis_ms_wchar = {
00132        mbfl_no_encoding_jis_ms,
00133        mbfl_no_encoding_wchar,
00134        mbfl_filt_conv_common_ctor,
00135        mbfl_filt_conv_common_dtor,
00136        mbfl_filt_conv_jis_ms_wchar,
00137        mbfl_filt_conv_common_flush,
00138 };
00139 
00140 const struct mbfl_convert_vtbl vtbl_wchar_jis_ms = {
00141        mbfl_no_encoding_wchar,
00142        mbfl_no_encoding_jis_ms,
00143        mbfl_filt_conv_common_ctor,
00144        mbfl_filt_conv_common_dtor,
00145        mbfl_filt_conv_wchar_jis_ms,
00146        mbfl_filt_conv_any_jis_flush
00147 };
00148 
00149 const struct mbfl_convert_vtbl vtbl_cp50220_wchar = {
00150        mbfl_no_encoding_cp50220,
00151        mbfl_no_encoding_wchar,
00152        mbfl_filt_conv_common_ctor,
00153        mbfl_filt_conv_common_dtor,
00154        mbfl_filt_conv_jis_ms_wchar,
00155        mbfl_filt_conv_common_flush
00156 };
00157 
00158 const struct mbfl_convert_vtbl vtbl_wchar_cp50220 = {
00159        mbfl_no_encoding_wchar,
00160        mbfl_no_encoding_cp50220,
00161        mbfl_filt_conv_wchar_cp50220_ctor,
00162        mbfl_filt_conv_wchar_cp50220_dtor,
00163        mbfl_filt_conv_wchar_cp50221,
00164        mbfl_filt_conv_any_jis_flush,
00165        mbfl_filt_conv_wchar_cp50220_copy
00166 };
00167 
00168 const struct mbfl_convert_vtbl vtbl_cp50220raw_wchar = {
00169        mbfl_no_encoding_cp50220raw,
00170        mbfl_no_encoding_wchar,
00171        mbfl_filt_conv_common_ctor,
00172        mbfl_filt_conv_common_dtor,
00173        mbfl_filt_conv_jis_ms_wchar,
00174        mbfl_filt_conv_common_flush
00175 };
00176 
00177 const struct mbfl_convert_vtbl vtbl_wchar_cp50220raw = {
00178        mbfl_no_encoding_wchar,
00179        mbfl_no_encoding_cp50220raw,
00180        mbfl_filt_conv_wchar_cp50220_ctor,
00181        mbfl_filt_conv_wchar_cp50220_dtor,
00182        mbfl_filt_conv_wchar_cp50220raw,
00183        mbfl_filt_conv_any_jis_flush,
00184        mbfl_filt_conv_wchar_cp50220_copy
00185 };
00186 
00187 const struct mbfl_convert_vtbl vtbl_cp50221_wchar = {
00188        mbfl_no_encoding_cp50221,
00189        mbfl_no_encoding_wchar,
00190        mbfl_filt_conv_common_ctor,
00191        mbfl_filt_conv_common_dtor,
00192        mbfl_filt_conv_jis_ms_wchar,
00193        mbfl_filt_conv_common_flush
00194 };
00195 
00196 const struct mbfl_convert_vtbl vtbl_wchar_cp50221 = {
00197        mbfl_no_encoding_wchar,
00198        mbfl_no_encoding_cp50221,
00199        mbfl_filt_conv_common_ctor,
00200        mbfl_filt_conv_common_dtor,
00201        mbfl_filt_conv_wchar_cp50221,
00202        mbfl_filt_conv_any_jis_flush
00203 };
00204 
00205 const struct mbfl_convert_vtbl vtbl_cp50222_wchar = {
00206        mbfl_no_encoding_cp50222,
00207        mbfl_no_encoding_wchar,
00208        mbfl_filt_conv_common_ctor,
00209        mbfl_filt_conv_common_dtor,
00210        mbfl_filt_conv_jis_ms_wchar,
00211        mbfl_filt_conv_common_flush
00212 };
00213 
00214 const struct mbfl_convert_vtbl vtbl_wchar_cp50222 = {
00215        mbfl_no_encoding_wchar,
00216        mbfl_no_encoding_cp50222,
00217        mbfl_filt_conv_common_ctor,
00218        mbfl_filt_conv_common_dtor,
00219        mbfl_filt_conv_wchar_cp50222,
00220        mbfl_filt_conv_wchar_cp50222_flush
00221 };
00222 
00223 #define CK(statement)       do { if ((statement) < 0) return (-1); } while (0)
00224 
00225 /*
00226  * JIS-ms => wchar
00227  */
00228 int
00229 mbfl_filt_conv_jis_ms_wchar(int c, mbfl_convert_filter *filter)
00230 {
00231        int c1, s, w;
00232 
00233 retry:
00234        switch (filter->status & 0xf) {
00235 /*     case 0x00:     ASCII */
00236 /*     case 0x10:     X 0201 latin */
00237 /*     case 0x20:     X 0201 kana */
00238 /*     case 0x80:     X 0208 */
00239 /*     case 0x90:     X 0212 */
00240        case 0:
00241               if (c == 0x1b) {
00242                      filter->status += 2;
00243               } else if (c == 0x0e) {            /* "kana in" */
00244                      filter->status = 0x20;
00245               } else if (c == 0x0f) {            /* "kana out" */
00246                      filter->status = 0;
00247               } else if (filter->status == 0x10 && c == 0x5c) {       /* YEN SIGN */
00248                      CK((*filter->output_function)(0xa5, filter->data));
00249               } else if (filter->status == 0x10 && c == 0x7e) {       /* OVER LINE */
00250                      CK((*filter->output_function)(0x203e, filter->data));
00251               } else if (filter->status == 0x20 && c > 0x20 && c < 0x60) {          /* kana */
00252                      CK((*filter->output_function)(0xff40 + c, filter->data));
00253               } else if ((filter->status == 0x80 || filter->status == 0x90) && c > 0x20 && c < 0x7f) {          /* kanji first char */
00254                      filter->cache = c;
00255                      filter->status += 1;
00256               } else if (c >= 0 && c < 0x80) {          /* latin, CTLs */
00257                      CK((*filter->output_function)(c, filter->data));
00258               } else if (c > 0xa0 && c < 0xe0) { /* GR kana */
00259                      CK((*filter->output_function)(0xfec0 + c, filter->data));
00260               } else {
00261                      w = c & MBFL_WCSGROUP_MASK;
00262                      w |= MBFL_WCSGROUP_THROUGH;
00263                      CK((*filter->output_function)(w, filter->data));
00264               }
00265               break;
00266 
00267 /*     case 0x81:     X 0208 second char */
00268 /*     case 0x91:     X 0212 second char */
00269        case 1:
00270               filter->status &= ~0xf;
00271               c1 = filter->cache;
00272               if (c > 0x20 && c < 0x7f) {
00273                      s = (c1 - 0x21)*94 + c - 0x21;
00274                      if (filter->status == 0x80) {
00275                             if (s >= 0 && s < jisx0208_ucs_table_size) {
00276                                    w = jisx0208_ucs_table[s];
00277                             } else if (s >= cp932ext1_ucs_table_min && s < cp932ext1_ucs_table_max) {
00278                                    w = cp932ext1_ucs_table[s - cp932ext1_ucs_table_min];
00279                             } else if (s >= cp932ext2_ucs_table_min && s < cp932ext2_ucs_table_max) {
00280                                    w = cp932ext2_ucs_table[s - cp932ext2_ucs_table_min];
00281                             } else if (s >= cp932ext3_ucs_table_min && s < cp932ext2_ucs_table_max) {
00282                                    w = cp932ext3_ucs_table[s - cp932ext3_ucs_table_min];
00283                             } else if (s >= 94 * 94 && s < 114 * 94) {
00284                                    /* user-defined => PUA (Microsoft extended) */
00285                                    w = (s & 0xff) + ((s >> 8) - 94) * 94 + 0xe000;
00286                             } else if (s >= 212 * 94 && s < 222 * 94) {
00287                                    /* user-defined => PUA (G3 85 - 94 Ku) */
00288                                    w = (s & 0xff) + ((s >> 8) - 212) * 94 + 0xe000 + 10 * 94;
00289                             } else {
00290                                    w = 0;
00291                             }
00292                             if (w <= 0) {
00293                                    w = (c1 << 8) | c;
00294                                    w &= MBFL_WCSPLANE_MASK;
00295                                    w |= MBFL_WCSPLANE_JIS0208;
00296                             }
00297                      } else {
00298                             if (s >= 0 && s < jisx0212_ucs_table_size) {
00299                                    w = jisx0212_ucs_table[s];
00300                             } else {
00301                                    w = 0;
00302                             }
00303                             if (w <= 0) {
00304                                    w = (c1 << 8) | c;
00305                                    w &= MBFL_WCSPLANE_MASK;
00306                                    w |= MBFL_WCSPLANE_JIS0212;
00307                             }
00308                      }
00309                      CK((*filter->output_function)(w, filter->data));
00310               } else if (c == 0x1b) {
00311                      filter->status += 2;
00312               } else if ((c >= 0 && c < 0x21) || c == 0x7f) {         /* CTLs */
00313                      CK((*filter->output_function)(c, filter->data));
00314               } else {
00315                      w = (c1 << 8) | c;
00316                      w &= MBFL_WCSGROUP_MASK;
00317                      w |= MBFL_WCSGROUP_THROUGH;
00318                      CK((*filter->output_function)(w, filter->data));
00319               }
00320               break;
00321 
00322        /* ESC */
00323 /*     case 0x02:    */
00324 /*     case 0x12:    */
00325 /*     case 0x22:    */
00326 /*     case 0x82:    */
00327 /*     case 0x92:    */
00328        case 2:
00329               if (c == 0x24) {            /* '$' */
00330                      filter->status++;
00331               } else if (c == 0x28) {            /* '(' */
00332                      filter->status += 3;
00333               } else {
00334                      filter->status &= ~0xf;
00335                      CK((*filter->output_function)(0x1b, filter->data));
00336                      goto retry;
00337               }
00338               break;
00339 
00340        /* ESC $ */
00341 /*     case 0x03:    */
00342 /*     case 0x13:    */
00343 /*     case 0x23:    */
00344 /*     case 0x83:    */
00345 /*     case 0x93:    */
00346        case 3:
00347               if (c == 0x40 || c == 0x42) {      /* '@' or 'B' */
00348                      filter->status = 0x80;
00349               } else if (c == 0x28) {                   /* '(' */
00350                      filter->status++;
00351               } else {
00352                      filter->status &= ~0xf;
00353                      CK((*filter->output_function)(0x1b, filter->data));
00354                      CK((*filter->output_function)(0x24, filter->data));
00355                      goto retry;
00356               }
00357               break;
00358 
00359        /* ESC $ ( */
00360 /*     case 0x04:    */
00361 /*     case 0x14:    */
00362 /*     case 0x24:    */
00363 /*     case 0x84:    */
00364 /*     case 0x94:    */
00365        case 4:
00366               if (c == 0x40 || c == 0x42) {      /* '@' or 'B' */
00367                      filter->status = 0x80;
00368               } else if (c == 0x44) {                   /* 'D' */
00369                      filter->status = 0x90;
00370               } else {
00371                      filter->status &= ~0xf;
00372                      CK((*filter->output_function)(0x1b, filter->data));
00373                      CK((*filter->output_function)(0x24, filter->data));
00374                      CK((*filter->output_function)(0x28, filter->data));
00375                      goto retry;
00376               }
00377               break;
00378 
00379        /* ESC ( */
00380 /*     case 0x05:    */
00381 /*     case 0x15:    */
00382 /*     case 0x25:    */
00383 /*     case 0x85:    */
00384 /*     case 0x95:    */
00385        case 5:
00386               if (c == 0x42 || c == 0x48) {             /* 'B' or 'H' */
00387                      filter->status = 0;
00388               } else if (c == 0x4a) {            /* 'J' */
00389                      filter->status = 0x10;
00390               } else if (c == 0x49) {            /* 'I' */
00391                      filter->status = 0x20;
00392               } else {
00393                      filter->status &= ~0xf;
00394                      CK((*filter->output_function)(0x1b, filter->data));
00395                      CK((*filter->output_function)(0x28, filter->data));
00396                      goto retry;
00397               }
00398               break;
00399 
00400        default:
00401               filter->status = 0;
00402               break;
00403        }
00404 
00405        return c;
00406 }
00407 
00408 /*
00409  * wchar => JIS
00410  */
00411 int
00412 mbfl_filt_conv_wchar_jis_ms(int c, mbfl_convert_filter *filter)
00413 {
00414        int c1, s;
00415 
00416        s = 0;
00417        if (c >= ucs_a1_jis_table_min && c < ucs_a1_jis_table_max) {
00418               s = ucs_a1_jis_table[c - ucs_a1_jis_table_min];
00419        } else if (c >= ucs_a2_jis_table_min && c < ucs_a2_jis_table_max) {
00420               s = ucs_a2_jis_table[c - ucs_a2_jis_table_min];
00421        } else if (c >= ucs_i_jis_table_min && c < ucs_i_jis_table_max) {
00422               s = ucs_i_jis_table[c - ucs_i_jis_table_min];
00423        } else if (c >= ucs_r_jis_table_min && c < ucs_r_jis_table_max) {
00424               s = ucs_r_jis_table[c - ucs_r_jis_table_min];
00425        } else if (c >= 0xe000 && c < (0xe000 + 10 * 94)) {
00426               /* PUE => Microsoft extended (pseudo 95ku - 114ku) */
00427               /* See http://www.opengroup.or.jp/jvc/cde/ucs-conv.html#ch4_2 */
00428               s = c - 0xe000;
00429               s = (s / 94 + 0x75) << 8 | (s % 94 + 0x21);
00430        } else if (c >= (0xe000 + 10 * 94) && c <= (0xe000 + 20 * 94)) {
00431               /* PUE => JISX0212 user-defined (G3 85ku - 94ku) */
00432               /* See http://www.opengroup.or.jp/jvc/cde/ucs-conv.html#ch4_2 */
00433               s = c - (0xe000 + 10 * 94);
00434               s = (s / 94 + 0xf5) << 8 | (s % 94 + 0xa1);
00435        }
00436 
00437        /* do some transliteration */
00438        if (s <= 0) {
00439               c1 = c & ~MBFL_WCSPLANE_MASK;
00440               if (c1 == MBFL_WCSPLANE_JIS0208) {
00441                      s = c & MBFL_WCSPLANE_MASK;
00442               } else if (c1 == MBFL_WCSPLANE_JIS0212) {
00443                      s = c & MBFL_WCSPLANE_MASK;
00444                      s |= 0x8080;
00445               } else if (c == 0xa5) {            /* YEN SIGN */
00446                      s = 0x1005c;
00447               } else if (c == 0x203e) {   /* OVER LINE */
00448                      s = 0x1007e;
00449               } else if (c == 0xff3c) {   /* FULLWIDTH REVERSE SOLIDUS */
00450                      s = 0x2140;
00451               } else if (c == 0xff5e) {   /* FULLWIDTH TILDE */
00452                      s = 0x2141;
00453               } else if (c == 0x2225) {   /* PARALLEL TO */
00454                      s = 0x2142;
00455               } else if (c == 0xff0d) {   /* FULLWIDTH HYPHEN-MINUS */
00456                      s = 0x215d;
00457               } else if (c == 0xffe0) {   /* FULLWIDTH CENT SIGN */
00458                      s = 0x2171;
00459               } else if (c == 0xffe1) {   /* FULLWIDTH POUND SIGN */
00460                      s = 0x2172;
00461               } else if (c == 0xffe2) {   /* FULLWIDTH NOT SIGN */
00462                      s = 0x224c;
00463               }
00464        }
00465        if (s <= 0 || s >= 0x8080 && s < 0x10000) {
00466               int i;
00467               s = -1;
00468 
00469               for (i = 0;
00470                             i < cp932ext1_ucs_table_max - cp932ext1_ucs_table_min; i++) {
00471                      const int oh = cp932ext1_ucs_table_min / 94;
00472 
00473                      if (c == cp932ext1_ucs_table[i]) {
00474                             s = ((i / 94 + oh + 0x21) << 8) + (i % 94 + 0x21);
00475                             break;
00476                      }
00477               }
00478 
00479               if (s < 0) {
00480                      const int oh = cp932ext2_ucs_table_min / 94;
00481                      const int cp932ext2_ucs_table_size =
00482                                    cp932ext2_ucs_table_max - cp932ext2_ucs_table_min;
00483                      for (i = 0; i < cp932ext2_ucs_table_size; i++) {
00484                             if (c == cp932ext2_ucs_table[i]) {
00485                                    s = ((i / 94 + oh + 0x21) << 8) + (i % 94 + 0x21);
00486                                    break;
00487                             }
00488                      }
00489               }
00490 
00491               if (s < 0) {
00492                      const int cp932ext3_ucs_table_size =
00493                                    cp932ext3_ucs_table_max - cp932ext3_ucs_table_min;
00494                      const int limit = cp932ext3_ucs_table_size >
00495                                    cp932ext3_eucjp_table_size ?
00496                                           cp932ext3_eucjp_table_size:
00497                                           cp932ext3_ucs_table_size;
00498                      for (i = 0; i < limit; i++) {
00499                             if (c == cp932ext3_ucs_table[i]) {
00500                                    s = cp932ext3_eucjp_table[i];
00501                                    break;
00502                             }
00503                      }
00504               }
00505 
00506               if (c == 0) {
00507                      s = 0;
00508               } else if (s <= 0) {
00509                      s = -1;
00510               }
00511        }
00512 
00513        if (s >= 0) {
00514               if (s < 0x80) { /* ASCII */
00515                      if ((filter->status & 0xff00) != 0) {
00516                             CK((*filter->output_function)(0x1b, filter->data));            /* ESC */
00517                             CK((*filter->output_function)(0x28, filter->data));            /* '(' */
00518                             CK((*filter->output_function)(0x42, filter->data));            /* 'B' */
00519                      }
00520                      filter->status = 0;
00521                      CK((*filter->output_function)(s, filter->data));
00522               } else if (s < 0x100) { /* kana */
00523                      if ((filter->status & 0xff00) != 0x100) {
00524                             CK((*filter->output_function)(0x1b, filter->data));            /* ESC */
00525                             CK((*filter->output_function)(0x28, filter->data));            /* '(' */
00526                             CK((*filter->output_function)(0x49, filter->data));            /* 'I' */
00527                      }
00528                      filter->status = 0x100;
00529                      CK((*filter->output_function)(s & 0x7f, filter->data));
00530               } else if (s < 0x8080) { /* X 0208 */
00531                      if ((filter->status & 0xff00) != 0x200) {
00532                             CK((*filter->output_function)(0x1b, filter->data));            /* ESC */
00533                             CK((*filter->output_function)(0x24, filter->data));            /* '$' */
00534                             CK((*filter->output_function)(0x42, filter->data));            /* 'B' */
00535                      }
00536                      filter->status = 0x200;
00537                      CK((*filter->output_function)((s >> 8) & 0x7f, filter->data));
00538                      CK((*filter->output_function)(s & 0x7f, filter->data));
00539               } else if (s < 0x10000) { /* X 0212 */
00540                      if ((filter->status & 0xff00) != 0x300) {
00541                             CK((*filter->output_function)(0x1b, filter->data));            /* ESC */
00542                             CK((*filter->output_function)(0x24, filter->data));            /* '$' */
00543                             CK((*filter->output_function)(0x28, filter->data));            /* '(' */
00544                             CK((*filter->output_function)(0x44, filter->data));            /* 'D' */
00545                      }
00546                      filter->status = 0x300;
00547                      CK((*filter->output_function)((s >> 8) & 0x7f, filter->data));
00548                      CK((*filter->output_function)(s & 0x7f, filter->data));
00549               } else { /* X 0201 latin */
00550                      if ((filter->status & 0xff00) != 0x400) {
00551                             CK((*filter->output_function)(0x1b, filter->data));            /* ESC */
00552                             CK((*filter->output_function)(0x28, filter->data));            /* '(' */
00553                             CK((*filter->output_function)(0x4a, filter->data));            /* 'J' */
00554                      }
00555                      filter->status = 0x400;
00556                      CK((*filter->output_function)(s & 0x7f, filter->data));
00557               }
00558        } else {
00559               if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
00560                      CK(mbfl_filt_conv_illegal_output(c, filter));
00561               }
00562        }
00563 
00564        return c;
00565 }
00566 
00567 /*
00568  * wchar => CP50220
00569  */
00570 static void
00571 mbfl_filt_conv_wchar_cp50220_ctor(mbfl_convert_filter *filt)
00572 {
00573        mbfl_filt_conv_wchar_cp50220_ctx *ctx;
00574 
00575        mbfl_filt_conv_common_ctor(filt);
00576 
00577        ctx = mbfl_malloc(sizeof(mbfl_filt_conv_wchar_cp50220_ctx));
00578        if (ctx == NULL) {
00579               mbfl_filt_conv_common_dtor(filt);
00580               return;
00581        }
00582 
00583        ctx->tl_param.mode = MBFL_FILT_TL_HAN2ZEN_KATAKANA | MBFL_FILT_TL_HAN2ZEN_GLUE;
00584 
00585        ctx->last = *filt;
00586        ctx->last.opaque = ctx;
00587        ctx->last.data = filt->data;
00588        filt->filter_function = vtbl_tl_jisx0201_jisx0208.filter_function;
00589        filt->filter_flush = vtbl_tl_jisx0201_jisx0208.filter_flush;
00590        filt->output_function = (int(*)(int, void *))ctx->last.filter_function;
00591        filt->flush_function = (int(*)(void *))ctx->last.filter_flush;
00592        filt->data = &ctx->last;
00593        filt->opaque = ctx;
00594        vtbl_tl_jisx0201_jisx0208.filter_ctor(filt);
00595 }
00596 
00597 static void
00598 mbfl_filt_conv_wchar_cp50220_copy(mbfl_convert_filter *src, mbfl_convert_filter *dest)
00599 {
00600        mbfl_filt_conv_wchar_cp50220_ctx *ctx;
00601 
00602        *dest = *src;
00603        ctx = mbfl_malloc(sizeof(mbfl_filt_conv_wchar_cp50220_ctx));
00604        if (ctx != NULL) {
00605               *ctx = *(mbfl_filt_conv_wchar_cp50220_ctx*)src->opaque;
00606        }
00607 
00608        dest->opaque = ctx;
00609        dest->data = &ctx->last;
00610 }
00611 
00612 static void
00613 mbfl_filt_conv_wchar_cp50220_dtor(mbfl_convert_filter *filt)
00614 {
00615        vtbl_tl_jisx0201_jisx0208.filter_dtor(filt);
00616 
00617        if (filt->opaque != NULL) {
00618               mbfl_free(filt->opaque);
00619        }
00620 
00621        mbfl_filt_conv_common_dtor(filt);
00622 }
00623 
00624 /*
00625  * wchar => cp50220raw
00626  */
00627 int
00628 mbfl_filt_conv_wchar_cp50220raw(int c, mbfl_convert_filter *filter)
00629 {
00630        if (c & MBFL_WCSPLANE_JIS0208) {
00631               const int s = c & MBFL_WCSPLANE_MASK;
00632        
00633               if ((filter->status & 0xff00) != 0x200) {
00634                      CK((*filter->output_function)(0x1b, filter->data));            /* ESC */
00635                      CK((*filter->output_function)(0x24, filter->data));            /* '$' */
00636                      CK((*filter->output_function)(0x42, filter->data));            /* 'B' */
00637                      filter->status = 0x200;
00638               }
00639               CK((*filter->output_function)((s >> 8) & 0x7f, filter->data));
00640               CK((*filter->output_function)(s & 0x7f, filter->data));
00641               return c;
00642        } else {
00643               return mbfl_filt_conv_wchar_cp50221(c, filter);
00644        }
00645 }
00646 
00647 /*
00648  * wchar => CP50221
00649  */
00650 int
00651 mbfl_filt_conv_wchar_cp50221(int c, mbfl_convert_filter *filter)
00652 {
00653        int s = 0;
00654 
00655        if (c >= ucs_a1_jis_table_min && c < ucs_a1_jis_table_max) {
00656               s = ucs_a1_jis_table[c - ucs_a1_jis_table_min];
00657        } else if (c >= ucs_a2_jis_table_min && c < ucs_a2_jis_table_max) {
00658               s = ucs_a2_jis_table[c - ucs_a2_jis_table_min];
00659        } else if (c >= ucs_i_jis_table_min && c < ucs_i_jis_table_max) {
00660               s = ucs_i_jis_table[c - ucs_i_jis_table_min];
00661        } else if (c >= ucs_r_jis_table_min && c < ucs_r_jis_table_max) {
00662               s = ucs_r_jis_table[c - ucs_r_jis_table_min];
00663        } else if (c >= 0xe000 && c < (0xe000 + 10 * 94)) {
00664               /* PUE => Microsoft extended */
00665               /* See http://www.opengroup.or.jp/jvc/cde/ucs-conv.html#ch4_2 */
00666               s = c - 0xe000;
00667               s = (s / 94 + 0x75) << 8 | (s % 94 + 0x21);
00668        } else if (c >= (0xe000 + 10 * 94) && c <= (0xe000 + 20 * 94)) {
00669               /* PUE => JISX0212 user-defined (G3 85ku - 94ku) */
00670               /* See http://www.opengroup.or.jp/jvc/cde/ucs-conv.html#ch4_2 */
00671               s = c - (0xe000 + 10 * 94);
00672               s = (s / 94 + 0xf5) << 8 | (s % 94 + 0xa1);
00673        }
00674 
00675        if (s <= 0) {
00676               if (c == 0xa5) {                   /* YEN SIGN */
00677                      s = 0x1005c;
00678               } else if (c == 0x203e) {   /* OVER LINE */
00679                      s = 0x1007e;
00680               } else if (c == 0xff3c) {   /* FULLWIDTH REVERSE SOLIDUS */
00681                      s = 0x2140;
00682               } else if (c == 0xff5e) {   /* FULLWIDTH TILDE */
00683                      s = 0x2141;
00684               } else if (c == 0x2225) {   /* PARALLEL TO */
00685                      s = 0x2142;
00686               } else if (c == 0xff0d) {   /* FULLWIDTH HYPHEN-MINUS */
00687                      s = 0x215d;
00688               } else if (c == 0xffe0) {   /* FULLWIDTH CENT SIGN */
00689                      s = 0x2171;
00690               } else if (c == 0xffe1) {   /* FULLWIDTH POUND SIGN */
00691                      s = 0x2172;
00692               } else if (c == 0xffe2) {   /* FULLWIDTH NOT SIGN */
00693                      s = 0x224c;
00694               }
00695        }
00696        if (s <= 0 || s >= 0x8080 && s < 0x10000) {
00697               int i;
00698               s = -1;
00699 
00700               for (i = 0;
00701                             i < cp932ext1_ucs_table_max - cp932ext1_ucs_table_min;
00702                             i++) {
00703                      const int oh = cp932ext1_ucs_table_min / 94;
00704 
00705                      if (c == cp932ext1_ucs_table[i]) {
00706                             s = ((i / 94 + oh + 0x21) << 8) + (i % 94 + 0x21);
00707                             break;
00708                      }
00709               }
00710 
00711               if (s < 0) {
00712                      const int oh = cp932ext2_ucs_table_min / 94;
00713                      const int cp932ext2_ucs_table_size =
00714                                    cp932ext2_ucs_table_max - cp932ext2_ucs_table_min;
00715                      for (i = 0; i < cp932ext2_ucs_table_size; i++) {
00716                             if (c == cp932ext2_ucs_table[i]) {
00717                                    s = ((i / 94 + oh + 0x21) << 8) + (i % 94 + 0x21);
00718                                    break;
00719                             }
00720                      }
00721               }
00722 
00723               if (s < 0) {
00724                      const int cp932ext3_ucs_table_size =
00725                                    cp932ext3_ucs_table_max - cp932ext3_ucs_table_min;
00726                      const int limit = cp932ext3_ucs_table_size >
00727                                    cp932ext3_eucjp_table_size ?
00728                                           cp932ext3_eucjp_table_size:
00729                                           cp932ext3_ucs_table_size;
00730                      for (i = 0; i < limit; i++) {
00731                             if (c == cp932ext3_ucs_table[i]) {
00732                                    s = cp932ext3_eucjp_table[i];
00733                                    break;
00734                             }
00735                      }
00736               }
00737 
00738               if (c == 0) {
00739                      s = 0;
00740               } else if (s <= 0) {
00741                      s = -1;
00742               }
00743        }
00744 
00745        if (s >= 0) {
00746               if (s < 0x80) { /* ASCII */
00747                      if ((filter->status & 0xff00) != 0) {
00748                             CK((*filter->output_function)(0x1b, filter->data));            /* ESC */
00749                             CK((*filter->output_function)(0x28, filter->data));            /* '(' */
00750                             CK((*filter->output_function)(0x42, filter->data));            /* 'B' */
00751                             filter->status = 0;
00752                      }
00753                      CK((*filter->output_function)(s, filter->data));
00754               } else if (s >= 0xa0 && s < 0xe0) { /* X 0201 kana */
00755                      if ((filter->status & 0xff00) != 0x500) {
00756                             CK((*filter->output_function)(0x1b, filter->data));            /* ESC */
00757                             CK((*filter->output_function)(0x28, filter->data));            /* '(' */
00758                             CK((*filter->output_function)(0x49, filter->data));            /* 'I' */
00759                             filter->status = 0x500;
00760                      }
00761                      CK((*filter->output_function)(s - 0x80, filter->data));
00762               } else if (s < 0x8080) { /* X 0208 */
00763                      if ((filter->status & 0xff00) != 0x200) {
00764                             CK((*filter->output_function)(0x1b, filter->data));            /* ESC */
00765                             CK((*filter->output_function)(0x24, filter->data));            /* '$' */
00766                             CK((*filter->output_function)(0x42, filter->data));            /* 'B' */
00767                             filter->status = 0x200;
00768                      }
00769                      CK((*filter->output_function)((s >> 8) & 0x7f, filter->data));
00770                      CK((*filter->output_function)(s & 0x7f, filter->data));
00771               } else if (s < 0x10000) { /* X0212 */
00772                      if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
00773                             CK(mbfl_filt_conv_illegal_output(c, filter));
00774                      }
00775               } else { /* X 0201 latin */
00776                      if ((filter->status & 0xff00) != 0x400) {
00777                             CK((*filter->output_function)(0x1b, filter->data));            /* ESC */
00778                             CK((*filter->output_function)(0x28, filter->data));            /* '(' */
00779                             CK((*filter->output_function)(0x4a, filter->data));            /* 'J' */
00780                      }
00781                      filter->status = 0x400;
00782                      CK((*filter->output_function)(s & 0x7f, filter->data));
00783               }
00784        } else {
00785               if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
00786                      CK(mbfl_filt_conv_illegal_output(c, filter));
00787               }
00788        }
00789 
00790        return c;
00791 }
00792 
00793 /*
00794  * wchar => CP50222
00795  */
00796 int
00797 mbfl_filt_conv_wchar_cp50222(int c, mbfl_convert_filter *filter)
00798 {
00799        int s;
00800 
00801        s = 0;
00802 
00803        if (c >= ucs_a1_jis_table_min && c < ucs_a1_jis_table_max) {
00804               s = ucs_a1_jis_table[c - ucs_a1_jis_table_min];
00805        } else if (c >= ucs_a2_jis_table_min && c < ucs_a2_jis_table_max) {
00806               s = ucs_a2_jis_table[c - ucs_a2_jis_table_min];
00807        } else if (c >= ucs_i_jis_table_min && c < ucs_i_jis_table_max) {
00808               s = ucs_i_jis_table[c - ucs_i_jis_table_min];
00809        } else if (c >= ucs_r_jis_table_min && c < ucs_r_jis_table_max) {
00810               s = ucs_r_jis_table[c - ucs_r_jis_table_min];
00811        } else if (c >= 0xe000 && c < (0xe000 + 10 * 94)) {
00812               /* PUE => Microsoft extended */
00813               /* See http://www.opengroup.or.jp/jvc/cde/ucs-conv.html#ch4_2 */
00814               s = c - 0xe000;
00815               s = (s / 94 + 0x75) << 8 | (s % 94 + 0x21);
00816        } else if (c >= (0xe000 + 10 * 94) && c <= (0xe000 + 20 * 94)) {
00817               /* PUE => JISX0212 user-defined (G3 85ku - 94ku) */
00818               /* See http://www.opengroup.or.jp/jvc/cde/ucs-conv.html#ch4_2 */
00819               s = c - (0xe000 + 10 * 94);
00820               s = (s / 94 + 0xf5) << 8 | (s % 94 + 0xa1);
00821        }
00822 
00823        if (s <= 0) {
00824               if (c == 0xa5) {                   /* YEN SIGN */
00825                      s = 0x1005c;
00826               } else if (c == 0x203e) {   /* OVER LINE */
00827                      s = 0x1007e;
00828               } else if (c == 0xff3c) {   /* FULLWIDTH REVERSE SOLIDUS */
00829                      s = 0x2140;
00830               } else if (c == 0xff5e) {   /* FULLWIDTH TILDE */
00831                      s = 0x2141;
00832               } else if (c == 0x2225) {   /* PARALLEL TO */
00833                      s = 0x2142;
00834               } else if (c == 0xff0d) {   /* FULLWIDTH HYPHEN-MINUS */
00835                      s = 0x215d;
00836               } else if (c == 0xffe0) {   /* FULLWIDTH CENT SIGN */
00837                      s = 0x2171;
00838               } else if (c == 0xffe1) {   /* FULLWIDTH POUND SIGN */
00839                      s = 0x2172;
00840               } else if (c == 0xffe2) {   /* FULLWIDTH NOT SIGN */
00841                      s = 0x224c;
00842               }
00843        }
00844        if (s <= 0 || s >= 0x8080 && s < 0x10000) {
00845               int i;
00846               s = -1;
00847 
00848               for (i = 0;
00849                             i < cp932ext1_ucs_table_max - cp932ext1_ucs_table_min; i++) {
00850                      const int oh = cp932ext1_ucs_table_min / 94;
00851 
00852                      if (c == cp932ext1_ucs_table[i]) {
00853                             s = ((i / 94 + oh + 0x21) << 8) + (i % 94 + 0x21);
00854                             break;
00855                      }
00856               }
00857 
00858               if (s <= 0) {
00859                      const int oh = cp932ext2_ucs_table_min / 94;
00860                      const int cp932ext2_ucs_table_size =
00861                                    cp932ext2_ucs_table_max - cp932ext2_ucs_table_min;
00862                      for (i = 0; i < cp932ext2_ucs_table_size; i++) {
00863                             if (c == cp932ext2_ucs_table[i]) {
00864                                    s = ((i / 94 + oh + 0x21) << 8) + (i % 94 + 0x21);
00865                                    break;
00866                             }
00867                      }
00868               }
00869 
00870               if (s <= 0) {
00871                      const int cp932ext3_ucs_table_size =
00872                                    cp932ext3_ucs_table_max - cp932ext3_ucs_table_min;
00873                      const int limit = cp932ext3_ucs_table_size >
00874                                    cp932ext3_eucjp_table_size ?
00875                                           cp932ext3_eucjp_table_size:
00876                                           cp932ext3_ucs_table_size;
00877                      for (i = 0; i < limit; i++) {
00878                             if (c == cp932ext3_ucs_table[i]) {
00879                                    s = cp932ext3_eucjp_table[i];
00880                                    break;
00881                             }
00882                      }
00883               }
00884 
00885               if (c == 0) {
00886                      s = 0;
00887               } else if (s <= 0) {
00888                      s = -1;
00889               }
00890        }
00891 
00892        if (s >= 0) {
00893               if (s < 0x80) { /* ASCII */
00894                      if ((filter->status & 0xff00) == 0x500) {
00895                             CK((*filter->output_function)(0x0f, filter->data));            /* SO */
00896                             filter->status = 0;
00897                      } else if ((filter->status & 0xff00) != 0) {
00898                             CK((*filter->output_function)(0x1b, filter->data));            /* ESC */
00899                             CK((*filter->output_function)(0x28, filter->data));            /* '(' */
00900                             CK((*filter->output_function)(0x42, filter->data));            /* 'B' */
00901                             filter->status = 0;
00902                      }
00903                      CK((*filter->output_function)(s, filter->data));
00904               } else if (s >= 0xa0 && s < 0xe0) { /* X 0201 kana */
00905                      if ((filter->status & 0xff00) != 0x500) {
00906                             CK((*filter->output_function)(0x0e, filter->data));            /* SI */
00907                             filter->status = 0x500;
00908                      }
00909                      CK((*filter->output_function)(s - 0x80, filter->data));
00910               } else if (s < 0x8080) { /* X 0208 */
00911                      if ((filter->status & 0xff00) == 0x500) {
00912                             CK((*filter->output_function)(0x0f, filter->data));            /* SO */
00913                             filter->status = 0;
00914                      }
00915                      if ((filter->status & 0xff00) != 0x200) {
00916                             CK((*filter->output_function)(0x1b, filter->data));            /* ESC */
00917                             CK((*filter->output_function)(0x24, filter->data));            /* '$' */
00918                             CK((*filter->output_function)(0x42, filter->data));            /* 'B' */
00919                             filter->status = 0x200;
00920                      }
00921                      CK((*filter->output_function)((s >> 8) & 0x7f, filter->data));
00922                      CK((*filter->output_function)(s & 0x7f, filter->data));
00923               } else if (s < 0x10000) { /* X0212 */
00924                      if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
00925                             CK(mbfl_filt_conv_illegal_output(c, filter));
00926                      }
00927               } else { /* X 0201 latin */
00928                      if ((filter->status & 0xff00) == 0x500) {
00929                             CK((*filter->output_function)(0x0f, filter->data));            /* SO */
00930                             filter->status = 0;
00931                      }
00932                      if ((filter->status & 0xff00) != 0x400) {
00933                             CK((*filter->output_function)(0x1b, filter->data));            /* ESC */
00934                             CK((*filter->output_function)(0x28, filter->data));            /* '(' */
00935                             CK((*filter->output_function)(0x4a, filter->data));            /* 'J' */
00936                      }
00937                      filter->status = 0x400;
00938                      CK((*filter->output_function)(s & 0x7f, filter->data));
00939               }
00940        } else {
00941               if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
00942                      CK(mbfl_filt_conv_illegal_output(c, filter));
00943               }
00944        }
00945 
00946        return c;
00947 }
00948 
00949 int
00950 mbfl_filt_conv_wchar_cp50222_flush(mbfl_convert_filter *filter)
00951 {
00952        /* back to latin */
00953        if ((filter->status & 0xff00) == 0x500) {
00954               CK((*filter->output_function)(0x0f, filter->data));            /* SO */
00955        } else if ((filter->status & 0xff00) != 0) {
00956               CK((*filter->output_function)(0x1b, filter->data));            /* ESC */
00957               CK((*filter->output_function)(0x28, filter->data));            /* '(' */
00958               CK((*filter->output_function)(0x42, filter->data));            /* 'B' */
00959        }
00960        filter->status &= 0xff;
00961 
00962        if (filter->flush_function != NULL) {
00963               return (*filter->flush_function)(filter->data);
00964        }
00965 
00966        return 0;
00967 }
00968 
00969 
00970 static int mbfl_filt_ident_jis_ms(int c, mbfl_identify_filter *filter)
00971 {
00972 retry:
00973        switch (filter->status & 0xf) {
00974 /*     case 0x00:     ASCII */
00975 /*     case 0x10:     X 0201 latin */
00976 /*     case 0x20:     X 0201 kana */
00977 /*     case 0x80:     X 0208 */
00978 /*     case 0x90:     X 0212 */
00979        case 0:
00980               if (c == 0x1b) {
00981                      filter->status += 2;
00982               } else if (c == 0x0e) {                   /* "kana in" */
00983                      filter->status = 0x20;
00984               } else if (c == 0x0f) {                   /* "kana out" */
00985                      filter->status = 0;
00986               } else if ((filter->status == 0x80 || filter->status == 0x90) && c > 0x20 && c < 0x7f) {          /* kanji first char */
00987                      filter->status += 1;
00988               } else if (c >= 0 && c < 0x80) {          /* latin, CTLs */
00989                      ;
00990               } else {
00991                      filter->flag = 1;    /* bad */
00992               }
00993               break;
00994 
00995 /*     case 0x81:     X 0208 second char */
00996 /*     case 0x91:     X 0212 second char */
00997        case 1:
00998               filter->status &= ~0xf;
00999               if (c == 0x1b) {
01000                      goto retry;
01001               } else if (c < 0x21 || c > 0x7e) {        /* bad */
01002                      filter->flag = 1;
01003               }
01004               break;
01005 
01006        /* ESC */
01007        case 2:
01008               if (c == 0x24) {            /* '$' */
01009                      filter->status++;
01010               } else if (c == 0x28) {            /* '(' */
01011                      filter->status += 3;
01012               } else {
01013                      filter->flag = 1;    /* bad */
01014                      filter->status &= ~0xf;
01015                      goto retry;
01016               }
01017               break;
01018 
01019        /* ESC $ */
01020        case 3:
01021               if (c == 0x40 || c == 0x42) {             /* '@' or 'B' */
01022                      filter->status = 0x80;
01023               } else if (c == 0x28) {            /* '(' */
01024                      filter->status++;
01025               } else {
01026                      filter->flag = 1;    /* bad */
01027                      filter->status &= ~0xf;
01028                      goto retry;
01029               }
01030               break;
01031 
01032        /* ESC $ ( */
01033        case 4:
01034               if (c == 0x40 || c == 0x42) {             /* '@' or 'B' */
01035                      filter->status = 0x80;
01036               } else if (c == 0x44) {            /* 'D' */
01037                      filter->status = 0x90;
01038               } else {
01039                      filter->flag = 1;    /* bad */
01040                      filter->status &= ~0xf;
01041                      goto retry;
01042               }
01043               break;
01044 
01045        /* ESC ( */
01046        case 5:
01047               if (c == 0x42 || c == 0x48) {             /* 'B' or 'H' */
01048                      filter->status = 0;
01049               } else if (c == 0x4a) {            /* 'J' */
01050                      filter->status = 0x10;
01051               } else if (c == 0x49) {            /* 'I' */
01052                      filter->status = 0x20;
01053               } else {
01054                      filter->flag = 1;    /* bad */
01055                      filter->status &= ~0xf;
01056                      goto retry;
01057               }
01058               break;
01059 
01060        default:
01061               filter->status = 0;
01062               break;
01063        }
01064 
01065        return c;
01066 }
01067 
01068 static int mbfl_filt_ident_cp50220(int c, mbfl_identify_filter *filter)
01069 {
01070 retry:
01071        switch (filter->status & 0xf) {
01072 /*     case 0x00:     ASCII */
01073 /*     case 0x10:     X 0201 latin */
01074 /*     case 0x80:     X 0208 */
01075        case 0:
01076               if (c == 0x1b) {
01077                      filter->status += 2;
01078               } else if (filter->status == 0x80 && c > 0x20 && c < 0x7f) {          /* kanji first char */
01079                      filter->status += 1;
01080               } else if (c >= 0 && c < 0x80) {          /* latin, CTLs */
01081                      ;
01082               } else {
01083                      filter->flag = 1;    /* bad */
01084               }
01085               break;
01086 
01087 /*     case 0x81:     X 0208 second char */
01088        case 1:
01089               if (c == 0x1b) {
01090                      filter->status++;
01091               } else {
01092                      filter->status &= ~0xf;
01093                      if (c < 0x21 || c > 0x7e) {        /* bad */
01094                             filter->flag = 1;
01095                      }
01096               }
01097               break;
01098 
01099        /* ESC */
01100        case 2:
01101               if (c == 0x24) {            /* '$' */
01102                      filter->status++;
01103               } else if (c == 0x28) {            /* '(' */
01104                      filter->status += 3;
01105               } else {
01106                      filter->flag = 1;    /* bad */
01107                      filter->status &= ~0xf;
01108                      goto retry;
01109               }
01110               break;
01111 
01112        /* ESC $ */
01113        case 3:
01114               if (c == 0x40 || c == 0x42) {             /* '@' or 'B' */
01115                      filter->status = 0x80;
01116               } else {
01117                      filter->flag = 1;    /* bad */
01118                      filter->status &= ~0xf;
01119                      goto retry;
01120               }
01121               break;
01122 
01123        /* ESC ( */
01124        case 5:
01125               if (c == 0x42) {            /* 'B' */
01126                      filter->status = 0;
01127               } else if (c == 0x4a) {            /* 'J' */
01128                      filter->status = 0x10;
01129               } else {
01130                      filter->flag = 1;    /* bad */
01131                      filter->status &= ~0xf;
01132                      goto retry;
01133               }
01134               break;
01135 
01136        default:
01137               filter->status = 0;
01138               break;
01139        }
01140 
01141        return c;
01142 }
01143 
01144 static int mbfl_filt_ident_cp50221(int c, mbfl_identify_filter *filter)
01145 {
01146 retry:
01147        switch (filter->status & 0xf) {
01148 /*     case 0x00:     ASCII */
01149 /*     case 0x10:     X 0201 latin */
01150 /*     case 0x80:     X 0208 */
01151        case 0:
01152               if (c == 0x1b) {
01153                      filter->status += 2;
01154               } else if (filter->status == 0x80 && c > 0x20 && c < 0x7f) {          /* kanji first char */
01155                      filter->status += 1;
01156               } else if (c >= 0 && c < 0x80) {          /* latin, CTLs */
01157                      ;
01158               } else {
01159                      filter->flag = 1;    /* bad */
01160               }
01161               break;
01162 
01163 /*     case 0x81:     X 0208 second char */
01164        case 1:
01165               if (c == 0x1b) {
01166                      filter->status++;
01167               } else {
01168                      filter->status &= ~0xf;
01169                      if (c < 0x21 || c > 0x7e) {        /* bad */
01170                             filter->flag = 1;
01171                      }
01172               }
01173               break;
01174 
01175        /* ESC */
01176        case 2:
01177               if (c == 0x24) {            /* '$' */
01178                      filter->status++;
01179               } else if (c == 0x28) {            /* '(' */
01180                      filter->status += 3;
01181               } else {
01182                      filter->flag = 1;    /* bad */
01183                      filter->status &= ~0xf;
01184                      goto retry;
01185               }
01186               break;
01187 
01188        /* ESC $ */
01189        case 3:
01190               if (c == 0x40 || c == 0x42) {             /* '@' or 'B' */
01191                      filter->status = 0x80;
01192               } else {
01193                      filter->flag = 1;    /* bad */
01194                      filter->status &= ~0xf;
01195                      goto retry;
01196               }
01197               break;
01198 
01199        /* ESC ( */
01200        case 5:
01201               if (c == 0x42) {            /* 'B' */
01202                      filter->status = 0;
01203               } else if (c == 0x4a) {            /* 'J' */
01204                      filter->status = 0x10;
01205               } else if (c == 0x49) {            /* 'I' */
01206                      filter->status = 0x20;
01207               } else {
01208                      filter->flag = 1;    /* bad */
01209                      filter->status &= ~0xf;
01210                      goto retry;
01211               }
01212               break;
01213 
01214        default:
01215               filter->status = 0;
01216               break;
01217        }
01218 
01219        return c;
01220 }
01221 
01222 static int mbfl_filt_ident_cp50222(int c, mbfl_identify_filter *filter)
01223 {
01224 retry:
01225        switch (filter->status & 0xf) {
01226 /*     case 0x00:     ASCII */
01227 /*     case 0x10:     X 0201 latin */
01228 /*     case 0x80:     X 0208 */
01229        case 0:
01230               if (c == 0x1b) {
01231                      filter->status += 2;
01232               } else if (filter->status == 0x80 && c > 0x20 && c < 0x7f) {          /* kanji first char */
01233                      filter->status += 1;
01234               } else if (c >= 0 && c < 0x80) {          /* latin, CTLs */
01235                      ;
01236               } else {
01237                      filter->flag = 1;    /* bad */
01238               }
01239               break;
01240 
01241 /*     case 0x81:     X 0208 second char */
01242        case 1:
01243               if (c == 0x1b) {
01244                      filter->status++;
01245               } else {
01246                      filter->status &= ~0xf;
01247                      if (c < 0x21 || c > 0x7e) {        /* bad */
01248                             filter->flag = 1;
01249                      }
01250               }
01251               break;
01252 
01253        /* ESC */
01254        case 2:
01255               if (c == 0x24) {            /* '$' */
01256                      filter->status++;
01257               } else if (c == 0x28) {            /* '(' */
01258                      filter->status += 3;
01259               } else {
01260                      filter->flag = 1;    /* bad */
01261                      filter->status &= ~0xf;
01262                      goto retry;
01263               }
01264               break;
01265 
01266        /* ESC $ */
01267        case 3:
01268               if (c == 0x40 || c == 0x42) {             /* '@' or 'B' */
01269                      filter->status = 0x80;
01270               } else {
01271                      filter->flag = 1;    /* bad */
01272                      filter->status &= ~0xf;
01273                      goto retry;
01274               }
01275               break;
01276 
01277        /* ESC ( */
01278        case 5:
01279               if (c == 0x42) {            /* 'B' */
01280                      filter->status = 0;
01281               } else if (c == 0x4a) {            /* 'J' */
01282                      filter->status = 0x10;
01283               } else {
01284                      filter->flag = 1;    /* bad */
01285                      filter->status &= ~0xf;
01286                      goto retry;
01287               }
01288               break;
01289 
01290        default:
01291               filter->status = 0;
01292               break;
01293        }
01294 
01295        return c;
01296 }
01297 
01298 
01299