1 /*
2 Copyright (C) 1994-2008 Edward Der-Hua Liu, Hsin-Chu, Taiwan
3 */
4
5
6 #include "gcin.h"
7 #include "pho.h"
8 #include <sys/stat.h>
9 #include <stdlib.h>
10 #include "gtab.h"
11 #include "gst.h"
12 #include "pho-status.h"
13
14 PHO_ST poo;
15 extern gboolean test_mode;
16
17 extern PHO_ITEM *ch_pho;
18
19 PHOKBM phkbm;
20 extern int text_pho_N;
21 gboolean b_hsu_kbm;
22 extern PIN_JUYIN *pin_juyin;
23 int pin_juyinN;
24
25 gboolean full_char_proc(KeySym keysym);
26 void hide_win_pho();
27 void ClrSelArea();
28
29 #define MAX_HASH_PHO 27
30 u_short hash_pho[MAX_HASH_PHO+1];
31
32 char typ_pho_len[]={5, 2, 4, 3};
33
34 gboolean same_query_show_pho_win();
35
typ_pho_empty3()36 gboolean typ_pho_empty3()
37 {
38 return !poo.typ_pho[0] &&!poo.typ_pho[1] &&!poo.typ_pho[2] &&!poo.typ_pho[3];
39 }
40
typ_pho_empty()41 gboolean typ_pho_empty()
42 {
43 return typ_pho_empty3() &&!poo.typ_pho[3];
44 }
45
pho_has_input()46 gboolean pho_has_input()
47 {
48 return !typ_pho_empty() || same_query_show_pho_win();
49 }
50
pho2key(char typ_pho[])51 phokey_t pho2key(char typ_pho[])
52 {
53 phokey_t key=typ_pho[0];
54 int i;
55
56 if (key==BACK_QUOTE_NO)
57 return (BACK_QUOTE_NO<<9) | typ_pho[1];
58
59 for(i=1; i < 4; i++) {
60 key = typ_pho[i] | (key << typ_pho_len[i]) ;
61 }
62
63 return key;
64 }
65
key_typ_pho(phokey_t phokey,u_char rtyp_pho[])66 void key_typ_pho(phokey_t phokey, u_char rtyp_pho[])
67 {
68 rtyp_pho[3] = phokey & 7;
69 phokey >>= 3;
70 rtyp_pho[2] = phokey & 0xf;
71 phokey >>=4;
72 rtyp_pho[1] = phokey & 0x3;
73 phokey >>=2;
74 rtyp_pho[0] = phokey;
75 }
76
mask_key_typ_pho(phokey_t * key)77 void mask_key_typ_pho(phokey_t *key)
78 {
79 if (poo.typ_pho[0] == BACK_QUOTE_NO)
80 return;
81 if (!poo.typ_pho[0]) *key &= ~(31<<9);
82 if (!poo.typ_pho[1]) *key &= ~(3<<7);
83 if (!poo.typ_pho[2]) *key &= ~(15<<3);
84 if (!poo.typ_pho[3]) *key &= ~(7);
85 }
86
87 #define TKBM 0
88 #define MIN_M_PHO 5
89
90 // skip table for hsu
91 static phokey_t skip[]={
92 0x1002, //ㄌ2
93 0x4604, //
94 0x30, // ㄟ
95 0x604, // ㄇ4
96 0x600, // ㄇ
97 0x400, // ㄆ
98 0xc00, // ㄊ
99 0x1600, // ㄏ
100 0xe00, // ㄋ
101 0x1400, // ㄎ
102 0x1c00, // ㄒ
103 0x1200, // ㄍ
104 0x1c01, // ㄒ1 pho-huge
105 0x1c02, // ㄒ2 pho-huge
106 0x1c03, // ㄒ3 pho-huge
107 0x1c04, // ㄒ4 pho-huge
108 0 // stop
109 };
110
111 #define HUGE_PHO 1
112
113 #if HUGE_PHO
find_match_phos_(u_char mtyp_pho[4],int * mcount,int newkey,gboolean mask_tone_only)114 static void find_match_phos_(u_char mtyp_pho[4], int *mcount, int newkey, gboolean mask_tone_only)
115 #else
116 static void find_match_phos(u_char mtyp_pho[4], int *mcount, int newkey)
117 #endif
118 {
119 int vv;
120 phokey_t key = pho2key(poo.typ_pho);
121 phokey_t mkey;
122
123 *mcount = 0;
124 bzero(mtyp_pho, sizeof(poo.typ_pho));
125
126 mask_key_typ_pho(&key);
127 #if TKBM
128 dbg("-------------------- %d --", poo.typ_pho[3]);
129 prph(key);
130 dbg("\n");
131 #endif
132 for (vv = hash_pho[poo.typ_pho[0]]; vv < hash_pho[poo.typ_pho[0]+1]; vv++) {
133 phokey_t ttt=idx_pho[vv].key;
134 #if TKBM
135 prph(ttt); dbg(" 0x%x\n", ttt);
136 #endif
137 int j;
138 for(j=0; skip[j]; j++)
139 if (skip[j]==ttt)
140 break;
141 if (skip[j])
142 continue;
143
144
145 if (newkey!=' ' && !poo.typ_pho[3]) {
146 #if HUGE_PHO
147 if (mask_tone_only)
148 ttt &= ~(7);
149 else
150 #endif
151 mask_key_typ_pho(&ttt);
152 }
153
154 if (ttt < key)
155 continue;
156
157 if (ttt > key)
158 break;
159
160 // dbg(" "); prph(ttt); dbg(" 0x%x\n", ttt);
161
162 int count = 0;
163
164 int i;
165 for(i=idx_pho[vv].start; i < idx_pho[vv+1].start; i++) {
166 // dbg("%d %s",vv, pho_idx_str(i));
167 if (utf8_sz(pho_idx_str(i)) > 1) {
168 #if 0
169 utf8_putchar(ch_pho[i].ch);
170 dbg(" ");
171 #endif
172 count++;
173 }
174 }
175
176 if (*mcount < count) {
177 *mcount = count;
178 memcpy(mtyp_pho, poo.typ_pho, sizeof(poo.typ_pho));
179 #if TKBM
180 dbg("count %d\n", count);
181 #endif
182
183 #if 0
184 if (*mcount > MIN_M_PHO)
185 break;
186 #endif
187 }
188 }
189
190 dbg("ret %d\n", *mcount);
191 }
192
193 #if HUGE_PHO
find_match_phos(u_char mtyp_pho[4],int * mcount,int newkey)194 static void find_match_phos(u_char mtyp_pho[4], int *mcount, int newkey) {
195 find_match_phos_(mtyp_pho, mcount, newkey, TRUE);
196 *mcount = *mcount*100;
197 if (*mcount==0) {
198 find_match_phos_(mtyp_pho, mcount, newkey, FALSE);
199 }
200 }
201 #endif
202
203 gboolean inph_typ_pho_pinyin(int newkey);
204
typ_pho_status()205 static int typ_pho_status()
206 {
207 return poo.typ_pho[3] ? PHO_STATUS_OK_NEW:PHO_STATUS_OK;
208 }
209
210 // only for 41 key
inph_typ_pho_no_tone(KeySym newkey)211 int inph_typ_pho_no_tone(KeySym newkey)
212 {
213 dbg("inph_typ_pho_no_tone %d %c\n", newkey, newkey);
214 int i;
215 int insert = -1;
216
217 if (poo.typ_pho[0]==BACK_QUOTE_NO) {
218 poo.typ_pho[1]=(char)newkey;
219 poo.inph[1]=newkey;
220 return PHO_STATUS_OK|PHO_STATUS_TONE;
221 }
222
223 if (newkey==' ') {
224 // dbg("zzzz\n");
225 if (!poo.typ_pho[0] && !poo.typ_pho[1] && !poo.typ_pho[2])
226 return PHO_STATUS_REJECT;
227 if (newkey==' ') {
228 u_char mtyp_pho[4];
229 int count;
230 find_match_phos(mtyp_pho, &count, newkey);
231 // dbg("count %d\n", count);
232 if (count > 0)
233 return PHO_STATUS_OK_NEW|PHO_STATUS_TONE;
234 return PHO_STATUS_OK_NEW;
235 }
236 if (poo.typ_pho[0]==BACK_QUOTE_NO && poo.typ_pho[1])
237 return PHO_STATUS_OK_NEW | PHO_STATUS_TONE;
238 // dbg("ok %d\n", poo.typ_pho[0]);
239 return PHO_STATUS_OK;
240 }
241
242
243 int max_in_idx;
244 for(max_in_idx=3; max_in_idx>=0 && !poo.typ_pho[max_in_idx]; max_in_idx--);
245
246 // try insert mode first
247 for(i=0; i < 3; i++) {
248 char num = phkbm.phokbm[(int)newkey][i].num;
249 int typ = phkbm.phokbm[(int)newkey][i].typ;
250
251 if (num && !poo.inph[typ] && typ>max_in_idx) {
252 poo.inph[typ] = newkey;
253 poo.typ_pho[typ] = num;
254 #if TKBM || 0
255 dbg("insert typ %d\n", typ);
256 #endif
257 insert = typ;
258 if (typ==3) {
259 poo.typ_pho[typ] = num;
260 return PHO_STATUS_OK_NEW | PHO_STATUS_TONE;
261 }
262
263 #if 1
264 if (typ==1) {
265 if (poo.typ_pho[0]) {
266 u_char mtyp_pho[4];
267 int count;
268 find_match_phos(mtyp_pho, &count, newkey);
269 if (!count) {
270 poo.typ_pho[1]=0;
271 insert=-1;
272 break;
273 }
274 }
275 }
276 #endif
277
278 #if 0
279 if (typ==2) {
280 if (poo.typ_pho[0]) {
281 u_char mtyp_pho[4];
282 int count;
283 find_match_phos(mtyp_pho, &count, newkey);
284 if (!count) {
285 poo.typ_pho[2]=0;
286 insert=-1;
287 break;
288 }
289 }
290 }
291 #endif
292
293
294 #if 0
295 if (typ==2) {
296 poo.typ_pho[typ] = num;
297 return PHO_STATUS_OK_NEW;
298 }
299 #endif
300 break;
301 }
302 }
303
304 if (insert < 0) {
305 bzero(poo.inph, sizeof(poo.inph));
306 poo.inph[0]=newkey;
307 // dbg("PHO_STATUS_PINYIN_LEFT\n");
308 return PHO_STATUS_OK_NEW|PHO_STATUS_PINYIN_LEFT;
309 }
310
311 return PHO_STATUS_OK;
312 }
313
314
inph_typ_pho(KeySym newkey)315 int inph_typ_pho(KeySym newkey)
316 {
317 int i;
318 int insert = -1;
319
320 if (pin_juyin) {
321 return inph_typ_pho_pinyin(newkey);
322 }
323
324 if (pho_no_tone) {
325 return inph_typ_pho_no_tone(newkey);
326 }
327
328 if (poo.typ_pho[0]==BACK_QUOTE_NO) {
329 poo.typ_pho[1]=(char)newkey;
330 poo.inph[1]=newkey;
331 return PHO_STATUS_OK;
332 }
333
334 int max_in_idx;
335 for(max_in_idx=3; max_in_idx>=0 && !poo.typ_pho[max_in_idx]; max_in_idx--);
336
337 // try insert mode first
338 for(i=0; i < 3; i++) {
339 char num = phkbm.phokbm[(int)newkey][i].num;
340 int typ = phkbm.phokbm[(int)newkey][i].typ;
341
342 if (num && !poo.inph[typ] && typ>max_in_idx) {
343 poo.inph[typ] = newkey;
344 poo.typ_pho[typ] = num;
345 #if TKBM
346 dbg("insert typ %d\n", typ);
347 #endif
348 insert = typ;
349 break;
350 }
351 }
352
353 if (insert < 0) {
354 // then overwrite mode
355 for(i=0; i < 3; i++) {
356 char num = phkbm.phokbm[newkey][i].num;
357 int typ = phkbm.phokbm[newkey][i].typ;
358
359 if (num) {
360 poo.inph[typ] = newkey;
361 poo.typ_pho[typ] = num;
362 insert = typ;
363 break;
364 }
365 }
366 }
367
368 // dbg("newkey %c\n", newkey);
369
370 int mcount = 0;
371 u_char mtyp_pho[4];
372 char mtyp0=0;
373
374 find_match_phos(mtyp_pho, &mcount, newkey);
375
376 // dbg("mcount %d\n", mcount);
377
378 int a;
379 for(a=0; a < 3; a++) {
380 int mc=0;
381 u_char ttyp[4];
382 char num = phkbm.phokbm[(int)poo.inph[0]][a].num;
383 char typ = phkbm.phokbm[(int)poo.inph[0]][a].typ;
384 #if 0
385 if (typ == 3)
386 continue;
387 #endif
388 if (!num)
389 continue;
390
391 if (num && mcount==0) {
392 if (typ==2 && poo.typ_pho[0] && !poo.typ_pho[2])
393 poo.typ_pho[0] = 0;
394 poo.typ_pho[(int)typ] = num;
395 #if TKBM
396 dbg("%d num %d\n",a, num);
397 #endif
398 find_match_phos(mtyp_pho, &mcount, newkey);
399 }
400
401 if (mcount==0)
402 for(i=0; i < 3; i++) {
403 char num = phkbm.phokbm[(int)poo.inph[2]][i].num;
404 char typ = phkbm.phokbm[(int)poo.inph[2]][i].typ;
405
406 if (!num)
407 break;
408
409 if (typ!=2)
410 continue;
411
412 poo.typ_pho[(int)typ] = num;
413
414 find_match_phos(mtyp_pho, &mcount, newkey);
415 #if 0
416 if (mcount > MIN_M_PHO) {
417 memcpy(poo.typ_pho, mtyp_pho, sizeof(poo.typ_pho));
418 return typ_pho_status();
419 }
420 #endif
421 }
422
423 if (mcount > 0 && typ != mtyp0)
424 continue;
425
426 poo.typ_pho[mtyp0] = 0;
427
428 poo.typ_pho[typ]=num;
429 find_match_phos(ttyp, &mc, newkey);
430
431 if (mc > mcount) {
432 memcpy(mtyp_pho, ttyp, sizeof(ttyp));
433 mcount = mc;
434 mtyp0 = typ;
435 }
436 }
437
438 if (mcount) {
439 memcpy(poo.typ_pho, mtyp_pho, sizeof(poo.typ_pho));
440 return typ_pho_status();
441 }
442
443 return PHO_STATUS_REJECT;
444 }
445
446
clrin_pho()447 void clrin_pho()
448 {
449 bzero(poo.typ_pho,sizeof(poo.typ_pho));
450 bzero(poo.inph,sizeof(poo.inph));
451 poo.maxi=poo.ityp3_pho=0;
452 poo.cpg=0;
453
454 if (gcin_pop_up_win && !same_query_show_pho_win()
455 && inmd[default_input_method].method_type==method_type_PHO)
456 hide_win_pho();
457 }
458
459 void disp_pho(int index, char *phochar);
clr_in_area_pho()460 void clr_in_area_pho()
461 {
462 int i;
463
464 clrin_pho();
465 for(i=0; i < text_pho_N; i++)
466 disp_pho(i, " ");
467 }
468
469 void hide_show_pho_in(gboolean show);
470
disp_in_area_pho()471 static void disp_in_area_pho()
472 {
473 int i;
474 if (test_mode)
475 return;
476
477 hide_show_pho_in(!gcin_display_on_the_spot_key());
478
479 text_pho_N = pin_juyin?7:4;
480 if (pin_juyin) {
481 for(i=0;i<text_pho_N;i++) {
482 disp_pho(i, &poo.inph[i]);
483 }
484 } else {
485 for(i=0;i<4;i++) {
486 if (i==1 && poo.typ_pho[0]==BACK_QUOTE_NO) {
487 disp_pho(i, &poo.inph[1]);
488 }
489 else
490 disp_pho(i, &pho_chars[i][poo.typ_pho[i]*3]);
491 }
492 }
493 }
494
qcmp_count(const void * aa,const void * bb)495 static int qcmp_count(const void *aa, const void *bb)
496 {
497 PHO_ITEM *a = (PHO_ITEM *)aa;
498 PHO_ITEM *b = (PHO_ITEM *)bb;
499
500 return b->count - a->count;
501 }
502
503 void disp_pho_sel(char *s);
504 void minimize_win_pho();
505
ClrPhoSelArea()506 static void ClrPhoSelArea()
507 {
508 disp_pho_sel("");
509 minimize_win_pho();
510 }
511
512
513 extern char *TableDir;
514 extern char phofname[128];
515
get_start_stop_idx(phokey_t key,int * start_i,int * stop_i)516 gboolean get_start_stop_idx(phokey_t key, int *start_i, int *stop_i)
517 {
518 int typ_pho0 = key >> 9;
519 int vv=hash_pho[typ_pho0];
520
521 while (vv<idxnum_pho) {
522 if (idx_pho[vv].key>=key) break;
523 else
524 vv++;
525 }
526
527 if (vv >= idxnum_pho || idx_pho[vv].key != key)
528 return FALSE;
529
530 *start_i=idx_pho[vv].start;
531 *stop_i=idx_pho[vv+1].start;
532
533 return TRUE;
534 }
535
536 // given the pho key & the utf8 char, return the idx in ch_pho
ch_key_to_ch_pho_idx(phokey_t phkey,char * utf8)537 int ch_key_to_ch_pho_idx(phokey_t phkey, char *utf8)
538 {
539 int start_i, stop_i;
540
541 if (!get_start_stop_idx(phkey, &start_i, &stop_i))
542 return -1;
543
544 int i;
545 for(i=start_i; i<stop_i; i++) {
546 char *ch = pho_idx_str(i);
547 #if 0
548 int u8len = utf8_sz(ch);
549 if (!memcmp(ch, utf8, u8len))
550 #else
551 if (!strcmp(ch, utf8))
552 #endif
553 {
554 return i;
555 }
556 }
557
558 // prph(phkey);
559 // dbg("error found %c%c", *big5, *(big5+1));
560 return -1;
561 }
562
563 // need this because android's qsort is not stable
my_sort(void * base,size_t nmemb,size_t size,int (* compar)(const void *,const void *))564 static void my_sort(void *base, size_t nmemb, size_t size,
565 int(*compar)(const void *, const void *))
566 {
567 char t[128];
568 int i;
569 for(i=0;i<nmemb-1;i++) {
570 void *pi = (char *)base + i * size;
571 int j;
572 for(j=i+1;j<nmemb;j++) {
573 void *pj = (char *)base + j * size;
574 if (compar(pi, pj) <= 0)
575 continue;
576
577 memcpy(t, pi, size);
578 memcpy(pi, pj, size);
579 memcpy(pj, t, size);
580 }
581 }
582 }
583
584 #if WIN32
585 #include <share.h>
586 #endif
587
588 static FILE *fw;
589
close_pho_fw()590 void close_pho_fw()
591 {
592 if (!fw)
593 return;
594 fclose(fw);
595 fw = NULL;
596 }
597
inc_pho_count(phokey_t key,int ch_idx)598 void inc_pho_count(phokey_t key, int ch_idx)
599 {
600 int start_i, stop_i;
601
602 if (!phonetic_char_dynamic_sequence)
603 return;
604
605 get_start_stop_idx(key, &start_i, &stop_i);
606
607 // dbg("start_i %d %d %d %d\n", start_i, stop_i, poo.start_idx, poo.stop_idx);
608
609 ch_pho[ch_idx].count++;
610 // dbg("count %d\n", ch_pho[ch_idx].count);
611
612 #if 0
613 qsort
614 #else
615 my_sort
616 #endif
617 (&ch_pho[start_i], stop_i - start_i, sizeof(PHO_ITEM), qcmp_count);
618
619 #if 0
620 int i;
621 for(i=start_i; i < stop_i; i++) {
622 dbg("uuuu %c%c%c %d\n", ch_pho[i].ch[0], ch_pho[i].ch[1],
623 ch_pho[i].ch[2], ch_pho[i].count);
624 }
625 #endif
626
627 // dbg("phofname %s\n", phofname);
628 #if UNIX
629 if (!fw && (fw=fopen(phofname,"rb+"))==NULL)
630 #else
631 if (!fw && (fw=_fsopen(phofname,"rb+", _SH_DENYWR))==NULL)
632 #endif
633 {
634 p_err("err %s\n", phofname);
635 }
636
637 if (fseek(fw, ch_pho_ofs + sizeof(PHO_ITEM) * start_i, SEEK_SET) < 0)
638 p_err("fseek err");
639 #if 1
640 if (fwrite(&ch_pho[start_i], sizeof(PHO_ITEM), stop_i - start_i, fw) <= 0)
641 p_err("fwrite err");
642 fflush(fw);
643 #endif
644
645 #if 0
646 fclose(fw);
647 #endif
648 }
649
650
651 void lookup_gtab(char *ch);
652 gboolean is_gtab_query_mode();
653 void set_gtab_target_displayed();
654
655 #include "gtab-buf.h"
656
putkey_pho(u_short key,int idx)657 void putkey_pho(u_short key, int idx)
658 {
659 dbg("putkey_pho test_mode:%d idx:%d\n", test_mode, idx);
660 if (test_mode)
661 return;
662
663 char *pho_str = pho_idx_str(idx);
664 dbg("pho_str %s\n", pho_str);
665 if (poo.same_pho_query_state==SAME_PHO_QUERY_pho_select && ggg.gbufN)
666 insert_gbuf_nokey(pho_str);
667 else {
668 send_text(pho_str);
669 }
670
671 lookup_gtab(pho_str);
672
673 inc_pho_count(key, idx);
674
675 clr_in_area_pho();
676 ClrSelArea();
677 ClrPhoSelArea();
678
679 if (is_gtab_query_mode())
680 set_gtab_target_displayed();
681 }
682
683 void load_pin_juyin();
684 void recreate_win1_if_nessary();
685
load_tab_pho_file()686 void load_tab_pho_file()
687 {
688 close_pho_fw();
689 pho_load();
690
691 bzero(poo.typ_pho,sizeof(poo.typ_pho));
692
693 u_int ttt=0;
694 int i;
695 for(i=0; i<MAX_HASH_PHO; i++) {
696 if (idx_pho[ttt].key >> 9 == i)
697 hash_pho[i]=ttt;
698 else {
699 continue;
700 }
701
702 while (ttt < idxnum_pho && idx_pho[ttt].key >> 9 == i)
703 ttt++;
704 }
705
706 for(i=MAX_HASH_PHO; !hash_pho[i]; i--)
707 hash_pho[i]=idxnum_pho;
708
709 char kbmfname[MAX_GCIN_STR];
710 FILE *fr;
711
712 free(pin_juyin);
713 pin_juyin = NULL;
714
715 if (!strstr(pho_kbm_name, "pinyin")) {
716 text_pho_N = 4;
717 } else {
718 load_pin_juyin();
719 }
720
721 if (strcmp(pho_kbm_name, "hsu"))
722 b_hsu_kbm = FALSE;
723 else
724 b_hsu_kbm = TRUE;
725
726 char pho_kbm_name_kbm[128];
727
728 strcat(strcpy(pho_kbm_name_kbm, pho_kbm_name), ".kbm");
729 dbg("phokbm_name: %s\n", pho_kbm_name_kbm);
730
731 get_sys_table_file_name(pho_kbm_name_kbm, kbmfname);
732
733 if ((fr=fopen(kbmfname,"rb"))==NULL)
734 p_err("Cannot open %s", kbmfname);
735
736 dbg("kbmfname %s\n", kbmfname);
737
738 int n = fread(&phkbm,sizeof(phkbm),1,fr);
739 fclose (fr);
740 phkbm.selkeyN = strlen(pho_selkey);
741
742 dbg("pho_selkey %s\n", pho_selkey);
743
744 recreate_win1_if_nessary();
745 #if 0
746 for(i='A'; i <= 'z'; i++)
747 dbg("%c %d %d\n", i, phkbm.phokbm[i][0].num, phkbm.phokbm[i][0].typ);
748 #endif
749 }
750
751
752 void show_win_pho();
753
init_tab_pho()754 void init_tab_pho()
755 {
756 if (!ch_pho) {
757 load_tab_pho_file();
758 }
759
760 show_win_pho();
761 clr_in_area_pho();
762 }
763
pho_idx_str_markup(int ii)764 static char *pho_idx_str_markup(int ii)
765 {
766 char *pho_str = pho_idx_str(ii);
767 if (!strcmp(pho_str, "<"))
768 pho_str = "<";
769 else
770 if (!strcmp(pho_str, ">"))
771 pho_str = ">";
772 return pho_str;
773 }
774
775
776 gboolean shift_char_proc(KeySym key, int kbstate);
777 gboolean pre_punctuation(KeySym xkey);
778 void pho_play(phokey_t key);
779 void close_gtab_pho_win();
780 gboolean pre_punctuation_hsu(KeySym xkey);
781 void case_inverse(KeySym *xkey, int shift_m);
782
feedkey_pho(KeySym xkey,int kbstate)783 int feedkey_pho(KeySym xkey, int kbstate)
784 {
785 int ctyp = 0;
786 #if 0
787 static unsigned int vv, ii;
788 static phokey_t key;
789 #endif
790 char *pp=NULL;
791 char kno;
792 int i,j,jj=0,kk=0;
793 char out_buffer[512];
794 int out_bufferN;
795 int shift_m=kbstate&ShiftMask;
796 int ctrl_m=kbstate&ControlMask;
797
798 dbg("%d ------------- feedkey_pho %d %d\n",test_mode, poo.ityp3_pho, poo.cpg);
799
800 if (ctrl_m)
801 return 0;
802
803
804 if (kbstate&LockMask) {
805 if (xkey >= 0x7e || xkey < ' ')
806 return FALSE;
807 if (gcin_capslock_lower)
808 case_inverse(&xkey, shift_m);
809 if (!test_mode)
810 send_ascii(xkey);
811 return 1;
812 }
813
814 if (xkey >= 'A' && xkey <='Z' && poo.typ_pho[0]!=BACK_QUOTE_NO)
815 xkey+=0x20;
816
817 switch (xkey) {
818 case XK_Escape:
819 if (typ_pho_empty())
820 return 0;
821 ClrPhoSelArea();
822 clr_in_area_pho();
823 if (is_gtab_query_mode())
824 close_gtab_pho_win();
825 return 1;
826 case XK_BackSpace:
827 poo.ityp3_pho=0;
828 for(j=3;j>=0;j--) if (poo.typ_pho[j]) {
829 poo.typ_pho[j]=0;
830 if (typ_pho_empty()) {
831 ClrSelArea();
832 clr_in_area_pho();
833 return 1;
834 }
835 break;
836 }
837
838 if (j<0)
839 return 0;
840
841 goto llll3;
842 case '<':
843 if (!poo.ityp3_pho && tsin_shift_punc) {
844 return pre_punctuation(xkey);
845 }
846 if (poo.cpg >= phkbm.selkeyN)
847 poo.cpg -= phkbm.selkeyN;
848 goto proc_state;
849 case ' ':
850 if (!poo.typ_pho[0] && !poo.typ_pho[1] && !poo.typ_pho[2]) {
851 if (current_CS->b_half_full_char)
852 return full_char_proc(xkey);
853 return 0;
854 }
855
856 // dbg("poo.ityp3_pho %d\n", poo.ityp3_pho);
857 if (!poo.ityp3_pho) {
858 poo.ityp3_pho = TRUE;
859 goto lll1;
860 }
861
862 poo.ii = poo.start_idx+ poo.cpg + phkbm.selkeyN;
863
864 if (poo.ii < poo.stop_idx) {
865 poo.cpg += phkbm.selkeyN;
866 dbg("spc pool.cpg %d\n", poo.cpg);
867 } else {
868 if (poo.cpg) {
869 poo.cpg=0;
870 poo.ii=poo.start_idx;
871 } else {
872 putkey_pho(poo.key, poo.start_idx);
873 return 1;
874 }
875 }
876
877 goto disp;
878 default:
879 if (xkey >= 127 || xkey < ' ')
880 return 0;
881
882 if (shift_m && tsin_shift_punc) {
883 // return shift_char_proc(xkey, kbstate);
884 if (pre_punctuation(xkey))
885 return 1;
886 return 0;
887 }
888
889 // dbg("poo.maxi:%d %d\n", poo.maxi, poo.cpg);
890
891 if ((pp=strchr(pho_selkey, xkey)) && poo.maxi && poo.ityp3_pho) {
892 int c=pp-pho_selkey;
893
894 if (c<poo.maxi) {
895 putkey_pho(poo.key, poo.start_idx + poo.cpg + c);
896 }
897 return 1;
898 }
899
900 if (poo.ityp3_pho && !poo.cpg) {
901 dbg("poo.start_idx: %d\n", poo.start_idx);
902 putkey_pho(poo.key, poo.start_idx);
903 }
904
905 // poo.cpg=0;
906 }
907
908 lll1:
909 inph_typ_pho(xkey);
910 // dbg("typ_pho %x %x\n", poo.typ_pho[0], poo.typ_pho[1]);
911
912 if (gcin_pop_up_win)
913 show_win_pho();
914
915 if (poo.typ_pho[3])
916 ctyp = 3;
917
918 jj=0;
919 kk=1;
920 llll2:
921 if (ctyp == 3) {
922 poo.ityp3_pho=1; /* last key is entered */
923 }
924 llll3:
925
926 poo.key = pho2key(poo.typ_pho);
927
928 #if 0
929 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]);
930 #endif
931 if (!poo.key) {
932 return pre_punctuation_hsu(xkey);
933 }
934
935 pho_play(poo.key);
936
937 poo.vv=hash_pho[poo.typ_pho[0]];
938 phokey_t ttt;
939 ttt=0xffff;
940
941 while (poo.vv < idxnum_pho) {
942 ttt=idx_pho[poo.vv].key;
943 mask_key_typ_pho(&ttt);
944
945 if (ttt>=poo.key)
946 break;
947 else
948 poo.vv++;
949 }
950
951 // dbg("vv %d %d\n", vv, idxnum_pho);
952
953 if (ttt > poo.key || (poo.ityp3_pho && idx_pho[poo.vv].key != poo.key) ) {
954 // dbg("not found\n");
955 while (jj<4) {
956 while(kk<3)
957 if (phkbm.phokbm[(int)poo.inph[jj]][kk].num ) {
958
959 if (kk) {
960 ctyp=phkbm.phokbm[(int)poo.inph[jj]][kk-1].typ;
961 poo.typ_pho[ctyp]=0;
962 }
963
964 kno=phkbm.phokbm[(int)poo.inph[jj]][kk].num;
965 ctyp=phkbm.phokbm[(int)poo.inph[jj]][kk].typ;
966 poo.typ_pho[ctyp]=kno;
967 kk++;
968 goto llll2;
969 }
970 else
971 kk++;
972 jj++;
973 kk=1;
974 }
975
976 bell();
977 poo.ityp3_pho=poo.typ_pho[3]=0;
978 disp_in_area_pho();
979
980 return 1;
981 }
982
983 proc_state:
984 disp_in_area_pho();
985 poo.start_idx = poo.ii = idx_pho[poo.vv].start;
986 poo.stop_idx = idx_pho[poo.vv+1].start;
987
988 // dbg("poo.start_idx: %d %d\n", poo.start_idx, poo.stop_idx);
989
990 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])
991 poo.ityp3_pho = 1;
992
993 poo.ii+=poo.cpg;
994
995 if (poo.ityp3_pho && poo.stop_idx - poo.start_idx==1) {
996 putkey_pho(poo.key, poo.ii);
997 poo.maxi=poo.ityp3_pho=0;
998 return 1;
999 }
1000
1001 disp:
1002 if (test_mode)
1003 return 1;
1004
1005 i=0;
1006 out_bufferN=0;
1007 out_buffer[0]=0;
1008
1009 if (poo.ityp3_pho) {
1010 // dbg("poo.cpg %d\n", poo.cpg);
1011
1012 while(i< phkbm.selkeyN && poo.ii < poo.stop_idx) {
1013 char tt[512];
1014 sprintf(tt, "<span foreground=\"%s\">%c</span>",
1015 gcin_sel_key_color, pho_selkey[i]);
1016 int ttlen = strlen(tt);
1017 memcpy(out_buffer+out_bufferN, tt, ttlen);
1018 out_bufferN+=ttlen;
1019 // strcat(out_buffer, tt);
1020 char *pho_str = pho_idx_str_markup(poo.ii);
1021 int len = strlen(pho_str);
1022 memcpy(&out_buffer[out_bufferN], pho_str, len);
1023 out_bufferN+=len;
1024 #if 0
1025 out_buffer[out_bufferN++] = ' ';
1026 #endif
1027 poo.ii++;
1028 i++;
1029 }
1030
1031 char *tt = poo.cpg ? "<" : " ";
1032 int ttlen = strlen(tt);
1033 memcpy(out_buffer+out_bufferN, tt, ttlen);
1034 out_bufferN+=ttlen;
1035
1036 if (poo.ii < poo.stop_idx) {
1037 out_buffer[out_bufferN++] = poo.cpg ? '\\' : ' ';
1038 tt = ">";
1039 ttlen = strlen(tt);
1040 memcpy(out_buffer+out_bufferN, tt, ttlen);
1041 out_bufferN+=strlen(tt);
1042 }
1043
1044 poo.maxi=i;
1045 } else {
1046 while(i<phkbm.selkeyN && poo.ii < poo.stop_idx) {
1047 char *pho_str = pho_idx_str_markup(poo.ii);
1048 int len = strlen(pho_str);
1049 memcpy(&out_buffer[out_bufferN], pho_str, len);
1050 out_bufferN+=len;
1051
1052 poo.ii++;
1053 i++;
1054 }
1055 poo.maxi=i;
1056 }
1057
1058 out_buffer[out_bufferN]=0;
1059 disp_pho_sel(out_buffer);
1060
1061 return 1;
1062 }
1063
typ_pho_no_to_xkey(int typ,u_char num)1064 static char typ_pho_no_to_xkey(int typ, u_char num)
1065 {
1066 int i, j;
1067
1068 for(i=' '; i < 127; i++)
1069 for(j=0; j < 3; j++)
1070 if (phkbm.phokbm[i][j].typ == typ && phkbm.phokbm[i][j].num == num)
1071 return i;
1072
1073 return 0;
1074 }
1075
1076
start_gtab_pho_query(char * utf8)1077 void start_gtab_pho_query(char *utf8)
1078 {
1079 phokey_t phokeys[32];
1080 int phokeysN, i;
1081
1082 phokeysN = utf8_pho_keys(utf8, phokeys);
1083 if (phokeysN <= 0)
1084 return;
1085
1086 u_char rtyp_pho[4];
1087 bzero(rtyp_pho, sizeof(rtyp_pho));
1088 key_typ_pho(phokeys[0], rtyp_pho);
1089
1090 char xkeys[4];
1091 bzero(xkeys, sizeof(xkeys));
1092
1093 for(i=0; i < 4; i++) {
1094 if (!rtyp_pho[i])
1095 continue;
1096
1097 xkeys[i] = typ_pho_no_to_xkey(i, rtyp_pho[i]);
1098 }
1099
1100 if (!xkeys[3])
1101 xkeys[3] = ' ';
1102
1103 for(i=0; i < 4; i++) {
1104 feedkey_pho(xkeys[i], 0);
1105 }
1106 }
1107
1108
pho_reset()1109 void pho_reset()
1110 {
1111 }
1112
1113 #if 0
1114 int feedkey_pho_release(KeySym xkey, int kbstate)
1115 {
1116 return 0;
1117 }
1118 #endif
1119
1120 #include "im-client/gcin-im-client-attr.h"
1121 extern GtkWidget *gwin_pho;
1122 int get_in_area_pho_tsin_str(char *out);
1123
pho_get_preedit(char * str,GCIN_PREEDIT_ATTR attr[],int * cursor,int * sub_comp_len)1124 int pho_get_preedit(char *str, GCIN_PREEDIT_ATTR attr[], int *cursor, int *sub_comp_len)
1125 {
1126 #if WIN32 || 1
1127 *sub_comp_len = !typ_pho_empty();;
1128 if (gwin_pho && GTK_WIDGET_VISIBLE(gwin_pho))
1129 *sub_comp_len|=2;
1130 #endif
1131 int attrN=0;
1132 #if DEBUG && 0
1133 dbg("tsin_get_preedit\n");
1134 #endif
1135 str[0]=0;
1136 if (gcin_display_on_the_spot_key())
1137 get_in_area_pho_tsin_str(str);
1138
1139 #if DEBUG && 0
1140 dbg("'%s'\n", str);
1141 #endif
1142
1143 *cursor = 0;
1144 #if 0
1145 #if WIN32 || 1
1146 *comp_flag = !typ_pho_empty();
1147 if (gwin1 && GTK_WIDGET_VISIBLE(gwin1))
1148 *comp_flag|=2;
1149 #if 1
1150 if (tss.c_len && !ap_only)
1151 *comp_flag|=4;
1152 #endif
1153 #endif
1154 #endif
1155
1156 return attrN;
1157 }
1158
1159 #if WIN32 || 1
1160 static PHO_ST temp_pho_st;
pho_save_gst()1161 void pho_save_gst()
1162 {
1163 temp_pho_st = poo;
1164 }
1165
pho_restore_gst()1166 void pho_restore_gst()
1167 {
1168 poo = temp_pho_st;
1169 }
1170 #endif
1171