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