1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /* Copyright 1995 by Sun Microsystems, Inc.
22 * All rights are reserved.
23 */
24
25 #include <stdio.h>
26 #include <string.h>
27 #include "kdefs.h"
28 #include "ktable.h"
29
30 int input_typ(char c);
31
32 struct _cv_state {
33 char temp_ibuf[5];
34 int ibuf_left;
35 int istart, iend;
36 char temp_obuf[1];
37 int flush_obuf;
38 };
39
40 KCHAR packtocomp(KCHAR comb2);
41
42 #ifndef SUNVIEW
43 char vowel_mix(char c1,char c2);
44 #endif
45
46 /*
47 * Hangul 7-bit(KS C 5601) to Standard 2-byte Combination code(87-3)
48 */
49
50
51 static int cur_stat = 1; /* current state of automata */
52 static int cur_act; /* current action of automata */
53
54 static char han_buf[5] = {0,0,0,0,0 }; /* Hangul buffer */
55
56 static int temp_flag; /* Hangul temporary flag */
57 static int han_temp = 0; /* Hangul temporary while two
58 2-byte code are generated */
59
60 static int next_stat[14][21]={ /* next state table[current state][input] */
61 /* input
62 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 */
63 /*state*/
64 /* 0 */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
65 /* 1 */ { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1},
66 /* 2 */ { 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 1, 2},
67 /* 3 */ { 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 1, 2},
68 /* 4 */ { 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 5, 6, 7, 2, 1, 2},
69 /* 5 */ { 0, 4, 9,10,11,12,13,13,13,13,13, 3, 8, 3, 8, 3, 3, 3, 2, 1, 2},
70 /* 6 */ { 0, 4, 9,10,11,12,13,13,13,13,13, 3, 3, 8, 8, 3, 3, 3, 2, 1, 2},
71 /* 7 */ { 0, 4, 9,10,11,12,13,13,13,13,13, 3, 3, 3, 8, 3, 3, 3, 2, 1, 2},
72 /* 8 */ { 0, 4, 9,10,11,12,13,13,13,13,13, 3, 3, 3, 3, 3, 3, 3, 2, 1, 2},
73 /* 9 */ { 0, 4, 4, 4, 4, 4, 4,13, 4, 4, 4, 8, 8, 8, 8, 5, 6, 7, 2, 1, 2},
74 /*10 */ { 0, 4, 4, 4, 4, 4, 4, 4,13,13, 4, 8, 8, 8, 8, 5, 6, 7, 2, 1, 2},
75 /*11 */ { 0, 4,13, 4, 4,13, 4,13, 4,13,13, 8, 8, 8, 8, 5, 6, 7, 2, 1, 2},
76 /*12 */ { 0, 4, 4, 4, 4, 4, 4,13, 4, 4, 4, 8, 8, 8, 8, 5, 6, 7, 2, 1, 2},
77 /*13 */ { 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 5, 6, 7, 2, 1, 2}
78 };
79
80 static int next_act[14][21]={ /* next action table[current state][input] */
81 /*input
82 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 */
83 /*state*/
84 /* 0 */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
85 /* 1 */ { 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 1, 4},/*4-1*/
86 /* 2 */ { 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,15,15,15,15,15,15,15, 1, 3, 4},
87 /* 3 */ { 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,15,15,15,15,15,15,15, 1, 3, 4},
88 /* 4 */ { 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 6, 6, 6, 6, 6, 6, 6,16,12,13},
89 /* 5 */ { 0, 9, 7, 7, 7, 7, 7, 7, 7, 7, 7,10,14,10,14,10,10,10,16,12,13},
90 /* 6 */ { 0, 9, 7, 7, 7, 7, 7, 7, 7, 7, 7,10,10,14,14,10,10,10,16,12,13},
91 /* 7 */ { 0, 9, 7, 7, 7, 7, 7, 7, 7, 7, 7,10,10,10,14,10,10,10,16,12,13},
92 /* 8 */ { 0, 9, 7, 7, 7, 7, 7, 7, 7, 7, 7,10,10,10,10,10,10,10,16,12,13},
93 /* 9 */ { 0, 9, 9, 9, 9, 9, 9, 8, 9, 9, 9,17,17,17,17,17,17,17,16,12,13},
94 /*10 */ { 0, 9, 9, 9, 9, 9, 9, 9, 8, 8, 9,17,17,17,17,17,17,17,16,12,13},
95 /*11 */ { 0, 9, 8, 9, 9, 8, 9, 8, 9, 8, 8,17,17,17,17,17,17,17,16,12,13},
96 /*12 */ { 0, 9, 9, 9, 9, 9, 9, 8, 9, 9, 9,17,17,17,17,17,17,17,16,12,13},
97 /*13 */ { 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,17,17,17,17,17,17,17,16,12,13}
98 };
99
100 KCHAR
getc_12(my_inbuf,my_inbytesleft,st)101 getc_12(my_inbuf, my_inbytesleft, st)
102 char **my_inbuf;
103 size_t *my_inbytesleft;
104 struct _cv_state *st;
105 {
106 register char c; /* input character */
107 register int cur_input; /* type of input character */
108 register KCHAR code_2; /* 2-byte char converted */
109 KCHAR make_2();
110
111 if(temp_flag == 1){
112 code_2 = han_temp;
113 temp_flag = 0;
114 return(code_2);
115 }
116 for(;;){ /* read 1 byte */
117 if (st->ibuf_left) {
118 c = st->temp_ibuf[st->istart];
119 st->istart++;
120 if (st->istart >= st->iend) {
121 st->ibuf_left = 0;
122 st->istart = 0;
123 st->iend = 0;
124 }
125 } else {
126 c = **my_inbuf;
127 (*my_inbuf)++, (*my_inbytesleft)--;
128 }
129 /* run Hangul automata */
130 cur_input = input_typ(c);
131 cur_act = next_act[cur_stat][cur_input];
132 cur_stat = next_stat[cur_stat][cur_input];
133 switch (cur_act) {
134 case 1:
135 break;
136 case 2:
137 break;
138 case 3:
139 break;
140 case 4:
141 return(0x0000 | c);
142 case 5:
143 han_buf[1] = c;
144 break;
145 case 6:
146 han_buf[2] = c;
147 if((code_2=packtocomp(make_2(2))) == 0xFFFF){
148 han_buf[2] = 0;
149 code_2 = make_2(0);
150 if (st->ibuf_left) {
151 st->istart--;
152 } else {
153 (*my_inbuf)--, (*my_inbytesleft)++;
154 }
155 cur_stat = 2;
156 return(code_2);
157 }
158 break;
159 case 7:
160 han_buf[3] = c;
161 if((code_2=packtocomp(make_2(2))) == 0xFFFF){
162 han_buf[3] = 0;
163 code_2 = make_2(0);
164 if (st->ibuf_left) {
165 st->istart--;
166 } else {
167 (*my_inbuf)--, (*my_inbytesleft)++;
168 }
169 cur_stat = 2;
170 return(code_2);
171 }
172 break;
173 case 8:
174 han_buf[4] = c;
175 if((code_2=packtocomp(make_2(2))) == 0xFFFF){
176 han_buf[4] = 0;
177 code_2 = make_2(0);
178 cur_stat = 2;
179 if (st->ibuf_left) {
180 st->istart--;
181 } else {
182 (*my_inbuf)--, (*my_inbytesleft)++;
183 }
184 return(code_2);
185 }
186 break;
187 case 9:
188 code_2 = make_2(0);
189 han_buf[1] = c;
190 return(code_2);
191 case 10:
192 code_2 = make_2(0);
193 han_buf[2] = c;
194 han_temp = make_2(0);
195 temp_flag = 1;
196 return(code_2);
197 case 11: /* Unused */
198 return(make_2(0));
199 case 12:
200 return(make_2(0));
201 case 13:
202 code_2 = make_2(0);
203 han_temp = (0x0000 | c);
204 temp_flag = 1;
205 return(code_2);
206 case 14:
207 han_buf[0] = han_buf[2]; /* Save */
208 han_buf[2] = vowel_mix(han_buf[2],c);
209 if((code_2=packtocomp(make_2(2))) == 0xFFFF){
210 han_buf[2] = han_buf[0]; /* Recover */
211 code_2 = make_2(0);
212 if (st->ibuf_left) {
213 st->istart--;
214 } else {
215 (*my_inbuf)--, (*my_inbytesleft)++;
216 }
217 cur_stat = 2;
218 return(code_2);
219 }
220 break;
221 case 15:
222 han_buf[2] = c;
223 return(make_2(0));
224 case 16:
225 return(make_2(0));
226 case 17:
227 code_2 = make_2(1);
228 han_buf[2] = c;
229 return(code_2);
230 default:
231 break;
232 }
233 }
234 }
235
input_typ(char c)236 int input_typ(char c)
237 {
238 switch(c) {
239 case D_DI_GUD: /* double di-gud 0x48 'H' */
240 case D_BI_UB: /* double bi-ub 0x52 'S' */
241 case D_JI_UD: /* double ji-ud 0x59 'Y' */
242 return(1);
243
244 case GI_UG: /* gi-ug 0x41 'A' */
245 return(2);
246
247 case NI_UN: /* ni-un 0x44 'D' */
248 return(3);
249
250 case RI_UL: /* ri-ul 0x49 'I' */
251 return(4);
252
253 case BI_UB: /* bi-ub 0x52 'R' */
254 return(5);
255
256 case D_GI_UG: /* double gi-ug 0x42 'B' */
257 case DI_GUD: /* di-gud 0x47 'G' */
258 case D_SI_OD: /* double si-od 0x56 'V' */
259 case YI_UNG: /* yi-ung 0x57 'W' */
260 case CHI_UD: /* chi-ud 0x5a 'Z' */
261 case KI_UK: /* ki-uk 0x5b '[' */
262 return(6);
263
264 case SI_OD: /* si-od 0x55 'U' */
265 return(7);
266
267 case JI_UD: /* ji_ud 0x58 'X' */
268 return(8);
269
270 case HI_UD: /* hi-ud 0x5e '^' */
271 return(9);
272
273 case MI_UM: /* mi-um 0x51 'Q' */
274 case PI_UP: /* pi-up 0x5d ']' */
275 case TI_GUT: /* ti-gut 0x51 '\' */
276 return(10);
277
278 case YEA: /* yea 0x6b 'k' */
279 case IA: /* ia 0x64 'd' */
280 case IYAI: /* iyai 0x65 'e' */
281 case IE: /* ie 0x6a 'j' */
282 case YO: /* yo 0x72 'r' */
283 case YU: /* yu 0x77 'g' */
284 return(11);
285
286 case A: /* a 0x62 'b' */
287 case AE: /* ae 0x63 'c' */
288 return(12);
289
290 case E: /* e 0x66 'f' */
291 case EA: /* ea 0x67 'g' */
292 return(13);
293
294 case I: /* i 0x7c '|' */
295 return(14);
296
297 case O: /* o 0x6c 'l' */
298 return(15);
299
300 case U: /* u 0x73 's' */
301 return(16);
302
303 case EU: /* eu 0x7a 'z' */
304 return(17);
305
306 default:
307 if(c == '\016') /* Ctrl-N Hangul delimiter */
308 return(18);
309 if(c == '\017' || c == '\024') /* Ctrl-O Ctrl-T English delimiter */
310 return(19);
311 return(20);
312 }
313 }
314
315 /* This routine make 2-byte code from hangul buffer, if parameter (1)
316 is given, han_buf[4] or han_buf[3] is eliminated before making a
317 2-byte code and inserted han_buf[1] after 2-byte code is made */
318
make_2(n)319 KCHAR make_2(n)
320 register int n;
321 {
322 register KCHAR code_2 = 0;
323 register char tmp = 0;
324 register int i;
325
326 /* if n = 1, save han_buf[3] or han_buf[4] */
327 if (n == 1) {
328 if(han_buf[4]){
329 tmp = han_buf[4];
330 han_buf[4] = 0;
331 } else{
332 tmp = han_buf[3];
333 han_buf[3] = 0;
334 }
335 }
336
337 if(han_buf[1] > BEG_OF_CONSO){
338 code_2 = code_2 | X32_19[han_buf[1] - BEG_OF_CONSO];
339 } else {
340 code_2 = 0x9;
341 }
342
343 if(han_buf[2] > BEG_OF_VOW){
344 code_2 = ((code_2 << 5) | X32_21[han_buf[2] - BEG_OF_VOW]);
345 } else{
346 code_2 = (code_2 << 5) | 0x1;
347 }
348
349 if(han_buf[3] > BEG_OF_CONSO){
350 code_2 = ((code_2 << 5) | X32_28[han_buf[3] - BEG_OF_CONSO]);
351 } else {
352 code_2 = code_2 << 5 | 0x01;
353 }
354
355 if(han_buf[4] > BEG_OF_CONSO){
356 switch(han_buf[3]){
357 /* process gi-ug si-od */
358 case GI_UG:
359 if(han_buf[4] == SI_OD){
360 code_2 += 2;
361 }
362 break;
363
364 /* process ni-un zi-ud, ni-un hi-ud */
365 case NI_UN:
366 switch (han_buf[4]) {
367 case JI_UD:
368 code_2++;
369 break;
370 case HI_UD:
371 code_2 += 2;
372 break;
373 default:
374 break;
375 }
376 break;
377
378 /* process ri-ul gi-ug, ri-ul mi-um,
379 ri-ul bi-ub, ri-ul si-od, ri-ul ti-ut,
380 ri-ul pi-up, ri-ul hi-ud */
381 case RI_UL:
382 switch (han_buf[4]) {
383 case GI_UG:
384 code_2++;
385 break;
386
387 case MI_UM:
388 code_2 += 2;
389 break;
390
391 case BI_UB:
392 code_2 += 3;
393 break;
394
395 case SI_OD:
396 code_2 += 4;
397 break;
398
399 case TI_GUT:
400 code_2 += 5;
401 break;
402
403 case PI_UP:
404 code_2 += 6;
405 break;
406
407 case HI_UD:
408 code_2 += 7;
409 break;
410
411 default:
412 break;
413 }
414 break;
415
416 /* process bi-ub si-od */
417 case BI_UB:
418 if(han_buf[4] == SI_OD){
419 code_2++;
420 }
421 break;
422
423 /* process si-od si-od */
424 case SI_OD:
425 if(han_buf[4] == SI_OD){
426 code_2++;
427 }
428 break;
429 }
430 }
431
432 /* set 1st 7-bit of code_2 */
433 code_2 = code_2 | 0x8000;
434
435 /* initialize Hangul buffer */
436 if(n != 2)
437 for(i = 0; i < 5; i++){
438 han_buf[i] = 0;
439 }
440
441 if(n == 1){ /* restore Hangul temporary */
442 han_buf[1] = tmp;
443 }
444
445 return(code_2);
446 }
447
448 /* This routine make double vowel from han_buf[2] and input character c */
449
450 #ifndef SUNVIEW
vowel_mix(char c1,char c2)451 char vowel_mix(char c1,char c2)
452 {
453 register char c = '\0'; /* result double vowel */
454
455 switch(c1){
456 /* process o-a, o-ae, o-i */
457 case O:
458 switch (c2) {
459 case A:
460 c = c1 + 1;
461 break;
462 case AE:
463 c = c1 + 2;
464 break;
465 case I:
466 c = c1 + 3;
467 break;
468 }
469 break;
470
471 /* process u-oe, u-e, u-i */
472 case U:
473 switch (c2) {
474 case E:
475 c = c1 + 1;
476 break;
477 case EA:
478 c = c1 + 2;
479 break;
480 case I:
481 c = c1 + 3;
482 break;
483 }
484 break;
485
486 /* process eu-i */
487 case EU:
488 if(c2 == I){
489 c = c1 + 1;
490 }
491 break;
492 }
493 return(c);
494 }
495 #endif
496