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_jis.c
26  * by rui hirokawa <hirokawa@php.net> on 18 aug 2011.
27  *
28  */
29 
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33 
34 #include "mbfilter.h"
35 #include "mbfilter_iso2022jp_2004.h"
36 #include "mbfilter_sjis_2004.h"
37 
38 #include "unicode_table_jis2004.h"
39 #include "unicode_table_jis.h"
40 
41 extern int mbfl_filt_conv_any_jis_flush(mbfl_convert_filter *filter);
42 static int mbfl_filt_ident_2022jp_2004(int c, mbfl_identify_filter *filter);
43 
44 const mbfl_encoding mbfl_encoding_2022jp_2004 = {
45 	mbfl_no_encoding_2022jp_2004,
46 	"ISO-2022-JP-2004",
47 	"ISO-2022-JP-2004",
48 	NULL,
49 	NULL,
50 	MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE | MBFL_ENCTYPE_GL_UNSAFE,
51 	&vtbl_2022jp_2004_wchar,
52 	&vtbl_wchar_2022jp_2004
53 };
54 
55 const struct mbfl_identify_vtbl vtbl_identify_2022jp_2004 = {
56 	mbfl_no_encoding_2022jp_2004,
57 	mbfl_filt_ident_common_ctor,
58 	mbfl_filt_ident_common_dtor,
59 	mbfl_filt_ident_2022jp_2004
60 };
61 
62 const struct mbfl_convert_vtbl vtbl_2022jp_2004_wchar = {
63 	mbfl_no_encoding_2022jp_2004,
64 	mbfl_no_encoding_wchar,
65 	mbfl_filt_conv_common_ctor,
66 	mbfl_filt_conv_common_dtor,
67 	mbfl_filt_conv_jis2004_wchar,
68 	mbfl_filt_conv_common_flush
69 };
70 
71 const struct mbfl_convert_vtbl vtbl_wchar_2022jp_2004 = {
72 	mbfl_no_encoding_wchar,
73 	mbfl_no_encoding_2022jp_2004,
74 	mbfl_filt_conv_common_ctor,
75 	mbfl_filt_conv_common_dtor,
76 	mbfl_filt_conv_wchar_jis2004,
77 	mbfl_filt_conv_jis2004_flush
78 };
79 
mbfl_filt_ident_2022jp_2004(int c,mbfl_identify_filter * filter)80 static int mbfl_filt_ident_2022jp_2004(int c, mbfl_identify_filter *filter)
81 {
82 retry:
83 	switch (filter->status & 0xf) {
84 /*	case 0x00:	 ASCII */
85 /*	case 0x80:	 X 0212 */
86 /*	case 0x90:	 X 0213 plane 1 */
87 /*	case 0xa0:	 X 0213 plane 2 */
88 	case 0:
89 		if (c == 0x1b) {
90 			filter->status += 2;
91 		} else if (filter->status == 0x80 && c > 0x20 && c < 0x7f) {		/* kanji first char */
92 			filter->status += 1;
93 		} else if (c >= 0 && c < 0x80) {		/* latin, CTLs */
94 			;
95 		} else {
96 			filter->flag = 1;	/* bad */
97 		}
98 		break;
99 
100 /*	case 0x81:	 X 0208 second char */
101 	case 1:
102 		if (c == 0x1b) {
103 			filter->status++;
104 		} else {
105 			filter->status &= ~0xf;
106 			if (c < 0x21 || c > 0x7e) {		/* bad */
107 				filter->flag = 1;
108 			}
109 		}
110 		break;
111 
112 	/* ESC */
113 	case 2:
114 		if (c == 0x24) {		/* '$' */
115 			filter->status++;
116 		} else if (c == 0x28) {		/* '(' */
117 			filter->status += 3;
118 		} else {
119 			filter->flag = 1;	/* bad */
120 			filter->status &= ~0xf;
121 			goto retry;
122 		}
123 		break;
124 
125 	/* ESC $ */
126 	case 3:
127 		if (c == 0x42) {		/* 'B' */
128 			filter->status = 0x80;
129 		} else if (c == 0x28) {		/* '(' */
130 			filter->status++;
131 		} else {
132 			filter->flag = 1;	/* bad */
133 			filter->status &= ~0xf;
134 			goto retry;
135 		}
136 		break;
137 
138 	/* ESC $ ( */
139 	case 4:
140 		if (c == 0x51) {		/* JIS X 0213 plane 1 */
141 			filter->status = 0x90;
142 		} else if (c == 0x50) {		/* JIS X 0213 plane 2 */
143 			filter->status = 0xa0;
144 		} else {
145 			filter->flag = 1;	/* bad */
146 			filter->status &= ~0xf;
147 			goto retry;
148 		}
149 		break;
150 
151 	/* ESC ( */
152 	case 5:
153 		if (c == 0x42) {		/* 'B' */
154 			filter->status = 0;
155 		} else {
156 			filter->flag = 1;	/* bad */
157 			filter->status &= ~0xf;
158 			goto retry;
159 		}
160 		break;
161 
162 	default:
163 		filter->status = 0;
164 		break;
165 	}
166 
167 	return c;
168 }
169