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 = "&lt;";
769   else
770   if (!strcmp(pho_str, ">"))
771     pho_str = "&gt;";
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 ? "&lt;" : " ";
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 = "&gt;";
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