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