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_sjis.c
26 * by rui hirokawa <hirokawa@php.net> on 15 aug 2011.
27 *
28 */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include "mbfilter.h"
35 #include "mbfilter_sjis_2004.h"
36
37 #include "unicode_table_jis2004.h"
38 #include "unicode_table_jis.h"
39
40 extern const unsigned char mblen_table_sjis[];
41
42 static int mbfl_filt_ident_sjis2004(int c, mbfl_identify_filter *filter);
43
44 extern int mbfl_filt_ident_sjis(int c, mbfl_identify_filter *filter);
45 extern int mbfl_bisec_srch(int w, const unsigned short *tbl, int n);
46 extern int mbfl_bisec_srch2(int w, const unsigned short tbl[], int n);
47
48 static const char *mbfl_encoding_sjis2004_aliases[] = {"SJIS2004","Shift_JIS-2004", NULL};
49
50 const mbfl_encoding mbfl_encoding_sjis2004 = {
51 mbfl_no_encoding_sjis2004,
52 "SJIS-2004",
53 "Shift_JIS",
54 (const char *(*)[])&mbfl_encoding_sjis2004_aliases,
55 mblen_table_sjis,
56 MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE
57 };
58
59 const struct mbfl_identify_vtbl vtbl_identify_sjis2004 = {
60 mbfl_no_encoding_sjis2004,
61 mbfl_filt_ident_common_ctor,
62 mbfl_filt_ident_common_dtor,
63 mbfl_filt_ident_sjis
64 };
65
66 const struct mbfl_convert_vtbl vtbl_sjis2004_wchar = {
67 mbfl_no_encoding_sjis2004,
68 mbfl_no_encoding_wchar,
69 mbfl_filt_conv_common_ctor,
70 mbfl_filt_conv_common_dtor,
71 mbfl_filt_conv_jis2004_wchar,
72 mbfl_filt_conv_common_flush
73 };
74
75 const struct mbfl_convert_vtbl vtbl_wchar_sjis2004 = {
76 mbfl_no_encoding_wchar,
77 mbfl_no_encoding_sjis2004,
78 mbfl_filt_conv_common_ctor,
79 mbfl_filt_conv_common_dtor,
80 mbfl_filt_conv_wchar_jis2004,
81 mbfl_filt_conv_jis2004_flush
82 };
83
84 #define CK(statement) do { if ((statement) < 0) return (-1); } while (0)
85
86 #define SJIS_ENCODE(c1,c2,s1,s2) \
87 do { \
88 s1 = c1; \
89 s1--; \
90 s1 >>= 1; \
91 if ((c1) < 0x5f) { \
92 s1 += 0x71; \
93 } else { \
94 s1 += 0xb1; \
95 } \
96 s2 = c2; \
97 if ((c1) & 1) { \
98 if ((c2) < 0x60) { \
99 s2--; \
100 } \
101 s2 += 0x20; \
102 } else { \
103 s2 += 0x7e; \
104 } \
105 } while (0)
106
107 #define SJIS_DECODE(c1,c2,s1,s2) \
108 do { \
109 s1 = c1; \
110 if (s1 < 0xa0) { \
111 s1 -= 0x81; \
112 } else { \
113 s1 -= 0xc1; \
114 } \
115 s1 <<= 1; \
116 s1 += 0x21; \
117 s2 = c2; \
118 if (s2 < 0x9f) { \
119 if (s2 < 0x7f) { \
120 s2++; \
121 } \
122 s2 -= 0x20; \
123 } else { \
124 s1++; \
125 s2 -= 0x7e; \
126 } \
127 } while (0)
128
129
130 /*
131 * JIS-2004 => wchar
132 */
133 int
mbfl_filt_conv_jis2004_wchar(int c,mbfl_convert_filter * filter)134 mbfl_filt_conv_jis2004_wchar(int c, mbfl_convert_filter *filter)
135 {
136 int k;
137 int c1, c2, s, s1 = 0, s2 = 0, w = 0, w1;
138
139 retry:
140 switch (filter->status & 0xf) {
141 case 0:
142 if (c >= 0 && c < 0x80) { /* latin */
143 if (filter->from->no_encoding == mbfl_no_encoding_eucjp2004) {
144 CK((*filter->output_function)(c, filter->data));
145 } else if (filter->from->no_encoding == mbfl_no_encoding_sjis2004) {
146 if (c == 0x5c) {
147 CK((*filter->output_function)(0x00a5, filter->data));
148 } else if (c == 0x7e) {
149 CK((*filter->output_function)(0x203e, filter->data));
150 } else {
151 CK((*filter->output_function)(c, filter->data));
152 }
153 } else { /* ISO-2022-JP-2004 */
154 if (c == 0x1b) {
155 filter->status += 6;
156 } else if ((filter->status == 0x80 || filter->status == 0x90 || filter->status == 0xa0)
157 && c > 0x20 && c < 0x7f) { /* kanji first char */
158 filter->cache = c;
159 if (filter->status == 0x90) {
160 filter->status += 1; /* JIS X 0213 plane 1 */
161 } else if (filter->status == 0xa0) {
162 filter->status += 4; /* JIS X 0213 plane 2 */
163 } else {
164 filter->status += 5; /* JIS X 0208 */
165 }
166 } else {
167 CK((*filter->output_function)(c, filter->data));
168 }
169 }
170 } else {
171 if (filter->from->no_encoding == mbfl_no_encoding_eucjp2004) {
172 if (c > 0xa0 && c < 0xff) { /* X 0213 plane 1 first char */
173 filter->status = 1;
174 filter->cache = c;
175 } else if (c == 0x8e) { /* kana first char */
176 filter->status = 2;
177 } else if (c == 0x8f) { /* X 0213 plane 2 first char */
178 filter->status = 3;
179 } else {
180 w = c & MBFL_WCSGROUP_MASK;
181 w |= MBFL_WCSGROUP_THROUGH;
182 CK((*filter->output_function)(w, filter->data));
183 }
184 } else if (filter->from->no_encoding == mbfl_no_encoding_sjis2004) {
185 if (c > 0xa0 && c < 0xe0) { /* kana */
186 CK((*filter->output_function)(0xfec0 + c, filter->data));
187 } else if (c > 0x80 && c < 0xfd && c != 0xa0) { /* kanji first char */
188 filter->status = 1;
189 filter->cache = c;
190 } else {
191 w = c & MBFL_WCSGROUP_MASK;
192 w |= MBFL_WCSGROUP_THROUGH;
193 CK((*filter->output_function)(w, filter->data));
194 }
195 } else {
196 w = c & MBFL_WCSGROUP_MASK;
197 w |= MBFL_WCSGROUP_THROUGH;
198 CK((*filter->output_function)(w, filter->data));
199 }
200 }
201 break;
202
203 case 1: /* kanji second char */
204 filter->status &= ~0xf;
205 c1 = filter->cache;
206
207 if (filter->from->no_encoding == mbfl_no_encoding_eucjp2004) {
208 if (c > 0xa0 && c < 0xff) {
209 s1 = c1 - 0x80;
210 s2 = c - 0x80;
211 }
212 } else if (filter->from->no_encoding == mbfl_no_encoding_sjis2004) {
213 if (c >= 0x40 && c <= 0xfc && c != 0x7f) {
214 SJIS_DECODE(c1, c, s1, s2);
215 }
216 } else {
217 s1 = c1;
218 s2 = c;
219 }
220 w1 = (s1 << 8) | s2;
221
222 if (w1 >= 0x2121) {
223 /* conversion for combining characters */
224 if ((w1 >= 0x2477 && w1 <= 0x2479) || (w1 >= 0x2479 && w1 <= 0x247B) ||
225 (w1 >= 0x2577 && w1 <= 0x257E) || w1 == 0x2678 || w1 == 0x2B44 ||
226 (w1 >= 0x2B48 && w1 <= 0x2B4F) || (w1 >= 0x2B65 && w1 <= 0x2B66)) {
227 k = mbfl_bisec_srch2(w1, jisx0213_u2_key, jisx0213_u2_tbl_len);
228 if (k >= 0) {
229 w = jisx0213_u2_tbl[2*k];
230 CK((*filter->output_function)(w, filter->data));
231 w = jisx0213_u2_tbl[2*k+1];
232 }
233 }
234
235 /* conversion for BMP */
236 if (w <= 0) {
237 w1 = (s1 - 0x21)*94 + s2 - 0x21;
238 if (w1 >= 0 && w1 < jisx0213_ucs_table_size) {
239 w = jisx0213_ucs_table[w1];
240 }
241 }
242
243 /* conversion for CJK Unified Ideographs ext.B (U+2XXXX) */
244 if (w <= 0) {
245 w1 = (s1 << 8) | s2;
246 k = mbfl_bisec_srch2(w1, jisx0213_jis_u5_key, jisx0213_u5_tbl_len);
247 if (k >= 0) {
248 w = jisx0213_jis_u5_tbl[k] + 0x20000;
249 }
250 }
251
252 if (w <= 0) {
253 if (s1 < 0x7f && s2 < 0x7f) {
254 w = (s1 << 8) | s2;
255 w &= MBFL_WCSPLANE_MASK;
256 w |= MBFL_WCSPLANE_JIS0213;
257 } else {
258 w = (c1 << 8) | c;
259 w &= MBFL_WCSGROUP_MASK;
260 w |= MBFL_WCSGROUP_THROUGH;
261 }
262 }
263 CK((*filter->output_function)(w, filter->data));
264 } else if ((c >= 0 && c < 0x21) || c == 0x7f) { /* CTLs */
265 CK((*filter->output_function)(c, filter->data));
266 } else {
267 w = (c1 << 8) | c;
268 w &= MBFL_WCSGROUP_MASK;
269 w |= MBFL_WCSGROUP_THROUGH;
270 CK((*filter->output_function)(w, filter->data));
271 }
272 break;
273
274 case 2: /* got 0x8e : EUC-JP-2004 kana */
275 filter->status = 0;
276 if (c > 0xa0 && c < 0xe0) {
277 w = 0xfec0 + c;
278 CK((*filter->output_function)(w, filter->data));
279 } else if ((c >= 0 && c < 0x21) || c == 0x7f) { /* CTLs */
280 CK((*filter->output_function)(c, filter->data));
281 } else {
282 w = 0x8e00 | c;
283 w &= MBFL_WCSGROUP_MASK;
284 w |= MBFL_WCSGROUP_THROUGH;
285 CK((*filter->output_function)(w, filter->data));
286 }
287 break;
288
289 case 3: /* X 0213 plane 2 first char : EUC-JP-2004 (0x8f), ISO-2022-JP-2004 */
290 if ((c >= 0 && c < 0x21) || c == 0x7f) { /* CTLs */
291 CK((*filter->output_function)(c, filter->data));
292 filter->status = 0;
293 } else {
294 if (filter->from->no_encoding == mbfl_no_encoding_eucjp2004) {
295 s1 = c - 0x80;
296 } else {
297 s1 = c;
298 }
299 if (s1 > 0x20 && s1 < 0x80) {
300 filter->cache = s1;
301 filter->status++;
302 } else {
303 if (filter->to->no_encoding == mbfl_no_encoding_eucjp2004) {
304 w = c | 0x8f00;
305 w &= MBFL_WCSGROUP_MASK;
306 w |= MBFL_WCSGROUP_THROUGH;
307 } else {
308 w = c & 0x7f;
309 w &= MBFL_WCSPLANE_MASK;
310 w |= MBFL_WCSPLANE_JIS0213;
311 }
312 CK((*filter->output_function)(w, filter->data));
313 }
314 }
315 break;
316
317 case 4: /* X 0213 plane 2 second char : EUC-JP-2004, ISO-2022-JP-2004 */
318
319 filter->status &= ~0xf;
320 c1 = filter->cache;
321 if (filter->from->no_encoding == mbfl_no_encoding_eucjp2004) {
322 c2 = c - 0x80;
323 } else {
324 c2 = c;
325 }
326 s1 = c1 - 0x21;
327 s2 = c2 - 0x21;
328
329 if (((s1 >= 0 && s1 <= 4 && s1 != 1) || s1 == 7 || (s1 >= 11 && s1 <= 14) ||
330 (s1 >= 77 && s1 < 94)) && s2 >= 0 && s2 < 94) {
331 /* calc offset from ku */
332 for (k = 0; k < jisx0213_p2_ofst_len; k++) {
333 if (s1 == jisx0213_p2_ofst[k]-1) {
334 break;
335 }
336 }
337 k = k - (jisx0213_p2_ofst[k]-1);
338
339 /* check for japanese chars in BMP */
340 s = (s1 + 94 + k)*94 + s2;
341 if (s >= 0 && s < jisx0213_ucs_table_size) {
342 w = jisx0213_ucs_table[s];
343 } else {
344 w = 0;
345 }
346
347 /* check for japanese chars in CJK Unified Ideographs ext.B (U+2XXXX) */
348 if (w <= 0) {
349 w1 = ((c1 + k + 94) << 8) | c2;
350 k = mbfl_bisec_srch2(w1, jisx0213_jis_u5_key, jisx0213_u5_tbl_len);
351 if (k >= 0) {
352 w = jisx0213_jis_u5_tbl[k] + 0x20000;
353 }
354 }
355
356 if (w <= 0) {
357 w = ((c1 & 0x7f) << 8) | (c2 & 0x7f);
358 w &= MBFL_WCSPLANE_MASK;
359 w |= MBFL_WCSPLANE_JIS0213;
360 }
361
362 CK((*filter->output_function)(w, filter->data));
363 } else if ((c >= 0 && c < 0x21) || c == 0x7f) { /* CTLs */
364 CK((*filter->output_function)(c, filter->data));
365 } else {
366 if (filter->to->no_encoding == mbfl_no_encoding_eucjp2004) {
367 w = (c1 << 8) | c | 0x8f0000;
368 w &= MBFL_WCSGROUP_MASK;
369 w |= MBFL_WCSGROUP_THROUGH;
370 } else {
371 w = ((c1 & 0x7f) << 8) | (c2 & 0x7f);
372 w &= MBFL_WCSPLANE_MASK;
373 w |= MBFL_WCSPLANE_JIS0213;
374 }
375 CK((*filter->output_function)(w, filter->data));
376 }
377
378 break;
379
380 case 5: /* X 0208 : ISO-2022-JP-2004 */
381 filter->status &= ~0xf;
382 c1 = filter->cache;
383 if (c > 0x20 && c < 0x7f) {
384 s = (c1 - 0x21)*94 + c - 0x21;
385 if (s >= 0 && s < jisx0208_ucs_table_size) {
386 w = jisx0208_ucs_table[s];
387 }
388 }
389 if (w <= 0) {
390 w = (c1 << 8) | c;
391 w &= MBFL_WCSPLANE_MASK;
392 w |= MBFL_WCSPLANE_JIS0208;
393 }
394 CK((*filter->output_function)(w, filter->data));
395 break;
396
397 /* ESC : ISO-2022-JP-2004 */
398 /* case 0x06: */
399 /* case 0x16: */
400 /* case 0x26: */
401 /* case 0x86: */
402 /* case 0x96: */
403 /* case 0xa6: */
404 case 6:
405 if (c == 0x24) { /* '$' */
406 filter->status++;
407 } else if (c == 0x28) { /* '(' */
408 filter->status += 3;
409 } else {
410 filter->status &= ~0xf;
411 CK((*filter->output_function)(0x1b, filter->data));
412 goto retry;
413 }
414 break;
415
416 /* ESC $ : ISO-2022-JP-2004 */
417 /* case 0x07: */
418 /* case 0x17: */
419 /* case 0x27: */
420 /* case 0x87: */
421 /* case 0x97: */
422 /* case 0xa7: */
423 case 7:
424 if (c == 0x42) { /* 'B' -> JIS X 0208-1983 */
425 filter->status = 0x80;
426 } else if (c == 0x28) { /* '(' */
427 filter->status++;
428 } else {
429 filter->status &= ~0xf;
430 CK((*filter->output_function)(0x1b, filter->data));
431 CK((*filter->output_function)(0x24, filter->data));
432 goto retry;
433 }
434 break;
435
436 break;
437
438 /* ESC $ ( : ISO-2022-JP-2004 */
439 /* case 0x08: */
440 /* case 0x18: */
441 /* case 0x28: */
442 /* case 0x88: */
443 /* case 0x98: */
444 /* case 0xa8: */
445 case 8:
446 if (c == 0x51) { /* JIS X 0213 plane 1 */
447 filter->status = 0x90;
448 } else if (c == 0x50) { /* JIS X 0213 plane 2 */
449 filter->status = 0xa0;
450 } else {
451 filter->status &= ~0xf;
452 CK((*filter->output_function)(0x1b, filter->data));
453 CK((*filter->output_function)(0x24, filter->data));
454 CK((*filter->output_function)(0x28, filter->data));
455 goto retry;
456 }
457 break;
458
459 /* ESC ( : ISO-2022-JP-2004 */
460 /* case 0x09: */
461 /* case 0x19: */
462 /* case 0x29: */
463 /* case 0x89: */
464 /* case 0x99: */
465 case 9:
466 if (c == 0x42) { /* 'B' : ASCII */
467 filter->status = 0;
468 } else {
469 filter->status &= ~0xf;
470 CK((*filter->output_function)(0x1b, filter->data));
471 CK((*filter->output_function)(0x28, filter->data));
472 goto retry;
473 }
474 break;
475
476 default:
477 filter->status = 0;
478 break;
479 }
480
481 return c;
482 }
483
484 int
mbfl_filt_conv_wchar_jis2004(int c,mbfl_convert_filter * filter)485 mbfl_filt_conv_wchar_jis2004(int c, mbfl_convert_filter *filter) {
486 int k;
487 int c1, c2, s1 = 0, s2;
488
489 retry:
490
491 /* check for 1st char of combining characters */
492 if ((filter->status & 0xf)== 0 && (
493 c == 0x00E6 ||
494 (c >= 0x0254 && c <= 0x02E9) ||
495 (c >= 0x304B && c <= 0x3053) ||
496 (c >= 0x30AB && c <= 0x30C8) ||
497 c == 0x31F7)) {
498 for (k=0;k<jisx0213_u2_tbl_len;k++) {
499 if (c == jisx0213_u2_tbl[2*k]) {
500 filter->status++;
501 filter->cache = k;
502 return c;
503 }
504 }
505 }
506
507 /* check for 2nd char of combining characters */
508 if ((filter->status & 0xf) == 1 &&
509 filter->cache >= 0 && filter->cache <= jisx0213_u2_tbl_len) {
510 k = filter->cache;
511 filter->status &= ~0xf;
512 filter->cache = 0;
513
514 c1 = jisx0213_u2_tbl[2*k];
515 if ((c1 == 0x0254 || c1 == 0x028C || c1 == 0x0259 || c1 == 0x025A)
516 && c == 0x0301) {
517 k++;
518 }
519 if (c == jisx0213_u2_tbl[2*k+1]) {
520 s1 = jisx0213_u2_key[k];
521 } else { /* fallback */
522 s1 = jisx0213_u2_fb_tbl[k];
523
524 if (filter->to->no_encoding == mbfl_no_encoding_sjis2004) {
525 c1 = (s1 >> 8) & 0xff;
526 c2 = s1 & 0xff;
527 SJIS_ENCODE(c1, c2, s1, s2);
528 } else if (filter->to->no_encoding == mbfl_no_encoding_eucjp2004) {
529 s2 = (s1 & 0xff) + 0x80;
530 s1 = ((s1 >> 8) & 0xff) + 0x80;
531 } else {
532 if (filter->status != 0x200) {
533 CK((*filter->output_function)(0x1b, filter->data));
534 CK((*filter->output_function)(0x24, filter->data));
535 CK((*filter->output_function)(0x28, filter->data));
536 CK((*filter->output_function)(0x51, filter->data));
537 }
538 filter->status = 0x200;
539
540 s2 = s1 & 0x7f;
541 s1 = (s1 >> 8) & 0x7f;
542 }
543
544 CK((*filter->output_function)(s1, filter->data));
545 CK((*filter->output_function)(s2, filter->data));
546 goto retry;
547 }
548 }
549
550 /* check for major japanese chars: U+4E00 - U+9FFF */
551 if (s1 <= 0) {
552 for (k=0; k < uni2jis_tbl_len ;k++) {
553 if (c >= uni2jis_tbl_range[k][0] && c <= uni2jis_tbl_range[k][1]) {
554 s1 = uni2jis_tbl[k][c-uni2jis_tbl_range[k][0]];
555 break;
556 }
557 }
558 }
559
560 /* check for japanese chars in compressed mapping area: U+1E00 - U+4DBF */
561 if (s1 <= 0 && c >= ucs_c1_jisx0213_min && c <= ucs_c1_jisx0213_max) {
562 k = mbfl_bisec_srch(c, ucs_c1_jisx0213_tbl, ucs_c1_jisx0213_tbl_len);
563 if (k >= 0) {
564 s1 = ucs_c1_jisx0213_ofst[k] + c - ucs_c1_jisx0213_tbl[2*k];
565 }
566 }
567
568 /* check for japanese chars in CJK Unified Ideographs ext.B (U+2XXXX) */
569 if (s1 <= 0 && c >= jisx0213_u5_tbl_min && c <= jisx0213_u5_tbl_max) {
570 k = mbfl_bisec_srch2(c - 0x20000, jisx0213_u5_jis_key, jisx0213_u5_tbl_len);
571 if (k >= 0) {
572 s1 = jisx0213_u5_jis_tbl[k];
573 }
574 }
575
576 if (s1 <= 0) {
577 /* CJK Compatibility Forms: U+FE30 - U+FE4F */
578 if (c == 0xfe45) {
579 s1 = 0x233e;
580 } else if (c == 0xfe46) {
581 s1 = 0x233d;
582 } else if (c >= 0xf91d && c <= 0xf9dc) {
583 /* CJK Compatibility Ideographs: U+F900 - U+F92A */
584 k = mbfl_bisec_srch2(c, ucs_r2b_jisx0213_cmap_key, ucs_r2b_jisx0213_cmap_len);
585 if (k >= 0) {
586 s1 = ucs_r2b_jisx0213_cmap_val[k];
587 }
588 }
589 }
590
591 if (s1 <= 0) {
592 c1 = c & ~MBFL_WCSPLANE_MASK;
593 if (c1 == MBFL_WCSPLANE_JIS0213) {
594 s1 = c & MBFL_WCSPLANE_MASK;
595 }
596 if (c == 0) {
597 s1 = 0;
598 } else if (s1 <= 0) {
599 s1 = -1;
600 }
601 } else if (s1 >= 0x9980) {
602 s1 = -1;
603 }
604
605 if (s1 >= 0) {
606 if (s1 < 0x80) { /* ASCII */
607 if (filter->to->no_encoding == mbfl_no_encoding_2022jp_2004 &&
608 (filter->status & 0xff00) != 0) {
609 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
610 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
611 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
612 }
613 filter->status = 0;
614 CK((*filter->output_function)(s1, filter->data));
615 } else if (s1 < 0x100) { /* latin or kana */
616 if (filter->to->no_encoding == mbfl_no_encoding_eucjp2004) {
617 CK((*filter->output_function)(0x8e, filter->data));
618 }
619 CK((*filter->output_function)(s1, filter->data));
620 } else if (s1 < 0x7f00) { /* X 0213 plane 1 */
621 if (filter->to->no_encoding == mbfl_no_encoding_sjis2004) {
622 c1 = (s1 >> 8) & 0xff;
623 c2 = s1 & 0xff;
624 SJIS_ENCODE(c1, c2, s1, s2);
625 } else if (filter->to->no_encoding == mbfl_no_encoding_eucjp2004) {
626 s2 = (s1 & 0xff) + 0x80;
627 s1 = ((s1 >> 8) & 0xff) + 0x80;
628 } else {
629 if ((filter->status & 0xff00) != 0x200) {
630 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
631 CK((*filter->output_function)(0x24, filter->data)); /* '$' */
632 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
633 CK((*filter->output_function)(0x51, filter->data)); /* 'Q' */
634 }
635 filter->status = 0x200;
636 s2 = s1 & 0xff;
637 s1 = (s1 >> 8) & 0xff;
638 }
639 CK((*filter->output_function)(s1, filter->data));
640 CK((*filter->output_function)(s2, filter->data));
641 } else { /* X 0213 plane 2 */
642 if (filter->to->no_encoding == mbfl_no_encoding_sjis2004) {
643 c1 = (s1 >> 8) & 0xff;
644 c2 = s1 & 0xff;
645 SJIS_ENCODE(c1, c2, s1, s2);
646 } else {
647 s2 = s1 & 0xff;
648 k = ((s1 >> 8) & 0xff) - 0x7f;
649 if (k >= 0 && k < jisx0213_p2_ofst_len) {
650 s1 = jisx0213_p2_ofst[k] - 1 + 0x21;
651 }
652 if (filter->to->no_encoding == mbfl_no_encoding_eucjp2004) {
653 s2 |= 0x80;
654 s1 |= 0x80;
655 CK((*filter->output_function)(0x8f, filter->data));
656 } else {
657 if ((filter->status & 0xff00) != 0x200) {
658 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
659 CK((*filter->output_function)(0x24, filter->data)); /* '$' */
660 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
661 CK((*filter->output_function)(0x50, filter->data)); /* 'P' */
662 }
663 filter->status = 0x200;
664 }
665 }
666
667 CK((*filter->output_function)(s1, filter->data));
668 CK((*filter->output_function)(s2, filter->data));
669 }
670 } else {
671 if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
672 CK(mbfl_filt_conv_illegal_output(c, filter));
673 }
674 }
675
676 return c;
677 }
678
679 int
mbfl_filt_conv_jis2004_flush(mbfl_convert_filter * filter)680 mbfl_filt_conv_jis2004_flush(mbfl_convert_filter *filter)
681 {
682 int k, c1, c2, s1, s2;
683
684 k = filter->cache;
685 filter->cache = 0;
686
687 if (filter->status == 1 && k >= 0 && k <= jisx0213_u2_tbl_len) {
688 s1 = jisx0213_u2_fb_tbl[k];
689
690 if (filter->to->no_encoding == mbfl_no_encoding_sjis2004) {
691 c1 = (s1 >> 8) & 0xff;
692 c2 = s1 & 0xff;
693 SJIS_ENCODE(c1, c2, s1, s2);
694 } else if (filter->to->no_encoding == mbfl_no_encoding_eucjp2004) {
695 s2 = (s1 & 0xff) | 0x80;
696 s1 = ((s1 >> 8) & 0xff) | 0x80;
697 } else {
698 s2 = s1 & 0x7f;
699 s1 = (s1 >> 8) & 0x7f;
700 if ((filter->status & 0xff00) != 0x200) {
701 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
702 CK((*filter->output_function)(0x24, filter->data)); /* '$' */
703 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
704 CK((*filter->output_function)(0x51, filter->data)); /* 'Q' */
705 }
706 filter->status = 0x200;
707 }
708
709 CK((*filter->output_function)(s1, filter->data));
710 CK((*filter->output_function)(s2, filter->data));
711 }
712
713 /* back to latin */
714 if ((filter->status & 0xff00) != 0) {
715 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
716 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
717 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
718 }
719
720 filter->status = 0;
721
722 if (filter->flush_function != NULL) {
723 return (*filter->flush_function)(filter->data);
724 }
725
726 return 0;
727 }
728