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_kr.c
26 : * by moriyoshi koizumi <moriyoshi@php.net> on 4 dec 2002.
27 : *
28 : */
29 :
30 : #ifdef HAVE_CONFIG_H
31 : #include "config.h"
32 : #endif
33 :
34 : #include "mbfilter.h"
35 : #include "mbfilter_iso2022_kr.h"
36 : #include "unicode_table_uhc.h"
37 :
38 : static int mbfl_filt_ident_2022kr(int c, mbfl_identify_filter *filter);
39 :
40 : const mbfl_encoding mbfl_encoding_2022kr = {
41 : mbfl_no_encoding_2022kr,
42 : "ISO-2022-KR",
43 : "ISO-2022-KR",
44 : NULL,
45 : NULL,
46 : MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE
47 : };
48 :
49 : const struct mbfl_identify_vtbl vtbl_identify_2022kr = {
50 : mbfl_no_encoding_2022kr,
51 : mbfl_filt_ident_common_ctor,
52 : mbfl_filt_ident_common_dtor,
53 : mbfl_filt_ident_2022kr
54 : };
55 :
56 : const struct mbfl_convert_vtbl vtbl_wchar_2022kr = {
57 : mbfl_no_encoding_wchar,
58 : mbfl_no_encoding_2022kr,
59 : mbfl_filt_conv_common_ctor,
60 : mbfl_filt_conv_common_dtor,
61 : mbfl_filt_conv_wchar_2022kr,
62 : mbfl_filt_conv_any_2022kr_flush
63 : };
64 :
65 : const struct mbfl_convert_vtbl vtbl_2022kr_wchar = {
66 : mbfl_no_encoding_2022kr,
67 : mbfl_no_encoding_wchar,
68 : mbfl_filt_conv_common_ctor,
69 : mbfl_filt_conv_common_dtor,
70 : mbfl_filt_conv_2022kr_wchar,
71 : mbfl_filt_conv_common_flush
72 : };
73 :
74 : #define CK(statement) do { if ((statement) < 0) return (-1); } while (0)
75 :
76 : /*
77 : * ISO-2022-KR => wchar
78 : */
79 : int
80 : mbfl_filt_conv_2022kr_wchar(int c, mbfl_convert_filter *filter)
81 91 : {
82 : int c1, w, flag;
83 :
84 91 : retry:
85 91 : switch (filter->status & 0xf) {
86 : /* case 0x00: ASCII */
87 : /* case 0x10: KSC5601 */
88 : case 0:
89 88 : if (c == 0x1b) { /* ESC */
90 1 : filter->status += 2;
91 87 : } else if (c == 0x0f) { /* SI (ASCII) */
92 1 : filter->status &= ~0xff;
93 86 : } else if (c == 0x0e) { /* SO (KSC5601) */
94 1 : filter->status |= 0x10;
95 85 : } else if ((filter->status & 0x10) != 0 && c > 0x20 && c < 0x7f) {
96 : /* KSC5601 lead byte */
97 0 : filter->cache = c;
98 0 : filter->status += 1;
99 102 : } else if ((filter->status & 0x10) == 0 && c >= 0 && c < 0x80) {
100 : /* latin, CTLs */
101 18 : CK((*filter->output_function)(c, filter->data));
102 : } else {
103 67 : w = c & MBFL_WCSGROUP_MASK;
104 67 : w |= MBFL_WCSGROUP_THROUGH;
105 67 : CK((*filter->output_function)(w, filter->data));
106 : }
107 86 : break;
108 :
109 : case 1: /* dbcs second byte */
110 0 : filter->status &= ~0xf;
111 0 : c1 = filter->cache;
112 0 : flag = 0;
113 0 : if (c1 > 0x20 && c1 < 0x47) {
114 0 : flag = 1;
115 0 : } else if (c1 >= 0x47 && c1 <= 0x7e && c1 != 0x49) {
116 0 : flag = 2;
117 : }
118 0 : if (flag > 0 && c > 0x20 && c < 0x7f) {
119 0 : if (flag == 1){
120 0 : w = (c1 - 0x21)*190 + (c - 0x41) + 0x80;
121 0 : if (w >= 0 && w < uhc2_ucs_table_size) {
122 0 : w = uhc2_ucs_table[w];
123 : } else {
124 0 : w = 0;
125 : }
126 : } else {
127 0 : w = (c1 - 0x47)*94 + (c - 0x21);
128 0 : if (w >= 0 && w < uhc3_ucs_table_size) {
129 0 : w = uhc3_ucs_table[w];
130 : } else {
131 0 : w = 0;
132 : }
133 : }
134 :
135 0 : if (w <= 0) {
136 0 : w = (c1 << 8) | c;
137 0 : w &= MBFL_WCSPLANE_MASK;
138 0 : w |= MBFL_WCSPLANE_KSC5601;
139 : }
140 0 : CK((*filter->output_function)(w, filter->data));
141 0 : } else if (c == 0x1b) { /* ESC */
142 0 : filter->status++;
143 0 : } else if ((c >= 0 && c < 0x21) || c == 0x7f) { /* CTLs */
144 0 : CK((*filter->output_function)(c, filter->data));
145 : } else {
146 0 : w = (c1 << 8) | c;
147 0 : w &= MBFL_WCSGROUP_MASK;
148 0 : w |= MBFL_WCSGROUP_THROUGH;
149 0 : CK((*filter->output_function)(w, filter->data));
150 : }
151 0 : break;
152 :
153 : case 2: /* ESC */
154 1 : if (c == 0x24) { /* '$' */
155 1 : filter->status++;
156 : } else {
157 0 : filter->status &= ~0xf;
158 0 : CK((*filter->output_function)(0x1b, filter->data));
159 0 : goto retry;
160 : }
161 1 : break;
162 : case 3: /* ESC $ */
163 1 : if (c == 0x29) { /* ')' */
164 1 : filter->status++;
165 : } else {
166 0 : filter->status &= ~0xf;
167 0 : CK((*filter->output_function)(0x1b, filter->data));
168 0 : CK((*filter->output_function)(0x24, filter->data));
169 0 : goto retry;
170 : }
171 1 : break;
172 : case 4: /* ESC $ ) */
173 1 : if (c == 0x43) { /* 'C' */
174 1 : filter->status &= ~0xf;
175 1 : filter->status |= 0x100;
176 : } else {
177 0 : filter->status &= ~0xf;
178 0 : CK((*filter->output_function)(0x1b, filter->data));
179 0 : CK((*filter->output_function)(0x24, filter->data));
180 0 : CK((*filter->output_function)(0x29, filter->data));
181 0 : goto retry;
182 : }
183 1 : break;
184 : default:
185 0 : filter->status = 0;
186 : break;
187 : }
188 :
189 89 : return c;
190 : }
191 :
192 : /*
193 : * wchar => ISO-2022-KR
194 : */
195 : int
196 : mbfl_filt_conv_wchar_2022kr(int c, mbfl_convert_filter *filter)
197 37 : {
198 : int c1, c2, s;
199 :
200 37 : s = 0;
201 :
202 61 : if (c >= ucs_a1_uhc_table_min && c < ucs_a1_uhc_table_max) {
203 24 : s = ucs_a1_uhc_table[c - ucs_a1_uhc_table_min];
204 13 : } else if (c >= ucs_a2_uhc_table_min && c < ucs_a2_uhc_table_max) {
205 0 : s = ucs_a2_uhc_table[c - ucs_a2_uhc_table_min];
206 13 : } else if (c >= ucs_a3_uhc_table_min && c < ucs_a3_uhc_table_max) {
207 0 : s = ucs_a3_uhc_table[c - ucs_a3_uhc_table_min];
208 13 : } else if (c >= ucs_i_uhc_table_min && c < ucs_i_uhc_table_max) {
209 0 : s = ucs_i_uhc_table[c - ucs_i_uhc_table_min];
210 21 : } else if (c >= ucs_s_uhc_table_min && c < ucs_s_uhc_table_max) {
211 8 : s = ucs_s_uhc_table[c - ucs_s_uhc_table_min];
212 5 : } else if (c >= ucs_r1_uhc_table_min && c < ucs_r1_uhc_table_max) {
213 0 : s = ucs_r1_uhc_table[c - ucs_r1_uhc_table_min];
214 5 : } else if (c >= ucs_r2_uhc_table_min && c < ucs_r2_uhc_table_max) {
215 0 : s = ucs_r2_uhc_table[c - ucs_r2_uhc_table_min];
216 : }
217 :
218 37 : c1 = (s >> 8) & 0xff;
219 37 : c2 = s & 0xff;
220 : /* exclude UHC extension area */
221 37 : if (c1 < 0xa1 || c2 < 0xa1){
222 29 : s = c;
223 : }
224 37 : if (s & 0x8000) {
225 8 : s -= 0x8080;
226 : }
227 :
228 37 : if (s <= 0) {
229 0 : c1 = c & ~MBFL_WCSPLANE_MASK;
230 0 : if (c1 == MBFL_WCSPLANE_KSC5601) {
231 0 : s = c & MBFL_WCSPLANE_MASK;
232 : }
233 0 : if (c == 0) {
234 0 : s = 0;
235 0 : } else if (s <= 0) {
236 0 : s = -1;
237 : }
238 37 : } else if ((s >= 0x80 && s < 0x2121) || (s > 0x8080)) {
239 5 : s = -1;
240 : }
241 37 : if (s >= 0) {
242 56 : if (s < 0x80 && s > 0) { /* ASCII */
243 24 : if ((filter->status & 0x10) != 0) {
244 2 : CK((*filter->output_function)(0x0f, filter->data)); /* SI */
245 2 : filter->status &= ~0x10;
246 : }
247 24 : CK((*filter->output_function)(s, filter->data));
248 : } else {
249 8 : if ( (filter->status & 0x100) == 0) {
250 2 : CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
251 2 : CK((*filter->output_function)(0x24, filter->data)); /* '$' */
252 2 : CK((*filter->output_function)(0x29, filter->data)); /* ')' */
253 2 : CK((*filter->output_function)(0x43, filter->data)); /* 'C' */
254 2 : filter->status |= 0x100;
255 : }
256 8 : if ((filter->status & 0x10) == 0) {
257 2 : CK((*filter->output_function)(0x0e, filter->data)); /* SO */
258 2 : filter->status |= 0x10;
259 : }
260 8 : CK((*filter->output_function)((s >> 8) & 0xff, filter->data));
261 8 : CK((*filter->output_function)(s & 0xff, filter->data));
262 : }
263 : } else {
264 5 : if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
265 5 : CK(mbfl_filt_conv_illegal_output(c, filter));
266 : }
267 : }
268 :
269 37 : return c;
270 : }
271 :
272 : int
273 : mbfl_filt_conv_any_2022kr_flush(mbfl_convert_filter *filter)
274 13 : {
275 : /* back to ascii */
276 13 : if ((filter->status & 0xff00) != 0) {
277 11 : CK((*filter->output_function)(0x0f, filter->data)); /* SI */
278 : }
279 13 : filter->status &= 0xff;
280 13 : return 0;
281 : }
282 :
283 : static int mbfl_filt_ident_2022kr(int c, mbfl_identify_filter *filter)
284 0 : {
285 0 : retry:
286 0 : switch (filter->status & 0xf) {
287 : /* case 0x00: ASCII */
288 : /* case 0x10: KSC5601 mode */
289 : /* case 0x20: KSC5601 DBCS */
290 : /* case 0x40: KSC5601 SBCS */
291 : case 0:
292 0 : if (!(filter->status & 0x10)) {
293 0 : if (c == 0x1b)
294 0 : filter->status += 2;
295 0 : } else if (filter->status == 0x20 && c > 0x20 && c < 0x7f) { /* kanji first char */
296 0 : filter->status += 1;
297 0 : } else if (c >= 0 && c < 0x80) { /* latin, CTLs */
298 : ;
299 : } else {
300 0 : filter->flag = 1; /* bad */
301 : }
302 0 : break;
303 :
304 : /* case 0x21: KSC5601 second char */
305 : case 1:
306 0 : filter->status &= ~0xf;
307 0 : if (c < 0x21 || c > 0x7e) { /* bad */
308 0 : filter->flag = 1;
309 : }
310 0 : break;
311 :
312 : /* ESC */
313 : case 2:
314 0 : if (c == 0x24) { /* '$' */
315 0 : filter->status++;
316 : } else {
317 0 : filter->flag = 1; /* bad */
318 0 : filter->status &= ~0xf;
319 0 : goto retry;
320 : }
321 0 : break;
322 :
323 : /* ESC $ */
324 : case 3:
325 0 : if (c == 0x29) { /* ')' */
326 0 : filter->status++;
327 : } else {
328 0 : filter->flag = 1; /* bad */
329 0 : filter->status &= ~0xf;
330 0 : goto retry;
331 : }
332 0 : break;
333 :
334 : /* ESC $) */
335 : case 5:
336 0 : if (c == 0x43) { /* 'C' */
337 0 : filter->status = 0x10;
338 : } else {
339 0 : filter->flag = 1; /* bad */
340 0 : filter->status &= ~0xf;
341 0 : goto retry;
342 : }
343 0 : break;
344 :
345 : default:
346 0 : filter->status = 0;
347 : break;
348 : }
349 :
350 0 : return c;
351 : }
352 :
353 :
|