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