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:
22 *
23 */
24 /*
25 * The source code included in this files was separated from mbfilter_ja.c
26 * by moriyoshi koizumi <moriyoshi@php.net> on 4 dec 2002.
27 *
28 */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include "mbfilter.h"
35 #include "mbfilter_jis.h"
36
37 #include "unicode_table_cp932_ext.h"
38 #include "unicode_table_jis.h"
39
40 static int mbfl_filt_ident_jis(int c, mbfl_identify_filter *filter);
41 static int mbfl_filt_ident_2022jp(int c, mbfl_identify_filter *filter);
42
43 const mbfl_encoding mbfl_encoding_jis = {
44 mbfl_no_encoding_jis,
45 "JIS",
46 "ISO-2022-JP",
47 NULL,
48 NULL,
49 MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE | MBFL_ENCTYPE_GL_UNSAFE,
50 &vtbl_jis_wchar,
51 &vtbl_wchar_jis
52 };
53
54 const mbfl_encoding mbfl_encoding_2022jp = {
55 mbfl_no_encoding_2022jp,
56 "ISO-2022-JP",
57 "ISO-2022-JP",
58 NULL,
59 NULL,
60 MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE | MBFL_ENCTYPE_GL_UNSAFE,
61 &vtbl_2022jp_wchar,
62 &vtbl_wchar_2022jp
63 };
64
65 const struct mbfl_identify_vtbl vtbl_identify_jis = {
66 mbfl_no_encoding_jis,
67 mbfl_filt_ident_common_ctor,
68 mbfl_filt_ident_common_dtor,
69 mbfl_filt_ident_jis
70 };
71
72 const struct mbfl_identify_vtbl vtbl_identify_2022jp = {
73 mbfl_no_encoding_2022jp,
74 mbfl_filt_ident_common_ctor,
75 mbfl_filt_ident_common_dtor,
76 mbfl_filt_ident_2022jp
77 };
78
79 const struct mbfl_convert_vtbl vtbl_jis_wchar = {
80 mbfl_no_encoding_jis,
81 mbfl_no_encoding_wchar,
82 mbfl_filt_conv_common_ctor,
83 mbfl_filt_conv_common_dtor,
84 mbfl_filt_conv_jis_wchar,
85 mbfl_filt_conv_common_flush
86 };
87
88 const struct mbfl_convert_vtbl vtbl_wchar_jis = {
89 mbfl_no_encoding_wchar,
90 mbfl_no_encoding_jis,
91 mbfl_filt_conv_common_ctor,
92 mbfl_filt_conv_common_dtor,
93 mbfl_filt_conv_wchar_jis,
94 mbfl_filt_conv_any_jis_flush
95 };
96
97 const struct mbfl_convert_vtbl vtbl_2022jp_wchar = {
98 mbfl_no_encoding_2022jp,
99 mbfl_no_encoding_wchar,
100 mbfl_filt_conv_common_ctor,
101 mbfl_filt_conv_common_dtor,
102 mbfl_filt_conv_jis_wchar,
103 mbfl_filt_conv_common_flush
104 };
105
106 const struct mbfl_convert_vtbl vtbl_wchar_2022jp = {
107 mbfl_no_encoding_wchar,
108 mbfl_no_encoding_2022jp,
109 mbfl_filt_conv_common_ctor,
110 mbfl_filt_conv_common_dtor,
111 mbfl_filt_conv_wchar_2022jp,
112 mbfl_filt_conv_any_jis_flush
113 };
114
115 #define CK(statement) do { if ((statement) < 0) return (-1); } while (0)
116
117 /*
118 * JIS => wchar
119 */
120 int
mbfl_filt_conv_jis_wchar(int c,mbfl_convert_filter * filter)121 mbfl_filt_conv_jis_wchar(int c, mbfl_convert_filter *filter)
122 {
123 int c1, s, w;
124
125 retry:
126 switch (filter->status & 0xf) {
127 /* case 0x00: ASCII */
128 /* case 0x10: X 0201 latin */
129 /* case 0x20: X 0201 kana */
130 /* case 0x80: X 0208 */
131 /* case 0x90: X 0212 */
132 case 0:
133 if (c == 0x1b) {
134 filter->status += 2;
135 } else if (c == 0x0e) { /* "kana in" */
136 filter->status = 0x20;
137 } else if (c == 0x0f) { /* "kana out" */
138 filter->status = 0;
139 } else if (filter->status == 0x10 && c == 0x5c) { /* YEN SIGN */
140 CK((*filter->output_function)(0xa5, filter->data));
141 } else if (filter->status == 0x10 && c == 0x7e) { /* OVER LINE */
142 CK((*filter->output_function)(0x203e, filter->data));
143 } else if (filter->status == 0x20 && c > 0x20 && c < 0x60) { /* kana */
144 CK((*filter->output_function)(0xff40 + c, filter->data));
145 } else if ((filter->status == 0x80 || filter->status == 0x90) && c > 0x20 && c < 0x7f) { /* kanji first char */
146 filter->cache = c;
147 filter->status += 1;
148 } else if (c >= 0 && c < 0x80) { /* latin, CTLs */
149 CK((*filter->output_function)(c, filter->data));
150 } else if (c > 0xa0 && c < 0xe0) { /* GR kana */
151 CK((*filter->output_function)(0xfec0 + c, filter->data));
152 } else {
153 w = c & MBFL_WCSGROUP_MASK;
154 w |= MBFL_WCSGROUP_THROUGH;
155 CK((*filter->output_function)(w, filter->data));
156 }
157 break;
158
159 /* case 0x81: X 0208 second char */
160 /* case 0x91: X 0212 second char */
161 case 1:
162 filter->status &= ~0xf;
163 c1 = filter->cache;
164 if (c > 0x20 && c < 0x7f) {
165 s = (c1 - 0x21)*94 + c - 0x21;
166 if (filter->status == 0x80) {
167 if (s >= 0 && s < jisx0208_ucs_table_size) {
168 w = jisx0208_ucs_table[s];
169 } else {
170 w = 0;
171 }
172 if (w <= 0) {
173 w = (c1 << 8) | c;
174 w &= MBFL_WCSPLANE_MASK;
175 w |= MBFL_WCSPLANE_JIS0208;
176 }
177 } else {
178 if (s >= 0 && s < jisx0212_ucs_table_size) {
179 w = jisx0212_ucs_table[s];
180 } else {
181 w = 0;
182 }
183 if (w <= 0) {
184 w = (c1 << 8) | c;
185 w &= MBFL_WCSPLANE_MASK;
186 w |= MBFL_WCSPLANE_JIS0212;
187 }
188 }
189 CK((*filter->output_function)(w, filter->data));
190 } else if (c == 0x1b) {
191 filter->status += 2;
192 } else if ((c >= 0 && c < 0x21) || c == 0x7f) { /* CTLs */
193 CK((*filter->output_function)(c, filter->data));
194 } else {
195 w = (c1 << 8) | c;
196 w &= MBFL_WCSGROUP_MASK;
197 w |= MBFL_WCSGROUP_THROUGH;
198 CK((*filter->output_function)(w, filter->data));
199 }
200 break;
201
202 /* ESC */
203 /* case 0x02: */
204 /* case 0x12: */
205 /* case 0x22: */
206 /* case 0x82: */
207 /* case 0x92: */
208 case 2:
209 if (c == 0x24) { /* '$' */
210 filter->status++;
211 } else if (c == 0x28) { /* '(' */
212 filter->status += 3;
213 } else {
214 filter->status &= ~0xf;
215 CK((*filter->output_function)(0x1b, filter->data));
216 goto retry;
217 }
218 break;
219
220 /* ESC $ */
221 /* case 0x03: */
222 /* case 0x13: */
223 /* case 0x23: */
224 /* case 0x83: */
225 /* case 0x93: */
226 case 3:
227 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */
228 filter->status = 0x80;
229 } else if (c == 0x28) { /* '(' */
230 filter->status++;
231 } else {
232 filter->status &= ~0xf;
233 CK((*filter->output_function)(0x1b, filter->data));
234 CK((*filter->output_function)(0x24, filter->data));
235 goto retry;
236 }
237 break;
238
239 /* ESC $ ( */
240 /* case 0x04: */
241 /* case 0x14: */
242 /* case 0x24: */
243 /* case 0x84: */
244 /* case 0x94: */
245 case 4:
246 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */
247 filter->status = 0x80;
248 } else if (c == 0x44) { /* 'D' */
249 filter->status = 0x90;
250 } else {
251 filter->status &= ~0xf;
252 CK((*filter->output_function)(0x1b, filter->data));
253 CK((*filter->output_function)(0x24, filter->data));
254 CK((*filter->output_function)(0x28, filter->data));
255 goto retry;
256 }
257 break;
258
259 /* ESC ( */
260 /* case 0x05: */
261 /* case 0x15: */
262 /* case 0x25: */
263 /* case 0x85: */
264 /* case 0x95: */
265 case 5:
266 if (c == 0x42 || c == 0x48) { /* 'B' or 'H' */
267 filter->status = 0;
268 } else if (c == 0x4a) { /* 'J' */
269 filter->status = 0x10;
270 } else if (c == 0x49) { /* 'I' */
271 filter->status = 0x20;
272 } else {
273 filter->status &= ~0xf;
274 CK((*filter->output_function)(0x1b, filter->data));
275 CK((*filter->output_function)(0x28, filter->data));
276 goto retry;
277 }
278 break;
279
280 default:
281 filter->status = 0;
282 break;
283 }
284
285 return c;
286 }
287
288 /*
289 * wchar => JIS
290 */
291 int
mbfl_filt_conv_wchar_jis(int c,mbfl_convert_filter * filter)292 mbfl_filt_conv_wchar_jis(int c, mbfl_convert_filter *filter)
293 {
294 int c1, s;
295
296 s = 0;
297 if (c >= ucs_a1_jis_table_min && c < ucs_a1_jis_table_max) {
298 s = ucs_a1_jis_table[c - ucs_a1_jis_table_min];
299 } else if (c >= ucs_a2_jis_table_min && c < ucs_a2_jis_table_max) {
300 s = ucs_a2_jis_table[c - ucs_a2_jis_table_min];
301 } else if (c >= ucs_i_jis_table_min && c < ucs_i_jis_table_max) {
302 s = ucs_i_jis_table[c - ucs_i_jis_table_min];
303 } else if (c >= ucs_r_jis_table_min && c < ucs_r_jis_table_max) {
304 s = ucs_r_jis_table[c - ucs_r_jis_table_min];
305 }
306 if (s <= 0) {
307 c1 = c & ~MBFL_WCSPLANE_MASK;
308 if (c1 == MBFL_WCSPLANE_JIS0208) {
309 s = c & MBFL_WCSPLANE_MASK;
310 } else if (c1 == MBFL_WCSPLANE_JIS0212) {
311 s = c & MBFL_WCSPLANE_MASK;
312 s |= 0x8080;
313 } else if (c == 0xa5) { /* YEN SIGN */
314 s = 0x1005c;
315 } else if (c == 0x203e) { /* OVER LINE */
316 s = 0x1007e;
317 } else if (c == 0xff3c) { /* FULLWIDTH REVERSE SOLIDUS */
318 s = 0x2140;
319 } else if (c == 0xff5e) { /* FULLWIDTH TILDE */
320 s = 0x2141;
321 } else if (c == 0x2225) { /* PARALLEL TO */
322 s = 0x2142;
323 } else if (c == 0xff0d) { /* FULLWIDTH HYPHEN-MINUS */
324 s = 0x215d;
325 } else if (c == 0xffe0) { /* FULLWIDTH CENT SIGN */
326 s = 0x2171;
327 } else if (c == 0xffe1) { /* FULLWIDTH POUND SIGN */
328 s = 0x2172;
329 } else if (c == 0xffe2) { /* FULLWIDTH NOT SIGN */
330 s = 0x224c;
331 }
332 if (c == 0) {
333 s = 0;
334 } else if (s <= 0) {
335 s = -1;
336 }
337 }
338 if (s >= 0) {
339 if (s < 0x80) { /* ASCII */
340 if ((filter->status & 0xff00) != 0) {
341 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
342 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
343 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
344 }
345 filter->status = 0;
346 CK((*filter->output_function)(s, filter->data));
347 } else if (s < 0x100) { /* kana */
348 if ((filter->status & 0xff00) != 0x100) {
349 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
350 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
351 CK((*filter->output_function)(0x49, filter->data)); /* 'I' */
352 }
353 filter->status = 0x100;
354 CK((*filter->output_function)(s & 0x7f, filter->data));
355 } else if (s < 0x8080) { /* X 0208 */
356 if ((filter->status & 0xff00) != 0x200) {
357 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
358 CK((*filter->output_function)(0x24, filter->data)); /* '$' */
359 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
360 }
361 filter->status = 0x200;
362 CK((*filter->output_function)((s >> 8) & 0x7f, filter->data));
363 CK((*filter->output_function)(s & 0x7f, filter->data));
364 } else if (s < 0x10000) { /* X 0212 */
365 if ((filter->status & 0xff00) != 0x300) {
366 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
367 CK((*filter->output_function)(0x24, filter->data)); /* '$' */
368 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
369 CK((*filter->output_function)(0x44, filter->data)); /* 'D' */
370 }
371 filter->status = 0x300;
372 CK((*filter->output_function)((s >> 8) & 0x7f, filter->data));
373 CK((*filter->output_function)(s & 0x7f, filter->data));
374 } else { /* X 0201 latin */
375 if ((filter->status & 0xff00) != 0x400) {
376 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
377 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
378 CK((*filter->output_function)(0x4a, filter->data)); /* 'J' */
379 }
380 filter->status = 0x400;
381 CK((*filter->output_function)(s & 0x7f, filter->data));
382 }
383 } else {
384 CK(mbfl_filt_conv_illegal_output(c, filter));
385 }
386
387 return c;
388 }
389
390
391 /*
392 * wchar => ISO-2022-JP
393 */
394 int
mbfl_filt_conv_wchar_2022jp(int c,mbfl_convert_filter * filter)395 mbfl_filt_conv_wchar_2022jp(int c, mbfl_convert_filter *filter)
396 {
397 int s;
398
399 s = 0;
400 if (c >= ucs_a1_jis_table_min && c < ucs_a1_jis_table_max) {
401 s = ucs_a1_jis_table[c - ucs_a1_jis_table_min];
402 } else if (c >= ucs_a2_jis_table_min && c < ucs_a2_jis_table_max) {
403 s = ucs_a2_jis_table[c - ucs_a2_jis_table_min];
404 } else if (c >= ucs_i_jis_table_min && c < ucs_i_jis_table_max) {
405 s = ucs_i_jis_table[c - ucs_i_jis_table_min];
406 } else if (c >= ucs_r_jis_table_min && c < ucs_r_jis_table_max) {
407 s = ucs_r_jis_table[c - ucs_r_jis_table_min];
408 }
409 if (s <= 0) {
410 if (c == 0xa5) { /* YEN SIGN */
411 s = 0x1005c;
412 } else if (c == 0x203e) { /* OVER LINE */
413 s = 0x1007e;
414 } else if (c == 0xff3c) { /* FULLWIDTH REVERSE SOLIDUS */
415 s = 0x2140;
416 } else if (c == 0xff5e) { /* FULLWIDTH TILDE */
417 s = 0x2141;
418 } else if (c == 0x2225) { /* PARALLEL TO */
419 s = 0x2142;
420 } else if (c == 0xff0d) { /* FULLWIDTH HYPHEN-MINUS */
421 s = 0x215d;
422 } else if (c == 0xffe0) { /* FULLWIDTH CENT SIGN */
423 s = 0x2171;
424 } else if (c == 0xffe1) { /* FULLWIDTH POUND SIGN */
425 s = 0x2172;
426 } else if (c == 0xffe2) { /* FULLWIDTH NOT SIGN */
427 s = 0x224c;
428 }
429 if (c == 0) {
430 s = 0;
431 } else if (s <= 0) {
432 s = -1;
433 }
434 } else if ((s >= 0x80 && s < 0x2121) || (s > 0x8080)) {
435 s = -1;
436 }
437 if (s >= 0) {
438 if (s < 0x80) { /* ASCII */
439 if ((filter->status & 0xff00) != 0) {
440 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
441 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
442 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
443 }
444 filter->status = 0;
445 CK((*filter->output_function)(s, filter->data));
446 } else if (s < 0x10000) { /* X 0208 */
447 if ((filter->status & 0xff00) != 0x200) {
448 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
449 CK((*filter->output_function)(0x24, filter->data)); /* '$' */
450 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
451 }
452 filter->status = 0x200;
453 CK((*filter->output_function)((s >> 8) & 0x7f, filter->data));
454 CK((*filter->output_function)(s & 0x7f, filter->data));
455 } else { /* X 0201 latin */
456 if ((filter->status & 0xff00) != 0x400) {
457 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
458 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
459 CK((*filter->output_function)(0x4a, filter->data)); /* 'J' */
460 }
461 filter->status = 0x400;
462 CK((*filter->output_function)(s & 0x7f, filter->data));
463 }
464 } else {
465 CK(mbfl_filt_conv_illegal_output(c, filter));
466 }
467
468 return c;
469 }
470
471 int
mbfl_filt_conv_any_jis_flush(mbfl_convert_filter * filter)472 mbfl_filt_conv_any_jis_flush(mbfl_convert_filter *filter)
473 {
474 /* back to latin */
475 if ((filter->status & 0xff00) != 0) {
476 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
477 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
478 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
479 }
480 filter->status &= 0xff;
481
482 if (filter->flush_function != NULL) {
483 return (*filter->flush_function)(filter->data);
484 }
485
486 return 0;
487 }
488
mbfl_filt_ident_jis(int c,mbfl_identify_filter * filter)489 static int mbfl_filt_ident_jis(int c, mbfl_identify_filter *filter)
490 {
491 retry:
492 switch (filter->status & 0xf) {
493 /* case 0x00: ASCII */
494 /* case 0x10: X 0201 latin */
495 /* case 0x20: X 0201 kana */
496 /* case 0x80: X 0208 */
497 /* case 0x90: X 0212 */
498 case 0:
499 if (c == 0x1b) {
500 filter->status += 2;
501 } else if (c == 0x0e) { /* "kana in" */
502 filter->status = 0x20;
503 } else if (c == 0x0f) { /* "kana out" */
504 filter->status = 0;
505 } else if ((filter->status == 0x80 || filter->status == 0x90) && c > 0x20 && c < 0x7f) { /* kanji first char */
506 filter->status += 1;
507 } else if (c >= 0 && c < 0x80) { /* latin, CTLs */
508 ;
509 } else {
510 filter->flag = 1; /* bad */
511 }
512 break;
513
514 /* case 0x81: X 0208 second char */
515 /* case 0x91: X 0212 second char */
516 case 1:
517 filter->status &= ~0xf;
518 if (c == 0x1b) {
519 goto retry;
520 } else if (c < 0x21 || c > 0x7e) { /* bad */
521 filter->flag = 1;
522 }
523 break;
524
525 /* ESC */
526 case 2:
527 if (c == 0x24) { /* '$' */
528 filter->status++;
529 } else if (c == 0x28) { /* '(' */
530 filter->status += 3;
531 } else {
532 filter->flag = 1; /* bad */
533 filter->status &= ~0xf;
534 goto retry;
535 }
536 break;
537
538 /* ESC $ */
539 case 3:
540 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */
541 filter->status = 0x80;
542 } else if (c == 0x28) { /* '(' */
543 filter->status++;
544 } else {
545 filter->flag = 1; /* bad */
546 filter->status &= ~0xf;
547 goto retry;
548 }
549 break;
550
551 /* ESC $ ( */
552 case 4:
553 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */
554 filter->status = 0x80;
555 } else if (c == 0x44) { /* 'D' */
556 filter->status = 0x90;
557 } else {
558 filter->flag = 1; /* bad */
559 filter->status &= ~0xf;
560 goto retry;
561 }
562 break;
563
564 /* ESC ( */
565 case 5:
566 if (c == 0x42 || c == 0x48) { /* 'B' or 'H' */
567 filter->status = 0;
568 } else if (c == 0x4a) { /* 'J' */
569 filter->status = 0x10;
570 } else if (c == 0x49) { /* 'I' */
571 filter->status = 0x20;
572 } else {
573 filter->flag = 1; /* bad */
574 filter->status &= ~0xf;
575 goto retry;
576 }
577 break;
578
579 default:
580 filter->status = 0;
581 break;
582 }
583
584 return c;
585 }
586
mbfl_filt_ident_2022jp(int c,mbfl_identify_filter * filter)587 static int mbfl_filt_ident_2022jp(int c, mbfl_identify_filter *filter)
588 {
589 retry:
590 switch (filter->status & 0xf) {
591 /* case 0x00: ASCII */
592 /* case 0x10: X 0201 latin */
593 /* case 0x80: X 0208 */
594 case 0:
595 if (c == 0x1b) {
596 filter->status += 2;
597 } else if (filter->status == 0x80 && c > 0x20 && c < 0x7f) { /* kanji first char */
598 filter->status += 1;
599 } else if (c >= 0 && c < 0x80) { /* latin, CTLs */
600 ;
601 } else {
602 filter->flag = 1; /* bad */
603 }
604 break;
605
606 /* case 0x81: X 0208 second char */
607 case 1:
608 if (c == 0x1b) {
609 filter->status++;
610 } else {
611 filter->status &= ~0xf;
612 if (c < 0x21 || c > 0x7e) { /* bad */
613 filter->flag = 1;
614 }
615 }
616 break;
617
618 /* ESC */
619 case 2:
620 if (c == 0x24) { /* '$' */
621 filter->status++;
622 } else if (c == 0x28) { /* '(' */
623 filter->status += 3;
624 } else {
625 filter->flag = 1; /* bad */
626 filter->status &= ~0xf;
627 goto retry;
628 }
629 break;
630
631 /* ESC $ */
632 case 3:
633 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */
634 filter->status = 0x80;
635 } else {
636 filter->flag = 1; /* bad */
637 filter->status &= ~0xf;
638 goto retry;
639 }
640 break;
641
642 /* ESC ( */
643 case 5:
644 if (c == 0x42) { /* 'B' */
645 filter->status = 0;
646 } else if (c == 0x4a) { /* 'J' */
647 filter->status = 0x10;
648 } else {
649 filter->flag = 1; /* bad */
650 filter->status &= ~0xf;
651 goto retry;
652 }
653 break;
654
655 default:
656 filter->status = 0;
657 break;
658 }
659
660 return c;
661 }
662