1 /*
2 Copyright (C) 1995-2008 Edward Der-Hua Liu, Hsin-Chu, Taiwan
3 */
4
5 #include "gcin.h"
6 #include "pho.h"
7 #include "tsin.h"
8 #include "gtab.h"
9 #include "gst.h"
10
qcmp_pre_sel_usecount(const void * aa,const void * bb)11 static int qcmp_pre_sel_usecount(const void *aa, const void *bb)
12 {
13 PRE_SEL *a = (PRE_SEL *) aa;
14 PRE_SEL *b = (PRE_SEL *) bb;
15
16 int d = b->usecount - a->usecount;
17
18 if (d != 0)
19 return d;
20
21 return a->len - b->len; // shorter first
22 }
23
qcmp_pre_sel_str(const void * aa,const void * bb)24 static int qcmp_pre_sel_str(const void *aa, const void *bb)
25 {
26 PRE_SEL *a = (PRE_SEL *) aa;
27 PRE_SEL *b = (PRE_SEL *) bb;
28
29 return strcmp(a->str, b->str);
30 }
31
32 void extract_gtab_key(gboolean is_en, int start, int len, void *out);
33 gboolean tsin_seek_ex(TSIN_HANDLE *th, void *pho, int plen, int *r_sti, int *r_edi, char *tone_mask);
34 void load_tsin_entry_ex(TSIN_HANDLE *ptsin_hand, int idx, char *len, usecount_t *usecount, void *pho, u_char *ch);
35 gboolean check_gtab_fixed_mismatch(int idx, char *mtch, int plen);
36 void mask_tone(phokey_t *pho, int plen, char *tone_off);
37 void init_pre_sel();
38 void mask_key_typ_pho(phokey_t *key);
39 extern u_int64_t vmaskci;
40
ph_key_length(TSIN_HANDLE * th,u_int64_t k)41 int ph_key_length(TSIN_HANDLE *th, u_int64_t k)
42 {
43 int klen=0;
44 if (th->ph_key_sz==2) {
45 int k1,k2,k3,k4;
46 phokey_t kk = (phokey_t) k;
47 k4=(kk&7);
48 kk>>=3;
49 k3=(kk&15);
50 kk>>=4;
51 k2=(kk&3);
52 kk>>=2;
53 k1=(kk&31);
54 if (k1)
55 klen++;
56 if (k2)
57 klen++;
58 if (k3)
59 klen++;
60 if (k4)
61 klen++;
62 } else {
63 klen = 3; // temporary fix
64 }
65
66 // dbg("ph_key_length %d\n", klen);
67 return klen;
68 }
69
70 extern char typ_pho_len[];
71 void mask_pho_ref(phokey_t *pho, phokey_t *refpho, int plen, char *tone_mask);
72
scanphr_e(TSIN_HANDLE * th,gboolean is_gtab,int chpho_idx,int plen,gboolean pho_incr,int * rselN)73 u_char scanphr_e(TSIN_HANDLE *th, gboolean is_gtab, int chpho_idx, int plen, gboolean pho_incr, int *rselN)
74 {
75 gboolean is_pho = th->ph_key_sz==2;
76 if (plen >= MAX_PHRASE_LEN)
77 goto empty;
78 if (chpho_idx < 0)
79 goto empty;
80
81 phokey_t tailpho, tailpho0head=0;
82
83 if (pho_incr) {
84 if (is_pho) {
85 tailpho = pho2key(poo.typ_pho);
86 if (!tailpho)
87 pho_incr = FALSE;
88
89 // If user input ㄣ, then ㄅㄧㄣ should not be selected
90 int i;
91 for(i=0;i<4;i++)
92 if (poo.typ_pho[i])
93 break;
94 if (i>0 && i < 4) {
95 tailpho0head |= (1 << typ_pho_len[0]) - 1;
96 int j;
97 for(j=1;j<4;j++) {
98 tailpho0head <<= typ_pho_len[j];
99 if (j < i)
100 tailpho0head |= ((1 << typ_pho_len[j]) - 1);
101 }
102 }
103
104 // dbg("i:%d tailpho0head %x\n",i, tailpho0head);
105 } else {
106 if (!ggg.kval)
107 pho_incr = FALSE;
108 }
109 }
110
111 u_int64_t pp64[MAX_PHRASE_LEN + 1];
112 phokey_t *pp = (phokey_t*)pp64;
113 char *pp8 = (char *)pp64;
114 int *pp32 = (int *)pp64;
115
116 if (!is_gtab) {
117 extract_pho(FALSE, chpho_idx, plen, pp);
118 } else {
119 extract_gtab_key(FALSE, chpho_idx, plen, pp64);
120 }
121
122 #if 0
123 dbg("scanphr %d\n", plen);
124
125 int t;
126 for(t=0; t < plen; t++) {
127 dbg("pp%d] %x ",t, pp[t]);
128 prph(pp[t]);
129 }
130 dbg("\n");
131 #endif
132
133 char pinyin_set[MAX_PH_BF_EXT];
134 char *t_pinyin_set = NULL;
135 gboolean is_pin_juyin = is_pho && (pin_juyin || pho_no_tone);
136 #define selNMax 50
137 PRE_SEL sel[selNMax], sel_nu[selNMax];
138 int selN = 0, sel_nuN=0;
139 tss.pre_selN = 0;
140 int maxlen=0;
141
142 if (is_pin_juyin) {
143 get_chpho_pinyin_set(pinyin_set);
144 t_pinyin_set = pinyin_set + chpho_idx;
145 mask_tone(pp, plen, t_pinyin_set);
146 }
147
148 int sti, edi;
149 if (!tsin_seek_ex(th, pp, plen, &sti, &edi, t_pinyin_set)) {
150 empty:
151 if (rselN)
152 *rselN = 0;
153 return 0;
154 }
155 // dbg("plen:%d sti:%d edi:%d\n", plen, sti, edi);
156
157 u_int64_t mtk64[MAX_PHRASE_LEN+1];
158 phokey_t *mtk = (phokey_t*) mtk64, mtko[MAX_PHRASE_LEN+1];
159 u_int *mtk32 = (u_int *)mtk64;
160 u_char *mtk8 = (u_char *)mtk64;
161 void *mtk_src = is_pin_juyin?(void*)mtko:(void*)mtk64;
162
163 while (sti < edi && selN < selNMax) {
164 u_char mtch[MAX_PHRASE_LEN*CH_SZ+1];
165 char match_len;
166 usecount_t usecount;
167
168 mtk[plen] = 0;
169 load_tsin_entry_ex(th, sti, &match_len, &usecount, mtk, mtch);
170 // dbg("mtch %s\n", mtch);
171
172 sti++;
173 if (plen > match_len || (pho_incr && plen==match_len)) {
174 continue;
175 }
176
177 if (is_pho) {
178 #if 0
179 mask_tone(mtk, plen, t_pinyin_set);
180 #else
181 if (is_pin_juyin) {
182 memcpy(mtko, mtk, sizeof(phokey_t)*match_len);
183 mask_pho_ref(mtk, pp, plen, t_pinyin_set);
184 }
185 #endif
186 }
187
188 int i;
189
190 if (is_pho) {
191 for(i=0; i < plen; i++) {
192 if (mtk[i]!=pp[i])
193 break;
194 }
195 } else {
196 if (th->ph_key_sz==4) {
197 for(i=0; i < plen; i++) {
198 if (mtk32[i]!=pp32[i])
199 break;
200 }
201 } else {
202 for(i=0; i < plen; i++) {
203 if (mtk64[i]!=pp64[i])
204 break;
205 }
206 }
207 }
208
209 if (i < plen) {
210 continue;
211 }
212
213 #if 1
214 if (pho_incr) {
215 // en doesn't need this
216 if (is_pho) {
217 phokey_t last_m = mtk[plen];
218 #if 1
219 if (last_m & tailpho0head) {
220 // dbg("%x ", last_m); prph(last_m); dbg("\n");
221 continue;
222 }
223 #endif
224 mask_key_typ_pho(&last_m);
225 if (last_m != tailpho)
226 continue;
227 } else {
228 u_int64_t v = th->ph_key_sz==4?mtk32[plen]:mtk64[plen];
229 if (ggg.kval != (v&vmaskci))
230 continue;
231 }
232 }
233 #endif
234
235 #if 0
236 dbg("nnn ");
237 nputs(mtch, match_len);
238 dbg("\n");
239 #endif
240
241 if (!is_gtab) {
242 if (check_fixed_mismatch(chpho_idx, (char *)mtch, plen))
243 continue;
244 } else {
245 if (check_gtab_fixed_mismatch(chpho_idx, (char *)mtch, plen))
246 continue;
247 }
248
249 if (maxlen < match_len)
250 maxlen = match_len;
251
252 if (usecount>0) {
253 bzero(sel[selN].phkey, sizeof(sel[selN].phkey));
254 memcpy(sel[selN].phkey, mtk_src, match_len*th->ph_key_sz);
255 sel[selN].len = match_len;
256 sel[selN].usecount = usecount;
257 utf8cpyN(sel[selN].str, (char *)mtch, match_len);
258 selN++;
259 } else {
260 if (sel_nuN < selNMax) {
261 bzero(sel_nu[sel_nuN].phkey, sizeof(sel_nu[sel_nuN].phkey));
262 memcpy(sel_nu[sel_nuN].phkey, mtk_src, match_len*th->ph_key_sz);
263 sel_nu[sel_nuN].len = match_len;
264 sel_nu[sel_nuN].usecount = usecount;
265 utf8cpyN(sel_nu[sel_nuN].str, (char *)mtch, match_len);
266 sel_nuN++;
267 }
268 }
269 }
270
271 // dbg("SelN:%d maxlen:%d\n", selN, maxlen);
272
273 if (selN < selNMax && sel_nuN) {
274 int d = selNMax - selN;
275 if (d > sel_nuN)
276 d = sel_nuN;
277 for(int i=0;i<d;i++)
278 sel[selN++]=sel_nu[i];
279 }
280
281 if (selN > 1) {
282 qsort(sel, selN, sizeof(PRE_SEL), qcmp_pre_sel_str);
283 int nselN = 0;
284 int i;
285 for(i=0;i<selN;i++)
286 if (sel[i].len>1 && (!i || strcmp(sel[i].str, sel[i-1].str)))
287 sel[nselN++]=sel[i];
288 selN = nselN;
289 }
290
291 #if 1
292 if (selN==1) {
293 // if (sel[0].len==1 || (sel[0].len==2 && ph_key_length(th, sel[0].phkey[1])<2))
294 if (sel[0].len==1)
295 goto empty;
296 }
297 #endif
298
299 qsort(sel, selN, sizeof(PRE_SEL), qcmp_pre_sel_usecount);
300
301 // dbg("selN:%d\n", selN);
302 if (!is_gtab)
303 tss.pre_selN = Min(selN, phkbm.selkeyN);
304 else
305 tss.pre_selN = Min(selN, (int)strlen(cur_inmd->selkey));
306
307 // dbg("tss.pre_selN %d\n", tss.pre_selN);
308 memcpy(tss.pre_sel, sel, sizeof(PRE_SEL) * tss.pre_selN);
309
310 if (rselN)
311 *rselN = selN;
312
313 return maxlen;
314 }
315
316
317
318 void hide_pre_sel();
319 void chpho_get_str(int idx, int len, char *ch);
320 void disp_pre_sel_page();
321 gboolean tsin_seek_ex(TSIN_HANDLE *th, void *pho, int plen, int *r_sti, int *r_edi, char *tone_mask);
322 int tsin_sele_by_idx(int c);
323
tsin_scan_pre_select(gboolean b_incr)324 void tsin_scan_pre_select(gboolean b_incr)
325 {
326 if (!tsin_phrase_pre_select)
327 return;
328 // dbg("tsin_scan_pre_select %d\n", b_incr);
329
330 tss.pre_selN = 0;
331
332 hide_pre_sel();
333
334 if (!tss.c_idx || !tss.c_len)
335 return;
336
337 init_pre_sel();
338
339 int Maxlen = tss.c_idx;
340 if (Maxlen > MAX_PHRASE_LEN)
341 Maxlen = MAX_PHRASE_LEN;
342
343 int len, selN, max_len=-1, max_selN=-1;
344 for(len=1; len <= Maxlen; len++) {
345 int idx = tss.c_idx - len;
346 if ((tss.chpho[idx].flag & FLAG_CHPHO_PHRASE_TAIL) || !(tss.chpho[idx].cha[0]&0x80)) {
347 // dbg("phrase tail %d\n", idx);
348 break;
349 }
350 #if 0
351 int mlen = scanphr_e(&tsin_hand, FALSE, tss.c_len - len, len, b_incr, &selN);
352 #else
353 int mlen = scanphr_e(&tsin_hand, FALSE, tss.c_idx - len, len, b_incr, &selN);
354 #endif
355 // dbg("mlen %d len:%d\n", mlen, len);
356
357 if (mlen) {
358 max_len = len;
359 max_selN = selN;
360 }
361 }
362
363 // dbg("max_len:%d max_selN:%d\n", max_len, max_selN);
364
365 if (max_len < 0 /* || max_selN >= strlen(pho_selkey) * 2 */ ) {
366 tss.pre_selN=0;
367 return;
368 }
369
370 #if 0
371 scanphr_e(&tsin_hand, FALSE, tss.c_len - max_len, max_len, b_incr, &selN);
372 #else
373 scanphr_e(&tsin_hand, FALSE, tss.c_idx - max_len, max_len, b_incr, &selN);
374 #endif
375
376 // dbg("selN:%d %d\n", selN, tss.pre_selN);
377
378 // dbg("selN %d %d\n",selN, tss.pre_selN);
379 #if 0
380 tss.ph_sta = tss.c_len - max_len;
381 #else
382 tss.ph_sta = tss.c_idx - max_len;
383 #endif
384
385 if (selN==1 && tss.pre_sel[0].len==max_len) {
386 char out[MAX_PHRASE_LEN * CH_SZ + 1];
387 chpho_get_str(tss.c_len - max_len, max_len, out);
388 if (!strcmp(out, tss.pre_sel[0].str)) {
389 // tsin_sele_by_idx(0);
390 return;
391 }
392 }
393
394 disp_pre_sel_page();
395 }
396
397 char *ch_mode_selkey(gboolean is_gtab);
398
en_sel_keys(gboolean is_gtab)399 char *en_sel_keys(gboolean is_gtab)
400 {
401 char *s = ch_mode_selkey(is_gtab);
402 static char *sel = "1234567890";
403
404 if (!s)
405 return sel;
406 int slen = strlen(s);
407 int i;
408 for(i=0; i < slen; i++)
409 if (s[i] < '0' || s[i] > '9')
410 break;
411 if (i < slen)
412 return sel;
413
414 return s;
415 }
416
en_sel_keys_len(gboolean is_gtab)417 int en_sel_keys_len(gboolean is_gtab)
418 {
419 return strlen(en_sel_keys(is_gtab));
420 }
421
422 extern int wselkeyN;
423 phokey_t utf8_pho_key(char *s);
424 gboolean tsin_seek_en(u_char *pho, int plen, int *r_sti, int *r_edi);
425
scanphr_en(TSIN_HANDLE * th,gboolean is_gtab,int chpho_idx,int plen,int * rselN)426 u_char scanphr_en(TSIN_HANDLE *th, gboolean is_gtab, int chpho_idx, int plen, int *rselN)
427 {
428 if (rselN)
429 *rselN = 0;
430
431 if (plen >= MAX_PHRASE_LEN)
432 return 0;
433 if (chpho_idx < 0)
434 return 0;
435
436 u_int64_t pp64[MAX_PHRASE_LEN + 1];
437 phokey_t *pp = (phokey_t*)pp64;
438 char *pp8 = (char *)pp64;
439
440 tss.pre_selN = 0;
441 int maxlen=0;
442 //#define selNMax 20
443 PRE_SEL sel[selNMax];
444 int selN = 0;
445
446 if (!is_gtab) {
447 extract_pho(TRUE, chpho_idx, plen, pp);
448 } else {
449 extract_gtab_key(TRUE, chpho_idx, plen, pp64);
450 }
451
452 gboolean isup = isupper(pp8[0]);
453 gboolean isup1 = isup && plen > 1 && isupper(pp8[1]);
454 int loopN = isup?4:5;
455
456 int loop;
457 int used_first;
458 char pp8_o[MAX_PHRASE_LEN * 8];
459 memcpy(pp8_o, pp8, plen);
460 pp8[plen]=0;
461 dbg("pp8 '%s'\n", pp8);
462
463 for(used_first=1;used_first>=0; used_first--) {
464 for(loop=0; loop<loopN;loop++) {
465 memcpy(pp8, pp8_o, plen);
466 if (loop==1) {
467 if (isup1) {
468 int i;
469 for(i=0;i<plen;i++)
470 pp8[i] = tolower(pp8[i]);
471 } else
472 if (isup){
473 pp8[0] = tolower(pp8[0]);
474 } else
475 pp8[0] = toupper(pp8[0]);
476 } else if (loop==2) {
477 // loop==2 SHOUT
478 int i;
479 for(i=0;i<plen;i++)
480 pp8[i] = toupper(pp8[i]);
481 } else if (loop==3) { // iPhone, iPad
482 pp8[1]=toupper(pp8[1]);
483 } else if (loop==4) { // loop==4 PlayStation
484 int i;
485 for(i=0;i<plen;i++)
486 pp8[i] = tolower(pp8[i]);
487 }
488
489 dbg("loop:%d %s\n", loop, pp8);
490
491 int sti, edi;
492 if (!tsin_seek_en((u_char *)pp8, plen, &sti, &edi)) {
493 continue;
494 }
495
496 dbg("plen:%d sti:%d edi:%d\n", loop, plen, sti, edi);
497
498 u_int64_t mtk64[MAX_PHRASE_LEN+1];
499 u_char *mtk8 = (u_char *)mtk64;
500
501 while (sti < edi && selN < selNMax) {
502 u_char mtch[MAX_PHRASE_LEN*CH_SZ+1];
503 char match_len;
504 usecount_t usecount;
505
506 load_tsin_entry_ex(th, sti, &match_len, &usecount, (phokey_t*)mtk64, mtch);
507 if (!mtch[0]) {
508 memcpy(mtch, mtk8, match_len);
509 mtch[match_len] = 0;
510 }
511
512 #if DEBUG && 0
513 dbg("load %d", sti);
514 utf8_putcharn((char*)mtk8, match_len);
515 dbg("\n");
516 #endif
517
518 sti++;
519 if (plen > match_len) {
520 continue;
521 }
522
523 if (used_first && !usecount)
524 continue;
525
526 int i;
527 if (loop == 4) {
528 for(i=0; i < plen; i++) {
529 if (tolower(mtch[i])!=pp8[i])
530 break;
531 }
532 } else {
533 for(i=0; i < plen; i++) {
534 if (mtk8[i]!=pp8[i])
535 break;
536 }
537 }
538
539 if (i < plen) {
540 continue;
541 }
542
543
544 #if 0
545 dbg("nnn ");
546 nputs(mtch, match_len);
547 dbg("\n");
548 #endif
549
550 if (maxlen < match_len)
551 maxlen = match_len;
552
553 sel[selN].len = match_len;
554 // sel[selN].phidx = sti - 1;
555 sel[selN].usecount = usecount;
556
557 if (loop==1) {
558 if (isup1) {
559 int i;
560 for(i=0;i<match_len;i++)
561 mtch[i]=toupper(mtch[i]);
562 } else
563 mtch[0]=toupper(mtch[0]);
564 }
565
566 memcpy(sel[selN].str, mtch, match_len);
567 sel[selN].str[match_len]=0;
568 dbg("%s %d\n", sel[selN].str, usecount);
569 for(i=0;i<selN;i++)
570 if (!strcmp(sel[i].str, sel[selN].str))
571 break;
572 if (i < selN) {
573 if (sel[i].usecount<usecount)
574 sel[i].usecount=usecount;
575 continue;
576 }
577
578 bzero(sel[selN].phkey, sizeof(sel[selN].phkey));
579
580 #if 0
581 for(i=0;i<match_len;) {
582 char t[CH_SZ + 1];
583 i+=utf8cpy(t, (char *)&mtk8[i]);
584 // sel[selN].phkey[i] = utf8_pho_key(t);
585 }
586 #endif
587 // memcpy(sel[selN].phkey, mtk8, match_len*th->ph_key_sz);
588 selN++;
589 }
590
591 }
592 }
593
594 dbg("SelN:%d maxlen:%d\n", selN, maxlen);
595 qsort(sel, selN, sizeof(PRE_SEL), qcmp_pre_sel_usecount);
596 dbg("selN:%d\n", selN);
597 #if 0
598 for(int i=0;i<selN;i++) {
599 dbg("%s:%d ", sel[i].str, sel[i].usecount);
600 }
601 dbg("\n");
602 #endif
603 tss.pre_selN = Min(selN, wselkeyN);
604 dbg("tss.pre_selN %d\n", tss.pre_selN);
605 memcpy(tss.pre_sel, sel, sizeof(PRE_SEL) * tss.pre_selN);
606
607 if (rselN)
608 *rselN = selN;
609
610 return maxlen;
611 }
612
613 void load_en_db();
614
misalpha(char c)615 gboolean misalpha(char c)
616 {
617 return c>='A' && c<='Z' || c>='a' && c<='z';
618 }
619
620 void get_en_miss_cand(FILE *fp, char *s, int slen, char best[][MAX_PHRASE_LEN]);
621
tsin_en_scan_pre_select()622 void tsin_en_scan_pre_select()
623 {
624 dbg("tsin_en_scan_pre_select\n");
625
626 if (!en_hand.fph)
627 load_en_db();
628
629 dbg("tsin_en_scan_pre_select %d th->ph_key_sz:%d\n", tss.c_len, en_hand.ph_key_sz);
630
631 tss.pre_selN = 0;
632
633 hide_pre_sel();
634
635 if (!tss.c_idx || !tss.c_len)
636 return;
637
638 init_pre_sel();
639
640 int Maxlen = tss.c_len;
641 if (Maxlen > MAX_PHRASE_LEN)
642 Maxlen = MAX_PHRASE_LEN;
643
644 int len, selN, max_len=-1, max_selN=-1;
645 for(len=2; len <= Maxlen; len++) {
646 int idx = tss.c_len - len;
647 if (tss.chpho[idx].flag & FLAG_CHPHO_PHRASE_TAIL) {
648 // dbg("phrase tail %d\n", idx);
649 break;
650 }
651
652 char c = tss.chpho[idx].cha[0];
653 char c1 = idx==0?0:tss.chpho[idx-1].cha[0];
654 char c2 = idx<=1?0:tss.chpho[idx-2].cha[0];
655
656 if (c & 0x80)
657 break;
658
659 if (misalpha(c1))
660 continue;
661 if (misalpha(c) && c1=='\'' && misalpha(c2))
662 continue;
663
664 int mlen = scanphr_en(&en_hand, FALSE, tss.c_len - len, len, &selN);
665 dbg("mlen %d len:%d\n", mlen, len);
666
667 if (mlen) {
668 max_len = len;
669 max_selN = selN;
670 }
671 }
672
673 dbg("max_len:%d max_selN:%d\n", max_len, max_selN);
674
675 if (max_len < 0 /* || max_selN > 40 */) { // will ctrl press/release + keys as select keys
676 dbg("too many or no %d\n", max_len);
677
678 if (max_len < 0) {
679 dbg("max_len < 0\n");
680 int i;
681 for(i=tss.c_len;i>0;i--) {
682 char c = tss.chpho[i-1].cha[0];
683 if (!((c>='A' && c<='Z') || (c>='a' && c<='z') || c=='@'))
684 break;
685 }
686
687 if (tss.c_len - i > 2) {
688 u_int64_t pp64[MAX_PHRASE_LEN + 1];
689 phokey_t *pp = (phokey_t*)pp64;
690 char *pp8 = (char *)pp64;
691 int len = tss.c_len-i;
692 extract_pho(TRUE, i, len, pp);
693 pp8[len]=0;
694 dbg("pp8 '%s'\n", pp8);
695 char best[10][MAX_PHRASE_LEN];
696 get_en_miss_cand(en_hand.fph, pp8, len, best);
697 int n=0;
698 for(int i=0;i<10;i++) {
699 if (best[i][0]) {
700 dbg("best %d %s", i, best[i]);
701 bzero(tss.pre_sel[i].phkey, sizeof(tss.pre_sel[i].phkey));
702 tss.pre_sel[i].len = strlen(best[i]);
703 strcpy(tss.pre_sel[i].str, best[i]);
704 n++;
705 }
706 }
707
708 dbg("\nn %d\n", n);
709 tss.pre_selN = n;
710 tss.ph_sta = tss.c_len - len;
711 disp_pre_sel_page();
712 return;
713 }
714 }
715
716 tss.pre_selN=0;
717 return;
718 }
719
720 scanphr_en(&en_hand, FALSE, tss.c_len - max_len, max_len, &selN);
721
722 dbg("selN %d %d\n",selN, tss.pre_selN);
723 tss.ph_sta = tss.c_len - max_len;
724
725 if (selN==1 && tss.pre_sel[0].len==max_len) {
726 char out[MAX_PHRASE_LEN * CH_SZ + 1];
727 chpho_get_str(tss.c_len - max_len, max_len, out);
728
729 dbg("rrr %s %s\n", out, tss.pre_sel[0].str);
730 if (!strcmp(out, tss.pre_sel[0].str)) {
731 dbg("ssss\n");
732 tsin_sele_by_idx(0);
733 return;
734 }
735 }
736
737 disp_pre_sel_page();
738 }
739