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