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 if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
567 CK(mbfl_filt_conv_illegal_output(c, filter));
568 }
569 }
570
571 return c;
572 }
573
574 /*
575 * wchar => CP50220
576 */
577 static void
mbfl_filt_conv_wchar_cp50220_ctor(mbfl_convert_filter * filt)578 mbfl_filt_conv_wchar_cp50220_ctor(mbfl_convert_filter *filt)
579 {
580 mbfl_filt_conv_wchar_cp50220_ctx *ctx;
581
582 mbfl_filt_conv_common_ctor(filt);
583
584 ctx = mbfl_malloc(sizeof(mbfl_filt_conv_wchar_cp50220_ctx));
585 if (ctx == NULL) {
586 mbfl_filt_conv_common_dtor(filt);
587 return;
588 }
589
590 ctx->tl_param.mode = MBFL_FILT_TL_HAN2ZEN_KATAKANA | MBFL_FILT_TL_HAN2ZEN_GLUE;
591
592 ctx->last = *filt;
593 ctx->last.opaque = ctx;
594 ctx->last.data = filt->data;
595 filt->filter_function = vtbl_tl_jisx0201_jisx0208.filter_function;
596 filt->filter_flush = vtbl_tl_jisx0201_jisx0208.filter_flush;
597 filt->output_function = (int(*)(int, void *))ctx->last.filter_function;
598 filt->flush_function = (int(*)(void *))ctx->last.filter_flush;
599 filt->data = &ctx->last;
600 filt->opaque = ctx;
601 vtbl_tl_jisx0201_jisx0208.filter_ctor(filt);
602 }
603
604 static void
mbfl_filt_conv_wchar_cp50220_copy(mbfl_convert_filter * src,mbfl_convert_filter * dest)605 mbfl_filt_conv_wchar_cp50220_copy(mbfl_convert_filter *src, mbfl_convert_filter *dest)
606 {
607 mbfl_filt_conv_wchar_cp50220_ctx *ctx;
608
609 *dest = *src;
610 ctx = mbfl_malloc(sizeof(mbfl_filt_conv_wchar_cp50220_ctx));
611 if (ctx != NULL) {
612 *ctx = *(mbfl_filt_conv_wchar_cp50220_ctx*)src->opaque;
613 }
614
615 dest->opaque = ctx;
616 dest->data = &ctx->last;
617 }
618
619 static void
mbfl_filt_conv_wchar_cp50220_dtor(mbfl_convert_filter * filt)620 mbfl_filt_conv_wchar_cp50220_dtor(mbfl_convert_filter *filt)
621 {
622 vtbl_tl_jisx0201_jisx0208.filter_dtor(filt);
623
624 if (filt->opaque != NULL) {
625 mbfl_free(filt->opaque);
626 }
627
628 mbfl_filt_conv_common_dtor(filt);
629 }
630
631 /*
632 * wchar => cp50220raw
633 */
634 int
mbfl_filt_conv_wchar_cp50220raw(int c,mbfl_convert_filter * filter)635 mbfl_filt_conv_wchar_cp50220raw(int c, mbfl_convert_filter *filter)
636 {
637 if (c & MBFL_WCSPLANE_JIS0208) {
638 const int s = c & MBFL_WCSPLANE_MASK;
639
640 if ((filter->status & 0xff00) != 0x200) {
641 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
642 CK((*filter->output_function)(0x24, filter->data)); /* '$' */
643 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
644 filter->status = 0x200;
645 }
646 CK((*filter->output_function)((s >> 8) & 0x7f, filter->data));
647 CK((*filter->output_function)(s & 0x7f, filter->data));
648 return c;
649 } else {
650 return mbfl_filt_conv_wchar_cp50221(c, filter);
651 }
652 }
653
654 /*
655 * wchar => CP50221
656 */
657 int
mbfl_filt_conv_wchar_cp50221(int c,mbfl_convert_filter * filter)658 mbfl_filt_conv_wchar_cp50221(int c, mbfl_convert_filter *filter)
659 {
660 int s = 0;
661
662 if (c >= ucs_a1_jis_table_min && c < ucs_a1_jis_table_max) {
663 s = ucs_a1_jis_table[c - ucs_a1_jis_table_min];
664 } else if (c >= ucs_a2_jis_table_min && c < ucs_a2_jis_table_max) {
665 s = ucs_a2_jis_table[c - ucs_a2_jis_table_min];
666 } else if (c >= ucs_i_jis_table_min && c < ucs_i_jis_table_max) {
667 s = ucs_i_jis_table[c - ucs_i_jis_table_min];
668 } else if (c >= ucs_r_jis_table_min && c < ucs_r_jis_table_max) {
669 s = ucs_r_jis_table[c - ucs_r_jis_table_min];
670 } else if (c >= 0xe000 && c < (0xe000 + 10 * 94)) {
671 /* PUE => Microsoft extended */
672 /* See http://www.opengroup.or.jp/jvc/cde/ucs-conv.html#ch4_2 */
673 s = c - 0xe000;
674 s = (s / 94 + 0x75) << 8 | (s % 94 + 0x21);
675 } else if (c >= (0xe000 + 10 * 94) && c <= (0xe000 + 20 * 94)) {
676 /* PUE => JISX0212 user-defined (G3 85ku - 94ku) */
677 /* See http://www.opengroup.or.jp/jvc/cde/ucs-conv.html#ch4_2 */
678 s = c - (0xe000 + 10 * 94);
679 s = (s / 94 + 0xf5) << 8 | (s % 94 + 0xa1);
680 }
681
682 if (s <= 0) {
683 if (c == 0xa5) { /* YEN SIGN */
684 s = 0x1005c;
685 } else if (c == 0x203e) { /* OVER LINE */
686 s = 0x1007e;
687 } else if (c == 0xff3c) { /* FULLWIDTH REVERSE SOLIDUS */
688 s = 0x2140;
689 } else if (c == 0xff5e) { /* FULLWIDTH TILDE */
690 s = 0x2141;
691 } else if (c == 0x2225) { /* PARALLEL TO */
692 s = 0x2142;
693 } else if (c == 0xff0d) { /* FULLWIDTH HYPHEN-MINUS */
694 s = 0x215d;
695 } else if (c == 0xffe0) { /* FULLWIDTH CENT SIGN */
696 s = 0x2171;
697 } else if (c == 0xffe1) { /* FULLWIDTH POUND SIGN */
698 s = 0x2172;
699 } else if (c == 0xffe2) { /* FULLWIDTH NOT SIGN */
700 s = 0x224c;
701 }
702 }
703 if (s <= 0 || (s >= 0x8080 && s < 0x10000)) {
704 int i;
705 s = -1;
706
707 for (i = 0;
708 i < cp932ext1_ucs_table_max - cp932ext1_ucs_table_min;
709 i++) {
710 const int oh = cp932ext1_ucs_table_min / 94;
711
712 if (c == cp932ext1_ucs_table[i]) {
713 s = ((i / 94 + oh + 0x21) << 8) + (i % 94 + 0x21);
714 break;
715 }
716 }
717
718 if (s < 0) {
719 const int oh = cp932ext2_ucs_table_min / 94;
720 const int cp932ext2_ucs_table_size =
721 cp932ext2_ucs_table_max - cp932ext2_ucs_table_min;
722 for (i = 0; i < cp932ext2_ucs_table_size; i++) {
723 if (c == cp932ext2_ucs_table[i]) {
724 s = ((i / 94 + oh + 0x21) << 8) + (i % 94 + 0x21);
725 break;
726 }
727 }
728 }
729
730 if (s < 0) {
731 const int cp932ext3_ucs_table_size =
732 cp932ext3_ucs_table_max - cp932ext3_ucs_table_min;
733 const int limit = cp932ext3_ucs_table_size >
734 cp932ext3_eucjp_table_size ?
735 cp932ext3_eucjp_table_size:
736 cp932ext3_ucs_table_size;
737 for (i = 0; i < limit; i++) {
738 if (c == cp932ext3_ucs_table[i]) {
739 s = cp932ext3_eucjp_table[i];
740 break;
741 }
742 }
743 }
744
745 if (c == 0) {
746 s = 0;
747 } else if (s <= 0) {
748 s = -1;
749 }
750 }
751
752 if (s >= 0) {
753 if (s < 0x80) { /* ASCII */
754 if ((filter->status & 0xff00) != 0) {
755 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
756 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
757 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
758 filter->status = 0;
759 }
760 CK((*filter->output_function)(s, filter->data));
761 } else if (s >= 0xa0 && s < 0xe0) { /* X 0201 kana */
762 if ((filter->status & 0xff00) != 0x500) {
763 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
764 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
765 CK((*filter->output_function)(0x49, filter->data)); /* 'I' */
766 filter->status = 0x500;
767 }
768 CK((*filter->output_function)(s - 0x80, filter->data));
769 } else if (s < 0x8080) { /* X 0208 */
770 if ((filter->status & 0xff00) != 0x200) {
771 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
772 CK((*filter->output_function)(0x24, filter->data)); /* '$' */
773 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
774 filter->status = 0x200;
775 }
776 CK((*filter->output_function)((s >> 8) & 0x7f, filter->data));
777 CK((*filter->output_function)(s & 0x7f, filter->data));
778 } else if (s < 0x10000) { /* X0212 */
779 if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
780 CK(mbfl_filt_conv_illegal_output(c, filter));
781 }
782 } else { /* X 0201 latin */
783 if ((filter->status & 0xff00) != 0x400) {
784 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
785 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
786 CK((*filter->output_function)(0x4a, filter->data)); /* 'J' */
787 }
788 filter->status = 0x400;
789 CK((*filter->output_function)(s & 0x7f, filter->data));
790 }
791 } else {
792 if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
793 CK(mbfl_filt_conv_illegal_output(c, filter));
794 }
795 }
796
797 return c;
798 }
799
800 /*
801 * wchar => CP50222
802 */
803 int
mbfl_filt_conv_wchar_cp50222(int c,mbfl_convert_filter * filter)804 mbfl_filt_conv_wchar_cp50222(int c, mbfl_convert_filter *filter)
805 {
806 int s;
807
808 s = 0;
809
810 if (c >= ucs_a1_jis_table_min && c < ucs_a1_jis_table_max) {
811 s = ucs_a1_jis_table[c - ucs_a1_jis_table_min];
812 } else if (c >= ucs_a2_jis_table_min && c < ucs_a2_jis_table_max) {
813 s = ucs_a2_jis_table[c - ucs_a2_jis_table_min];
814 } else if (c >= ucs_i_jis_table_min && c < ucs_i_jis_table_max) {
815 s = ucs_i_jis_table[c - ucs_i_jis_table_min];
816 } else if (c >= ucs_r_jis_table_min && c < ucs_r_jis_table_max) {
817 s = ucs_r_jis_table[c - ucs_r_jis_table_min];
818 } else if (c >= 0xe000 && c < (0xe000 + 10 * 94)) {
819 /* PUE => Microsoft extended */
820 /* See http://www.opengroup.or.jp/jvc/cde/ucs-conv.html#ch4_2 */
821 s = c - 0xe000;
822 s = (s / 94 + 0x75) << 8 | (s % 94 + 0x21);
823 } else if (c >= (0xe000 + 10 * 94) && c <= (0xe000 + 20 * 94)) {
824 /* PUE => JISX0212 user-defined (G3 85ku - 94ku) */
825 /* See http://www.opengroup.or.jp/jvc/cde/ucs-conv.html#ch4_2 */
826 s = c - (0xe000 + 10 * 94);
827 s = (s / 94 + 0xf5) << 8 | (s % 94 + 0xa1);
828 }
829
830 if (s <= 0) {
831 if (c == 0xa5) { /* YEN SIGN */
832 s = 0x1005c;
833 } else if (c == 0x203e) { /* OVER LINE */
834 s = 0x1007e;
835 } else if (c == 0xff3c) { /* FULLWIDTH REVERSE SOLIDUS */
836 s = 0x2140;
837 } else if (c == 0xff5e) { /* FULLWIDTH TILDE */
838 s = 0x2141;
839 } else if (c == 0x2225) { /* PARALLEL TO */
840 s = 0x2142;
841 } else if (c == 0xff0d) { /* FULLWIDTH HYPHEN-MINUS */
842 s = 0x215d;
843 } else if (c == 0xffe0) { /* FULLWIDTH CENT SIGN */
844 s = 0x2171;
845 } else if (c == 0xffe1) { /* FULLWIDTH POUND SIGN */
846 s = 0x2172;
847 } else if (c == 0xffe2) { /* FULLWIDTH NOT SIGN */
848 s = 0x224c;
849 }
850 }
851 if (s <= 0 || (s >= 0x8080 && s < 0x10000)) {
852 int i;
853 s = -1;
854
855 for (i = 0;
856 i < cp932ext1_ucs_table_max - cp932ext1_ucs_table_min; i++) {
857 const int oh = cp932ext1_ucs_table_min / 94;
858
859 if (c == cp932ext1_ucs_table[i]) {
860 s = ((i / 94 + oh + 0x21) << 8) + (i % 94 + 0x21);
861 break;
862 }
863 }
864
865 if (s <= 0) {
866 const int oh = cp932ext2_ucs_table_min / 94;
867 const int cp932ext2_ucs_table_size =
868 cp932ext2_ucs_table_max - cp932ext2_ucs_table_min;
869 for (i = 0; i < cp932ext2_ucs_table_size; i++) {
870 if (c == cp932ext2_ucs_table[i]) {
871 s = ((i / 94 + oh + 0x21) << 8) + (i % 94 + 0x21);
872 break;
873 }
874 }
875 }
876
877 if (s <= 0) {
878 const int cp932ext3_ucs_table_size =
879 cp932ext3_ucs_table_max - cp932ext3_ucs_table_min;
880 const int limit = cp932ext3_ucs_table_size >
881 cp932ext3_eucjp_table_size ?
882 cp932ext3_eucjp_table_size:
883 cp932ext3_ucs_table_size;
884 for (i = 0; i < limit; i++) {
885 if (c == cp932ext3_ucs_table[i]) {
886 s = cp932ext3_eucjp_table[i];
887 break;
888 }
889 }
890 }
891
892 if (c == 0) {
893 s = 0;
894 } else if (s <= 0) {
895 s = -1;
896 }
897 }
898
899 if (s >= 0) {
900 if (s < 0x80) { /* ASCII */
901 if ((filter->status & 0xff00) == 0x500) {
902 CK((*filter->output_function)(0x0f, filter->data)); /* SO */
903 filter->status = 0;
904 } else if ((filter->status & 0xff00) != 0) {
905 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
906 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
907 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
908 filter->status = 0;
909 }
910 CK((*filter->output_function)(s, filter->data));
911 } else if (s >= 0xa0 && s < 0xe0) { /* X 0201 kana */
912 if ((filter->status & 0xff00) != 0x500) {
913 CK((*filter->output_function)(0x0e, filter->data)); /* SI */
914 filter->status = 0x500;
915 }
916 CK((*filter->output_function)(s - 0x80, filter->data));
917 } else if (s < 0x8080) { /* X 0208 */
918 if ((filter->status & 0xff00) == 0x500) {
919 CK((*filter->output_function)(0x0f, filter->data)); /* SO */
920 filter->status = 0;
921 }
922 if ((filter->status & 0xff00) != 0x200) {
923 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
924 CK((*filter->output_function)(0x24, filter->data)); /* '$' */
925 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
926 filter->status = 0x200;
927 }
928 CK((*filter->output_function)((s >> 8) & 0x7f, filter->data));
929 CK((*filter->output_function)(s & 0x7f, filter->data));
930 } else if (s < 0x10000) { /* X0212 */
931 if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
932 CK(mbfl_filt_conv_illegal_output(c, filter));
933 }
934 } else { /* X 0201 latin */
935 if ((filter->status & 0xff00) == 0x500) {
936 CK((*filter->output_function)(0x0f, filter->data)); /* SO */
937 filter->status = 0;
938 }
939 if ((filter->status & 0xff00) != 0x400) {
940 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
941 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
942 CK((*filter->output_function)(0x4a, filter->data)); /* 'J' */
943 }
944 filter->status = 0x400;
945 CK((*filter->output_function)(s & 0x7f, filter->data));
946 }
947 } else {
948 if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
949 CK(mbfl_filt_conv_illegal_output(c, filter));
950 }
951 }
952
953 return c;
954 }
955
956 int
mbfl_filt_conv_wchar_cp50222_flush(mbfl_convert_filter * filter)957 mbfl_filt_conv_wchar_cp50222_flush(mbfl_convert_filter *filter)
958 {
959 /* back to latin */
960 if ((filter->status & 0xff00) == 0x500) {
961 CK((*filter->output_function)(0x0f, filter->data)); /* SO */
962 } else if ((filter->status & 0xff00) != 0) {
963 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
964 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
965 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
966 }
967 filter->status &= 0xff;
968
969 if (filter->flush_function != NULL) {
970 return (*filter->flush_function)(filter->data);
971 }
972
973 return 0;
974 }
975
976
mbfl_filt_ident_jis_ms(int c,mbfl_identify_filter * filter)977 static int mbfl_filt_ident_jis_ms(int c, mbfl_identify_filter *filter)
978 {
979 retry:
980 switch (filter->status & 0xf) {
981 /* case 0x00: ASCII */
982 /* case 0x10: X 0201 latin */
983 /* case 0x20: X 0201 kana */
984 /* case 0x80: X 0208 */
985 /* case 0x90: X 0212 */
986 case 0:
987 if (c == 0x1b) {
988 filter->status += 2;
989 } else if (c == 0x0e) { /* "kana in" */
990 filter->status = 0x20;
991 } else if (c == 0x0f) { /* "kana out" */
992 filter->status = 0;
993 } else if ((filter->status == 0x80 || filter->status == 0x90) && c > 0x20 && c < 0x7f) { /* kanji first char */
994 filter->status += 1;
995 } else if (c >= 0 && c < 0x80) { /* latin, CTLs */
996 ;
997 } else {
998 filter->flag = 1; /* bad */
999 }
1000 break;
1001
1002 /* case 0x81: X 0208 second char */
1003 /* case 0x91: X 0212 second char */
1004 case 1:
1005 filter->status &= ~0xf;
1006 if (c == 0x1b) {
1007 goto retry;
1008 } else if (c < 0x21 || c > 0x7e) { /* bad */
1009 filter->flag = 1;
1010 }
1011 break;
1012
1013 /* ESC */
1014 case 2:
1015 if (c == 0x24) { /* '$' */
1016 filter->status++;
1017 } else if (c == 0x28) { /* '(' */
1018 filter->status += 3;
1019 } else {
1020 filter->flag = 1; /* bad */
1021 filter->status &= ~0xf;
1022 goto retry;
1023 }
1024 break;
1025
1026 /* ESC $ */
1027 case 3:
1028 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */
1029 filter->status = 0x80;
1030 } else if (c == 0x28) { /* '(' */
1031 filter->status++;
1032 } else {
1033 filter->flag = 1; /* bad */
1034 filter->status &= ~0xf;
1035 goto retry;
1036 }
1037 break;
1038
1039 /* ESC $ ( */
1040 case 4:
1041 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */
1042 filter->status = 0x80;
1043 } else if (c == 0x44) { /* 'D' */
1044 filter->status = 0x90;
1045 } else {
1046 filter->flag = 1; /* bad */
1047 filter->status &= ~0xf;
1048 goto retry;
1049 }
1050 break;
1051
1052 /* ESC ( */
1053 case 5:
1054 if (c == 0x42 || c == 0x48) { /* 'B' or 'H' */
1055 filter->status = 0;
1056 } else if (c == 0x4a) { /* 'J' */
1057 filter->status = 0x10;
1058 } else if (c == 0x49) { /* 'I' */
1059 filter->status = 0x20;
1060 } else {
1061 filter->flag = 1; /* bad */
1062 filter->status &= ~0xf;
1063 goto retry;
1064 }
1065 break;
1066
1067 default:
1068 filter->status = 0;
1069 break;
1070 }
1071
1072 return c;
1073 }
1074
mbfl_filt_ident_cp50220(int c,mbfl_identify_filter * filter)1075 static int mbfl_filt_ident_cp50220(int c, mbfl_identify_filter *filter)
1076 {
1077 retry:
1078 switch (filter->status & 0xf) {
1079 /* case 0x00: ASCII */
1080 /* case 0x10: X 0201 latin */
1081 /* case 0x80: X 0208 */
1082 case 0:
1083 if (c == 0x1b) {
1084 filter->status += 2;
1085 } else if (filter->status == 0x80 && c > 0x20 && c < 0x7f) { /* kanji first char */
1086 filter->status += 1;
1087 } else if (c >= 0 && c < 0x80) { /* latin, CTLs */
1088 ;
1089 } else {
1090 filter->flag = 1; /* bad */
1091 }
1092 break;
1093
1094 /* case 0x81: X 0208 second char */
1095 case 1:
1096 if (c == 0x1b) {
1097 filter->status++;
1098 } else {
1099 filter->status &= ~0xf;
1100 if (c < 0x21 || c > 0x7e) { /* bad */
1101 filter->flag = 1;
1102 }
1103 }
1104 break;
1105
1106 /* ESC */
1107 case 2:
1108 if (c == 0x24) { /* '$' */
1109 filter->status++;
1110 } else if (c == 0x28) { /* '(' */
1111 filter->status += 3;
1112 } else {
1113 filter->flag = 1; /* bad */
1114 filter->status &= ~0xf;
1115 goto retry;
1116 }
1117 break;
1118
1119 /* ESC $ */
1120 case 3:
1121 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */
1122 filter->status = 0x80;
1123 } else {
1124 filter->flag = 1; /* bad */
1125 filter->status &= ~0xf;
1126 goto retry;
1127 }
1128 break;
1129
1130 /* ESC ( */
1131 case 5:
1132 if (c == 0x42) { /* 'B' */
1133 filter->status = 0;
1134 } else if (c == 0x4a) { /* 'J' */
1135 filter->status = 0x10;
1136 } else {
1137 filter->flag = 1; /* bad */
1138 filter->status &= ~0xf;
1139 goto retry;
1140 }
1141 break;
1142
1143 default:
1144 filter->status = 0;
1145 break;
1146 }
1147
1148 return c;
1149 }
1150
mbfl_filt_ident_cp50221(int c,mbfl_identify_filter * filter)1151 static int mbfl_filt_ident_cp50221(int c, mbfl_identify_filter *filter)
1152 {
1153 retry:
1154 switch (filter->status & 0xf) {
1155 /* case 0x00: ASCII */
1156 /* case 0x10: X 0201 latin */
1157 /* case 0x80: X 0208 */
1158 case 0:
1159 if (c == 0x1b) {
1160 filter->status += 2;
1161 } else if (filter->status == 0x80 && c > 0x20 && c < 0x7f) { /* kanji first char */
1162 filter->status += 1;
1163 } else if (c >= 0 && c < 0x80) { /* latin, CTLs */
1164 ;
1165 } else {
1166 filter->flag = 1; /* bad */
1167 }
1168 break;
1169
1170 /* case 0x81: X 0208 second char */
1171 case 1:
1172 if (c == 0x1b) {
1173 filter->status++;
1174 } else {
1175 filter->status &= ~0xf;
1176 if (c < 0x21 || c > 0x7e) { /* bad */
1177 filter->flag = 1;
1178 }
1179 }
1180 break;
1181
1182 /* ESC */
1183 case 2:
1184 if (c == 0x24) { /* '$' */
1185 filter->status++;
1186 } else if (c == 0x28) { /* '(' */
1187 filter->status += 3;
1188 } else {
1189 filter->flag = 1; /* bad */
1190 filter->status &= ~0xf;
1191 goto retry;
1192 }
1193 break;
1194
1195 /* ESC $ */
1196 case 3:
1197 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */
1198 filter->status = 0x80;
1199 } else {
1200 filter->flag = 1; /* bad */
1201 filter->status &= ~0xf;
1202 goto retry;
1203 }
1204 break;
1205
1206 /* ESC ( */
1207 case 5:
1208 if (c == 0x42) { /* 'B' */
1209 filter->status = 0;
1210 } else if (c == 0x4a) { /* 'J' */
1211 filter->status = 0x10;
1212 } else if (c == 0x49) { /* 'I' */
1213 filter->status = 0x20;
1214 } else {
1215 filter->flag = 1; /* bad */
1216 filter->status &= ~0xf;
1217 goto retry;
1218 }
1219 break;
1220
1221 default:
1222 filter->status = 0;
1223 break;
1224 }
1225
1226 return c;
1227 }
1228
mbfl_filt_ident_cp50222(int c,mbfl_identify_filter * filter)1229 static int mbfl_filt_ident_cp50222(int c, mbfl_identify_filter *filter)
1230 {
1231 retry:
1232 switch (filter->status & 0xf) {
1233 /* case 0x00: ASCII */
1234 /* case 0x10: X 0201 latin */
1235 /* case 0x80: X 0208 */
1236 case 0:
1237 if (c == 0x1b) {
1238 filter->status += 2;
1239 } else if (filter->status == 0x80 && c > 0x20 && c < 0x7f) { /* kanji first char */
1240 filter->status += 1;
1241 } else if (c >= 0 && c < 0x80) { /* latin, CTLs */
1242 ;
1243 } else {
1244 filter->flag = 1; /* bad */
1245 }
1246 break;
1247
1248 /* case 0x81: X 0208 second char */
1249 case 1:
1250 if (c == 0x1b) {
1251 filter->status++;
1252 } else {
1253 filter->status &= ~0xf;
1254 if (c < 0x21 || c > 0x7e) { /* bad */
1255 filter->flag = 1;
1256 }
1257 }
1258 break;
1259
1260 /* ESC */
1261 case 2:
1262 if (c == 0x24) { /* '$' */
1263 filter->status++;
1264 } else if (c == 0x28) { /* '(' */
1265 filter->status += 3;
1266 } else {
1267 filter->flag = 1; /* bad */
1268 filter->status &= ~0xf;
1269 goto retry;
1270 }
1271 break;
1272
1273 /* ESC $ */
1274 case 3:
1275 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */
1276 filter->status = 0x80;
1277 } else {
1278 filter->flag = 1; /* bad */
1279 filter->status &= ~0xf;
1280 goto retry;
1281 }
1282 break;
1283
1284 /* ESC ( */
1285 case 5:
1286 if (c == 0x42) { /* 'B' */
1287 filter->status = 0;
1288 } else if (c == 0x4a) { /* 'J' */
1289 filter->status = 0x10;
1290 } else {
1291 filter->flag = 1; /* bad */
1292 filter->status &= ~0xf;
1293 goto retry;
1294 }
1295 break;
1296
1297 default:
1298 filter->status = 0;
1299 break;
1300 }
1301
1302 return c;
1303 }
1304