Intial commit
[profile/ivi/w3m.git] / libwc / hkscs.c
1
2 #include "wc.h"
3 #include "big5.h"
4 #include "hkscs.h"
5 #include "search.h"
6 #include "wtf.h"
7 #ifdef USE_UNICODE
8 #include "ucs.h"
9 #endif
10
11 #define C0 WC_HKSCS_MAP_C0
12 #define GL WC_HKSCS_MAP_GL
13 #define C1 WC_HKSCS_MAP_C1
14 #define LB WC_HKSCS_MAP_LB
15 #define UB WC_HKSCS_MAP_UB
16 #define UH WC_HKSCS_MAP_UH
17
18 wc_uint8 WC_HKSCS_MAP[ 0x100 ] = {
19     C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0,
20     C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0,
21     GL, GL, GL, GL, GL, GL, GL, GL, GL, GL, GL, GL, GL, GL, GL, GL,
22     GL, GL, GL, GL, GL, GL, GL, GL, GL, GL, GL, GL, GL, GL, GL, GL,
23     LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB,
24     LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB,
25     LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB,
26     LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, LB, C0,
27
28     C1, C1, C1, C1, C1, C1, C1, C1, UH, UH, UH, UH, UH, UH, UH, UH,
29     UH, UH, UH, UH, UH, UH, UH, UH, UH, UH, UH, UH, UH, UH, UH, UH,
30     UH, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB,
31     UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB,
32     UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB,
33     UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB,
34     UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB,
35     UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, UB, C1,
36 };
37
38 wc_wchar_t
39 wc_hkscs_to_cs128w(wc_wchar_t cc)
40 {
41     cc.code = WC_HKSCS_N(cc.code);
42     if (cc.code < 0x4000)
43         cc.ccs = WC_CCS_HKSCS_1;
44     else {
45         cc.ccs = WC_CCS_HKSCS_2;
46         cc.code -= 0x4000;
47     }
48     cc.code = WC_N_CS128W(cc.code);
49     return cc;
50 }
51
52 wc_wchar_t
53 wc_cs128w_to_hkscs(wc_wchar_t cc)
54 {
55     cc.code = WC_CS128W_N(cc.code);
56     if (cc.ccs == WC_CCS_HKSCS_2)
57         cc.code += 0x4000;
58     cc.ccs = WC_CCS_HKSCS;
59     cc.code = WC_N_HKSCS(cc.code);
60     return cc;
61 }
62
63 wc_uint32
64 wc_hkscs_to_N(wc_uint32 c)
65 {
66     if (c < 0xA140)     /* 0x8840 - 0xA0FE */
67         return WC_HKSCS_N(c);
68                         /* 0xFA40 - 0xFEFE */
69     return WC_HKSCS_N(c) - 0x59 * 0x9D;
70 }
71
72 Str
73 wc_conv_from_hkscs(Str is, wc_ces ces)
74 {
75     Str os;
76     wc_uchar *sp = (wc_uchar *)is->ptr;
77     wc_uchar *ep = sp + is->length;
78     wc_uchar *p;
79     int state = WC_HKSCS_NOSTATE;
80     wc_uint32 hkscs;
81
82     for (p = sp; p < ep && *p < 0x80; p++) 
83         ;
84     if (p == ep)
85         return is;
86     os = Strnew_size(is->length);
87     if (p > sp)
88         Strcat_charp_n(os, (char *)is->ptr, (int)(p - sp));
89
90     for (; p < ep; p++) {
91         switch (state) {
92         case WC_HKSCS_NOSTATE:
93             switch (WC_HKSCS_MAP[*p]) {
94             case UB:
95             case UH:
96                 state = WC_HKSCS_MBYTE1;
97                 break;
98             case C1:
99                 wtf_push_unknown(os, p, 1);
100                 break;
101             default:
102                 Strcat_char(os, (char)*p);
103                 break;
104             }
105             break;
106         case WC_HKSCS_MBYTE1:
107             if (WC_HKSCS_MAP[*p] & LB) {
108                 hkscs = ((wc_uint32)*(p-1) << 8) | *p;
109                 if (*(p-1) >= 0xA1 && *(p-1) <= 0xF9)
110                     wtf_push(os, WC_CCS_BIG5, hkscs);
111                 else
112                     wtf_push(os, WC_CCS_HKSCS, hkscs);
113             } else
114                 wtf_push_unknown(os, p-1, 2);
115             state = WC_HKSCS_NOSTATE;
116             break;
117         }
118     }
119     switch (state) {
120     case WC_HKSCS_MBYTE1:
121         wtf_push_unknown(os, p-1, 1);
122         break;
123     }
124     return os;
125 }
126
127 void
128 wc_push_to_hkscs(Str os, wc_wchar_t cc, wc_status *st)
129 {
130   while (1) {
131     switch (cc.ccs) {
132     case WC_CCS_US_ASCII:
133         Strcat_char(os, (char)cc.code);
134         return;
135     case WC_CCS_BIG5_1:
136     case WC_CCS_BIG5_2:
137         cc = wc_cs94w_to_big5(cc);
138     case WC_CCS_BIG5:
139         Strcat_char(os, (char)(cc.code >> 8));
140         Strcat_char(os, (char)(cc.code & 0xff));
141         return;
142     case WC_CCS_HKSCS_1:
143     case WC_CCS_HKSCS_2:
144         cc = wc_cs128w_to_hkscs(cc);
145     case WC_CCS_HKSCS:
146         Strcat_char(os, (char)(cc.code >> 8));
147         Strcat_char(os, (char)(cc.code & 0xff));
148         return;
149     case WC_CCS_UNKNOWN_W:
150         if (!WcOption.no_replace)
151             Strcat_charp(os, WC_REPLACE_W);
152         return;
153     case WC_CCS_UNKNOWN:
154         if (!WcOption.no_replace)
155             Strcat_charp(os, WC_REPLACE);
156         return;
157     default:
158 #ifdef USE_UNICODE
159         if (WcOption.ucs_conv)
160             cc = wc_any_to_any_ces(cc, st);
161         else
162 #endif
163             cc.ccs = WC_CCS_IS_WIDE(cc.ccs) ? WC_CCS_UNKNOWN_W : WC_CCS_UNKNOWN;
164         continue;
165     }
166   }
167 }
168
169 Str
170 wc_char_conv_from_hkscs(wc_uchar c, wc_status *st)
171 {
172     static Str os;
173     static wc_uchar hkscsu;
174     wc_uint32 hkscs;
175
176     if (st->state == -1) {
177         st->state = WC_HKSCS_NOSTATE;
178         os = Strnew_size(8);
179     }
180
181     switch (st->state) {
182     case WC_HKSCS_NOSTATE:
183         switch (WC_HKSCS_MAP[c]) {
184         case UB:
185         case UH:
186             hkscsu = c;
187             st->state = WC_HKSCS_MBYTE1;
188             return NULL;
189         case C1:
190             break;
191         default:
192             Strcat_char(os, (char)c);
193             break;
194         }
195         break;
196     case WC_HKSCS_MBYTE1:
197         if (WC_HKSCS_MAP[c] & LB) {
198             hkscs = ((wc_uint32)hkscsu << 8) | c;
199             if (hkscsu >= 0xA1 && hkscsu <= 0xF9 && c >= 0xA1)
200                 wtf_push(os, WC_CCS_BIG5, hkscs);
201             else
202                 wtf_push(os, WC_CCS_HKSCS, hkscs);
203         }
204         break;
205     }
206     st->state = -1;
207     return os;
208 }