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