1 #include "gcin.h"
2 #include "gtab.h"
3 #include "gcin-conf.h"
4 #include "gcin-endian.h"
5 #include "pho.h"
6 #include "tsin.h"
7 #include "tsin-parse.h"
8 #include "win-save-phrase.h"
9 #include "gtab-buf.h"
10 #include "gst.h"
11 #if WIN32
12 #include <io.h>
13 #endif
14
15 void disp_gbuf(), ClrIn(), clear_after_put();
16 gboolean gtab_phrase_on();
17 int page_len();
18 void show_win_gtab();
19 void disp_selection0(gboolean phrase_selected, gboolean force_disp);
20 void disp_gtab_sel(char *s);
21 void add_cache(int start, int usecount, TSIN_PARSE *out, short match_phr_N, short no_match_ch_N, int tc_len);
22 int ch_pos_find(char *ch, int pos);
23 void inc_gtab_usecount(char *str), ClrSelArea();
24 void lookup_gtabn(char *ch, char *out);
25 char *htmlspecialchars(char *s, char out[]);
26 void hide_gtab_pre_sel();
27 gboolean gtab_vertical_select_on();
28
29 extern gint64 key_press_time, key_press_time_ctrl;
30
31 extern gboolean test_mode;
32
33 GEDIT *gbuf;
34 extern char **seltab;
35 extern int ph_key_sz;
36
extract_gtab_key(gboolean is_en,int start,int len,void * out)37 void extract_gtab_key(gboolean is_en, int start, int len, void *out)
38 {
39 int i;
40 char *p=(char *)out;
41
42 if (is_en) {
43 for(i=0; i < len; i++) {
44 *(p++) = gbuf[i+start].ch[0];
45 }
46 } else
47 if (tsin_hand.ph_key_sz==4) {
48 for(i=0; i < len; i++) {
49 u_int k = gbuf[i+start].keys[0];
50 memcpy(p, &k, sizeof(k));
51 p+=sizeof(k);
52 }
53 } else
54 if (tsin_hand.ph_key_sz==8){
55 for(i=0; i < len; i++) {
56 memcpy(p, &gbuf[i+start].keys[0], sizeof(u_int64_t));
57 p+=sizeof(u_int64_t);
58 }
59 }
60 }
61
extract_gbuf_str(int start,int len,char * out)62 void extract_gbuf_str(int start, int len, char *out)
63 {
64 int i;
65 out[0]=0;
66 for(i=0;i<len;i++)
67 strcat(out, gbuf[i+start].ch);
68 }
69
70
gtab_cursor_end()71 gboolean gtab_cursor_end()
72 {
73 return ggg.gbuf_cursor==ggg.gbufN;
74 }
75
dump_gbuf()76 void dump_gbuf()
77 {
78 int i;
79
80 for(i=0; i<ggg.gbufN; i++) {
81 int j;
82 for(j=0;j < gbuf[i].selN; j++)
83 printf("%d:%s ", j, gbuf[i].sel[j]);
84 puts("");
85 }
86 }
87
88 #if 0
89 static char latin_chars[]=
90 "ÀÁÂÃÄÅÆÆÇÈÉÊËÌÍÎÏÐÐÑÒÓÔÕÖØÙÚÛÜÝÞÞßàáâãäåææçèéêëìíîïððñòóôõöøùúûüýþþÿ"
91 "ĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJIJijijĴĵĶķĸĹĺĻļĽľĿŀŁł"
92 "ŃńŅņŇňʼnŊŋŌōŎŏŐőŒŒœœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽž";
93
94 int en_word_len(char *bf)
95 {
96 char *s;
97
98 for(s=bf;*s;) {
99 int sz = utf8_sz(s);
100 if (sz==1) {
101 if (!(*s >= 'A' && *s<='Z' || *s >= 'a' && *s<='z' || strchr("-_'", *s)))
102 break;
103 } else
104 if (sz==2) {
105 char *p;
106 for (p=latin_chars; *p; p+=2)
107 if (!memcmp(p, s, 2))
108 break;
109 if (!(*p))
110 break;
111 } else
112 if (sz>=3)
113 break;
114 s+=sz;
115 }
116
117 if (*s)
118 return 0;
119 return strlen(bf);
120 }
121 #endif
122
gen_buf_str(int start,gboolean add_spc)123 static char *gen_buf_str(int start, gboolean add_spc)
124 {
125 int i;
126 char *out = tmalloc(char, 1);
127 int outN=0;
128
129 gboolean last_en_word = FALSE;
130 for(i=start;i<ggg.gbufN;i++) {
131 char *t = gbuf[i].ch;
132 int len = strlen(t);
133
134 #if 0
135 if (add_spc && en_word_len(t) && !(gbuf[i].flag & FLAG_CHPHO_GTAB_BUF_EN_NO_SPC)) {
136 if (last_en_word) {
137 out = trealloc(out, char, outN+1);
138 out[outN++]=' ';
139 }
140 last_en_word = TRUE;
141 } else
142 last_en_word = FALSE;
143 #endif
144
145 out = trealloc(out, char, outN+len+1);
146 memcpy(out + outN, t, len);
147 outN+=len;
148 }
149
150 out[outN] = 0;
151 return out;
152 }
153
154 extern gboolean last_cursor_off;
155
gen_buf_str_disp()156 static char *gen_buf_str_disp()
157 {
158 #if 0
159 if (!ggg.gbufN) {
160 return strdup("");
161 }
162 #endif
163
164 int i;
165 char *out = tmalloc(char, 1);
166 int outN=0;
167
168 out[0]=0;
169 // gbuf[ggg.gbufN].ch = " ";
170
171 // gboolean last_is_en_word = FALSE;
172
173 #if 0
174 int N = last_cursor_off ? ggg.gbufN-1:ggg.gbufN;
175 #else
176 int N = ggg.gbufN;
177 #endif
178 for(i=0;i <= N;i++) {
179 char addspc[MAX_CIN_PHR * 2 + 2];
180 char spec[MAX_CIN_PHR * 2 + 2];
181 int len = i<N?strlen(gbuf[i].ch):0;
182 // dbg("i %d N:%d bufN:%d\n",i,N,ggg.gbufN);
183 #if 0
184 if (gbuf[i].flag & FLAG_CHPHO_GTAB_BUF_EN_NO_SPC)
185 len = 0;
186 #endif
187 // dbg("%d %d is_en:%d\n",i, len, last_is_en_word);
188
189 if (len) {
190 #if 0
191 if (last_is_en_word) {
192 strcpy(addspc, " ");
193 strcat(addspc, gbuf[i].ch);
194 } else
195 #endif
196 strcpy(addspc, gbuf[i].ch);
197 // last_is_en_word = TRUE;
198 } else {
199 // last_is_en_word = FALSE;
200 strcpy(addspc, " ");
201 }
202
203 htmlspecialchars(addspc, spec);
204 // dbg("addspc '%s' spec:%s out:%s\n", addspc, spec, out);
205
206 char www[MAX_CIN_PHR * 2 + 2];
207 char *t = spec;
208
209 if (i==ggg.gbuf_cursor) {
210 sprintf(www, "<span background=\"%s\">%s</span>", tsin_pho_mode()?tsin_cursor_color:"green", spec);
211 t = www;
212 }
213
214 len = strlen(t);
215 out = trealloc(out, char, outN+len+1);
216 memcpy(out + outN, t, len);
217 outN+=len;
218 out[outN] = 0;
219 }
220
221 return out;
222 }
223
224
225 void disp_label_edit(char *str);
226
free_pgbuf(GEDIT * p)227 static void free_pgbuf(GEDIT *p) {
228 if (p->sel) {
229 int i;
230 for (i = 0; i < p->selN; i++) {
231 free(p->sel[i]);
232 p->sel[i] = NULL;
233 }
234 free(p->sel);
235 p->sel = NULL;
236 }
237
238 p->ch = NULL;
239 p->selN = 0;
240 p->flag = 0;
241 }
242
free_gbuf(int idx)243 static void free_gbuf(int idx)
244 {
245 if (!gbuf || idx >= ggg.gbufN || idx < 0)
246 return;
247 free_pgbuf(&gbuf[idx]);
248 }
249
clear_gtab_buf_all()250 void clear_gtab_buf_all()
251 {
252 int i;
253 for(i=0;i<ggg.gbufN;i++)
254 free_gbuf(i);
255 ggg.gbuf_cursor = ggg.gbufN=0;
256 ggg.gtab_buf_select = 0;
257 disp_gbuf();
258 }
259
260
261 void minimize_win_gtab();
disp_gbuf()262 void disp_gbuf()
263 {
264 #if WIN32
265 if (test_mode)
266 return;
267 #endif
268 char *bf=gen_buf_str_disp();
269 disp_label_edit(bf);
270
271 if (ggg.gbufN && gtab_disp_key_codes)
272 lookup_gtabn(gbuf[ggg.gbufN-1].ch, NULL);
273
274 free(bf);
275
276 minimize_win_gtab();
277 }
278
clear_gbuf_sel()279 void clear_gbuf_sel()
280 {
281 #if WIN32
282 if (test_mode)
283 return;
284 #endif
285 ggg.gtab_buf_select = 0;
286 ggg.total_matchN = 0;
287 ggg.pg_idx = 0;
288 ClrSelArea();
289 }
290
gbuf_cursor_left()291 int gbuf_cursor_left()
292 {
293 hide_gtab_pre_sel();
294 if (!ggg.gbuf_cursor)
295 return ggg.gbufN;
296 #if WIN32
297 if (test_mode)
298 return 1;
299 #endif
300 if (ggg.gtab_buf_select)
301 clear_gbuf_sel();
302 ClrIn();
303 ggg.gbuf_cursor--;
304 disp_gbuf();
305 return 1;
306 }
307
308
gbuf_cursor_right()309 int gbuf_cursor_right()
310 {
311 hide_gtab_pre_sel();
312 if (ggg.gbuf_cursor==ggg.gbufN)
313 return ggg.gbufN;
314 #if WIN32
315 if (test_mode)
316 return 1;
317 #endif
318 if (ggg.gtab_buf_select)
319 clear_gbuf_sel();
320 ggg.gbuf_cursor++;
321 disp_gbuf();
322 return 1;
323 }
324
gbuf_cursor_home()325 int gbuf_cursor_home()
326 {
327 hide_gtab_pre_sel();
328 if (!ggg.gbufN)
329 return 0;
330 #if WIN32
331 if (test_mode)
332 return 1;
333 #endif
334 if (ggg.gtab_buf_select)
335 clear_gbuf_sel();
336
337 ggg.gbuf_cursor = 0;
338 disp_gbuf();
339 return 1;
340 }
341
342
gbuf_cursor_end()343 int gbuf_cursor_end()
344 {
345 hide_gtab_pre_sel();
346 if (!ggg.gbufN)
347 return 0;
348 #if WIN32
349 if (test_mode)
350 return 1;
351 #endif
352 if (ggg.gtab_buf_select)
353 clear_gbuf_sel();
354
355 ggg.gbuf_cursor = ggg.gbufN;
356 disp_gbuf();
357 return 1;
358 }
359
360 void inc_gtab_use_count(char *s);
361 gboolean inc_tsin_use_count(TSIN_HANDLE *th, void *pho, char *ch, int N);
362 gboolean inc_tsin_use_count_en(char *s, int len);
363 gboolean is_legal_en_char(char *ch);
364 void strtolower(char *u8, int len), hide_win_gtab();
365 gboolean gtab_has_input();
366
output_gbuf_()367 gboolean output_gbuf_()
368 {
369 hide_gtab_pre_sel();
370 // ClrIn();
371
372 if (!ggg.gbufN)
373 return FALSE;
374 #if WIN32
375 if (test_mode)
376 return TRUE;
377 #endif
378 char *bf=gen_buf_str(0, TRUE);
379 #if 1
380 dbg("oggg.gbufN:%d ut %s\n", ggg.gbufN, bf);
381 #endif
382
383 send_text(bf);
384 free(bf);
385
386 int i;
387 for(i=0; i < ggg.gbufN;) {
388 char t[MAX_CIN_PHR+1];
389 t[0]=0;
390 inc_gtab_use_count(gbuf[i].ch);
391
392 int j;
393 gboolean is_en = TRUE;
394 for(j=i; j < ggg.gbufN && j < i+gbuf[i].plen; j++) {
395 strcat(t, gbuf[j].ch);
396 if (!is_legal_en_char(gbuf[j].ch))
397 is_en = FALSE;
398 }
399
400 int plen = gbuf[i].plen;
401 if (!plen) {
402 dbg("plen zero\n");
403 i++;
404 } else {
405 if (is_en) {
406 dbg("is_en %s\n", t);
407 inc_tsin_use_count_en(t, plen);
408 } else {
409 u_int64_t kk[MAX_PHRASE_LEN];
410 extract_gtab_key(FALSE, i, plen, kk);
411 inc_tsin_use_count(&tsin_hand, kk, t, plen);
412 }
413
414 i+=plen;
415 }
416 }
417
418 clear_gtab_buf_all();
419
420 if (gcin_pop_up_win && !gtab_has_input()) {
421 hide_win_gtab();
422 }
423 return TRUE;
424 }
425
output_gbuf()426 gboolean output_gbuf() {
427 ClrIn();
428 return output_gbuf_();
429 }
430
431
check_gtab_fixed_mismatch(int idx,char * mtch,int plen)432 gboolean check_gtab_fixed_mismatch(int idx, char *mtch, int plen)
433 {
434 int j;
435 char *p = mtch;
436
437 for(j=0; j < plen; j++) {
438 int u8sz = utf8_sz(p);
439 if (!(gbuf[idx+j].flag & FLAG_CHPHO_FIXED))
440 continue;
441
442 if (memcmp(gbuf[idx+j].ch, p, u8sz))
443 break;
444
445 p+= u8sz;
446 }
447
448 if (j < plen)
449 return TRUE;
450
451 return FALSE;
452 }
453
set_gtab_user_head()454 void set_gtab_user_head()
455 {
456 #if WIN32
457 if (test_mode)
458 return;
459 #endif
460 gbuf[ggg.gbuf_cursor].flag |= FLAG_CHPHO_PHRASE_USER_HEAD;
461 }
462
463
464 CACHE *cache_lookup(int start);
465
466 #define DBG 0
467
468 void init_cache();
469 void free_cache();
470 void init_tsin_table();
471 void set_tsin_parse_len(int);
472
gtab_parse()473 void gtab_parse()
474 {
475 int i;
476 TSIN_PARSE out[MAX_PH_BF_EXT+1];
477 bzero(out, sizeof(out));
478
479 if (test_mode)
480 return;
481
482 if (ggg.gbufN <= 1)
483 return;
484
485 init_tsin_table();
486
487 init_cache(ggg.gbufN);
488
489 set_tsin_parse_len(ggg.gbufN);
490
491 short smatch_phr_N, sno_match_ch_N;
492 tsin_parse_recur(0, out, &smatch_phr_N, &sno_match_ch_N);
493 #if 0
494 puts("vvvvvvvvvvvvvvvv");
495 for(i=0; i < out[i].len; i++) {
496 printf("%x %d:", out[i].str, out[i].len);
497 utf8_putcharn(out[i].str, out[i].len);
498 }
499 dbg("\n");
500 #endif
501
502 for(i=0; i < ggg.gbufN; i++)
503 gbuf[i].flag &= ~(FLAG_CHPHO_PHRASE_HEAD|FLAG_CHPHO_PHRASE_BODY);
504
505 int ofsi;
506 for(ofsi=i=0; out[i].len; i++) {
507 int j, ofsj;
508
509 if (out[i].flag & FLAG_TSIN_PARSE_PHRASE) {
510 gbuf[ofsi].flag |= FLAG_CHPHO_PHRASE_HEAD;
511 gbuf[ofsi].plen = out[i].len;
512 }
513
514 for(ofsj=j=0; j < out[i].len; j++) {
515 char *w = (char *)&out[i].str[ofsj];
516 int wsz = utf8_sz(w);
517 ofsj += wsz;
518
519 int k;
520 for(k=0;k<gbuf[ofsi].selN; k++) {
521 int sz = utf8_sz(gbuf[ofsi].sel[k]);
522 if (wsz == sz && !memcmp(gbuf[ofsi].sel[k], w, sz))
523 break;
524 }
525 if (k==gbuf[ofsi].selN) {
526 #if 0
527 dbg("qq ");
528 utf8_putchar(w);
529 p_err(" err 1 selN:%d ofsi:%d", gbuf[ofsi].selN, ofsi);
530 #endif
531 k=0;
532 }
533
534 if (!(gbuf[ofsi].flag & FLAG_CHPHO_FIXED)) {
535 gbuf[ofsi].ch = gbuf[ofsi].sel[k];
536 gbuf[ofsi].c_sel = k;
537 }
538 gbuf[ofsi].flag |= FLAG_CHPHO_PHRASE_BODY;
539
540 ofsi++;
541 }
542 }
543
544 #if 0
545 puts("-----------------------------");
546 for(i=0;i<ggg.gbufN;i++)
547 puts(gbuf[i].ch);
548 #endif
549 free_cache();
550 }
551
cursor_gbuf()552 static GEDIT *cursor_gbuf()
553 {
554 return ggg.gbuf_cursor == ggg.gbufN ? &gbuf[ggg.gbuf_cursor-1] : &gbuf[ggg.gbuf_cursor];
555 }
556
557 typedef struct {
558 char *s;
559 int usecount;
560 int org_seq;
561 } GITEM;
562
563 int get_gtab_use_count(char *s);
564
qcmp_gitem(const void * aa,const void * bb)565 int qcmp_gitem(const void *aa, const void *bb)
566 {
567 int d = ((GITEM *)bb)->usecount - ((GITEM *)aa)->usecount;
568 if (d)
569 return d;
570
571 return ((GITEM *)aa)->org_seq - ((GITEM *)bb)->org_seq;
572 }
573
574 void hide_row2_if_necessary();
575
576 char auto_end_punch[]=", . ? : ; ! [ ] 「 」 , 。 ? ; : 、 ~ ! ( )";
insert_gbuf_cursor(char ** sel,int selN,u_int64_t key,gboolean b_gtab_en_no_spc)577 GEDIT *insert_gbuf_cursor(char **sel, int selN, u_int64_t key, gboolean b_gtab_en_no_spc)
578 {
579 #if WIN32
580 if (test_mode)
581 return NULL;
582 #endif
583 dbg("insert_gbuf_cursor test_mode:%d\n", test_mode);
584 hide_row2_if_necessary();
585
586 if (!sel || !selN)
587 return NULL;
588 // dbg("insert_gbuf_cursor %x\n", key);
589
590 gbuf=trealloc(gbuf, GEDIT, ggg.gbufN+2);
591
592 GEDIT *pbuf = &gbuf[ggg.gbuf_cursor];
593
594 if (ggg.gbuf_cursor < ggg.gbufN)
595 memmove(&gbuf[ggg.gbuf_cursor+1], &gbuf[ggg.gbuf_cursor], sizeof(GEDIT) * (ggg.gbufN - ggg.gbuf_cursor));
596
597 ggg.gbuf_cursor++;
598 ggg.gbufN++;
599
600 bzero(pbuf, sizeof(GEDIT));
601 bzero(gbuf+ggg.gbufN, sizeof(GEDIT));
602
603 GITEM *items = tmalloc(GITEM, selN);
604
605 int i;
606 for(i=0; i < selN; i++) {
607 items[i].s = sel[i];
608 items[i].org_seq = i;
609 items[i].usecount = get_gtab_use_count(sel[i]);
610 }
611 qsort(items, selN, sizeof(GITEM), qcmp_gitem);
612
613 for(i=0; i < selN; i++)
614 sel[i] = items[i].s;
615
616 pbuf->ch = sel[0];
617 pbuf->sel = sel;
618 pbuf->selN = selN;
619 pbuf->c_sel = 0;
620 pbuf->keys[0] = key;
621 pbuf->keysN=1;
622 // dbg("insert_gbuf_cursor %s %d\n", sel[0],b_gtab_en_no_spc);
623 pbuf->flag = b_gtab_en_no_spc ? FLAG_CHPHO_GTAB_BUF_EN_NO_SPC:0;
624
625
626 if (!tsin_pho_mode()) {
627 if (ggg.gbufN==ggg.gbuf_cursor && selN==1 && (strstr(",.?/:", sel[0]) /* || (sel[0][0]==' ' && ggg.gbufN==1) */ ) ) {
628 output_gbuf();
629 } else {
630 disp_gbuf();
631 }
632 } else
633 if (gcin_punc_auto_send && ggg.gbufN==ggg.gbuf_cursor && selN==1 && strstr(auto_end_punch, sel[0])) {
634 char_play(pbuf->ch);
635 output_gbuf();
636 } else {
637 gtab_parse();
638 disp_gbuf();
639 char_play(pbuf->ch);
640 }
641
642 free(items);
643 return pbuf;
644 }
645
646
set_gbuf_c_sel(int v)647 void set_gbuf_c_sel(int v)
648 {
649 GEDIT *pbuf = cursor_gbuf();
650
651 pbuf->c_sel = v + ggg.pg_idx;
652 pbuf->ch = pbuf->sel[pbuf->c_sel];
653 // dbg("zzzsel v:%d %d %s\n",v, pbuf->c_sel,pbuf->ch);
654 pbuf->flag |= FLAG_CHPHO_FIXED;
655 ggg.gtab_buf_select = 0;
656 ggg.more_pg = 0;
657 disp_gtab_sel("");
658 gtab_parse();
659 disp_gbuf();
660
661 if (gcin_buffer_select_char_auto_right) {
662 gbuf_cursor_right();
663 }
664 // dbg("zzzsel v:%d\n", pbuf->c_sel);
665 }
666
insert_gbuf_cursor1(char * s,u_int64_t key,gboolean b_gtab_en_no_spc)667 GEDIT *insert_gbuf_cursor1(char *s, u_int64_t key, gboolean b_gtab_en_no_spc)
668 {
669 #if WIN32
670 if (test_mode)
671 return NULL;
672 #endif
673 if (!gtab_phrase_on())
674 return NULL;
675
676 char **sel = tmalloc(char *, 1);
677 sel[0] = strdup(s);
678 // dbg("insert_gbuf_cursor1 %s %llx %d\n", s, key, b_gtab_en_no_spc);
679 GEDIT *e = insert_gbuf_cursor(sel, 1, key, b_gtab_en_no_spc);
680 clear_after_put();
681 return e;
682 }
683
insert_gbuf_cursor_phrase(char * s,void * key,int N)684 void insert_gbuf_cursor_phrase(char *s, void *key, int N)
685 {
686 u_int *key32 = (u_int *)key;
687 u_int64_t *key64 = (u_int64_t *)key;
688
689 // dbg("insert_gbuf_cursor_phrase\n");
690
691 int i;
692 for(i=0; i < N; i++) {
693 char ch[CH_SZ+1];
694 int n = utf8cpy(ch, s);
695 u_int64_t v = tsin_hand.ph_key_sz==4?key32[i]:key64[i];
696 GEDIT *e = insert_gbuf_cursor1(ch, v, TRUE);
697 e->flag |= FLAG_CHPHO_FIXED;
698 s+=n;
699 if (i==0)
700 e->plen = N;
701 }
702 }
703
key_N(u_int64_t k)704 static int key_N(u_int64_t k)
705 {
706 int n=0;
707 int mask = (1 << KeyBits) - 1;
708
709 while (k) {
710 k>>=mask;
711 n++;
712 }
713
714 return n;
715 }
716
qcmp_key_N(const void * aa,const void * bb)717 static int qcmp_key_N(const void *aa, const void *bb)
718 {
719 u_int64_t a = *((u_int64_t *)aa);
720 u_int64_t b = *((u_int64_t *)bb);
721
722 return key_N(a) - key_N(b);
723 }
724
725
insert_gbuf_nokey(char * s)726 void insert_gbuf_nokey(char *s)
727 {
728 #if WIN32
729 if (test_mode)
730 return;
731 #endif
732 if (!gtab_phrase_on())
733 return;
734
735 dbg("insert_gbuf_nokey %s\n", s);
736
737 int i;
738 #define MKEY 32
739 u_int64_t keys[MKEY];
740 int keysN=0;
741 int sz = utf8_sz(s);
742
743 keys[0]=0;
744 if (cur_inmd->tbl64) {
745 for(i=0; i < cur_inmd->DefChars; i++) {
746 if (!memcmp(cur_inmd->tbl64[i].ch, s, sz)) {
747 u_int64_t t;
748 memcpy(&t, cur_inmd->tbl64[i].key, sizeof(u_int64_t));
749 keys[keysN++] = t;
750 if (keysN >= MKEY)
751 break;
752 }
753 }
754 } else
755 if (cur_inmd->tbl) {
756 for(i=0; i < cur_inmd->DefChars; i++) {
757 if (!memcmp(cur_inmd->tbl[i].ch, s, sz)) {
758 u_int t;
759 memcpy(&t, cur_inmd->tbl[i].key, sizeof(u_int));
760 keys[keysN++] = t;
761 if (keysN >= MKEY)
762 break;
763 }
764 }
765 }
766
767 qsort(keys, keysN, sizeof(u_int64_t), qcmp_key_N);
768
769 GEDIT *e = insert_gbuf_cursor1(s, keys[0], FALSE /* TRUE */);
770 if (keysN > 8)
771 keysN = 8;
772
773 memcpy(e->keys, keys, sizeof(u_int64_t) * keysN);
774 e->keysN = keysN;
775 }
776
insert_gbuf_cursor1_cond(char * s,u_int64_t key,gboolean valid_key)777 void insert_gbuf_cursor1_cond(char *s, u_int64_t key, gboolean valid_key)
778 {
779 #if WIN32
780 if (test_mode)
781 return;
782 #endif
783 dbg("insert_gbuf_cursor1_cond %s\n", s);
784 if (valid_key)
785 insert_gbuf_cursor1(s, key, FALSE);
786 else
787 insert_gbuf_nokey(s);
788 }
789
insert_gbuf_cursor_char(char ch)790 void insert_gbuf_cursor_char(char ch)
791 {
792 #if WIN32
793 if (test_mode)
794 return;
795 #endif
796 char t[2];
797 t[0]=ch;
798 t[1]=0;
799 insert_gbuf_cursor1(t, 0, TRUE);
800 }
801
802 gboolean gtab_has_input();
803 void hide_win_gtab();
804
gtab_buf_delete_ex(gboolean auto_hide)805 int gtab_buf_delete_ex(gboolean auto_hide)
806 {
807 if (ggg.gbuf_cursor==ggg.gbufN)
808 return 0;
809 #if WIN32
810 if (test_mode)
811 return 1;
812 #endif
813 if (ggg.gtab_buf_select)
814 clear_gbuf_sel();
815
816 free_gbuf(ggg.gbuf_cursor);
817 memmove(&gbuf[ggg.gbuf_cursor], &gbuf[ggg.gbuf_cursor+1], sizeof(GEDIT) * (ggg.gbufN - ggg.gbuf_cursor -1));
818 ggg.gbufN--;
819 disp_gbuf();
820
821 if (gcin_pop_up_win && !gtab_has_input() && auto_hide)
822 hide_win_gtab();
823
824 return 1;
825 }
826
gtab_buf_delete()827 int gtab_buf_delete()
828 {
829 return gtab_buf_delete_ex(TRUE);
830 }
831
832
833 gboolean gtab_has_input();
834 void hide_win_gtab();
835
gtab_buf_backspace_ex(gboolean auto_hide)836 int gtab_buf_backspace_ex(gboolean auto_hide)
837 {
838 if (!ggg.gbuf_cursor) {
839 return ggg.gbufN>0;
840 }
841
842 #if WIN32
843 if (test_mode)
844 return 1;
845 #endif
846
847 ggg.gbuf_cursor--;
848 gtab_buf_delete_ex(auto_hide);
849
850 if (gcin_pop_up_win && !gtab_has_input() && auto_hide)
851 hide_win_gtab();
852
853 return 1;
854 }
855
gtab_buf_backspace()856 int gtab_buf_backspace()
857 {
858 return gtab_buf_backspace_ex(TRUE);
859 }
860
861
gtab_buf_backspaceN(int n)862 void gtab_buf_backspaceN(int n)
863 {
864 int i;
865 for(i=0; i < n; i++)
866 gtab_buf_backspace_ex(FALSE);
867 }
868
869 extern int more_pg;
870
gtab_disp_sel()871 void gtab_disp_sel()
872 {
873 int idx = ggg.gbuf_cursor==ggg.gbufN ? ggg.gbuf_cursor-1:ggg.gbuf_cursor;
874 GEDIT *pbuf=&gbuf[idx];
875
876 int i;
877 for(i=0; i < cur_inmd->M_DUP_SEL; i++) {
878 int v = i + ggg.pg_idx;
879 if (v >= pbuf->selN)
880 seltab[i][0]=0;
881 else
882 strcpy(seltab[i], pbuf->sel[v]);
883 }
884
885 if (pbuf->selN > page_len())
886 ggg.more_pg = 1;
887 #if WIN32
888 show_win_gtab();
889 disp_selection0(FALSE, TRUE);
890 #else
891 disp_selection0(FALSE, TRUE);
892 show_win_gtab();
893 #endif
894 }
895
896
show_buf_select()897 int show_buf_select()
898 {
899 if (!ggg.gbufN)
900 return 0;
901 #if WIN32
902 if (test_mode)
903 return 1;
904 #endif
905 int idx = ggg.gbuf_cursor==ggg.gbufN ? ggg.gbuf_cursor-1:ggg.gbuf_cursor;
906 GEDIT *pbuf=&gbuf[idx];
907 ggg.gtab_buf_select = 1;
908 ggg.total_matchN = pbuf->selN;
909 ggg.pg_idx = 0;
910
911 gtab_disp_sel();
912 hide_gtab_pre_sel();
913
914 return 1;
915 }
916
gbuf_prev_pg()917 void gbuf_prev_pg()
918 {
919 ggg.pg_idx -= page_len();
920 if (ggg.pg_idx < 0)
921 ggg.pg_idx = 0;
922
923 gtab_disp_sel();
924 }
925
gbuf_next_pg()926 void gbuf_next_pg()
927 {
928 #if WIN32
929 if (test_mode)
930 return;
931 #endif
932 ggg.pg_idx += page_len();
933 if (ggg.pg_idx >= ggg.total_matchN)
934 ggg.pg_idx = 0;
935
936 gtab_disp_sel();
937 }
938
939 #include "im-client/gcin-im-client-attr.h"
940
941 int get_DispInArea_str(char *out);
942
gtab_get_preedit(char * str,GCIN_PREEDIT_ATTR attr[],int * pcursor,int * sub_comp_len)943 int gtab_get_preedit(char *str, GCIN_PREEDIT_ATTR attr[], int *pcursor, int *sub_comp_len)
944 {
945 int i=0;
946 int strN=0;
947 int attrN=0;
948 int ch_N=0;
949
950 // dbg("gtab_get_preedit\n");
951 str[0]=0;
952 *pcursor=0;
953
954 #if WIN32 || 1
955 *sub_comp_len = ggg.ci > 0;
956 #if 1
957 if (ggg.gbufN && !gcin_edit_display_ap_only())
958 *sub_comp_len|=4;
959 #endif
960 #endif
961 gboolean ap_only = gcin_edit_display_ap_only();
962
963 if (gtab_phrase_on()) {
964 attr[0].flag=GCIN_PREEDIT_ATTR_FLAG_UNDERLINE;
965 attr[0].ofs0=0;
966
967 if (ggg.gbufN)
968 attrN=1;
969
970 // gboolean last_is_en_word = FALSE;
971 for(i=0; i < ggg.gbufN; i++) {
972 char *s = gbuf[i].ch;
973 char tt[MAX_CIN_PHR+2];
974 #if 0
975 if (en_word_len(s) && !(gbuf[i].flag & FLAG_CHPHO_GTAB_BUF_EN_NO_SPC)) {
976 if (last_is_en_word) {
977 strcpy(tt, " ");
978 strcat(tt, s);
979 s = tt;
980 }
981 last_is_en_word = TRUE;
982 } else {
983 last_is_en_word = FALSE;
984 }
985 #endif
986 int len = strlen(s);
987 int N = utf8_str_N(s);
988 ch_N+=N;
989 if (i < ggg.gbuf_cursor)
990 *pcursor+=N;
991 if (ap_only && i==ggg.gbuf_cursor) {
992 attr[1].ofs0=*pcursor;
993 attr[1].ofs1=*pcursor+N;
994 attr[1].flag=GCIN_PREEDIT_ATTR_FLAG_REVERSE;
995 attrN++;
996 }
997
998 if (gcin_display_on_the_spot_key() && i==ggg.gbuf_cursor)
999 strN += get_DispInArea_str(str+strN);
1000
1001 memcpy(str+strN, s, len);
1002 strN+=len;
1003 }
1004 }
1005
1006
1007 if (gcin_display_on_the_spot_key() && i==ggg.gbuf_cursor)
1008 strN += get_DispInArea_str(str+strN);
1009
1010 str[strN]=0;
1011
1012 attr[0].ofs1 = ch_N;
1013 return attrN;
1014 }
1015
1016 extern GtkWidget *gwin_gtab;
gtab_reset()1017 void gtab_reset()
1018 {
1019 #if UNIX
1020 if (!gwin_gtab)
1021 return;
1022 #endif
1023 #if WIN32
1024 if (test_mode)
1025 return;
1026 #endif
1027 clear_gtab_buf_all();
1028 clear_gbuf_sel();
1029 ClrIn();
1030 if (gcin_pop_up_win)
1031 hide_win_gtab();
1032 return;
1033 }
1034
1035 int ch_to_gtab_keys(INMD *tinmd, char *ch, u_int64_t keys[]);
1036
save_gtab_buf_phrase_idx(int idx0,int len)1037 void save_gtab_buf_phrase_idx(int idx0, int len)
1038 {
1039 if (len > MAX_PHRASE_LEN)
1040 return;
1041 WSP_S wsp[MAX_PHRASE_LEN];
1042
1043 bzero(wsp, sizeof(wsp));
1044 int i;
1045 for(i=0; i < len; i++) {
1046 u8cpy(wsp[i].ch, gbuf[idx0 + i].ch);
1047 u_int64_t key = gbuf[idx0 + i].keys[0];
1048
1049 if (!key) {
1050 u_int64_t keys[64];
1051 int keysN = ch_to_gtab_keys(cur_inmd, wsp[i].ch, keys);
1052 if (keysN)
1053 key = keys[0];
1054 }
1055
1056 wsp[i].key = key;
1057 }
1058
1059 create_win_save_phrase(wsp, len);
1060 }
1061
save_gtab_buf_phrase(KeySym key)1062 void save_gtab_buf_phrase(KeySym key)
1063 {
1064 int len = key - '0';
1065 int idx0 = ggg.gbuf_cursor - len;
1066 int idx1 = ggg.gbuf_cursor - 1;
1067
1068 if (idx0 < 0 || idx0 > idx1)
1069 return;
1070
1071 save_gtab_buf_phrase_idx(idx0, len);
1072 }
1073
save_gtab_buf_shift_enter()1074 gboolean save_gtab_buf_shift_enter()
1075 {
1076 int start = ggg.gbufN == ggg.gbuf_cursor ? 0:ggg.gbuf_cursor;
1077 int N = ggg.gbufN - start;
1078 if (!N || N > MAX_CIN_PHR_N)
1079 return 0;
1080 #if WIN32
1081 if (test_mode)
1082 return TRUE;
1083 #endif
1084 save_gtab_buf_phrase_idx(start, N);
1085 gbuf_cursor_end();
1086 return 1;
1087 }
1088
1089
1090 void load_tsin_db0(char *infname, gboolean is_gtab_i);
1091 gboolean init_tsin_table_fname(INMD *p, char *fname);
1092
init_tsin_table()1093 void init_tsin_table()
1094 {
1095 char fname[256];
1096 if (!current_CS)
1097 return;
1098
1099 init_tsin_table_fname(&inmd[current_CS->in_method], fname);
1100 load_tsin_db0(fname, TRUE);
1101 }
1102
1103 u_char scanphr_e(TSIN_HANDLE *th, gboolean is_gtab, int chpho_idx, int plen, gboolean pho_incr, int *rselN);
1104 void init_pre_sel();
1105 void clear_sele();
1106 void set_sele_text(int i, char *text, int len);
1107 void get_win_gtab_geom();
1108 void disp_selections(int x, int y);
1109
1110 gboolean use_tsin_sel_win();
1111 void init_tsin_selection_win();
1112
1113 static int gtab_pre_select_phrase_len;
1114
1115 void disp_gtab_pre_sel(char *s);
1116 extern GtkWidget *gwin1;
1117
gtab_scan_pre_select(gboolean b_incr)1118 void gtab_scan_pre_select(gboolean b_incr)
1119 {
1120 #if WIN32
1121 if (test_mode)
1122 return;
1123 #endif
1124
1125 if (!gtab_phrase_pre_select)
1126 return;
1127 // dbg("gtab_scan_pre_select\n");
1128
1129 tss.pre_selN = 0;
1130
1131 hide_gtab_pre_sel();
1132
1133 if (!gtab_cursor_end() || !ggg.gbufN)
1134 return;
1135
1136 init_tsin_table();
1137 init_pre_sel();
1138
1139 int Maxlen = ggg.gbufN;
1140 if (Maxlen > MAX_PHRASE_LEN)
1141 Maxlen = MAX_PHRASE_LEN;
1142
1143 int len, selN, max_len=-1, max_selN;
1144 for(len=1; len <= Maxlen; len++) {
1145 int idx = ggg.gbufN - len;
1146 if (gbuf[idx].flag & FLAG_CHPHO_PHRASE_TAIL)
1147 break;
1148 int mlen = scanphr_e(&tsin_hand, TRUE, ggg.gbufN - len, len, b_incr, &selN);
1149 if (mlen) {
1150 max_len = len;
1151 max_selN = selN;
1152 }
1153 }
1154
1155 // dbg("max_len:%d max_selN:%d\n", max_len, max_selN);
1156
1157 if (max_len < 0 || max_selN >= strlen(cur_inmd->selkey) * 2) {
1158 tss.pre_selN = 0;
1159 return;
1160 }
1161
1162 gtab_pre_select_phrase_len = max_len;
1163
1164 scanphr_e(&tsin_hand, TRUE, ggg.gbufN - max_len, max_len, b_incr, &selN);
1165
1166 // dbg("selN:%d %d\n", selN, tss.pre_selN);
1167
1168 if (selN==1 && tss.pre_sel[0].len==max_len) {
1169 char out[MAX_PHRASE_LEN * CH_SZ + 1];
1170 extract_gbuf_str(ggg.gbufN - max_len, max_len, out);
1171 if (!strcmp(out, tss.pre_sel[0].str))
1172 return;
1173 }
1174
1175 // dbg("selN %d %d\n",selN, tss.pre_selN);
1176
1177 if (use_tsin_sel_win()) {
1178 if (gwin1)
1179 clear_sele();
1180 else
1181 init_tsin_selection_win();
1182
1183 int i;
1184 for(i=0;i<tss.pre_selN; i++)
1185 set_sele_text(i,tss.pre_sel[i].str, -1);
1186 get_win_gtab_geom();
1187 disp_selections(-1, -1);
1188 return;
1189 }
1190
1191 char tt[4096];
1192 tt[0]=0;
1193 int i;
1194
1195 for(i=0;i<tss.pre_selN; i++) {
1196 char ts[(MAX_PHRASE_LEN+3) * CH_SZ + 1];
1197 char *br= (i < tss.pre_selN-1 && gtab_vertical_select_on())?"\n":"";
1198
1199 sprintf(ts, "<span foreground=\"%s\">%c</span>%s%s", gcin_sel_key_color,
1200 cur_inmd->selkey[i], tss.pre_sel[i].str, br);
1201 strcat(tt, ts);
1202 if (!gtab_vertical_select_on() && i < tss.pre_selN-1)
1203 strcat(tt, " ");
1204 }
1205
1206 // dbg("tt %s\n", tt);
1207 disp_gtab_pre_sel(tt);
1208 }
1209
1210
1211 int shift_key_idx(char *s, KeySym xkey);
1212
gtab_pre_select_idx(int c)1213 gboolean gtab_pre_select_idx(int c)
1214 {
1215 if (c < 0)
1216 return FALSE;
1217 if (c >= tss.pre_selN)
1218 return TRUE;
1219
1220 #if 0
1221 dbg("c %d %s ggg.gbuf_cursor:%d,%d\n", c, tss.pre_sel[c].str,
1222 ggg.gbuf_cursor, ggg.gbufN);
1223 #endif
1224 #if WIN32
1225 if (!test_mode)
1226 #endif
1227 {
1228 gtab_buf_backspaceN(gtab_pre_select_phrase_len);
1229 int len = tss.pre_sel[c].len;
1230
1231 if (!tsin_pho_mode()) {
1232 len = utf8_str_N(tss.pre_sel[c].str);
1233 }
1234
1235 insert_gbuf_cursor_phrase(tss.pre_sel[c].str, tss.pre_sel[c].phkey, len);
1236 gbuf[ggg.gbufN-1].flag |= FLAG_CHPHO_PHRASE_TAIL;
1237
1238 hide_gtab_pre_sel();
1239 if (gcin_edit_display_ap_only() && gcin_on_the_spot_key)
1240 hide_win_gtab();
1241 }
1242 return TRUE;
1243 }
1244
1245 extern char noshi_sele[], shift_sele[];
1246
gtab_pre_select_shift(KeySym key,int kbstate)1247 gboolean gtab_pre_select_shift(KeySym key, int kbstate)
1248 {
1249 dbg("gtab_pre_select_shift %c\n", key);
1250 if (!gtab_phrase_pre_select || !tss.pre_selN)
1251 return FALSE;
1252
1253 // If the key(123) is not defined as gtab keys, the shift keys(!@#) should be used for punc, not preselect
1254 int c;
1255 char *p;
1256 if ((p=strchr(cur_inmd->selkey, key))) {
1257 c = p - cur_inmd->selkey;
1258 return gtab_pre_select_idx(c);
1259 } else
1260 c = shift_key_idx(cur_inmd->selkey, key);
1261
1262 if (c < 0)
1263 return FALSE;
1264 p = strchr(shift_sele, key);
1265 if (!p)
1266 return FALSE;
1267 int idx = p - shift_sele;
1268 char noshi = noshi_sele[idx];
1269 if (!cur_inmd->keymap[noshi])
1270 return FALSE;
1271
1272 return gtab_pre_select_idx(c);
1273 }
1274
1275 void tsin_toggle_eng_ch();
1276 void set_key_codes_label(char *s, int better);
1277
feedkey_gtab_release(KeySym xkey,int kbstate)1278 int feedkey_gtab_release(KeySym xkey, int kbstate)
1279 {
1280 gint64 kpt;
1281
1282 switch (xkey) {
1283 case XK_Control_L:
1284 case XK_Control_R:
1285 kpt = key_press_time_ctrl;
1286 if (!test_mode)
1287 key_press_time_ctrl = 0;
1288
1289 if (current_time() - kpt < 300000 && tss.pre_selN) {
1290 if (!test_mode) {
1291 tss.ctrl_pre_sel = TRUE;
1292 }
1293 return 1;
1294 } else
1295 return 0;
1296 #if 1
1297 case XK_Shift_L:
1298 case XK_Shift_R:
1299 kpt = key_press_time;
1300 if (!test_mode)
1301 key_press_time = 0;
1302
1303 // dbg("release xkey %x\n", xkey);
1304 if (
1305 ( (tsin_chinese_english_toggle_key == TSIN_CHINESE_ENGLISH_TOGGLE_KEY_Shift) ||
1306 (tsin_chinese_english_toggle_key == TSIN_CHINESE_ENGLISH_TOGGLE_KEY_ShiftL
1307 && xkey == XK_Shift_L) ||
1308 (tsin_chinese_english_toggle_key == TSIN_CHINESE_ENGLISH_TOGGLE_KEY_ShiftR
1309 && xkey == XK_Shift_R))
1310 && current_time() - kpt < 300000) {
1311 if (!test_mode) {
1312 tsin_toggle_eng_ch();
1313 if (!tsin_pho_mode())
1314 set_key_codes_label(NULL, FALSE);
1315 ClrIn();
1316 disp_gbuf();
1317 }
1318 return 1;
1319 } else
1320 return 0;
1321 #endif
1322 default:
1323 return 0;
1324 }
1325 }
1326
1327 #include "win1.h"
1328
gtab_set_win1_cb()1329 void gtab_set_win1_cb()
1330 {
1331 set_win1_cb((cb_selec_by_idx_t)gtab_pre_select_idx, NULL, NULL);
1332 }
1333
1334 void load_en_db();
1335 u_char scanphr_en(TSIN_HANDLE *th, gboolean is_gtab, int chpho_idx, int plen, int *rselN);
1336 gboolean misalpha(char c);
1337 void disp_pre_sel_page();
1338 extern char *wselkey;
1339 void get_en_miss_cand(FILE *fp, char *s, int slen, char best[][MAX_PHRASE_LEN]);
1340
disp_gtab_pre()1341 void disp_gtab_pre() {
1342 if (use_tsin_sel_win()) {
1343 if (gwin1)
1344 clear_sele();
1345 else
1346 init_tsin_selection_win();
1347
1348 dbg("-------------> tss.pre_selN:%d\n", tss.pre_selN);
1349 int i;
1350 for(i=0;i<tss.pre_selN; i++)
1351 set_sele_text(i,tss.pre_sel[i].str, -1);
1352 get_win_gtab_geom();
1353 disp_selections(-1, -1);
1354 return;
1355 }
1356
1357 char tt[4096];
1358 tt[0]=0;
1359 int i;
1360
1361 for(i=0;i<tss.pre_selN; i++) {
1362 char ts[(MAX_PHRASE_LEN+3) * CH_SZ + 1];
1363 char *br= (i < tss.pre_selN-1 && gtab_vertical_select_on())?"\n":"";
1364
1365 sprintf(ts, "<span foreground=\"%s\">%c</span>%s%s", gcin_sel_key_color,
1366 wselkey[i], tss.pre_sel[i].str, br);
1367 strcat(tt, ts);
1368 if (!gtab_vertical_select_on() && i < tss.pre_selN-1)
1369 strcat(tt, " ");
1370 }
1371
1372 dbg("tt %s\n", tt);
1373 disp_gtab_pre_sel(tt);
1374 }
1375
gtab_en_scan_pre_select()1376 void gtab_en_scan_pre_select()
1377 {
1378 dbg("gtab_en_scan_pre_select\n");
1379
1380 if (!en_hand.fph)
1381 load_en_db();
1382
1383 dbg("gtab_en_scan_pre_select %d th->ph_key_sz:%d\n", tss.c_len, en_hand.ph_key_sz);
1384
1385 tss.pre_selN = 0;
1386
1387 hide_gtab_pre_sel();
1388
1389 if (!ggg.gbuf_cursor || !ggg.gbufN)
1390 return;
1391
1392 init_pre_sel();
1393
1394 int Maxlen = ggg.gbufN;
1395 if (Maxlen > MAX_PHRASE_LEN)
1396 Maxlen = MAX_PHRASE_LEN;
1397
1398 int len, selN, max_len=-1, max_selN=-1;
1399 for(len=2; len <= Maxlen; len++) {
1400 int idx = ggg.gbufN - len;
1401 if (gbuf[idx].flag & FLAG_CHPHO_PHRASE_TAIL) {
1402 // dbg("phrase tail %d\n", idx);
1403 break;
1404 }
1405
1406 char c = gbuf[idx].ch[0];
1407 char c1 = idx==0?0:gbuf[idx-1].ch[0];
1408 char c2 = idx<=1?0:gbuf[idx-2].ch[0];
1409
1410 if (c & 0x80)
1411 break;
1412
1413 if (misalpha(c1))
1414 continue;
1415 if (misalpha(c) && c1=='\'' && misalpha(c2))
1416 continue;
1417
1418 int mlen = scanphr_en(&en_hand, TRUE, ggg.gbufN - len, len, &selN);
1419 dbg("mlen %d len:%d\n", mlen, len);
1420
1421 if (mlen) {
1422 max_len = len;
1423 max_selN = selN;
1424 }
1425 }
1426
1427 dbg("max_len:%d max_selN:%d\n", max_len, max_selN);
1428
1429 if (max_len < 0 || max_selN > 50) { // will ctrl press/release + keys as select keys
1430 dbg("too many or no %d\n", max_len);
1431 tss.pre_selN=0;
1432
1433 #if 1
1434 int i;
1435 for(i=ggg.gbufN;i>0;i--) {
1436 char c = gbuf[i-1].ch[0];
1437 if (!((c>='A' && c<='Z') || (c>='a' && c<='z')))
1438 break;
1439 }
1440
1441 dbg("i %d\n", i);
1442
1443 if (ggg.gbufN - i > 2) {
1444 int len = ggg.gbufN-i;
1445 char en[128];
1446 for(int j=0;j<len;j++)
1447 en[j]=gbuf[i+j].ch[0];
1448 en[len]=0;
1449 dbg("pp8 '%s'\n", en);
1450 char best[10][MAX_PHRASE_LEN];
1451 get_en_miss_cand(en_hand.fph, en, len, best);
1452 int n=0;
1453 for(int i=0;i<10;i++) {
1454 if (best[i][0]) {
1455 dbg("best %d %s", i, best[i]);
1456 bzero(tss.pre_sel[i].phkey, sizeof(tss.pre_sel[i].phkey));
1457 tss.pre_sel[i].len = strlen(best[i]);
1458 strcpy(tss.pre_sel[i].str, best[i]);
1459 n++;
1460 }
1461 }
1462
1463 dbg("\nn %d\n", n);
1464
1465 tss.pre_selN = n;
1466 if (n > 0) {
1467 gtab_pre_select_phrase_len = len;
1468 disp_gtab_pre();
1469 }
1470
1471 return;
1472 }
1473 #endif
1474 return;
1475 }
1476
1477 gtab_pre_select_phrase_len = max_len;
1478 scanphr_en(&en_hand, TRUE, ggg.gbufN - max_len, max_len, &selN);
1479
1480 if (selN==1 && tss.pre_sel[0].len==max_len) {
1481 char out[MAX_PHRASE_LEN * CH_SZ + 1];
1482 extract_gbuf_str(ggg.gbufN - max_len, max_len, out);
1483 if (!strcmp(out, tss.pre_sel[0].str))
1484 return;
1485 }
1486
1487 disp_gtab_pre();
1488 }
1489
1490