1 /*
2 * Copyright (C) 2020 The HIME team, Taiwan
3 * Copyright (C) 2004-2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation version 2.1
8 * of the License.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include <regex.h>
21
22 #include <sys/stat.h>
23
24 #include "hime.h"
25
26 #include "gst.h"
27 #include "gtab.h"
28 #include "hime-conf.h"
29 #include "hime-endian.h"
30 #include "pho.h"
31 #include "tsin.h"
32
33 GTAB_space_pressed_E _gtab_space_auto_first;
34 char **seltab;
35 extern gboolean test_mode;
36 extern unich_t *fullchar[];
37 INMD *cur_inmd;
38 GTAB_ST ggg = {.sel1st_i = MAX_SELKEY - 1};
39
40 /* for array30-like quick code */
41 static char keyrow[] =
42 "qwertyuiop"
43 "asdfghjkl;"
44 "zxcvbnm,./";
45
gtab_phrase_on()46 gboolean gtab_phrase_on () {
47 int val = cur_inmd && cur_inmd->DefChars > 500 &&
48 (gtab_auto_select_by_phrase == GTAB_OPTION_YES ||
49 (gtab_auto_select_by_phrase == GTAB_OPTION_AUTO && (cur_inmd->flag & FLAG_AUTO_SELECT_BY_PHRASE)));
50
51 return val;
52 }
53
gtab_pre_select_on()54 gboolean gtab_pre_select_on () {
55 int val = cur_inmd &&
56 (gtab_pre_select == GTAB_OPTION_YES ||
57 (gtab_pre_select == GTAB_OPTION_AUTO && (cur_inmd->flag & FLAG_GTAB_DISP_FULL_MATCH)));
58
59 return val;
60 }
61
gtab_disp_partial_match_on()62 gboolean gtab_disp_partial_match_on () {
63 int val = cur_inmd &&
64 (gtab_disp_partial_match == GTAB_OPTION_YES ||
65 (gtab_disp_partial_match == GTAB_OPTION_AUTO && (cur_inmd->flag & FLAG_GTAB_DISP_PARTIAL_MATCH)));
66
67 return val;
68 }
69
gtab_vertical_select_on()70 gboolean gtab_vertical_select_on () {
71 int val = cur_inmd &&
72 (gtab_vertical_select == GTAB_OPTION_YES ||
73 (gtab_vertical_select == GTAB_OPTION_AUTO && (cur_inmd->flag & FLAG_GTAB_VERTICAL_SELECTION)));
74
75 return val;
76 }
77
gtab_press_full_auto_send_on()78 gboolean gtab_press_full_auto_send_on () {
79 int val = cur_inmd &&
80 (gtab_press_full_auto_send == GTAB_OPTION_YES ||
81 (gtab_press_full_auto_send == GTAB_OPTION_AUTO && (cur_inmd->flag & FLAG_GTAB_PRESS_FULL_AUTO_SEND)));
82
83 return val;
84 }
85
gtab_unique_auto_send_on()86 gboolean gtab_unique_auto_send_on () {
87 int val = cur_inmd &&
88 (gtab_unique_auto_send == GTAB_OPTION_YES ||
89 (gtab_unique_auto_send == GTAB_OPTION_AUTO && (cur_inmd->flag & FLAG_GTAB_UNIQUE_AUTO_SEND)));
90
91 return val;
92 }
93
key_col(char cha)94 int key_col (char cha) {
95 char *p = strchr (keyrow, cha);
96 if (!p)
97 return 0;
98 return (p - keyrow) % 10;
99 }
100
init_seltab(char *** p)101 void init_seltab (char ***p) {
102 if (!*p) {
103 *p = tmalloc (char *, MAX_SELKEY);
104 int i;
105 for (i = 0; i < MAX_SELKEY; i++)
106 (*p)[i] = (char *) zmalloc (MAX_CIN_PHR);
107 }
108 }
109
file_mtime(char * fname)110 time_t file_mtime (char *fname) {
111 struct stat st;
112
113 if (stat (fname, &st) < 0)
114 return 0;
115
116 return st.st_mtime;
117 }
118
find_tab_file(char * fname,char * out_file)119 time_t find_tab_file (char *fname, char *out_file) {
120 get_hime_user_fname (fname, out_file);
121 time_t mtime = file_mtime (out_file);
122
123 if (!mtime) {
124 strcat (strcpy (out_file, TableDir), "/");
125 strcat (out_file, fname);
126 if (!(mtime = file_mtime (out_file))) {
127 dbg ("init_tab:1 err open %s\n", out_file);
128 return 0;
129 }
130 }
131
132 return mtime;
133 }
134
init_gtab(int inmdno)135 void init_gtab (int inmdno) {
136 FILE *fp;
137 char ttt[128], uuu[128];
138 int i;
139 INMD *inp = &inmd[inmdno];
140 struct TableHead th;
141
142 ggg.sel1st_i = MAX_SELKEY - 1;
143 init_seltab (&seltab);
144
145 // current_CS->b_half_full_char = FALSE;
146 if (!inmd[inmdno].filename || !strcmp (inmd[inmdno].filename, "-")) {
147 // dbg("filename is empty\n");
148 return;
149 }
150
151 time_t mtime;
152
153 if (!(mtime = find_tab_file (inmd[inmdno].filename, ttt)))
154 return;
155
156 char append[64], append_user[128];
157 strcat (strcpy (append, inmd[inmdno].filename), ".append");
158 get_hime_user_fname (append, append_user);
159 time_t mtime_append = file_mtime (append_user);
160
161 if (mtime_append) {
162 char append_user_gtab[128];
163
164 strcat (strcpy (append_user_gtab, append_user), ".gtab");
165 time_t mtime_append_gtab = file_mtime (append_user_gtab);
166
167 if (mtime_append_gtab < mtime || mtime_append_gtab < mtime_append) {
168 char exe[512];
169
170 snprintf (exe, sizeof (exe), HIME_BIN_DIR "/hime-gtab-merge %s %s %s", ttt, append_user, append_user_gtab);
171 dbg ("exe %s\n", exe);
172 system (exe);
173
174 mtime_append_gtab = file_mtime (append_user_gtab);
175 }
176
177 if (mtime_append_gtab) {
178 strcpy (ttt, append_user_gtab);
179 mtime = mtime_append_gtab;
180 free (inmd[inmdno].filename_append);
181 inmd[inmdno].filename_append = strdup (append_user_gtab);
182 }
183 }
184
185 if (mtime == inp->file_modify_time) {
186 // dbg("unchanged\n");
187 // set_gtab_input_method_name(inp->cname);
188 cur_inmd = inp;
189
190 if (gtab_space_auto_first == GTAB_space_auto_first_none)
191 _gtab_space_auto_first = cur_inmd->space_style;
192 else
193 _gtab_space_auto_first = (GTAB_space_pressed_E) gtab_space_auto_first;
194
195 if (gtab_phrase_on () && _gtab_space_auto_first == GTAB_space_auto_first_any)
196 _gtab_space_auto_first = GTAB_space_auto_first_nofull;
197
198 return; /* table is already loaded */
199 }
200
201 inp->file_modify_time = mtime;
202
203 if ((fp = fopen (ttt, "rb")) == NULL)
204 p_err ("init_tab:2 err open %s", ttt);
205
206 dbg ("gtab file %s\n", ttt);
207
208 strcpy (uuu, ttt);
209
210 fread (&th, 1, sizeof (th), fp);
211
212 if (th.keybits < 6 || th.keybits > 7)
213 th.keybits = 6;
214
215 inp->keybits = th.keybits;
216 dbg ("keybits:%d\n", th.keybits);
217
218 #if NEED_SWAP
219 swap_byte_4 (&th.version);
220 swap_byte_4 (&th.flag);
221 swap_byte_4 (&th.space_style);
222 swap_byte_4 (&th.KeyS);
223 swap_byte_4 (&th.MaxPress);
224 swap_byte_4 (&th.M_DUP_SEL);
225 swap_byte_4 (&th.DefC);
226 #endif
227
228 if (th.MaxPress * th.keybits > 32) {
229 inp->max_keyN = 64 / th.keybits;
230 inp->key64 = TRUE;
231 dbg ("it's a 64-bit .gtab\n");
232 } else {
233 inp->max_keyN = 32 / th.keybits;
234 }
235
236 free (inp->endkey);
237 inp->endkey = strdup (th.endkey);
238
239 if (th.flag & FLAG_GTAB_SYM_KBM)
240 dbg ("symbol kbm\n");
241
242 if (th.flag & FLAG_PHRASE_AUTO_SKIP_ENDKEY)
243 dbg ("PHRASE_AUTO_SKIP_ENDKEY\n");
244
245 fread (ttt, 1, th.KeyS, fp);
246 dbg ("KeyS %d\n", th.KeyS);
247
248 if (inp->keyname)
249 free (inp->keyname);
250 inp->keyname = tmalloc (char, (th.KeyS + 3) * CH_SZ);
251 fread (inp->keyname, CH_SZ, th.KeyS, fp);
252 inp->WILD_QUES = th.KeyS + 1;
253 inp->WILD_STAR = th.KeyS + 2;
254 utf8cpy (&inp->keyname[inp->WILD_QUES * CH_SZ], "?"); /* for wild card */
255 utf8cpy (&inp->keyname[inp->WILD_STAR * CH_SZ], "*");
256
257 // for boshiamy
258 gboolean all_full_ascii = TRUE;
259 char keyname_lookup[256];
260
261 memset (keyname_lookup, 0, sizeof (keyname_lookup));
262 for (i = 1; i < th.KeyS; i++) {
263 char *keyname = &inp->keyname[i * CH_SZ];
264 int len = utf8_sz (keyname);
265 int j;
266
267 if (len == 1 && utf8_sz (keyname + 1)) { // array30
268 all_full_ascii = FALSE;
269 break;
270 }
271
272 #define FULLN (127 - ' ')
273
274 for (j = 0; j < FULLN; j++)
275 if (!memcmp (_ (fullchar[j]), keyname, len)) {
276 break;
277 }
278
279 if (j == FULLN) {
280 dbg ("all_full_ascii %d\n", j);
281 all_full_ascii = FALSE;
282 break;
283 }
284
285 keyname_lookup[i] = ' ' + j;
286 }
287
288 if (all_full_ascii) {
289 dbg ("all_full_ascii\n");
290 int mkeys = 1 << th.keybits;
291 free (inp->keyname_lookup);
292 inp->keyname_lookup = (char *) malloc (sizeof (char) * mkeys);
293 memcpy (inp->keyname_lookup, keyname_lookup, mkeys);
294 }
295
296 inp->KeyS = th.KeyS;
297 inp->MaxPress = th.MaxPress;
298 inp->DefChars = th.DefC;
299 free (inp->selkey);
300
301 if (th.selkey[sizeof (th.selkey) - 1]) {
302 char tt[32];
303 memset (tt, 0, sizeof (tt));
304 memcpy (tt, th.selkey, sizeof (th.selkey));
305 strcat (tt, th.selkey2);
306 inp->selkey = strdup (tt);
307 } else
308 inp->selkey = strdup (th.selkey);
309
310 dbg ("selkey %s\n", inp->selkey);
311
312 inp->M_DUP_SEL = th.M_DUP_SEL;
313 inp->space_style = th.space_style;
314 inp->flag = th.flag;
315 free (inp->cname);
316 inp->cname = strdup (th.cname);
317
318 // dbg("MaxPress:%d M_DUP_SEL:%d\n", th.MaxPress, th.M_DUP_SEL);
319
320 free (inp->keymap);
321 inp->keymap = tzmalloc (char, 128);
322
323 if (!(th.flag & FLAG_GTAB_SYM_KBM)) {
324 inp->keymap[(int) '?'] = inp->WILD_QUES;
325 if (!strchr (th.selkey, '*'))
326 inp->keymap[(int) '*'] = inp->WILD_STAR;
327 }
328
329 free (inp->keycol);
330 inp->keycol = tzmalloc (char, th.KeyS + 1);
331 for (i = 0; i < th.KeyS; i++) {
332 dbg ("%c", ttt[i]);
333 inp->keymap[(int) ttt[i]] = i;
334 // dbg("%d %d %c\n", i, inp->keymap[(int)ttt[i]], ttt[i]);
335 if (!BITON (inp->flag, FLAG_KEEP_KEY_CASE))
336 inp->keymap[toupper (ttt[i])] = i;
337 inp->keycol[i] = key_col (ttt[i]);
338 }
339 dbg ("\n");
340
341 free (inp->idx1);
342 inp->idx1 = tmalloc (gtab_idx1_t, th.KeyS + 1);
343 fread (inp->idx1, sizeof (gtab_idx1_t), th.KeyS + 1, fp);
344 #if NEED_SWAP
345 for (i = 0; i <= th.KeyS + 1; i++)
346 swap_byte_4 (&inp->idx1[i]);
347 #endif
348 /* printf("chars: %d\n",th.DefC); */
349 dbg ("inmdno: %d th.KeyS:%d MaxPress:%d\n", inmdno, th.KeyS, th.MaxPress);
350
351 if (inp->key64) {
352 if (inp->tbl64) {
353 dbg ("free %x\n", inp->tbl64);
354 free (inp->tbl64);
355 }
356
357 if ((inp->tbl64 = tmalloc (ITEM64, th.DefC)) == NULL) {
358 p_err ("malloc err");
359 }
360
361 fread (inp->tbl64, sizeof (ITEM64), th.DefC, fp);
362 #if NEED_SWAP
363 for (i = 0; i < th.DefC; i++) {
364 swap_byte_8 (&inp->tbl64[i].key);
365 }
366 #endif
367 } else {
368 if (inp->tbl) {
369 dbg ("free %x\n", inp->tbl);
370 free (inp->tbl);
371 }
372
373 if ((inp->tbl = tmalloc (ITEM, th.DefC)) == NULL) {
374 p_err ("malloc err");
375 }
376
377 fread (inp->tbl, sizeof (ITEM), th.DefC, fp);
378 #if NEED_SWAP
379 for (i = 0; i < th.DefC; i++) {
380 swap_byte_4 (&inp->tbl[i].key);
381 }
382 #endif
383 }
384
385 dbg ("chars %d\n", th.DefC);
386
387 free (inp->qkeys);
388 inp->use_quick = th.qkeys.quick1[1][0][0] != 0; // only array 30 use this
389 if (inp->use_quick) {
390 inp->qkeys = tmalloc (QUICK_KEYS, 1);
391 memcpy (inp->qkeys, &th.qkeys, sizeof (th.qkeys));
392 }
393
394 fread (&inp->phrnum, sizeof (int), 1, fp);
395 #if NEED_SWAP
396 swap_byte_4 (&inp->phrnum);
397 for (i = 0; i < inp->phrnum; i++) {
398 swap_byte_4 (&inp->phrnum);
399 }
400 #endif
401 dbg ("inp->phrnum: %d\n", inp->phrnum);
402 free (inp->phridx);
403 inp->phridx = tmalloc (int, inp->phrnum);
404 fread (inp->phridx, sizeof (int), inp->phrnum, fp);
405 #if NEED_SWAP
406 for (i = 0; i < inp->phrnum; i++) {
407 swap_byte_4 (&inp->phridx[i]);
408 }
409 #endif
410
411 #if 0
412 for(i=0; i < inp->phrnum; i++)
413 dbg("inp->phridx %d %d\n", i, inp->phridx[i]);
414 #endif
415
416 int nbuf = 0;
417 if (inp->phrnum)
418 nbuf = inp->phridx[inp->phrnum - 1];
419
420 free (inp->phrbuf);
421 inp->phrbuf = (char *) malloc (nbuf);
422 fread (inp->phrbuf, 1, nbuf, fp);
423
424 fclose (fp);
425
426 cur_inmd = inp;
427 // reset_inp();
428 // set_gtab_input_method_name(inp->cname);
429 // DispInArea();
430
431 dbg ("key64: %d\n", inp->key64);
432
433 if (gtab_space_auto_first == GTAB_space_auto_first_none)
434 _gtab_space_auto_first = th.space_style;
435 else
436 _gtab_space_auto_first = (GTAB_space_pressed_E) gtab_space_auto_first;
437
438 if (gtab_phrase_on () && _gtab_space_auto_first == GTAB_space_auto_first_any)
439 _gtab_space_auto_first = GTAB_space_auto_first_nofull;
440
441 inp->last_k_bitn = (((cur_inmd->key64 ? 64 : 32) / inp->keybits) - 1) * inp->keybits;
442 inp->kmask = (1 << th.keybits) - 1;
443
444 #if 0
445 for(i='A'; i < 127; i++)
446 printf("%d] %c %d\n", i, i, inp->keymap[i]);
447 #endif
448 #if 0
449 for(i=0; i < Min(100,th.DefC) ; i++) {
450 u_char *ch = tblch(i);
451 dbg("%d] %x %c%c%c\n", i, *((int *)inp->tbl[i].key), ch[0], ch[1], ch[2]);
452 }
453 #endif
454 }
455