1 /*
2  * Copyright (C) 2020 The HIME team, Taiwan
3  * Copyright (C) 1994-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 <stdlib.h>
21 
22 #include <sys/stat.h>
23 
24 #include "hime.h"
25 
26 #include "gst.h"
27 #include "gtab.h"
28 #include "pho-status.h"
29 #include "pho.h"
30 
31 extern PHO_ST poo;
32 
33 extern PHO_ITEM *ch_pho;
34 
35 extern PHOKBM phkbm;
36 gboolean b_hsu_kbm;
37 extern PIN_JUYIN *pin_juyin;
38 
39 gboolean full_char_proc (KeySym keysym);
40 void hide_win_pho ();
41 void ClrSelArea ();
42 
43 #define MAX_HASH_PHO 27
44 u_short hash_pho[MAX_HASH_PHO + 1];
45 
46 static char typ_pho_len[] = {5, 2, 4, 3};
47 
48 gboolean same_query_show_pho_win ();
49 
typ_pho_empty()50 gboolean typ_pho_empty () {
51     return !poo.typ_pho[0] && !poo.typ_pho[1] && !poo.typ_pho[2] && !poo.typ_pho[3];
52 }
53 
pho_has_input()54 gboolean pho_has_input () {
55     return !typ_pho_empty () || same_query_show_pho_win ();
56 }
57 
pho2key(char typ_pho[])58 phokey_t pho2key (char typ_pho[]) {
59     phokey_t key = typ_pho[0];
60     int i;
61 
62     if (key == BACK_QUOTE_NO)
63         return (BACK_QUOTE_NO << 9) | typ_pho[1];
64 
65     for (i = 1; i < 4; i++) {
66         key = typ_pho[i] | (key << typ_pho_len[i]);
67     }
68 
69     return key;
70 }
71 
key_typ_pho(phokey_t phokey,u_char rtyp_pho[])72 void key_typ_pho (phokey_t phokey, u_char rtyp_pho[]) {
73     rtyp_pho[3] = phokey & 7;
74     phokey >>= 3;
75     rtyp_pho[2] = phokey & 0xf;
76     phokey >>= 4;
77     rtyp_pho[1] = phokey & 0x3;
78     phokey >>= 2;
79     rtyp_pho[0] = phokey;
80 }
81 
mask_key_typ_pho(phokey_t * key)82 void mask_key_typ_pho (phokey_t *key) {
83     if (poo.typ_pho[0] == BACK_QUOTE_NO)
84         return;
85     if (!poo.typ_pho[0])
86         *key &= ~(31 << 9);
87     if (!poo.typ_pho[1])
88         *key &= ~(3 << 7);
89     if (!poo.typ_pho[2])
90         *key &= ~(15 << 3);
91     if (!poo.typ_pho[3])
92         *key &= ~(7);
93 }
94 
95 #define TKBM 0
96 #define MIN_M_PHO 5
97 
find_match_phos(u_char mtyp_pho[4],int * mcount,int newkey)98 static void find_match_phos (u_char mtyp_pho[4], int *mcount, int newkey) {
99     int vv;
100     phokey_t key = pho2key (poo.typ_pho);
101 
102     mask_key_typ_pho (&key);
103 #if TKBM
104     dbg ("-------------------- %d --", poo.typ_pho[3]);
105     prph (key);
106     dbg ("\n");
107 #endif
108     for (vv = hash_pho[(int) poo.typ_pho[0]]; vv < hash_pho[(int) poo.typ_pho[0] + 1]; vv++) {
109         phokey_t ttt = idx_pho[vv].key;
110 
111         if (newkey != ' ' && !poo.typ_pho[3])
112             mask_key_typ_pho (&ttt);
113 
114         if (ttt > key)
115             break;
116 
117         int count = 0;
118 
119         int i;
120         for (i = idx_pho[vv].start; i < idx_pho[vv + 1].start; i++) {
121             if (utf8_sz (pho_idx_str (i)) > 1) {
122 #if 0
123             utf8_putchar(ch_pho[i].ch);
124             dbg(" ");
125 #endif
126                 count++;
127             }
128         }
129 
130         if (*mcount < count) {
131             *mcount = count;
132             memcpy (mtyp_pho, poo.typ_pho, sizeof (poo.typ_pho));
133 #if TKBM
134             dbg ("count %d\n", count);
135 #endif
136             if (*mcount > MIN_M_PHO)
137                 break;
138         }
139     }
140 }
141 
142 gboolean inph_typ_pho_pinyin (int newkey);
143 
typ_pho_status()144 static int typ_pho_status () {
145     return poo.typ_pho[3] ? PHO_STATUS_OK_NEW : PHO_STATUS_OK;
146 }
147 
inph_typ_pho(KeySym newkey)148 int inph_typ_pho (KeySym newkey) {
149     int i;
150     int insert = -1;
151 
152     if (pin_juyin) {
153         return inph_typ_pho_pinyin (newkey);
154     }
155 
156     if (poo.typ_pho[0] == BACK_QUOTE_NO) {
157         poo.typ_pho[1] = (char) newkey;
158         poo.inph[1] = newkey;
159         return PHO_STATUS_OK;
160     }
161 
162     int max_in_idx;
163     for (max_in_idx = 3; max_in_idx >= 0 && !poo.typ_pho[max_in_idx]; max_in_idx--)
164         ;
165 
166     // try insert mode first
167     if (insert < 0)
168         for (i = 0; i < 3; i++) {
169             char num = phkbm.phokbm[(int) newkey][i].num;
170             int typ = phkbm.phokbm[(int) newkey][i].typ;
171 
172             if (num && !poo.inph[typ] && typ > max_in_idx) {
173                 poo.inph[typ] = newkey;
174                 poo.typ_pho[typ] = num;
175 #if TKBM
176                 dbg ("insert typ %d\n", typ);
177 #endif
178                 insert = typ;
179                 break;
180             }
181         }
182 
183     if (insert < 0) {
184         // then overwrite mode
185         for (i = 0; i < 3; i++) {
186             char num = phkbm.phokbm[newkey][i].num;
187             int typ = phkbm.phokbm[newkey][i].typ;
188 
189             if (num) {
190                 poo.inph[typ] = newkey;
191                 poo.typ_pho[typ] = num;
192                 insert = typ;
193                 break;
194             }
195         }
196     }
197 
198     //  dbg("newkey %c\n", newkey);
199 
200     int mcount = 0;
201     u_char mtyp_pho[4];
202 
203     int a;
204 
205     for (a = 0; a < 3; a++) {
206         char num = phkbm.phokbm[(int) poo.inph[0]][a].num;
207         char typ = phkbm.phokbm[(int) poo.inph[0]][a].typ;
208 
209         if (typ == 3)
210             continue;
211 
212         if (num) {
213             if (typ == 2 && poo.typ_pho[0] && !poo.typ_pho[2])
214                 poo.typ_pho[0] = 0;
215             poo.typ_pho[(int) typ] = num;
216 #if TKBM
217             dbg ("%d num %d\n", a, num);
218 #endif
219             find_match_phos (mtyp_pho, &mcount, newkey);
220         }
221 
222         for (i = 0; i < 3; i++) {
223             char num = phkbm.phokbm[(int) poo.inph[2]][i].num;
224             char typ = phkbm.phokbm[(int) poo.inph[2]][i].typ;
225 
226             if (!num)
227                 break;
228 
229             if (typ != 2)
230                 continue;
231 
232             poo.typ_pho[(int) typ] = num;
233 
234             find_match_phos (mtyp_pho, &mcount, newkey);
235 
236             if (mcount > MIN_M_PHO) {
237                 return typ_pho_status ();
238             }
239         }
240 
241         find_match_phos (mtyp_pho, &mcount, newkey);
242 
243         if (mcount > MIN_M_PHO) {
244             return typ_pho_status ();
245         }
246     }
247 
248     if (mcount) {
249         memcpy (poo.typ_pho, mtyp_pho, sizeof (poo.typ_pho));
250         return typ_pho_status ();
251     }
252 
253     return PHO_STATUS_REJECT;
254 }
255 
clrin_pho()256 void clrin_pho () {
257     memset (poo.typ_pho, 0, sizeof (poo.typ_pho));
258     memset (poo.inph, 0, sizeof (poo.inph));
259     poo.maxi = poo.ityp3_pho = 0;
260     poo.cpg = 0;
261 
262     if (hime_pop_up_win && !same_query_show_pho_win ())
263         hide_win_pho ();
264 }
265 
266 void disp_pho (int index, char *phochar);
clr_in_area_pho()267 void clr_in_area_pho () {
268     int i;
269 
270     clrin_pho ();
271     for (i = 0; i < text_pho_N; i++)
272         disp_pho (i, "  ");
273 }
274 
disp_in_area_pho()275 static void disp_in_area_pho () {
276     int i;
277 
278     text_pho_N = pin_juyin ? 7 : 4;
279     if (pin_juyin) {
280         for (i = 0; i < text_pho_N; i++) {
281             disp_pho (i, &poo.inph[i]);
282         }
283     } else {
284         for (i = 0; i < 4; i++) {
285             if (i == 1 && poo.typ_pho[0] == BACK_QUOTE_NO) {
286                 disp_pho (i, &poo.inph[1]);
287             } else
288                 disp_pho (i, &pho_chars[i][poo.typ_pho[i] * 3]);
289         }
290     }
291 }
292 
qcmp_count(const void * aa,const void * bb)293 static int qcmp_count (const void *aa, const void *bb) {
294     PHO_ITEM *a = (PHO_ITEM *) aa;
295     PHO_ITEM *b = (PHO_ITEM *) bb;
296 
297     return b->count - a->count;
298 }
299 
300 void disp_pho_sel (char *s);
301 
ClrPhoSelArea()302 static void ClrPhoSelArea () {
303     disp_pho_sel ("");
304 }
305 
306 extern char *TableDir;
307 extern char phofname[128];
308 
get_start_stop_idx(phokey_t key,int * start_i,int * stop_i)309 gboolean get_start_stop_idx (phokey_t key, int *start_i, int *stop_i) {
310     int typ_pho0 = key >> 9;
311     int vv = hash_pho[typ_pho0];
312 
313     while (vv < idxnum_pho) {
314         if (idx_pho[vv].key >= key)
315             break;
316         else
317             vv++;
318     }
319 
320     if (vv >= idxnum_pho || idx_pho[vv].key != key)
321         return FALSE;
322 
323     *start_i = idx_pho[vv].start;
324     *stop_i = idx_pho[vv + 1].start;
325 
326     return TRUE;
327 }
328 
329 // given the pho key & the utf8 char, return the idx in ch_pho
ch_key_to_ch_pho_idx(phokey_t phkey,char * utf8)330 int ch_key_to_ch_pho_idx (phokey_t phkey, char *utf8) {
331     int start_i, stop_i;
332 
333     get_start_stop_idx (phkey, &start_i, &stop_i);
334 
335     int i;
336     for (i = start_i; i < stop_i; i++) {
337         char *ch = pho_idx_str (i);
338         int u8len = utf8_sz (ch);
339         if (!memcmp (ch, utf8, u8len)) {
340             return i;
341         }
342     }
343 
344     //  prph(phkey);
345     //  dbg("error found   %c%c", *big5, *(big5+1));
346     return -1;
347 }
348 
inc_pho_count(phokey_t key,int ch_idx)349 void inc_pho_count (phokey_t key, int ch_idx) {
350     int start_i, stop_i;
351 
352     if (!phonetic_char_dynamic_sequence)
353         return;
354 
355     get_start_stop_idx (key, &start_i, &stop_i);
356 
357     //  dbg("start_i %d %d    %d %d\n", start_i, stop_i, poo.start_idx, poo.stop_idx);
358 
359     ch_pho[ch_idx].count++;
360     //  dbg("count %d\n", ch_pho[ch_idx].count);
361 
362     qsort (&ch_pho[start_i], stop_i - start_i, sizeof (PHO_ITEM), qcmp_count);
363 #if 0
364   int i;
365   for(i=start_i; i < stop_i; i++) {
366     dbg("uuuu %c%c%c %d\n", ch_pho[i].ch[0], ch_pho[i].ch[1],
367       ch_pho[i].ch[2], ch_pho[i].count);
368   }
369 #endif
370 
371     FILE *fw;
372 
373     //  dbg("phofname %s\n", phofname);
374     if ((fw = fopen (phofname, "rb+")) == NULL) {
375         p_err ("err %s\n", phofname);
376     }
377 
378     if (fseek (fw, ch_pho_ofs + sizeof (PHO_ITEM) * start_i, SEEK_SET) < 0)
379         p_err ("fseek err");
380 #if 1
381     if (fwrite (&ch_pho[start_i], sizeof (PHO_ITEM), stop_i - start_i, fw) <= 0)
382         p_err ("fwrite err");
383 #endif
384     fclose (fw);
385 }
386 
387 void lookup_gtab (char *ch);
388 gboolean is_gtab_query_mode ();
389 void set_gtab_target_displayed ();
390 
391 #include "gtab-buf.h"
392 
putkey_pho(u_short key,int idx)393 void putkey_pho (u_short key, int idx) {
394     char *pho_str = pho_idx_str (idx);
395 
396     if (poo.same_pho_query_state == SAME_PHO_QUERY_pho_select && ggg.gbufN)
397         insert_gbuf_nokey (pho_str);
398     else
399         send_text (pho_str);
400 
401     lookup_gtab (pho_str);
402 
403     inc_pho_count (key, idx);
404 
405     clr_in_area_pho ();
406     ClrSelArea ();
407 
408     if (is_gtab_query_mode ())
409         set_gtab_target_displayed ();
410 }
411 
412 void recreate_win1_if_nessary ();
413 
load_tab_pho_file()414 void load_tab_pho_file () {
415     pho_load ();
416 
417     memset (poo.typ_pho, 0, sizeof (poo.typ_pho));
418 
419     u_int ttt = 0;
420     int i;
421     for (i = 0; i < MAX_HASH_PHO; i++) {
422         if (idx_pho[ttt].key >> 9 == i)
423             hash_pho[i] = ttt;
424         else {
425             continue;
426         }
427 
428         while (ttt < idxnum_pho && idx_pho[ttt].key >> 9 == i)
429             ttt++;
430     }
431 
432     for (i = MAX_HASH_PHO; !hash_pho[i]; i--)
433         hash_pho[i] = idxnum_pho;
434 
435     char kbmfname[MAX_HIME_STR];
436     FILE *fr;
437 
438     free (pin_juyin);
439     pin_juyin = NULL;
440 
441     if (!strstr (pho_kbm_name, "pinyin")) {
442         text_pho_N = 4;
443     } else {
444         load_pin_juyin ();
445     }
446 
447     if (strcmp (pho_kbm_name, "hsu"))
448         b_hsu_kbm = FALSE;
449     else
450         b_hsu_kbm = TRUE;
451 
452     char pho_kbm_name_kbm[128];
453 
454     strcat (strcpy (pho_kbm_name_kbm, pho_kbm_name), ".kbm");
455     dbg ("phokbm_name: %s\n", pho_kbm_name_kbm);
456 
457     get_sys_table_file_name (pho_kbm_name_kbm, kbmfname);
458 
459     if ((fr = fopen (kbmfname, "rb")) == NULL)
460         p_err ("Cannot open %s", kbmfname);
461 
462     dbg ("kbmfname %s\n", kbmfname);
463 
464     fread (&phkbm, sizeof (phkbm), 1, fr);
465     fclose (fr);
466     phkbm.selkeyN = strlen (pho_selkey);
467 
468     dbg ("pho_selkey %s\n", pho_selkey);
469 
470     recreate_win1_if_nessary ();
471 #if 0
472   for(i='A'; i <= 'z'; i++)
473     dbg("%c %d %d\n", i, phkbm.phokbm[i][0].num, phkbm.phokbm[i][0].typ);
474 #endif
475 }
476 
477 void show_win_pho ();
478 
init_tab_pho()479 void init_tab_pho () {
480     if (!ch_pho) {
481         load_tab_pho_file ();
482     }
483 
484     show_win_pho ();
485     clr_in_area_pho ();
486 }
487 
pho_idx_str_markup(int ii)488 static char *pho_idx_str_markup (int ii) {
489     char *pho_str = pho_idx_str (ii);
490     if (!strcmp (pho_str, "<"))
491         pho_str = "&lt;";
492     else if (!strcmp (pho_str, ">"))
493         pho_str = "&gt;";
494     return pho_str;
495 }
496 
497 gboolean shift_char_proc (KeySym key, int kbstate);
498 gboolean pre_punctuation (KeySym xkey);
499 void pho_play (phokey_t key);
500 void close_gtab_pho_win ();
501 gboolean pre_punctuation_hsu (KeySym xkey);
502 
feedkey_pho(KeySym xkey,int kbstate)503 int feedkey_pho (KeySym xkey, int kbstate) {
504     int ctyp = 0;
505     static unsigned int vv, ii;
506     static phokey_t key;
507     char *pp = NULL;
508     char kno;
509     int i, j, jj = 0, kk = 0;
510     char out_buffer[512];
511     int out_bufferN;
512     int shift_m = kbstate & ShiftMask;
513     int ctrl_m = kbstate & ControlMask;
514 
515     if (ctrl_m)
516         return 0;
517 
518     if (kbstate & LockMask) {
519         if (xkey >= 0x7e || xkey < ' ')
520             return FALSE;
521         if (hime_capslock_lower)
522             case_inverse (&xkey, shift_m);
523         send_ascii (xkey);
524         return 1;
525     }
526 
527     if (xkey >= 'A' && xkey <= 'Z' && poo.typ_pho[0] != BACK_QUOTE_NO)
528         xkey += 0x20;
529 
530     switch (xkey) {
531     case XK_Escape:
532         if (typ_pho_empty ())
533             return 0;
534         ClrPhoSelArea ();
535         clr_in_area_pho ();
536         if (is_gtab_query_mode ())
537             close_gtab_pho_win ();
538         return 1;
539     case XK_BackSpace:
540         poo.ityp3_pho = 0;
541         for (j = 3; j >= 0; j--)
542             if (poo.typ_pho[j]) {
543                 poo.typ_pho[j] = 0;
544                 if (typ_pho_empty ()) {
545                     ClrSelArea ();
546                     clr_in_area_pho ();
547                     return 1;
548                 }
549                 break;
550             }
551 
552         if (j < 0)
553             return 0;
554 
555         goto llll3;
556     case '<':
557         if (!poo.ityp3_pho) {
558             return pre_punctuation (xkey);
559         }
560         if (poo.cpg >= phkbm.selkeyN)
561             poo.cpg -= phkbm.selkeyN;
562         goto proc_state;
563     case ' ':
564         if (!poo.typ_pho[0] && !poo.typ_pho[1] && !poo.typ_pho[2]) {
565             if (current_CS->b_half_full_char)
566                 return full_char_proc (xkey);
567             return 0;
568         }
569 
570         //      dbg("poo.ityp3_pho %d\n", poo.ityp3_pho);
571         if (!poo.ityp3_pho) {
572             poo.ityp3_pho = TRUE;
573             goto lll1;
574         }
575 
576         ii = poo.start_idx + poo.cpg + phkbm.selkeyN;
577 
578         if (ii < poo.stop_idx) {
579             poo.cpg += phkbm.selkeyN;
580             dbg ("spc pool.cpg %d\n", poo.cpg);
581         } else {
582             if (poo.cpg) {
583                 poo.cpg = 0;
584                 ii = poo.start_idx;
585             } else {
586                 putkey_pho (key, poo.start_idx);
587                 return 1;
588             }
589         }
590 
591         goto disp;
592     default:
593         if (xkey >= 127 || xkey < ' ')
594             return 0;
595 
596         if (shift_m) {
597             //        return shift_char_proc(xkey, kbstate);
598             if (pre_punctuation (xkey))
599                 return 1;
600             return 0;
601         }
602 
603         //    dbg("poo.maxi:%d  %d\n", poo.maxi, poo.cpg);
604 
605         if ((pp = strchr (pho_selkey, xkey)) && poo.maxi && poo.ityp3_pho) {
606             int c = pp - pho_selkey;
607 
608             if (c < poo.maxi) {
609                 putkey_pho (key, poo.start_idx + poo.cpg + c);
610             }
611             return 1;
612         }
613 
614         if (poo.ityp3_pho && !poo.cpg) {
615             //        dbg("poo.start_idx: %d\n", poo.start_idx);
616             putkey_pho (key, poo.start_idx);
617         }
618 
619         //      poo.cpg=0;
620     }
621 
622 lll1:
623     inph_typ_pho (xkey);
624     //  dbg("typ_pho %x %x\n", poo.typ_pho[0], poo.typ_pho[1]);
625 
626     if (hime_pop_up_win)
627         show_win_pho ();
628 
629     if (poo.typ_pho[3])
630         ctyp = 3;
631 
632     jj = 0;
633     kk = 1;
634 llll2:
635     if (ctyp == 3) {
636         poo.ityp3_pho = 1; /* last key is entered */
637     }
638 llll3:
639 
640     key = pho2key (poo.typ_pho);
641 
642 #if 0
643   dbg("poo.typ_pho %d %d %d %d\n", poo.typ_pho[0], poo.typ_pho[1], poo.typ_pho[2], poo.typ_pho[3]);
644 #endif
645     if (!key) {
646         return pre_punctuation_hsu (xkey);
647     }
648 
649     pho_play (key);
650 
651     vv = hash_pho[(int) poo.typ_pho[0]];
652     phokey_t ttt;
653     ttt = 0xffff;
654 
655     while (vv < idxnum_pho) {
656         ttt = idx_pho[vv].key;
657         mask_key_typ_pho (&ttt);
658 
659         if (ttt >= key)
660             break;
661         else
662             vv++;
663     }
664 
665     //  dbg("vv %d %d\n", vv, idxnum_pho);
666 
667     if (ttt > key || (poo.ityp3_pho && idx_pho[vv].key != key)) {
668         //    dbg("not found\n");
669         while (jj < 4) {
670             while (kk < 3)
671                 if (phkbm.phokbm[(int) poo.inph[jj]][kk].num) {
672 
673                     if (kk) {
674                         ctyp = phkbm.phokbm[(int) poo.inph[jj]][kk - 1].typ;
675                         poo.typ_pho[ctyp] = 0;
676                     }
677 
678                     kno = phkbm.phokbm[(int) poo.inph[jj]][kk].num;
679                     ctyp = phkbm.phokbm[(int) poo.inph[jj]][kk].typ;
680                     poo.typ_pho[ctyp] = kno;
681                     kk++;
682                     goto llll2;
683                 } else
684                     kk++;
685             jj++;
686             kk = 1;
687         }
688 
689         bell ();
690         poo.ityp3_pho = poo.typ_pho[3] = 0;
691         disp_in_area_pho ();
692         return 1;
693     }
694 
695 proc_state:
696     disp_in_area_pho ();
697     poo.start_idx = ii = idx_pho[vv].start;
698     poo.stop_idx = idx_pho[vv + 1].start;
699 
700     //  dbg("poo.start_idx: %d %d\n", poo.start_idx, poo.stop_idx);
701 
702     if (poo.typ_pho[0] == L_BRACKET_NO || poo.typ_pho[0] == R_BRACKET_NO || (poo.typ_pho[0] == BACK_QUOTE_NO && poo.typ_pho[1]))
703         poo.ityp3_pho = 1;
704 
705     ii += poo.cpg;
706 
707     if (poo.ityp3_pho && poo.stop_idx - poo.start_idx == 1) {
708         putkey_pho (key, ii);
709         poo.maxi = poo.ityp3_pho = 0;
710         return 1;
711     }
712 
713 disp:
714     i = 0;
715     out_bufferN = 0;
716     out_buffer[0] = 0;
717 
718     if (poo.ityp3_pho) {
719         //    dbg("poo.cpg %d\n", poo.cpg);
720 
721         while (i < phkbm.selkeyN && ii < poo.stop_idx) {
722             char tt[512];
723             snprintf (tt, sizeof (tt), "<span foreground=\"%s\">%c</span>",
724                       hime_sel_key_color, pho_selkey[i]);
725             int ttlen = strlen (tt);
726             memcpy (out_buffer + out_bufferN, tt, ttlen);
727             out_bufferN += ttlen;
728             //      strcat(out_buffer, tt);
729             char *pho_str = pho_idx_str_markup (ii);
730             int len = strlen (pho_str);
731             memcpy (&out_buffer[out_bufferN], pho_str, len);
732             out_bufferN += len;
733             out_buffer[out_bufferN++] = ' ';
734 
735             ii++;
736             i++;
737         }
738 
739         char *tt = poo.cpg ? "&lt;" : " ";
740         int ttlen = strlen (tt);
741         memcpy (out_buffer + out_bufferN, tt, ttlen);
742         out_bufferN += ttlen;
743 
744         if (ii < poo.stop_idx) {
745             out_buffer[out_bufferN++] = poo.cpg ? '\\' : ' ';
746             tt = "&gt;";
747             ttlen = strlen (tt);
748             memcpy (out_buffer + out_bufferN, tt, ttlen);
749             out_bufferN += strlen (tt);
750         }
751 
752         poo.maxi = i;
753     } else {
754         while (i < phkbm.selkeyN && ii < poo.stop_idx) {
755             char *pho_str = pho_idx_str_markup (ii);
756             int len = strlen (pho_str);
757             memcpy (&out_buffer[out_bufferN], pho_str, len);
758             out_bufferN += len;
759 
760             ii++;
761             i++;
762         }
763         poo.maxi = i;
764     }
765 
766     out_buffer[out_bufferN] = 0;
767     disp_pho_sel (out_buffer);
768 
769     return 1;
770 }
771 
typ_pho_no_to_xkey(int typ,u_char num)772 static char typ_pho_no_to_xkey (int typ, u_char num) {
773     int i, j;
774 
775     for (i = ' '; i < 127; i++)
776         for (j = 0; j < 3; j++)
777             if (phkbm.phokbm[i][j].typ == typ && phkbm.phokbm[i][j].num == num)
778                 return i;
779 
780     return 0;
781 }
782 
start_gtab_pho_query(char * utf8)783 void start_gtab_pho_query (char *utf8) {
784     phokey_t phokeys[32];
785     int phokeysN, i;
786 
787     phokeysN = utf8_pho_keys (utf8, phokeys);
788     if (phokeysN <= 0)
789         return;
790 
791     u_char rtyp_pho[4];
792     memset (rtyp_pho, 0, sizeof (rtyp_pho));
793     key_typ_pho (phokeys[0], rtyp_pho);
794 
795     char xkeys[4];
796     memset (xkeys, 0, sizeof (xkeys));
797 
798     for (i = 0; i < 4; i++) {
799         if (!rtyp_pho[i])
800             continue;
801 
802         xkeys[i] = typ_pho_no_to_xkey (i, rtyp_pho[i]);
803     }
804 
805     if (!xkeys[3])
806         xkeys[3] = ' ';
807 
808     for (i = 0; i < 4; i++) {
809         feedkey_pho (xkeys[i], 0);
810     }
811 }
812 
pho_reset()813 void pho_reset () {
814 }
815 
816 #include "im-client/hime-im-client-attr.h"
817 extern GtkWidget *gwin_pho;
818 
pho_get_preedit(char * str,HIME_PREEDIT_ATTR attr[],int * cursor,int * sub_comp_len)819 int pho_get_preedit (char *str, HIME_PREEDIT_ATTR attr[], int *cursor, int *sub_comp_len) {
820     *sub_comp_len = !typ_pho_empty ();
821     ;
822     if (gwin_pho && gtk_widget_get_visible (gwin_pho))
823         *sub_comp_len |= 2;
824     *cursor = 0;
825     str[0] = 0;
826     return 0;
827 }
828 
829 static PHO_ST temp_pho_st;
pho_save_gst()830 void pho_save_gst () {
831     temp_pho_st = poo;
832 }
833 
pho_restore_gst()834 void pho_restore_gst () {
835     poo = temp_pho_st;
836 }
837