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 };
52 
53 const struct mbfl_identify_vtbl vtbl_identify_2022jp_2004 = {
54 	mbfl_no_encoding_2022jp_2004,
55 	mbfl_filt_ident_common_ctor,
56 	mbfl_filt_ident_common_dtor,
57 	mbfl_filt_ident_2022jp_2004
58 };
59 
60 const struct mbfl_convert_vtbl vtbl_2022jp_2004_wchar = {
61 	mbfl_no_encoding_2022jp_2004,
62 	mbfl_no_encoding_wchar,
63 	mbfl_filt_conv_common_ctor,
64 	mbfl_filt_conv_common_dtor,
65 	mbfl_filt_conv_jis2004_wchar,
66 	mbfl_filt_conv_common_flush
67 };
68 
69 const struct mbfl_convert_vtbl vtbl_wchar_2022jp_2004 = {
70 	mbfl_no_encoding_wchar,
71 	mbfl_no_encoding_2022jp_2004,
72 	mbfl_filt_conv_common_ctor,
73 	mbfl_filt_conv_common_dtor,
74 	mbfl_filt_conv_wchar_jis2004,
75 	mbfl_filt_conv_jis2004_flush
76 };
77 
mbfl_filt_ident_2022jp_2004(int c,mbfl_identify_filter * filter)78 static int mbfl_filt_ident_2022jp_2004(int c, mbfl_identify_filter *filter)
79 {
80 retry:
81 	switch (filter->status & 0xf) {
82 /*	case 0x00:	 ASCII */
83 /*	case 0x80:	 X 0212 */
84 /*	case 0x90:	 X 0213 plane 1 */
85 /*	case 0xa0:	 X 0213 plane 2 */
86 	case 0:
87 		if (c == 0x1b) {
88 			filter->status += 2;
89 		} else if (filter->status == 0x80 && c > 0x20 && c < 0x7f) {		/* kanji first char */
90 			filter->status += 1;
91 		} else if (c >= 0 && c < 0x80) {		/* latin, CTLs */
92 			;
93 		} else {
94 			filter->flag = 1;	/* bad */
95 		}
96 		break;
97 
98 /*	case 0x81:	 X 0208 second char */
99 	case 1:
100 		if (c == 0x1b) {
101 			filter->status++;
102 		} else {
103 			filter->status &= ~0xf;
104 			if (c < 0x21 || c > 0x7e) {		/* bad */
105 				filter->flag = 1;
106 			}
107 		}
108 		break;
109 
110 	/* ESC */
111 	case 2:
112 		if (c == 0x24) {		/* '$' */
113 			filter->status++;
114 		} else if (c == 0x28) {		/* '(' */
115 			filter->status += 3;
116 		} else {
117 			filter->flag = 1;	/* bad */
118 			filter->status &= ~0xf;
119 			goto retry;
120 		}
121 		break;
122 
123 	/* ESC $ */
124 	case 3:
125 		if (c == 0x42) {		/* 'B' */
126 			filter->status = 0x80;
127 		} else if (c == 0x28) {		/* '(' */
128 			filter->status++;
129 		} else {
130 			filter->flag = 1;	/* bad */
131 			filter->status &= ~0xf;
132 			goto retry;
133 		}
134 		break;
135 
136 	/* ESC $ ( */
137 	case 4:
138 		if (c == 0x51) {		/* JIS X 0213 plane 1 */
139 			filter->status = 0x90;
140 		} else if (c == 0x50) {		/* JIS X 0213 plane 2 */
141 			filter->status = 0xa0;
142 		} else {
143 			filter->flag = 1;	/* bad */
144 			filter->status &= ~0xf;
145 			goto retry;
146 		}
147 		break;
148 
149 	/* ESC ( */
150 	case 5:
151 		if (c == 0x42) {		/* 'B' */
152 			filter->status = 0;
153 		} else {
154 			filter->flag = 1;	/* bad */
155 			filter->status &= ~0xf;
156 			goto retry;
157 		}
158 		break;
159 
160 	default:
161 		filter->status = 0;
162 		break;
163 	}
164 
165 	return c;
166 }
167 
168 
169