1 /* Copyright (C) 2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation version 2.1
6 * of the License.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #include "hime.h"
19
20 #include "gst.h"
21 #include "gtab-buf.h"
22 #include "gtab.h"
23 #include "hime-conf.h"
24 #include "hime-endian.h"
25 #include "pho.h"
26 #include "tsin-parse.h"
27 #include "tsin.h"
28 #include "win-save-phrase.h"
29
30 void disp_gbuf (), ClrIn (), clear_after_put ();
31 gboolean gtab_phrase_on ();
32 int page_len ();
33 void show_win_gtab ();
34 void disp_selection0 (gboolean phrase_selected, gboolean force_disp);
35 void disp_gtab_sel (char *s);
36 void add_cache (int start, int usecount, TSIN_PARSE *out, short match_phr_N, short no_match_ch_N, int tc_len);
37 int ch_pos_find (char *ch, int pos);
38 void inc_gtab_usecount (char *str), ClrSelArea ();
39 void lookup_gtabn (char *ch, char *out);
40 char *htmlspecialchars (char *s, char out[]);
41 void hide_gtab_pre_sel ();
42 gboolean gtab_vertical_select_on ();
43
44 extern gboolean key_press_alt, key_press_ctrl;
45
46 extern gboolean test_mode;
47
48 GEDIT *gbuf;
49 extern char **seltab;
50 extern int ph_key_sz;
51
extract_gtab_key(int start,int len,void * out)52 void extract_gtab_key (int start, int len, void *out) {
53 int i;
54
55 char *p = (char *) out;
56 if (ph_key_sz == 4) {
57 for (i = 0; i < len; i++) {
58 u_int k = gbuf[i + start].keys[0];
59 memcpy (p, &k, sizeof (k));
60 p += sizeof (k);
61 }
62 } else {
63 for (i = 0; i < len; i++) {
64 memcpy (p, &gbuf[i + start].keys[0], sizeof (u_int64_t));
65 p += sizeof (u_int64_t);
66 }
67 }
68 }
69
extract_gbuf_str(int start,int len,char * out)70 void extract_gbuf_str (int start, int len, char *out) {
71 int i;
72 out[0] = 0;
73 for (i = 0; i < len; i++)
74 strcat (out, gbuf[i + start].ch);
75 }
76
gtab_cursor_end()77 gboolean gtab_cursor_end () {
78 return ggg.gbuf_cursor == ggg.gbufN;
79 }
80
dump_gbuf()81 void dump_gbuf () {
82 int i;
83
84 for (i = 0; i < ggg.gbufN; i++) {
85 int j;
86 for (j = 0; j < gbuf[i].selN; j++)
87 printf ("%d:%s ", j, gbuf[i].sel[j]);
88 puts ("");
89 }
90 }
91
92 static unich_t latin_chars[] =
93 "ÀÁÂÃÄÅÆÆÇÈÉÊËÌÍÎÏÐÐÑÒÓÔÕÖØÙÚÛÜÝÞÞßàáâãäåææçèéêëìíîïððñòóôõöøùúûüýþþÿ"
94 "ĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJIJijijĴĵĶķĸĹĺĻļĽľĿŀŁł"
95 "ŃńŅņŇňʼnŊŋŌōŎŏŐőŒŒœœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽž";
96
en_word_len(char * bf)97 int en_word_len (char *bf) {
98 char *s;
99
100 for (s = bf; *s;) {
101 int sz = utf8_sz (s);
102 if (sz == 1) {
103 if (!((*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z') || strchr ("-_'", *s)))
104 break;
105 } else if (sz == 2) {
106 char *p;
107 for (p = latin_chars; *p; p += 2)
108 if (!memcmp (p, s, 2))
109 break;
110 if (!(*p))
111 break;
112 } else if (sz >= 3)
113 break;
114 s += sz;
115 }
116
117 if (*s)
118 return 0;
119 return strlen (bf);
120 }
121
gen_buf_str(int start,gboolean add_spc)122 static char *gen_buf_str (int start, gboolean add_spc) {
123 int i;
124 char *out = tmalloc (char, 1);
125 int outN = 0;
126
127 gboolean last_en_word = FALSE;
128 for (i = start; i < ggg.gbufN; i++) {
129 char *t = gbuf[i].ch;
130 int len = strlen (t);
131
132 if (add_spc && en_word_len (t) && !(gbuf[i].flag & FLAG_CHPHO_GTAB_BUF_EN_NO_SPC)) {
133 if (last_en_word) {
134 out = trealloc (out, char, outN + 1);
135 out[outN++] = ' ';
136 }
137 last_en_word = TRUE;
138 } else
139 last_en_word = FALSE;
140
141 out = trealloc (out, char, outN + len + 1);
142 memcpy (out + outN, t, len);
143 outN += len;
144 }
145
146 out[outN] = 0;
147 return out;
148 }
149
150 extern gboolean last_cursor_off;
151
gen_buf_str_disp()152 static char *gen_buf_str_disp () {
153 if (!ggg.gbufN) {
154 return strdup ("");
155 }
156
157 int i;
158 char *out = tmalloc (char, 1);
159 int outN = 0;
160
161 out[0] = 0;
162 gbuf[ggg.gbufN].ch = " ";
163
164 gboolean last_is_en_word = FALSE;
165
166 int N = last_cursor_off ? ggg.gbufN - 1 : ggg.gbufN;
167 for (i = 0; i <= N; i++) {
168 char addspc[MAX_CIN_PHR * 2 + 2];
169 char spec[MAX_CIN_PHR * 2 + 2];
170 int len = en_word_len (gbuf[i].ch);
171 // dbg("i %d N:%d bufN:%d\n",i,N,ggg.gbufN);
172 if (gbuf[i].flag & FLAG_CHPHO_GTAB_BUF_EN_NO_SPC)
173 len = 0;
174 // dbg("%d %d is_en:%d\n",i, len, last_is_en_word);
175
176 if (len) {
177 if (last_is_en_word) {
178 strcpy (addspc, " ");
179 strcat (addspc, gbuf[i].ch);
180 } else
181 strcpy (addspc, gbuf[i].ch);
182 last_is_en_word = TRUE;
183 } else {
184 last_is_en_word = FALSE;
185 strcpy (addspc, gbuf[i].ch);
186 }
187
188 htmlspecialchars (addspc, spec);
189 // dbg("addspc '%s' spec:%s out:%s\n", addspc, spec, out);
190
191 char www[MAX_CIN_PHR * 2 + 2];
192 char *t = spec;
193
194 if (i == ggg.gbuf_cursor) {
195 if (hime_win_color_use)
196 snprintf (www, sizeof (www), "<span foreground=\"white\" background=\"%s\">%s</span>", tsin_cursor_color, spec);
197 else
198 snprintf (www, sizeof (www), "<span foreground=\"white\" background=\"" TSIN_CURSOR_COLOR_DEFAULT "\">%s</span>", spec);
199 t = www;
200 }
201
202 len = strlen (t);
203 out = trealloc (out, char, outN + len + 1);
204 memcpy (out + outN, t, len);
205 outN += len;
206 out[outN] = 0;
207 }
208
209 return out;
210 }
211
212 void disp_label_edit (char *str);
213
free_pgbuf(GEDIT * p)214 static void free_pgbuf (GEDIT *p) {
215 int i;
216 for (i = 0; i < p->selN; i++)
217 free (p->sel[i]);
218 free (p->sel);
219 p->ch = NULL;
220 p->sel = NULL;
221 p->flag = 0;
222 }
223
free_gbuf(int idx)224 static void free_gbuf (int idx) {
225 free_pgbuf (&gbuf[idx]);
226 }
227
clear_gtab_buf_all()228 static void clear_gtab_buf_all () {
229 int i;
230 for (i = 0; i < ggg.gbufN; i++)
231 free_gbuf (i);
232 ggg.gbuf_cursor = ggg.gbufN = 0;
233 ggg.gtab_buf_select = 0;
234 disp_gbuf ();
235 }
236
disp_gbuf()237 void disp_gbuf () {
238 char *bf = gen_buf_str_disp ();
239 disp_label_edit (bf);
240
241 if (ggg.gbufN && gtab_disp_key_codes)
242 lookup_gtabn (gbuf[ggg.gbufN - 1].ch, NULL);
243
244 free (bf);
245 }
246
clear_gbuf_sel()247 void clear_gbuf_sel () {
248 ggg.gtab_buf_select = 0;
249 ggg.total_matchN = 0;
250 ClrSelArea ();
251 }
252
gbuf_cursor_left()253 int gbuf_cursor_left () {
254 hide_gtab_pre_sel ();
255 if (!ggg.gbuf_cursor)
256 return ggg.gbufN;
257 if (ggg.gtab_buf_select)
258 clear_gbuf_sel ();
259 ClrIn ();
260 ggg.gbuf_cursor--;
261 disp_gbuf ();
262 return 1;
263 }
264
gbuf_cursor_right()265 int gbuf_cursor_right () {
266 hide_gtab_pre_sel ();
267 if (ggg.gbuf_cursor == ggg.gbufN)
268 return ggg.gbufN;
269 if (ggg.gtab_buf_select)
270 clear_gbuf_sel ();
271 ggg.gbuf_cursor++;
272 disp_gbuf ();
273 return 1;
274 }
275
gbuf_cursor_home()276 int gbuf_cursor_home () {
277 hide_gtab_pre_sel ();
278 if (!ggg.gbufN)
279 return 0;
280 if (ggg.gtab_buf_select)
281 clear_gbuf_sel ();
282
283 ggg.gbuf_cursor = 0;
284 disp_gbuf ();
285 return 1;
286 }
287
gbuf_cursor_end()288 int gbuf_cursor_end () {
289 hide_gtab_pre_sel ();
290 if (!ggg.gbufN)
291 return 0;
292 if (ggg.gtab_buf_select)
293 clear_gbuf_sel ();
294
295 ggg.gbuf_cursor = ggg.gbufN;
296 disp_gbuf ();
297 return 1;
298 }
299
300 void inc_gtab_use_count (char *s);
301 void inc_dec_tsin_use_count (void *pho, char *ch, int N);
302
output_gbuf()303 gboolean output_gbuf () {
304 hide_gtab_pre_sel ();
305
306 if (!ggg.gbufN)
307 return FALSE;
308 char *bf = gen_buf_str (0, TRUE);
309 #if 0
310 printf("out %s\n", bf);
311 #endif
312
313 #if 0
314 // single character
315 char *p;
316 for(p=bf; *p; p+=utf8_sz(p))
317 inc_gtab_use_count(p);
318 #endif
319
320 send_text (bf);
321 free (bf);
322
323 int i;
324 for (i = 0; i < ggg.gbufN;) {
325 char t[MAX_CIN_PHR + 1];
326 t[0] = 0;
327 inc_gtab_use_count (gbuf[i].ch);
328
329 int j;
330 for (j = i; j < i + gbuf[i].plen; j++)
331 strcat (t, gbuf[j].ch);
332
333 if (!gbuf[i].plen)
334 i++;
335 else {
336 u_int64_t kk[MAX_PHRASE_LEN];
337 extract_gtab_key (i, gbuf[i].plen, kk);
338 inc_dec_tsin_use_count (kk, t, gbuf[i].plen);
339 i += gbuf[i].plen;
340 }
341 }
342
343 clear_gtab_buf_all ();
344 ClrIn ();
345 return TRUE;
346 }
347
check_gtab_fixed_mismatch(int idx,char * mtch,int plen)348 gboolean check_gtab_fixed_mismatch (int idx, char *mtch, int plen) {
349 int j;
350 char *p = mtch;
351
352 for (j = 0; j < plen; j++) {
353 int u8sz = utf8_sz (p);
354 if (!(gbuf[idx + j].flag & FLAG_CHPHO_FIXED))
355 continue;
356
357 if (memcmp (gbuf[idx + j].ch, p, u8sz))
358 break;
359
360 p += u8sz;
361 }
362
363 if (j < plen)
364 return TRUE;
365
366 return FALSE;
367 }
368
set_gtab_user_head()369 void set_gtab_user_head () {
370 gbuf[ggg.gbuf_cursor].flag |= FLAG_CHPHO_PHRASE_USER_HEAD;
371 }
372
373 #define DBG 0
374
375 void free_cache ();
376 void init_tsin_table ();
377 void set_tsin_parse_len (int);
378
gtab_parse()379 void gtab_parse () {
380 int i;
381 TSIN_PARSE out[MAX_PH_BF_EXT + 1];
382 memset (out, 0, sizeof (out));
383
384 if (test_mode)
385 return;
386
387 if (ggg.gbufN <= 1)
388 return;
389
390 init_tsin_table ();
391
392 init_cache (ggg.gbufN);
393
394 set_tsin_parse_len (ggg.gbufN);
395
396 short smatch_phr_N, sno_match_ch_N;
397 tsin_parse_recur (0, out, &smatch_phr_N, &sno_match_ch_N);
398 #if 0
399 puts("vvvvvvvvvvvvvvvv");
400 for(i=0; i < out[i].len; i++) {
401 printf("%x %d:", out[i].str, out[i].len);
402 utf8_putcharn(out[i].str, out[i].len);
403 }
404 dbg("\n");
405 #endif
406
407 for (i = 0; i < ggg.gbufN; i++)
408 gbuf[i].flag &= ~(FLAG_CHPHO_PHRASE_HEAD | FLAG_CHPHO_PHRASE_BODY);
409
410 int ofsi;
411 for (ofsi = i = 0; out[i].len; i++) {
412 int j, ofsj;
413
414 if (out[i].flag & FLAG_TSIN_PARSE_PHRASE) {
415 gbuf[ofsi].flag |= FLAG_CHPHO_PHRASE_HEAD;
416 gbuf[ofsi].plen = out[i].len;
417 }
418
419 for (ofsj = j = 0; j < out[i].len; j++) {
420 char *w = (char *) &out[i].str[ofsj];
421 int wsz = utf8_sz (w);
422 ofsj += wsz;
423
424 int k;
425 for (k = 0; k < gbuf[ofsi].selN; k++) {
426 int sz = utf8_sz (gbuf[ofsi].sel[k]);
427 if (wsz == sz && !memcmp (gbuf[ofsi].sel[k], w, sz))
428 break;
429 }
430 if (k == gbuf[ofsi].selN) {
431 #if 0
432 dbg("qq ");
433 utf8_putchar(w);
434 p_err(" err 1 selN:%d ofsi:%d", gbuf[ofsi].selN, ofsi);
435 #endif
436 k = 0;
437 }
438
439 if (!(gbuf[ofsi].flag & FLAG_CHPHO_FIXED)) {
440 gbuf[ofsi].ch = gbuf[ofsi].sel[k];
441 gbuf[ofsi].c_sel = k;
442 }
443 gbuf[ofsi].flag |= FLAG_CHPHO_PHRASE_BODY;
444
445 ofsi++;
446 }
447 }
448
449 #if 0
450 puts("-----------------------------");
451 for(i=0;i<ggg.gbufN;i++)
452 puts(gbuf[i].ch);
453 #endif
454 free_cache ();
455 }
456
cursor_gbuf()457 static GEDIT *cursor_gbuf () {
458 return ggg.gbuf_cursor == ggg.gbufN ? &gbuf[ggg.gbuf_cursor - 1] : &gbuf[ggg.gbuf_cursor];
459 }
460
461 typedef struct {
462 char *s;
463 int usecount;
464 int org_seq;
465 } GITEM;
466
467 int get_gtab_use_count (char *s);
468
qcmp_gitem(const void * aa,const void * bb)469 int qcmp_gitem (const void *aa, const void *bb) {
470 int d = ((GITEM *) bb)->usecount - ((GITEM *) aa)->usecount;
471 if (d)
472 return d;
473
474 return ((GITEM *) aa)->org_seq - ((GITEM *) bb)->org_seq;
475 }
476
477 void hide_row2_if_necessary ();
478
479 unich_t auto_end_punch[] = ", . ? : ; ! [ ] 「 」 , 。 ? ; : 、 ~ ! ( )";
insert_gbuf_cursor(char ** sel,int selN,u_int64_t key,gboolean b_gtab_en_no_spc)480 GEDIT *insert_gbuf_cursor (char **sel, int selN, u_int64_t key, gboolean b_gtab_en_no_spc) {
481 hide_row2_if_necessary ();
482
483 if (!sel || !selN)
484 return NULL;
485 // dbg("insert_gbuf_cursor %x\n", key);
486
487 gbuf = trealloc (gbuf, GEDIT, ggg.gbufN + 2);
488
489 GEDIT *pbuf = &gbuf[ggg.gbuf_cursor];
490
491 if (ggg.gbuf_cursor < ggg.gbufN)
492 memmove (&gbuf[ggg.gbuf_cursor + 1], &gbuf[ggg.gbuf_cursor], sizeof (GEDIT) * (ggg.gbufN - ggg.gbuf_cursor));
493
494 ggg.gbuf_cursor++;
495 ggg.gbufN++;
496
497 memset (pbuf, 0, sizeof (GEDIT));
498 memset (gbuf + ggg.gbufN, 0, sizeof (GEDIT));
499
500 GITEM *items = tmalloc (GITEM, selN);
501
502 int i;
503 for (i = 0; i < selN; i++) {
504 items[i].s = sel[i];
505 items[i].org_seq = i;
506 items[i].usecount = get_gtab_use_count (sel[i]);
507 }
508 qsort (items, selN, sizeof (GITEM), qcmp_gitem);
509
510 for (i = 0; i < selN; i++)
511 sel[i] = items[i].s;
512
513 pbuf->ch = sel[0];
514 pbuf->sel = sel;
515 pbuf->selN = selN;
516 pbuf->c_sel = 0;
517 pbuf->keys[0] = key;
518 pbuf->keysN = 1;
519 pbuf->flag = b_gtab_en_no_spc ? FLAG_CHPHO_GTAB_BUF_EN_NO_SPC : 0;
520
521 if (hime_punc_auto_send && ggg.gbufN == ggg.gbuf_cursor && selN == 1 && strstr (_ (auto_end_punch), sel[0])) {
522 char_play (pbuf->ch);
523 output_gbuf ();
524 } else {
525 gtab_parse ();
526 disp_gbuf ();
527 char_play (pbuf->ch);
528 }
529
530 free (items);
531 return pbuf;
532 }
533
set_gbuf_c_sel(int v)534 void set_gbuf_c_sel (int v) {
535 GEDIT *pbuf = cursor_gbuf ();
536
537 pbuf->c_sel = v + ggg.pg_idx;
538 pbuf->ch = pbuf->sel[pbuf->c_sel];
539 // dbg("zzzsel v:%d %d %s\n",v, pbuf->c_sel,pbuf->ch);
540 pbuf->flag |= FLAG_CHPHO_FIXED;
541 ggg.gtab_buf_select = 0;
542 ggg.more_pg = 0;
543 disp_gtab_sel ("");
544 gtab_parse ();
545 disp_gbuf ();
546 // dbg("zzzsel v:%d\n", pbuf->c_sel);
547 }
548
insert_gbuf_cursor1(char * s,u_int64_t key,gboolean b_gtab_en_no_spc)549 GEDIT *insert_gbuf_cursor1 (char *s, u_int64_t key, gboolean b_gtab_en_no_spc) {
550 if (!gtab_phrase_on ())
551 return NULL;
552
553 // dbg("insert_gbuf_cursor1 %s %x\n", s, key);
554 char **sel = tmalloc (char *, 1);
555 sel[0] = strdup (s);
556 GEDIT *e = insert_gbuf_cursor (sel, 1, key, b_gtab_en_no_spc);
557 clear_after_put ();
558 return e;
559 }
560
insert_gbuf_cursor_phrase(char * s,void * key,int N)561 void insert_gbuf_cursor_phrase (char *s, void *key, int N) {
562 u_int *key32 = (u_int *) key;
563 u_int64_t *key64 = (u_int64_t *) key;
564
565 int i;
566 for (i = 0; i < N; i++) {
567 char ch[CH_SZ + 1];
568 int n = utf8cpy (ch, s);
569 u_int64_t v = ph_key_sz == 4 ? key32[i] : key64[i];
570 GEDIT *e = insert_gbuf_cursor1 (ch, v, TRUE);
571 e->flag |= FLAG_CHPHO_FIXED;
572 s += n;
573 }
574 }
575
key_N(u_int64_t k)576 static int key_N (u_int64_t k) {
577 int n = 0;
578 int mask = (1 << KeyBits) - 1;
579
580 while (k) {
581 k >>= mask;
582 n++;
583 }
584
585 return n;
586 }
587
qcmp_key_N(const void * aa,const void * bb)588 static int qcmp_key_N (const void *aa, const void *bb) {
589 u_int64_t a = *((u_int64_t *) aa);
590 u_int64_t b = *((u_int64_t *) bb);
591
592 return key_N (a) - key_N (b);
593 }
594
insert_gbuf_nokey(char * s)595 void insert_gbuf_nokey (char *s) {
596 if (!gtab_phrase_on ())
597 return;
598
599 // dbg("insert_gbuf_nokey\n");
600
601 int i;
602 u_int64_t keys[32];
603 int keysN = 0;
604 int sz = utf8_sz (s);
605
606 keys[0] = 0;
607 if (cur_inmd->tbl64) {
608 for (i = 0; i < cur_inmd->DefChars; i++) {
609 if (!memcmp (cur_inmd->tbl64[i].ch, s, sz)) {
610 u_int64_t t;
611 memcpy (&t, cur_inmd->tbl64[i].key, sizeof (u_int64_t));
612 keys[keysN++] = t;
613 }
614 }
615 } else if (cur_inmd->tbl) {
616 for (i = 0; i < cur_inmd->DefChars; i++) {
617 if (!memcmp (cur_inmd->tbl[i].ch, s, sz)) {
618 u_int t;
619 memcpy (&t, cur_inmd->tbl[i].key, sizeof (u_int));
620 keys[keysN++] = t;
621 }
622 }
623 }
624
625 qsort (keys, keysN, sizeof (u_int64_t), qcmp_key_N);
626
627 GEDIT *e = insert_gbuf_cursor1 (s, keys[0], TRUE);
628 if (keysN > 8)
629 keysN = 8;
630
631 memcpy (e->keys, keys, sizeof (u_int64_t) * keysN);
632 e->keysN = keysN;
633 }
634
insert_gbuf_cursor1_cond(char * s,u_int64_t key,gboolean valid_key)635 void insert_gbuf_cursor1_cond (char *s, u_int64_t key, gboolean valid_key) {
636 if (valid_key)
637 insert_gbuf_cursor1 (s, key, FALSE);
638 else
639 insert_gbuf_nokey (s);
640 }
641
insert_gbuf_cursor_char(char ch)642 void insert_gbuf_cursor_char (char ch) {
643 char t[2];
644 t[0] = ch;
645 t[1] = 0;
646 insert_gbuf_cursor1 (t, 0, TRUE);
647 }
648
649 gboolean gtab_has_input ();
650 void hide_win_gtab ();
651
gtab_buf_delete_ex(gboolean auto_hide)652 int gtab_buf_delete_ex (gboolean auto_hide) {
653 if (ggg.gbuf_cursor == ggg.gbufN)
654 return 0;
655
656 if (test_mode)
657 return 1;
658
659 if (ggg.gtab_buf_select)
660 clear_gbuf_sel ();
661
662 free_gbuf (ggg.gbuf_cursor);
663 memmove (&gbuf[ggg.gbuf_cursor], &gbuf[ggg.gbuf_cursor + 1], sizeof (GEDIT) * (ggg.gbufN - ggg.gbuf_cursor - 1));
664 ggg.gbufN--;
665 disp_gbuf ();
666
667 if (hime_pop_up_win && !gtab_has_input () && auto_hide)
668 hide_win_gtab ();
669
670 return 1;
671 }
672
gtab_buf_delete()673 int gtab_buf_delete () {
674 return gtab_buf_delete_ex (TRUE);
675 }
676
677 gboolean gtab_has_input ();
678 void hide_win_gtab ();
679
gtab_buf_backspace_ex(gboolean auto_hide)680 int gtab_buf_backspace_ex (gboolean auto_hide) {
681 if (!ggg.gbuf_cursor) {
682 return ggg.gbufN > 0;
683 }
684 ggg.gbuf_cursor--;
685 gtab_buf_delete_ex (auto_hide);
686
687 if (hime_pop_up_win && !gtab_has_input () && auto_hide)
688 hide_win_gtab ();
689
690 return 1;
691 }
692
gtab_buf_backspace()693 int gtab_buf_backspace () {
694 return gtab_buf_backspace_ex (TRUE);
695 }
696
gtab_buf_backspaceN(int n)697 void gtab_buf_backspaceN (int n) {
698 int i;
699 for (i = 0; i < n; i++)
700 gtab_buf_backspace_ex (FALSE);
701 }
702
703 extern int more_pg;
704
gtab_disp_sel()705 void gtab_disp_sel () {
706 int idx = ggg.gbuf_cursor == ggg.gbufN ? ggg.gbuf_cursor - 1 : ggg.gbuf_cursor;
707 GEDIT *pbuf = &gbuf[idx];
708
709 int i;
710 for (i = 0; i < cur_inmd->M_DUP_SEL; i++) {
711 int v = i + ggg.pg_idx;
712 if (v >= pbuf->selN)
713 seltab[i][0] = 0;
714 else
715 strcpy (seltab[i], pbuf->sel[v]);
716 }
717
718 if (pbuf->selN > page_len ())
719 ggg.more_pg = 1;
720 disp_selection0 (FALSE, TRUE);
721 show_win_gtab ();
722 }
723
show_buf_select()724 int show_buf_select () {
725 if (!ggg.gbufN)
726 return 0;
727
728 int idx = ggg.gbuf_cursor == ggg.gbufN ? ggg.gbuf_cursor - 1 : ggg.gbuf_cursor;
729 GEDIT *pbuf = &gbuf[idx];
730 ggg.gtab_buf_select = 1;
731 ggg.total_matchN = pbuf->selN;
732 ggg.pg_idx = 0;
733
734 gtab_disp_sel ();
735 hide_gtab_pre_sel ();
736
737 return 1;
738 }
739
gbuf_prev_pg()740 void gbuf_prev_pg () {
741 ggg.pg_idx -= page_len ();
742 if (ggg.pg_idx < 0)
743 ggg.pg_idx = 0;
744
745 gtab_disp_sel ();
746 }
747
gbuf_next_pg()748 void gbuf_next_pg () {
749 ggg.pg_idx += page_len ();
750 if (ggg.pg_idx >= ggg.total_matchN)
751 ggg.pg_idx = 0;
752
753 gtab_disp_sel ();
754 }
755
756 #include "im-client/hime-im-client-attr.h"
757
758 int get_DispInArea_str (char *out);
759
gtab_get_preedit(char * str,HIME_PREEDIT_ATTR attr[],int * pcursor,int * sub_comp_len)760 int gtab_get_preedit (char *str, HIME_PREEDIT_ATTR attr[], int *pcursor, int *sub_comp_len) {
761 int i = 0;
762 int strN = 0;
763 int attrN = 0;
764 int ch_N = 0;
765
766 // dbg("gtab_get_preedit\n");
767 str[0] = 0;
768 *pcursor = 0;
769
770 *sub_comp_len = ggg.ci > 0;
771 #if 1
772 if (ggg.gbufN && !hime_edit_display_ap_only ())
773 *sub_comp_len |= 4;
774 #endif
775 gboolean ap_only = hime_edit_display_ap_only ();
776
777 if (gtab_phrase_on ()) {
778 attr[0].flag = HIME_PREEDIT_ATTR_FLAG_UNDERLINE;
779 attr[0].ofs0 = 0;
780
781 if (ggg.gbufN)
782 attrN = 1;
783
784 gboolean last_is_en_word = FALSE;
785 for (i = 0; i < ggg.gbufN; i++) {
786 char *s = gbuf[i].ch;
787 char tt[MAX_CIN_PHR + 2];
788
789 if (en_word_len (s) && !(gbuf[i].flag & FLAG_CHPHO_GTAB_BUF_EN_NO_SPC)) {
790 if (last_is_en_word) {
791 strcpy (tt, " ");
792 strcat (tt, s);
793 s = tt;
794 }
795 last_is_en_word = TRUE;
796 } else {
797 last_is_en_word = FALSE;
798 }
799
800 int len = strlen (s);
801 int N = utf8_str_N (s);
802 ch_N += N;
803 if (i < ggg.gbuf_cursor)
804 *pcursor += N;
805 if (ap_only && i == ggg.gbuf_cursor) {
806 attr[1].ofs0 = *pcursor;
807 attr[1].ofs1 = *pcursor + N;
808 attr[1].flag = HIME_PREEDIT_ATTR_FLAG_REVERSE;
809 attrN++;
810 }
811
812 if (hime_display_on_the_spot_key () && i == ggg.gbuf_cursor)
813 strN += get_DispInArea_str (str + strN);
814
815 memcpy (str + strN, s, len);
816 strN += len;
817 }
818 }
819
820 if (hime_display_on_the_spot_key () && i == ggg.gbuf_cursor)
821 strN += get_DispInArea_str (str + strN);
822
823 str[strN] = 0;
824
825 attr[0].ofs1 = ch_N;
826 return attrN;
827 }
828
829 extern GtkWidget *gwin_gtab;
gtab_reset()830 void gtab_reset () {
831 if (!gwin_gtab)
832 return;
833 clear_gtab_buf_all ();
834 clear_gbuf_sel ();
835 ClrIn ();
836 return;
837 }
838
839 int ch_to_gtab_keys (INMD *tinmd, char *ch, u_int64_t keys[]);
840
save_gtab_buf_phrase_idx(int idx0,int len)841 void save_gtab_buf_phrase_idx (int idx0, int len) {
842 WSP_S wsp[MAX_PHRASE_LEN];
843
844 memset (wsp, 0, sizeof (wsp));
845 int i;
846 for (i = 0; i < len; i++) {
847 u8cpy (wsp[i].ch, gbuf[idx0 + i].ch);
848 u_int64_t key = gbuf[idx0 + i].keys[0];
849
850 if (!key) {
851 u_int64_t keys[64];
852 int keysN = ch_to_gtab_keys (cur_inmd, wsp[i].ch, keys);
853 if (keysN)
854 key = keys[0];
855 }
856
857 wsp[i].key = key;
858 }
859
860 create_win_save_phrase (wsp, len);
861 }
862
save_gtab_buf_phrase(KeySym key)863 void save_gtab_buf_phrase (KeySym key) {
864 int len = key - '0';
865 int idx0 = ggg.gbuf_cursor - len;
866 int idx1 = ggg.gbuf_cursor - 1;
867
868 if (idx0 < 0 || idx0 > idx1)
869 return;
870
871 save_gtab_buf_phrase_idx (idx0, len);
872 }
873
save_gtab_buf_shift_enter()874 gboolean save_gtab_buf_shift_enter () {
875 if (!ggg.gbufN)
876 return 0;
877 int idx0 = 0;
878 if (ggg.gbufN != ggg.gbuf_cursor)
879 idx0 = ggg.gbuf_cursor;
880 int len = ggg.gbufN - idx0;
881 if (len > MAX_PHRASE_LEN)
882 return 0;
883
884 save_gtab_buf_phrase_idx (idx0, len);
885 gbuf_cursor_end ();
886 return 1;
887 }
888
889 void load_tsin_db0 (char *infname, gboolean is_gtab_i);
890 gboolean init_tsin_table_fname (INMD *p, char *fname);
891
init_tsin_table()892 void init_tsin_table () {
893 char fname[256];
894 if (!current_CS)
895 return;
896
897 init_tsin_table_fname (&inmd[current_CS->in_method], fname);
898 load_tsin_db0 (fname, TRUE);
899 }
900
901 extern u_char scanphr_e (int chpho_idx, int plen, gboolean pho_incr, int *rselN);
902 void init_pre_sel ();
903 void clear_sele ();
904 void set_sele_text (int tN, int i, char *text, int len);
905 void get_win_gtab_geom ();
906 void disp_selections (int x, int y);
907
908 gboolean use_tsin_sel_win ();
909 void init_tsin_selection_win ();
910
911 static int gtab_pre_select_phrase_len;
912
913 void disp_gtab_pre_sel (char *s);
914 extern GtkWidget *gwin1;
915
gtab_scan_pre_select(gboolean b_incr)916 void gtab_scan_pre_select (gboolean b_incr) {
917 if (!gtab_phrase_pre_select)
918 return;
919 // dbg("gtab_scan_pre_select\n");
920
921 tss.pre_selN = 0;
922
923 hide_gtab_pre_sel ();
924
925 if (!gtab_cursor_end () || !ggg.gbufN)
926 return;
927
928 init_tsin_table ();
929 init_pre_sel ();
930
931 int Maxlen = ggg.gbufN;
932 if (Maxlen > MAX_PHRASE_LEN)
933 Maxlen = MAX_PHRASE_LEN;
934
935 int len, selN, max_len = -1, max_selN;
936 for (len = 1; len <= Maxlen; len++) {
937 int idx = ggg.gbufN - len;
938 if (gbuf[idx].flag & FLAG_CHPHO_PHRASE_TAIL)
939 break;
940 int mlen = scanphr_e (ggg.gbufN - len, len, b_incr, &selN);
941 if (mlen) {
942 max_len = len;
943 max_selN = selN;
944 }
945 }
946
947 // dbg("max_len:%d max_selN:%d\n", max_len, max_selN);
948
949 if (max_len < 0 || max_selN >= strlen (cur_inmd->selkey) * 2) {
950 tss.pre_selN = 0;
951 return;
952 }
953
954 gtab_pre_select_phrase_len = max_len;
955
956 scanphr_e (ggg.gbufN - max_len, max_len, b_incr, &selN);
957
958 // dbg("selN:%d %d\n", selN, tss.pre_selN);
959
960 if (selN == 1 && tss.pre_sel[0].len == max_len) {
961 char out[MAX_PHRASE_LEN * CH_SZ + 1];
962 extract_gbuf_str (ggg.gbufN - max_len, max_len, out);
963 if (!strcmp (out, tss.pre_sel[0].str))
964 return;
965 }
966
967 // dbg("selN %d %d\n",selN, tss.pre_selN);
968
969 if (use_tsin_sel_win ()) {
970 if (gwin1)
971 clear_sele ();
972 else
973 init_tsin_selection_win ();
974
975 int i;
976 for (i = 0; i < tss.pre_selN; i++)
977 set_sele_text (tss.pre_selN, i, tss.pre_sel[i].str, -1);
978 get_win_gtab_geom ();
979 disp_selections (-1, -1);
980 return;
981 }
982
983 char tt[4096];
984 tt[0] = 0;
985 int i;
986
987 for (i = 0; i < tss.pre_selN; i++) {
988 char ts[(MAX_PHRASE_LEN + 3) * CH_SZ + 1];
989 char *br = (i < tss.pre_selN - 1 && gtab_vertical_select_on ()) ? "\n" : "";
990 if (hime_win_color_use)
991 snprintf (ts, sizeof (ts), "<span foreground=\"%s\">%c</span>%s%s", hime_sel_key_color, cur_inmd->selkey[i], tss.pre_sel[i].str, br);
992 else
993 snprintf (ts, sizeof (ts), "<span foreground=\"" HIME_SEL_KEY_COLOR_DEFAULT "\">%c</span>%s%s", cur_inmd->selkey[i], tss.pre_sel[i].str, br);
994 strcat (tt, ts);
995 if (!gtab_vertical_select_on () && i < tss.pre_selN - 1)
996 strcat (tt, " ");
997 }
998
999 // dbg("tt %s\n", tt);
1000 disp_gtab_pre_sel (tt);
1001 }
1002
1003 int shift_key_idx (char *s, KeySym xkey);
1004
gtab_pre_select_idx(int c)1005 gboolean gtab_pre_select_idx (int c) {
1006 if (c < 0)
1007 return FALSE;
1008 if (c >= tss.pre_selN)
1009 return TRUE;
1010
1011 #if 0
1012 dbg("c %d %s ggg.gbuf_cursor:%d,%d\n", c, tss.pre_sel[c].str,
1013 ggg.gbuf_cursor, ggg.gbufN);
1014 #endif
1015
1016 gtab_buf_backspaceN (gtab_pre_select_phrase_len);
1017 int len = tss.pre_sel[c].len;
1018 insert_gbuf_cursor_phrase (tss.pre_sel[c].str, tss.pre_sel[c].phkey, len);
1019 gbuf[ggg.gbufN - 1].flag |= FLAG_CHPHO_PHRASE_TAIL;
1020
1021 hide_gtab_pre_sel ();
1022 if (hime_pop_up_win)
1023 hide_win_gtab ();
1024
1025 return TRUE;
1026 }
1027
gtab_pre_select_shift(KeySym key,int kbstate)1028 gboolean gtab_pre_select_shift (KeySym key, int kbstate) {
1029 // dbg("gtab_pre_select_shift %c\n", key);
1030 if (!gtab_phrase_pre_select || !tss.pre_selN)
1031 return FALSE;
1032
1033 int c = shift_key_idx (cur_inmd->selkey, key);
1034 return gtab_pre_select_idx (c);
1035 }
1036
1037 void tsin_toggle_eng_ch ();
1038
feedkey_gtab_release(KeySym xkey,int kbstate)1039 int feedkey_gtab_release (KeySym xkey, int kbstate) {
1040 switch (xkey) {
1041 case XK_Control_L:
1042 case XK_Control_R:
1043 if (key_press_ctrl && tss.pre_selN) {
1044 if (!test_mode) {
1045 tss.ctrl_pre_sel = TRUE;
1046 }
1047 key_press_ctrl = FALSE;
1048 return 1;
1049 } else
1050 return 0;
1051 #if 1
1052 case XK_Shift_L:
1053 case XK_Shift_R:
1054 // dbg("release xkey %x\n", xkey);
1055 if (((tsin_chinese_english_toggle_key == TSIN_CHINESE_ENGLISH_TOGGLE_KEY_Shift) ||
1056 (tsin_chinese_english_toggle_key == TSIN_CHINESE_ENGLISH_TOGGLE_KEY_ShiftL && xkey == XK_Shift_L) ||
1057 (tsin_chinese_english_toggle_key == TSIN_CHINESE_ENGLISH_TOGGLE_KEY_ShiftR && xkey == XK_Shift_R)) &&
1058 key_press_alt) {
1059 if (!test_mode) {
1060 tsin_toggle_eng_ch ();
1061 }
1062 key_press_alt = FALSE;
1063 return 1;
1064 } else
1065 return 0;
1066 #endif
1067 default:
1068 return 0;
1069 }
1070 }
1071
1072 #include "win1.h"
1073
gtab_set_win1_cb()1074 void gtab_set_win1_cb () {
1075 set_win1_cb ((cb_selec_by_idx_t) gtab_pre_select_idx, NULL, NULL);
1076 }
1077