1 #include "gcin.h"
2 #include "gtab.h"
3 #if UNIX
4 #include <signal.h>
5 #include <X11/extensions/XTest.h>
6 #if !GTK_CHECK_VERSION(2,16,0)
7 #include <X11/XKBlib.h>
8 #include <gdk/gdkx.h>
9 #define gdk_keymap_get_caps_lock_state(x) get_caps_lock_state()
10 #endif
11 #endif
12 #include "pho.h"
13 #include "gst.h"
14 #include "im-client/gcin-im-client-attr.h"
15 #include "win1.h"
16 #include "gcin-module.h"
17 #include "gcin-module-cb.h"
18
19 #define STRBUFLEN 64
20
21 extern Display *dpy;
22 #if USE_XIM
23 extern XIMS current_ims;
24 static IMForwardEventStruct *current_forward_eve;
25 #endif
26 extern gboolean win_kbm_inited;
27
28 static char *callback_str_buffer;
29 Window focus_win;
30 static int timeout_handle;
31 char *output_buffer;
32 int output_bufferN;
33 static char *output_buffer_raw, *output_buffer_raw_bak;
34 static int output_buffer_rawN;
35 #if WIN32
36 gboolean test_mode;
37 int last_input_method;
38 #endif
39 void set_wselkey();
40 void gtab_set_win1_cb();
41 void toggle_symbol_table();
42
43 gboolean old_capslock_on;
44
45
46 void init_gtab(int inmdno);
47
current_method_type()48 char current_method_type()
49 {
50 // dbg("default_input_method %d\n",default_input_method);
51 if (!current_CS)
52 #if UNIX
53 return inmd[default_input_method].method_type;
54 #else
55 {
56 if (!last_input_method)
57 last_input_method = default_input_method;
58 return inmd[last_input_method].method_type;
59 }
60 #endif
61
62 // dbg("current_CS->in_method %d\n", current_CS->in_method);
63 return inmd[current_CS->in_method].method_type;
64 }
65
66
67 #if WIN32
68 void win32_FakeKey(UINT vk, bool key_pressed);
69 #endif
send_fake_key_eve(KeySym key)70 void send_fake_key_eve(KeySym key)
71 {
72 #if WIN32
73 win32_FakeKey(key, true);
74 Sleep(10);
75 win32_FakeKey(key, false);
76 #else
77 KeyCode kc = XKeysymToKeycode(dpy, key);
78 XTestFakeKeyEvent(dpy, kc, True, CurrentTime);
79 usleep(10000);
80 XTestFakeKeyEvent(dpy, kc, False, CurrentTime);
81 #endif
82 }
83
fake_shift()84 void fake_shift()
85 {
86 #if 0
87 send_fake_key_eve(XK_Control_L);
88 #else
89 send_fake_key_eve(XK_Shift_L);
90 #endif
91 }
92
swap_ptr(char ** a,char ** b)93 void swap_ptr(char **a, char **b)
94 {
95 char *t = *a;
96 *a = *b;
97 *b = t;
98 }
99
100 int force_preedit=0;
force_preedit_shift()101 void force_preedit_shift()
102 {
103 fake_shift();
104 force_preedit=1;
105 }
106
send_text_call_back(char * text)107 void send_text_call_back(char *text)
108 {
109 callback_str_buffer = (char *)realloc(callback_str_buffer, strlen(text)+1);
110 strcpy(callback_str_buffer, text);
111 fake_shift();
112 }
113
output_buffer_call_back()114 void output_buffer_call_back()
115 {
116 swap_ptr(&callback_str_buffer, &output_buffer);
117
118 if (output_buffer)
119 output_buffer[0] = 0;
120 output_bufferN = 0;
121
122 fake_shift();
123 }
124
125 ClientState *current_CS;
126 static ClientState temp_CS;
127
save_CS_current_to_temp()128 void save_CS_current_to_temp()
129 {
130 #if UNIX
131 if (!gcin_single_state)
132 return;
133
134 // dbg("save_CS_current_to_temp\n");
135 temp_CS.b_half_full_char = current_CS->b_half_full_char;
136 temp_CS.im_state = current_CS->im_state;
137 temp_CS.in_method = current_CS->in_method;
138 temp_CS.tsin_pho_mode = current_CS->tsin_pho_mode;
139 #endif
140 }
141
142
save_CS_temp_to_current()143 void save_CS_temp_to_current()
144 {
145 #if UNIX
146 if (!gcin_single_state)
147 return;
148
149 // dbg("save_CS_temp_to_current\n");
150 current_CS->b_half_full_char = temp_CS.b_half_full_char;
151 current_CS->im_state = temp_CS.im_state;
152 current_CS->in_method = temp_CS.in_method;
153 current_CS->tsin_pho_mode = temp_CS.tsin_pho_mode;
154 #endif
155 }
156
157
158 gboolean init_in_method(int in_no);
159
160
clear_output_buffer()161 void clear_output_buffer()
162 {
163 if (output_buffer)
164 output_buffer[0] = 0;
165 output_bufferN = 0;
166
167 swap_ptr(&output_buffer_raw, &output_buffer_raw_bak);
168
169 if (output_buffer_raw)
170 output_buffer_raw[0] = 0;
171 output_buffer_rawN = 0;
172 }
173
174 gboolean gb_output = FALSE;
175
toggle_gb_output()176 void toggle_gb_output()
177 {
178 gb_output = !gb_output;
179 }
180
append_str(char ** buf,int * bufN,char * text,int len)181 static void append_str(char **buf, int *bufN, char *text, int len)
182 {
183 int requiredN = len + 1 + *bufN;
184 *buf = (char *)realloc(*buf, requiredN);
185 (*buf)[*bufN] = 0;
186 strcat(*buf, text);
187 *bufN += len;
188 }
189
190 int trad2sim(char *str, int strN, char **out);
191 void add_ch_time_str(char *s);
192
send_text(char * text)193 void send_text(char *text)
194 {
195 #if WIN32
196 if (test_mode)
197 return;
198 #endif
199 dbg("send_text %s\n", text);
200 char *filter;
201
202 if (!text)
203 return;
204 int len = strlen(text);
205
206 add_ch_time_str(text);
207
208 append_str(&output_buffer_raw, &output_buffer_rawN, text, len);
209
210 char *utf8_gbtext = NULL;
211
212 if (gb_output) {
213 len = trad2sim(text, len, &utf8_gbtext);
214 text = utf8_gbtext;
215 }
216
217 direct:
218 #if UNIX && 0
219 filter = getenv("GCIN_OUTPUT_FILTER");
220 char filter_text[512];
221
222 if (filter) {
223 int pfdr[2], pfdw[2];
224
225 if (pipe(pfdr) == -1) {
226 dbg("cannot pipe r\n");
227 goto next;
228 }
229
230 if (pipe(pfdw) == -1) {
231 dbg("cannot pipe w\n");
232 goto next;
233 }
234
235 int pid = fork();
236
237 if (pid < 0) {
238 dbg("cannot fork filter\n");
239 goto next;
240 }
241
242 if (pid) {
243 close(pfdw[0]);
244 close(pfdr[1]);
245 if (write(pfdw[1], text, len) < 0) {
246 }
247 close(pfdw[1]);
248 int rn = read(pfdr[0], filter_text, sizeof(filter_text) - 1);
249 filter_text[rn] = 0;
250 // puts(filter_text);
251 close(pfdr[0]);
252 text = filter_text;
253 len = rn;
254 } else {
255 close(pfdr[0]);
256 close(pfdw[1]);
257 dup2(pfdw[0], 0);
258 dup2(pfdr[1], 1);
259 if (execl(filter, filter, NULL) < 0) {
260 dbg("execl %s err", filter);
261 goto next;
262 }
263 }
264
265 }
266 #endif
267 next:
268 if (len) {
269 append_str(&output_buffer, &output_bufferN, text, len);
270 }
271
272 free(utf8_gbtext);
273 }
274
send_output_buffer_bak()275 void send_output_buffer_bak()
276 {
277 send_text(output_buffer_raw_bak);
278 }
279
set_output_buffer_bak_to_clipboard()280 void set_output_buffer_bak_to_clipboard()
281 {
282 char *text, *utf8_gbtext=NULL;
283
284 if (gb_output) {
285 trad2sim(output_buffer_raw_bak, strlen(output_buffer_raw_bak),
286 &utf8_gbtext);
287 text = utf8_gbtext;
288 } else
289 text = output_buffer_raw_bak;
290
291 #if UNIX && 0
292 GtkClipboard *pclipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
293 #else
294 GtkClipboard *pclipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
295 #endif
296
297 gtk_clipboard_set_text(pclipboard, text, -1);
298
299 free(utf8_gbtext);
300 }
301
send_utf8_ch(char * bchar)302 void send_utf8_ch(char *bchar)
303 {
304 #if WIN32
305 if (test_mode)
306 return;
307 #endif
308 char tt[CH_SZ+1];
309 int len = utf8_sz(bchar);
310
311 memcpy(tt, bchar, len);
312 tt[len]=0;
313
314 send_text(tt);
315 }
316
317
send_ascii(char key)318 void send_ascii(char key)
319 {
320 send_utf8_ch(&key);
321 }
322
323 #if USE_XIM
export_text_xim()324 void export_text_xim()
325 {
326 char *text = output_buffer;
327
328 if (!output_bufferN)
329 return;
330
331 XTextProperty tp;
332 #if 0
333 char outbuf[512];
334 utf8_big5(output_buffer, outbuf);
335 text = outbuf;
336 XmbTextListToTextProperty(dpy, &text, 1, XCompoundTextStyle, &tp);
337 #else
338 Xutf8TextListToTextProperty(dpy, &text, 1, XCompoundTextStyle, &tp);
339 #endif
340
341 #if DEBUG && 0
342 dbg("send_utf8_ch: %s\n", text);
343 #endif
344
345 ((IMCommitStruct*)current_forward_eve)->flag |= XimLookupChars;
346 ((IMCommitStruct*)current_forward_eve)->commit_string = (char *)tp.value;
347 IMCommitString(current_ims, (XPointer)current_forward_eve);
348
349 clear_output_buffer();
350
351 XFree(tp.value);
352 }
353
354
bounce_back_key()355 static void bounce_back_key()
356 {
357 IMForwardEventStruct forward_ev = *(current_forward_eve);
358 IMForwardEvent(current_ims, (XPointer)&forward_ev);
359 }
360 #endif
361
362 void hide_win0();
363 void hide_win_gtab();
364 void hide_win_pho();
365
366 int current_in_win_x = -1, current_in_win_y = -1; // request x/y
367
reset_current_in_win_xy()368 void reset_current_in_win_xy()
369 {
370 #if 0
371 current_in_win_x = current_in_win_y = -1;
372 #endif
373 }
374
module_cb1(ClientState * cs)375 GCIN_module_callback_functions *module_cb1(ClientState *cs)
376 {
377 return inmd[cs->in_method].mod_cb_funcs;
378 }
379
module_cb()380 GCIN_module_callback_functions *module_cb()
381 {
382 if (!current_CS)
383 return NULL;
384 return module_cb1(current_CS);
385 }
386
hide_in_win(ClientState * cs)387 void hide_in_win(ClientState *cs)
388 {
389 #if WIN32
390 if (test_mode)
391 return;
392 #endif
393 if (!cs) {
394 #if 0
395 dbg("hide_in_win: ic is null\n");
396 #endif
397 return;
398 }
399 #if 0
400 dbg("hide_in_win %d\n", ic->in_method);
401 #endif
402
403 if (timeout_handle) {
404 g_source_remove(timeout_handle);
405 timeout_handle = 0;
406 }
407
408 switch (current_method_type()) {
409 case method_type_PHO:
410 hide_win_pho();
411 break;
412 #if USE_TSIN
413 case method_type_TSIN:
414 // flush_tsin_buffer();
415 hide_win0();
416 break;
417 #endif
418 case method_type_MODULE:
419 if (inmd[cs->in_method].mod_cb_funcs)
420 module_cb1(cs)->module_hide_win();
421 break;
422 default:
423 hide_win_gtab();
424 }
425
426 reset_current_in_win_xy();
427 }
428
429 void show_win_pho();
430 void show_win0();
431 void show_win_gtab();
432 void disp_tray_icon();
433
check_CS()434 void check_CS()
435 {
436 if (!current_CS) {
437 // dbg("!current_CS");
438 current_CS = &temp_CS;
439 // temp_CS.input_style = InputStyleOverSpot;
440 // temp_CS.im_state = GCIN_STATE_CHINESE;
441 #if TRAY_ENABLED
442 disp_tray_icon();
443 #endif
444 }
445 else {
446 #if 0
447 if (gcin_single_state)
448 save_CS_temp_to_current();
449 else
450 #endif
451 temp_CS = *current_CS;
452 }
453 }
454
455 gboolean force_show;
456
show_in_win(ClientState * cs)457 void show_in_win(ClientState *cs)
458 {
459 if (!cs) {
460 #if 0
461 dbg("show_in_win: ic is null");
462 #endif
463 return;
464 }
465
466 switch (current_method_type()) {
467 case method_type_PHO:
468 show_win_pho();
469 break;
470 #if USE_TSIN
471 case method_type_TSIN:
472 show_win0();
473 break;
474 #endif
475 case method_type_MODULE:
476 if (!module_cb1(cs))
477 return;
478 module_cb1(cs)->module_show_win();
479 break;
480 default:
481 show_win_gtab();
482 }
483 #if 0
484 show_win_stautus();
485 #endif
486 }
487
488
489 void move_win_gtab(int x, int y);
490 void move_win0(int x, int y);
491 void move_win_pho(int x, int y);
492 void disp_selections(int x, int y);
493 extern GtkWidget *gwin1;
494
move_in_win(ClientState * cs,int x,int y)495 void move_in_win(ClientState *cs, int x, int y)
496 {
497 check_CS();
498
499 if (current_CS && current_CS->fixed_pos) {
500 x = current_CS->fixed_x;
501 y = current_CS->fixed_y;
502 } else
503 if (gcin_input_style == InputStyleRoot) {
504 x = gcin_root_x;
505 y = gcin_root_y;
506 }
507
508 #if 0
509 dbg("move_in_win %d %d\n",x, y);
510 #endif
511 #if 0
512 if (current_in_win_x == x && current_in_win_y == y)
513 return;
514 #endif
515 current_in_win_x = x ; current_in_win_y = y;
516
517 switch (current_method_type()) {
518 case method_type_PHO:
519 move_win_pho(x, y);
520 break;
521 case method_type_TSIN:
522 move_win0(x, y);
523 break;
524 case method_type_MODULE:
525 if (inmd[cs->in_method].mod_cb_funcs)
526 module_cb1(cs)->module_move_win(x, y);
527 break;
528 default:
529 if (!cs->in_method)
530 return;
531 move_win_gtab(x, y);
532 }
533
534 #if WIN32
535 if (GTK_WIDGET_VISIBLE(gwin1))
536 disp_selections(-1, -1);
537 #endif
538 }
539 #if UNIX
xerror_handler(Display * d,XErrorEvent * eve)540 static int xerror_handler(Display *d, XErrorEvent *eve)
541 {
542 return 0;
543 }
544 #endif
545
getRootXY(Window win,int wx,int wy,int * tx,int * ty)546 void getRootXY(Window win, int wx, int wy, int *tx, int *ty)
547 {
548 if (!win) {
549 *tx = wx;
550 *ty = wy;
551 return;
552 }
553
554 #if WIN32
555 POINT pt;
556 pt.x = wx; pt.y = wy;
557 ClientToScreen((HWND)win, &pt);
558 *tx = pt.x; *ty=pt.y;
559 #else
560 Window ow;
561 XErrorHandler olderr = XSetErrorHandler((XErrorHandler)xerror_handler);
562 XTranslateCoordinates(dpy,win,root,wx,wy,tx,ty,&ow);
563 XSetErrorHandler(olderr);
564 #endif
565 }
566
567 extern int dpy_x_ofs, dpy_y_ofs;
568
move_IC_in_win(ClientState * cs)569 void move_IC_in_win(ClientState *cs)
570 {
571 #if 0
572 dbg("move_IC_in_win %d,%d\n", cs->spot_location.x, cs->spot_location.y);
573 #endif
574 #if WIN32
575 if (test_mode)
576 return;
577 #endif
578
579 Window inpwin = cs->client_win;
580 #if UNIX
581 if (!inpwin) {
582 dbg("no inpwin %p\n", cs);
583 return;
584 }
585 #endif
586 // non focus win filtering is done in the client lib
587 if (inpwin != focus_win && focus_win && !cs->b_gcin_protocol) {
588 return;
589 }
590
591 int inpx = cs->spot_location.x;
592 int inpy = cs->spot_location.y;
593 #if WIN32 && 0
594 if (inpx >= dpy_xl-1 || inpy >= dpy_yl-1)
595 return;
596 #endif
597 dbg("move_IC_in_win %d,%d\n", inpx, inpy);
598
599 #if UNIX
600 XWindowAttributes att;
601 XGetWindowAttributes(dpy, inpwin, &att);
602 // chrome window is override_redirect
603 // if (att.override_redirect)
604 // return;
605
606 if (inpx >= att.width)
607 inpx = att.width - 1;
608 if (inpy >= att.height)
609 inpy = att.height - 1;
610 #else
611 if (inpwin) {
612 RECT rect;
613 GetClientRect((HWND)inpwin, &rect);
614
615 rect.right -= dpy_x_ofs;
616 rect.bottom -= dpy_y_ofs;
617
618 if (inpx >= rect.right)
619 inpx = rect.right - 1;
620 if (inpy >= rect.bottom)
621 inpy = rect.bottom - 1;
622 }
623 dbg("GetClientRect %x %d,%d\n", inpwin, inpx, inpy);
624 #endif
625 int tx,ty;
626 getRootXY(inpwin, inpx, inpy, &tx, &ty);
627
628 #if 1
629 dbg("move_IC_in_win inpxy:%d,%d txy:%d,%d\n", inpx, inpy, tx, ty);
630 #endif
631
632 move_in_win(cs, tx, ty+1);
633 }
634
635
update_in_win_pos()636 void update_in_win_pos()
637 {
638 #if WIN32
639 if (test_mode)
640 return;
641 #endif
642
643 check_CS();
644
645 // dbg("update_in_win_pos %x %d\n", current_CS, current_CS->input_style);
646
647 if (current_CS->input_style == InputStyleRoot) {
648 #if UNIX
649 Window r_root, r_child;
650 int winx, winy, rootx, rooty;
651 u_int mask;
652
653 XQueryPointer(dpy, root, &r_root, &r_child, &rootx, &rooty, &winx, &winy, &mask);
654
655 winx++; winy++;
656
657 Window inpwin = current_CS->client_win;
658 #if 0
659 dbg("update_in_win_pos\n");
660 #endif
661 if (inpwin) {
662 int tx, ty;
663 Window ow;
664
665 XTranslateCoordinates(dpy, root, inpwin, winx, winy, &tx, &ty, &ow);
666
667 current_CS->spot_location.x = tx;
668 current_CS->spot_location.y = ty;
669 }
670 #else
671 int winx=0, winy=0;
672 current_CS->spot_location.x = 0;
673 current_CS->spot_location.y = 0;
674 #endif
675
676 move_in_win(current_CS, winx, winy);
677 } else {
678 move_IC_in_win(current_CS);
679 }
680
681 disp_tray_icon();
682 }
683
684 void win_pho_disp_half_full();
685 void win_tsin_disp_half_full();
686 void win_gtab_disp_half_full();
687 void update_tray_icon(), load_tray_icon(), load_tray_icon_win32();
688 static int current_gcin_win32_icon = -1;
689 void restart_gcin0();
690 extern void destroy_tray_win32();
691 extern void destroy_tray_icon();
692 void load_tray_icon_indicator();
693 void destroy_tray_indicator();
694
695 #if TRAY_ENABLED
696 #if UNIX
destroy_tray()697 void destroy_tray()
698 {
699 if (current_gcin_win32_icon==GCIN_TRAY_WIN32)
700 destroy_tray_win32();
701 else
702 if (current_gcin_win32_icon==GCIN_TRAY_UNIX)
703 destroy_tray_icon();
704 #if USE_INDICATOR
705 else
706 destroy_tray_indicator();
707 #endif
708 }
709 #endif
710
disp_tray_icon()711 void disp_tray_icon()
712 {
713 #if WIN32
714 if (test_mode)
715 return;
716 #endif
717 // dbg("disp_tray_icon\n");
718 //dbg("disp_tray_icon %d %d\n", current_gcin_win32_icon, gcin_win32_icon);
719 #if UNIX
720 if (current_gcin_win32_icon >= 0 && current_gcin_win32_icon != gcin_win32_icon) {
721 destroy_tray();
722 }
723
724 current_gcin_win32_icon = gcin_win32_icon;
725
726 if (gcin_win32_icon==GCIN_TRAY_WIN32)
727 #endif
728 load_tray_icon_win32();
729 #if UNIX
730 else
731 if (gcin_win32_icon==GCIN_TRAY_UNIX)
732 load_tray_icon();
733 #if USE_INDICATOR
734 else
735 load_tray_icon_indicator();
736 #endif
737 #endif
738 }
739 #endif
740
disp_im_half_full()741 void disp_im_half_full()
742 {
743 // dbg("disp_im_half_full\n");
744 #if WIN32
745 if (test_mode)
746 return;
747 #endif
748
749 #if TRAY_ENABLED
750 disp_tray_icon();
751 #endif
752
753 switch (current_method_type()) {
754 case method_type_PHO:
755 win_pho_disp_half_full();
756 break;
757 #if USE_TSIN
758 case method_type_TSIN:
759 win_tsin_disp_half_full();
760 break;
761 #endif
762 default:
763 win_gtab_disp_half_full();
764 break;
765 }
766 }
767
768 void flush_tsin_buffer();
769 void reset_gtab_all();
770 void set_tsin_pho_mode0(ClientState *cs, gboolean tsin_pho_mode);
771
772 //static u_int orig_caps_state;
773 gboolean init_in_method2(ClientState *cs, int in_no);
774 void set_wselkey();
775
init_state_chinese(ClientState * cs,gboolean tsin_pho_mode)776 void init_state_chinese(ClientState *cs, gboolean tsin_pho_mode)
777 {
778 dbg("init_state_chinese %p\n",cs);
779 #if WIN32
780 if (test_mode)
781 return;
782 #endif
783
784 cs->im_state = GCIN_STATE_CHINESE;
785 set_tsin_pho_mode0(cs, tsin_pho_mode);
786 if (!cs->in_method)
787 #if UNIX
788 init_in_method2(cs, default_input_method);
789 #else
790 if (!last_input_method)
791 last_input_method = default_input_method;
792 init_in_method(last_input_method);
793 #endif
794
795 set_wselkey();
796 save_CS_current_to_temp();
797 }
798
799 gboolean output_gbuf();
800 void update_win_kbm();
801 void flush_edit_buffer(), ClrIn();
802 void tsin_set_eng_ch(int nmod);
803 int current_kbd_state;
804
toggle_im_enabled()805 void toggle_im_enabled()
806 {
807 // dbg("toggle_im_enabled\n");
808 #if WIN32
809 if (test_mode)
810 return;
811 #endif
812
813 check_CS();
814
815 if (current_CS->in_method < 0)
816 p_err("err found");
817
818 int status=0;
819
820 // dbg("feedkey_pp %x %x\n", xkey, kbstate);
821 // if (xkey=='1')
822 // dbg("aaa\n");
823
824
825 if (current_CS->im_state != GCIN_STATE_DISABLED) {
826 if (current_CS->im_state == GCIN_STATE_ENG_FULL) {
827 current_CS->im_state = GCIN_STATE_CHINESE;
828 disp_im_half_full();
829 save_CS_current_to_temp();
830 return;
831 }
832
833 flush_edit_buffer();
834
835 hide_in_win(current_CS);
836 #if 0
837 hide_win_status();
838 #endif
839 current_CS->im_state = GCIN_STATE_DISABLED;
840
841 update_win_kbm();
842
843 disp_tray_icon();
844 } else {
845 if (!current_method_type())
846 init_gtab(current_CS->in_method);
847
848 ClrIn();
849
850 init_state_chinese(current_CS, TRUE);
851 reset_current_in_win_xy();
852 #if 1
853 show_in_win(current_CS);
854 update_in_win_pos();
855 #else
856 update_in_win_pos();
857 show_in_win(current_CS);
858 #endif
859
860 update_win_kbm();
861
862 if (tsin_chinese_english_toggle_key == TSIN_CHINESE_ENGLISH_TOGGLE_KEY_CapsLock) {
863 tsin_set_eng_ch(!(current_kbd_state&LockMask));
864 }
865
866 disp_tray_icon();
867 }
868
869 save_CS_current_to_temp();
870 }
871
872 void get_win_gtab_geom();
873 void get_win0_geom();
874 void get_win_pho_geom();
875
update_active_in_win_geom()876 void update_active_in_win_geom()
877 {
878 #if WIN32
879 if (test_mode)
880 return;
881 #endif
882 // dbg("update_active_in_win_geom\n");
883 switch (current_method_type()) {
884 case method_type_PHO:
885 get_win_pho_geom();
886 break;
887 #if USE_TSIN
888 case method_type_TSIN:
889 get_win0_geom();
890 break;
891 #endif
892 case method_type_MODULE:
893 if (module_cb() && module_cb()->module_get_win_geom)
894 module_cb()->module_get_win_geom();
895 break;
896 default:
897 get_win_gtab_geom();
898 break;
899 }
900 }
901
902 extern GtkWidget *gwin_pho, *gwin0, *gwin_gtab;
903
win_is_visible()904 gboolean win_is_visible()
905 {
906 if (!current_CS)
907 return FALSE;
908 switch (current_method_type()) {
909 case method_type_PHO:
910 return gwin_pho && GTK_WIDGET_VISIBLE(gwin_pho);
911 #if USE_TSIN
912 case method_type_TSIN:
913 return gwin0 && GTK_WIDGET_VISIBLE(gwin0);
914 #endif
915 case method_type_MODULE:
916 if (!module_cb())
917 return FALSE;
918 return module_cb()->module_win_visible();
919 default:
920 if (!gwin_gtab)
921 return FALSE;
922 return gwin_gtab && GTK_WIDGET_VISIBLE(gwin_gtab);
923 }
924
925 return FALSE;
926 }
927
928
929 void disp_gtab_half_full(gboolean hf);
930 void tsin_toggle_half_full();
931
toggle_half_full_char_sub()932 void toggle_half_full_char_sub()
933 {
934 #if WIN32
935 if (test_mode)
936 return;
937 #endif
938
939 if (current_method_type() == method_type_TSIN && current_CS->im_state == GCIN_STATE_CHINESE) {
940 tsin_toggle_half_full();
941 }
942 else {
943 if (current_CS->im_state == GCIN_STATE_ENG_FULL) {
944 current_CS->im_state = GCIN_STATE_DISABLED;
945 hide_in_win(current_CS);
946 } else
947 if (current_CS->im_state == GCIN_STATE_DISABLED) {
948 toggle_im_enabled();
949 current_CS->im_state = GCIN_STATE_ENG_FULL;
950 } else
951 if (current_CS->im_state == GCIN_STATE_CHINESE) {
952 current_CS->b_half_full_char = !current_CS->b_half_full_char;
953 }
954
955 // dbg("current_CS->in_method %d\n", current_CS->in_method);
956 disp_im_half_full();
957 }
958
959 save_CS_current_to_temp();
960 }
961
toggle_half_full_char()962 void toggle_half_full_char()
963 {
964 #if WIN32
965 if (test_mode)
966 return;
967 #endif
968
969 check_CS();
970
971 if (!gcin_shift_space_eng_full) {
972 current_CS->b_half_full_char = 0;
973 tss.tsin_half_full=0;
974 disp_im_half_full();
975 return;
976 }
977
978 // dbg("toggle_half_full_char\n");
979 toggle_half_full_char_sub() ;
980 }
981
982 void init_tab_pp(gboolean init);
983 void init_tab_pho();
984
985
986 extern int b_show_win_kbm;
987
988 void hide_win_kbm();
989 extern gboolean win_sym_enabled;
990 void show_win_kbm();
991 extern char *TableDir;
992 void set_gtab_input_method_name(char *s);
993 GCIN_module_callback_functions *init_GCIN_module_callback_functions(char *sofile);
994 time_t find_tab_file(char *fname, char *out_file);
995 gboolean tsin_page_up(), tsin_page_down();
996 int tsin_sele_by_idx(int);
997 void free_tsin();
998
tsin_set_win1_cb()999 void tsin_set_win1_cb()
1000 {
1001 set_win1_cb((cb_selec_by_idx_t)tsin_sele_by_idx, (cb_page_ud_t)tsin_page_up, (cb_page_ud_t)tsin_page_down);
1002 }
1003
update_win_kbm_inited()1004 void update_win_kbm_inited()
1005 {
1006 if (win_kbm_inited)
1007 update_win_kbm();
1008 }
1009
init_in_method2(ClientState * cs,int in_no)1010 gboolean init_in_method2(ClientState *cs, int in_no)
1011 {
1012 dbg("init_in_method2 %p %d\n", cs, in_no);
1013 gboolean init_im = !(cur_inmd && (cur_inmd->flag & FLAG_GTAB_SYM_KBM));
1014
1015 if (in_no < 0)
1016 return FALSE;
1017
1018 if (cs==current_CS && cs->in_method != in_no) {
1019 if (!(inmd[in_no].flag & FLAG_GTAB_SYM_KBM)) {
1020 flush_edit_buffer();
1021 hide_in_win(cs);
1022 }
1023
1024 if (cur_inmd && (cur_inmd->flag & FLAG_GTAB_SYM_KBM))
1025 hide_win_kbm();
1026 }
1027 #if 0
1028 if (cs==current_CS)
1029 reset_current_in_win_xy();
1030 #endif
1031
1032 // dbg("switch init_in_method %x %d\n", current_CS, in_no);
1033 // set_tsin_pho_mode0(cs, ini_tsin_pho_mode);
1034 tsin_set_win1_cb();
1035
1036 switch (inmd[in_no].method_type) {
1037 case method_type_PHO:
1038 #if WIN32
1039 if (test_mode)
1040 break;
1041 #endif
1042 cs->in_method = in_no;
1043 init_tab_pho();
1044 break;
1045 case method_type_TSIN:
1046 #if WIN32
1047 if (test_mode)
1048 break;
1049 #endif
1050 free_tsin();
1051 set_wselkey();
1052 cs->in_method = in_no;
1053 // if (cs==current_CS || !current_CS)
1054 init_tab_pp(init_im);
1055 break;
1056 case method_type_SYMBOL_TABLE:
1057 #if WIN32
1058 if (test_mode)
1059 break;
1060 #endif
1061 toggle_symbol_table();
1062 break;
1063 case method_type_MODULE:
1064 {
1065 #if WIN32
1066 if (test_mode)
1067 break;
1068 #endif
1069 GCIN_module_main_functions gmf;
1070 init_GCIN_module_main_functions(&gmf);
1071 if (!inmd[in_no].mod_cb_funcs) {
1072 char ttt[256];
1073 strcpy(ttt, inmd[in_no].filename);
1074
1075 dbg("module %s\n", ttt);
1076 if (!(inmd[in_no].mod_cb_funcs = init_GCIN_module_callback_functions(ttt))) {
1077 dbg("module not found\n");
1078 return FALSE;
1079 }
1080 }
1081
1082 if ((cs==current_CS || !current_CS) && inmd[in_no].mod_cb_funcs->module_init_win(&gmf)) {
1083 #if WIN32
1084 if (!test_mode)
1085 #endif
1086 {
1087 cs->in_method = in_no;
1088 module_cb()->module_show_win();
1089 if (cs==current_CS)
1090 set_wselkey();
1091 }
1092 } else {
1093 return FALSE;
1094 }
1095
1096 break;
1097 }
1098 case method_type_EN:
1099 {
1100 #if WIN32
1101 if (test_mode)
1102 return TRUE;
1103 #endif
1104 if (cs==current_CS && current_CS->im_state==GCIN_STATE_CHINESE)
1105 toggle_im_enabled();
1106 return TRUE;
1107 }
1108 case method_type_GTAB:
1109 {
1110 dbg("method_type_GTAB\n");
1111 #if WIN32
1112 // if (!test_mode)
1113 {
1114 #endif
1115 free_tsin();
1116 if (cs==current_CS || !current_CS)
1117 init_gtab(in_no);
1118 #if WIN32
1119 }
1120 #endif
1121
1122 if (!inmd[in_no].DefChars)
1123 return FALSE;
1124
1125 #if WIN32
1126 if (test_mode)
1127 return TRUE;
1128 #endif
1129 cs->in_method = in_no;
1130 if (!(inmd[in_no].flag & FLAG_GTAB_SYM_KBM))
1131 show_win_gtab();
1132 else {
1133 win_kbm_inited = 1;
1134 show_win_kbm();
1135 }
1136
1137 set_gtab_input_method_name(inmd[in_no].cname);
1138 break;
1139 }
1140 default:
1141 dbg("unknown\n");
1142 return FALSE;
1143 }
1144
1145 #if WIN32
1146 if (test_mode)
1147 return TRUE;
1148
1149 if (cs==current_CS && current_CS->in_method != last_input_method)
1150 last_input_method = current_CS->in_method;
1151 #endif
1152
1153 if (cs==current_CS) {
1154 char *selkey;
1155 // if (selkey=inmd[current_CS->in_method].selkey)
1156 {
1157 set_wselkey();
1158 gtab_set_win1_cb();
1159 // dbg("aa selkey %s\n", inmd[current_CS->in_method].selkey);
1160 }
1161 update_in_win_pos();
1162 update_win_kbm_inited();
1163 disp_tray_icon();
1164 }
1165
1166 return TRUE;
1167 }
1168
init_in_method(int in_no)1169 gboolean init_in_method(int in_no)
1170 {
1171 check_CS();
1172 return init_in_method2(current_CS, in_no);
1173 }
1174
cycle_next_in_method()1175 static void cycle_next_in_method()
1176 {
1177 int i;
1178 dbg("cycle_next_in_method\n");
1179 #if WIN32
1180 if (test_mode)
1181 return;
1182 #endif
1183
1184 for(i=0; i < inmdN; i++) {
1185 int v = (current_CS->in_method + 1 + i) % inmdN;
1186 if (!inmd[v].in_cycle)
1187 continue;
1188 if (!inmd[v].cname || !inmd[v].cname[0])
1189 continue;
1190
1191 if (!init_in_method(v))
1192 continue;
1193
1194 return;
1195 }
1196 }
1197
1198 void add_to_tsin_buf_str(char *str);
1199 gboolean gtab_phrase_on();
1200 void insert_gbuf_nokey(char *s);
1201
full_char_proc(KeySym keysym)1202 gboolean full_char_proc(KeySym keysym)
1203 {
1204 char *s = half_char_to_full_char(keysym);
1205 if (!s)
1206 return 0;
1207
1208 #if WIN32
1209 if (test_mode)
1210 return TRUE;
1211 #endif
1212
1213 char tt[CH_SZ+1];
1214
1215 utf8cpy(tt, s);
1216
1217 if (current_CS->im_state == GCIN_STATE_ENG_FULL) {
1218 send_text(tt);
1219 return 1;
1220 }
1221
1222 if (current_method_type() == method_type_TSIN && current_CS->im_state == GCIN_STATE_CHINESE)
1223 add_to_tsin_buf_str(tt);
1224 else
1225 if (gtab_phrase_on() && ggg.gbufN)
1226 insert_gbuf_nokey(tt);
1227 else
1228 send_text(tt);
1229
1230 return 1;
1231 }
1232
1233 int feedkey_pho(KeySym xkey, int kbstate);
1234 int feedkey_tsin(KeySym xkey, int state);
1235 int feedkey_gtab(KeySym key, int kbstate);
1236 int feed_phrase(KeySym ksym, int state);
1237 void tsin_set_eng_ch(int nmod);
1238 static KeySym last_keysym;
1239
timeout_raise_window(gpointer data)1240 gboolean timeout_raise_window(gpointer data)
1241 {
1242 // dbg("timeout_raise_window\n");
1243 timeout_handle = 0;
1244 show_in_win(current_CS);
1245 return FALSE;
1246 }
1247
1248 extern Window xwin_pho, xwin0, xwin_gtab;
1249 void create_win_sym(), win_kbm_disp_caplock();
1250
1251 #if !GTK_CHECK_VERSION(2,16,0) && 0
1252 #include <X11/extensions/XKBsrv.h>
get_caps_lock_state()1253 gboolean get_caps_lock_state()
1254 {
1255 XkbStateRec states;
1256
1257 if (XkbGetState(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XkbUseCoreKbd, &states) == Success) {
1258 if (states.locked_mods & LockMask) return TRUE;
1259 }
1260 return FALSE;
1261 }
1262 #endif
1263
1264 gboolean capslock_on;
1265
disp_win_kbm_capslock()1266 void disp_win_kbm_capslock()
1267 {
1268 if (!b_show_win_kbm)
1269 return;
1270
1271 gboolean o_state = old_capslock_on;
1272 old_capslock_on = capslock_on;
1273
1274 // dbg("%x %x\n", old_capslock_on, o_state);
1275
1276 if (o_state != old_capslock_on) {
1277 win_kbm_disp_caplock();
1278 }
1279 }
1280
1281
disp_win_kbm_capslock_init()1282 void disp_win_kbm_capslock_init()
1283 {
1284 old_capslock_on = gdk_keymap_get_caps_lock_state(gdk_keymap_get_default());
1285 // dbg("disp_win_kbm_capslock_init %d\n",old_capslock_on);
1286
1287 if (b_show_win_kbm)
1288 win_kbm_disp_caplock();
1289 }
1290
toggle_symbol_table()1291 void toggle_symbol_table()
1292 {
1293 #if WIN32
1294 if (test_mode)
1295 return;
1296 #endif
1297 if (current_CS->im_state == GCIN_STATE_CHINESE) {
1298 if (!win_is_visible())
1299 win_sym_enabled=1;
1300 else
1301 win_sym_enabled^=1;
1302 } else
1303 win_sym_enabled=0;
1304
1305 create_win_sym();
1306 if (win_sym_enabled) {
1307 force_show = TRUE;
1308 if (current_CS->im_state == GCIN_STATE_CHINESE)
1309 show_in_win(current_CS);
1310 force_show = FALSE;
1311 }
1312 }
1313
1314
1315 void destroy_phrase_save_menu();
1316 int gcin_switch_keys_lookup(int key);
1317 gboolean b_menu_key_pressed;
1318 void cb_trad_sim_toggle();
1319 void set_tsin_pho_mode();
1320
1321 // return TRUE if the key press is processed
ProcessKeyPress(KeySym keysym,u_int kev_state)1322 gboolean ProcessKeyPress(KeySym keysym, u_int kev_state)
1323 {
1324 #if 1
1325 dbg("key press %x %x\n", keysym, kev_state);
1326 #endif
1327
1328 current_kbd_state = kev_state;
1329 destroy_phrase_save_menu();
1330
1331 capslock_on = (kev_state&LockMask) > 0;
1332 if (keysym == XK_Caps_Lock) {
1333 #if UNIX
1334 capslock_on = !(kev_state&LockMask);
1335 #endif
1336 disp_tray_icon();
1337 }
1338
1339 disp_win_kbm_capslock();
1340 check_CS();
1341
1342 if (current_CS->client_win)
1343 focus_win = current_CS->client_win;
1344
1345 if (
1346 callback_str_buffer && strlen(callback_str_buffer)) {
1347 #if WIN32
1348 if (!test_mode)
1349 #endif
1350 {
1351 send_text(callback_str_buffer);
1352 callback_str_buffer[0]=0;
1353 }
1354 return TRUE;
1355 }
1356
1357 if (force_preedit==1) {
1358 dbg("orce_preedit==1\n");
1359 force_preedit = 2;
1360 return 1;
1361 }
1362
1363 #if 1
1364 // Chrome win32 has this problem
1365 if (keysym==XK_Menu) {
1366 b_menu_key_pressed = TRUE;
1367 } else {
1368 gboolean old_pressed = b_menu_key_pressed;
1369 b_menu_key_pressed = FALSE;
1370 if (old_pressed && strchr("utcpda", keysym))
1371 return FALSE;
1372 }
1373 #endif
1374
1375
1376 if (keysym == XK_space) {
1377 #if 0
1378 dbg("state %x\n", kev->state);
1379 dbg("%x\n", Mod4Mask);
1380 #endif
1381 if (
1382 ((kev_state & (ControlMask|Mod1Mask|ShiftMask))==ControlMask && gcin_im_toggle_keys==Control_Space) ||
1383 ((kev_state & Mod1Mask) && gcin_im_toggle_keys==Alt_Space) ||
1384 ((kev_state & ShiftMask) && gcin_im_toggle_keys==Shift_Space) ||
1385 ((kev_state & Mod4Mask) && gcin_im_toggle_keys==Windows_Space)
1386 ) {
1387 dbg("ctrl-space\n");
1388
1389 if (
1390 #if 0
1391 current_method_type() == method_type_TSIN &&
1392 #endif
1393 tsin_chinese_english_toggle_key != TSIN_CHINESE_ENGLISH_TOGGLE_KEY_CapsLock) {
1394 tsin_set_eng_ch(1);
1395 }
1396
1397 toggle_im_enabled();
1398 #if UNIX
1399 return TRUE;
1400 #else
1401 #if 0
1402 return TRUE;
1403 #else
1404 return FALSE;
1405 #endif
1406 #endif
1407 }
1408 }
1409
1410 if (keysym == XK_space && (kev_state & ShiftMask)) {
1411 if (last_keysym != XK_Shift_L && last_keysym != XK_Shift_R)
1412 return FALSE;
1413
1414 toggle_half_full_char();
1415
1416 return TRUE;
1417 }
1418
1419
1420 if (((kev_state & (Mod1Mask|ShiftMask)) == (Mod1Mask|ShiftMask)) ||
1421 (gcin_ctrl_punc && (kev_state&(Mod1Mask|Mod5Mask|ShiftMask|ControlMask))==ControlMask && keysym < 127 && !(keysym>='0' && keysym<='9')) ) {
1422 if (current_CS->im_state != GCIN_STATE_DISABLED || gcin_eng_phrase_enabled)
1423 return feed_phrase(keysym, kev_state);
1424 else
1425 return 0;
1426 }
1427
1428 // dbg("state %x\n", kev_state);
1429 if ((current_CS->im_state & (GCIN_STATE_ENG_FULL)) ) {
1430 return full_char_proc(keysym);
1431 }
1432
1433
1434 if ((kev_state & ControlMask) && (kev_state&(Mod1Mask|Mod5Mask|ShiftMask))) {
1435 if (keysym == 'g' || keysym == 'r' || keysym == XK_F5) {
1436 last_keysym = 0;
1437 send_output_buffer_bak();
1438 return TRUE;
1439 }
1440
1441 if (keysym == XK_F8) {
1442 last_keysym = 0;
1443 cb_trad_sim_toggle();
1444 }
1445
1446 if (!gcin_enable_ctrl_alt_switch)
1447 return FALSE;
1448
1449 #if WIN32
1450 if (kev_state & ShiftMask) {
1451 struct {
1452 KeySym frm, to;
1453 } tkeys[]={{0x1e, '6'}, {0,0}};
1454
1455 for(int i=0; tkeys[i].frm; i++) {
1456 if (tkeys[i].frm == keysym) {
1457 keysym = tkeys[i].to;
1458 break;
1459 }
1460 }
1461 }
1462 #endif
1463
1464 int kidx = gcin_switch_keys_lookup(keysym);
1465 dbg("kidx 0 %d\n", kidx);
1466
1467 #if WIN32
1468 if (!test_mode)
1469 #endif
1470 last_keysym = keysym;
1471
1472 if (kidx < 0) {
1473 return FALSE;
1474 }
1475
1476 if (inmd[kidx].method_type == method_type_SYMBOL_TABLE) {
1477 toggle_symbol_table();
1478 return TRUE;
1479 }
1480
1481 if (!inmd[kidx].cname)
1482 return FALSE;
1483
1484 dbg("kidx %d\n", kidx);
1485
1486 #if WIN32
1487 if (!test_mode)
1488 #endif
1489 {
1490 current_CS->im_state = GCIN_STATE_CHINESE;
1491 init_in_method(kidx);
1492 set_tsin_pho_mode();
1493 }
1494
1495 return TRUE;
1496 }
1497 #if WIN32
1498 if (!test_mode)
1499 #endif
1500 last_keysym = keysym;
1501
1502 if (current_CS->im_state == GCIN_STATE_DISABLED) {
1503 return FALSE;
1504 }
1505
1506 #if 0
1507 if (!current_CS->b_gcin_protocol) {
1508 if (((keysym == XK_Control_L || keysym == XK_Control_R)
1509 && (kev_state & ShiftMask)) ||
1510 ((keysym == XK_Shift_L || keysym == XK_Shift_R)
1511 && (kev_state & ControlMask))) {
1512 cycle_next_in_method();
1513 return TRUE;
1514 }
1515 }
1516 #endif
1517
1518 #if WIN32
1519 if (!test_mode) {
1520 #endif
1521 if (current_CS->b_raise_window && keysym>=' ' && keysym < 127) {
1522 if (timeout_handle)
1523 g_source_remove(timeout_handle);
1524 timeout_handle = g_timeout_add(200, timeout_raise_window, NULL);
1525 }
1526 #if WIN32
1527 }
1528 #endif
1529
1530 switch(current_method_type()) {
1531 case method_type_PHO:
1532 return feedkey_pho(keysym, kev_state);
1533 case method_type_TSIN:
1534 return feedkey_tsin(keysym, kev_state);
1535 case method_type_MODULE:
1536 if (!module_cb())
1537 return FALSE;
1538 return module_cb()->module_feedkey(keysym, kev_state);
1539 case method_type_GTAB:
1540 return feedkey_gtab(keysym, kev_state);
1541 default:
1542 dbg("ProcessKeyPress unknown current_CS:%x %d\n", current_CS, current_method_type());
1543 }
1544
1545 return FALSE;
1546 }
1547
1548 int feedkey_pp_release(KeySym xkey, int kbstate);
1549 int feedkey_gtab_release(KeySym xkey, int kbstate);
1550 int feedkey_pho_release(KeySym xkey, int kbstate);
1551
1552 // return TRUE if the key press is processed
ProcessKeyRelease(KeySym keysym,u_int kev_state)1553 gboolean ProcessKeyRelease(KeySym keysym, u_int kev_state)
1554 {
1555 check_CS();
1556 current_kbd_state = kev_state;
1557
1558 if (force_preedit==2) {
1559 dbg("orce_preedit==2\n");
1560 force_preedit = 0;
1561 return TRUE;
1562 }
1563
1564 disp_win_kbm_capslock();
1565
1566 // check_CS();
1567 #if 0
1568 dbg_time("key release %x %x\n", keysym, kev_state);
1569 #endif
1570
1571 if (current_CS->im_state == GCIN_STATE_DISABLED)
1572 return FALSE;
1573
1574
1575 #if 1
1576 dbg("last_keysym %x\n", last_keysym);
1577
1578 if (current_CS->b_gcin_protocol && (last_keysym == XK_Shift_L ||
1579 last_keysym == XK_Shift_R || last_keysym == XK_Control_L || last_keysym == XK_Control_R)) {
1580 if (((keysym == XK_Control_L || keysym == XK_Control_R)
1581 && (kev_state & ShiftMask)) ||
1582 ((keysym == XK_Shift_L || keysym == XK_Shift_R)
1583 && (kev_state & ControlMask))) {
1584 cycle_next_in_method();
1585 return TRUE;
1586 }
1587 }
1588 #endif
1589
1590 switch(current_method_type()) {
1591 case method_type_TSIN:
1592 return feedkey_pp_release(keysym, kev_state);
1593 #if 0
1594 case method_type_PHO:
1595 return feedkey_pho_release(keysym, kev_state);
1596 #endif
1597 case method_type_MODULE:
1598 if (!module_cb())
1599 return FALSE;
1600 return module_cb()->module_feedkey_release(keysym, kev_state);
1601 case method_type_GTAB:
1602 return feedkey_gtab_release(keysym, kev_state);
1603 }
1604
1605 return FALSE;
1606 }
1607
1608
1609 #if USE_XIM
xim_ForwardEventHandler(IMForwardEventStruct * call_data)1610 int xim_ForwardEventHandler(IMForwardEventStruct *call_data)
1611 {
1612 current_forward_eve = call_data;
1613
1614 if (call_data->event.type != KeyPress && call_data->event.type != KeyRelease) {
1615 #if DEBUG || 1
1616 dbg("bogus event type, ignored\n");
1617 #endif
1618 return True;
1619 }
1620
1621 char strbuf[STRBUFLEN];
1622 KeySym keysym;
1623
1624 bzero(strbuf, STRBUFLEN);
1625 XKeyEvent *kev = (XKeyEvent*)¤t_forward_eve->event;
1626 XLookupString(kev, strbuf, STRBUFLEN, &keysym, NULL);
1627
1628 int ret;
1629 if (call_data->event.type == KeyPress)
1630 ret = ProcessKeyPress(keysym, kev->state);
1631 else
1632 ret = ProcessKeyRelease(keysym, kev->state);
1633
1634 if (!ret)
1635 bounce_back_key();
1636
1637 export_text_xim();
1638
1639 return False;
1640 }
1641 #endif
1642
1643
1644 void gcin_reset();
1645
1646 #if UNIX
is_tip_window(Window inpwin)1647 gboolean is_tip_window(Window inpwin)
1648 {
1649 // Dirty fix for chrome, doesn't work well.
1650 if (!inpwin)
1651 return FALSE;
1652 XWindowAttributes att;
1653 XGetWindowAttributes(dpy, inpwin, &att);
1654
1655 dbg("%d, %d\n", att.width, att.height);
1656 // chrome window is override_redirect
1657 // if (att.override_redirect)
1658 // return;
1659
1660 return att.override_redirect && att.height < 24;
1661 }
1662 #endif
1663
gcin_FocusIn(ClientState * cs)1664 int gcin_FocusIn(ClientState *cs)
1665 {
1666 dbg("gcin_FocusIn %p\n", cs);
1667 if (!cs) {
1668 dbg("cs is null");
1669 return FALSE;
1670 } else {
1671 // dbg("gcin_FocusIn %x\n", cs);
1672 }
1673
1674 Window win = cs->client_win;
1675 dbg("win: %x\n", win);
1676
1677 if (!win) {
1678 dbg("!win");
1679 return FALSE;
1680 }
1681 #if UNIX && 0
1682 if (is_tip_window(win)) {
1683 dbg("is_tip_window\n");
1684 return FALSE;
1685 }
1686 #endif
1687 reset_current_in_win_xy();
1688
1689 if (cs) {
1690 Window win = cs->client_win;
1691
1692 if (focus_win != win) {
1693 #if 1
1694 dbg("reset %x,%x\n", focus_win, win);
1695 gcin_reset();
1696 #endif
1697 hide_in_win(current_CS);
1698 focus_win = win;
1699 }
1700 }
1701
1702 current_CS = cs;
1703 save_CS_temp_to_current();
1704
1705 // dbg("current_CS %x %d %d\n", cs, cs->im_state, current_CS->im_state);
1706
1707 if (win == focus_win) {
1708 if (cs->im_state != GCIN_STATE_DISABLED) {
1709 show_in_win(cs);
1710 move_IC_in_win(cs);
1711 } else {
1712 hide_in_win(cs);
1713 move_IC_in_win(cs);
1714 }
1715 }
1716
1717 cur_inmd = &inmd[current_CS->in_method];
1718
1719 // if (inmd[cs->in_method].selkey)
1720 // set_wselkey();
1721 // else
1722 {
1723 set_wselkey();
1724 #if 0
1725 gtab_set_win1_cb();
1726 tsin_set_win1_cb();
1727 #endif
1728 }
1729
1730 update_win_kbm();
1731
1732 disp_tray_icon();
1733
1734 #if 0
1735 dbg_time("gcin_FocusIn %x %x\n",cs, current_CS);
1736 #endif
1737 return True;
1738 }
1739
1740
1741 #if USE_XIM
1742 IC *FindIC(CARD16 icid);
1743 void load_IC(IC *rec);
1744 CARD16 connect_id;
1745
xim_gcin_FocusIn(IMChangeFocusStruct * call_data)1746 int xim_gcin_FocusIn(IMChangeFocusStruct *call_data)
1747 {
1748 IC *ic = FindIC(call_data->icid);
1749 ClientState *cs = &ic->cs;
1750 connect_id = call_data->connect_id;
1751
1752 if (ic) {
1753 gcin_FocusIn(cs);
1754
1755 load_IC(ic);
1756 }
1757
1758 #if DEBUG
1759 dbg("xim_gcin_FocusIn %d\n", call_data->icid);
1760 #endif
1761 return True;
1762 }
1763 #endif
1764
1765
1766
1767 static gint64 last_focus_out_time;
1768
gcin_FocusOut(ClientState * cs)1769 int gcin_FocusOut(ClientState *cs)
1770 {
1771 gint64 t = current_time();
1772 // dbg("gcin_FocusOut\n");
1773
1774 if (cs != current_CS)
1775 return FALSE;
1776
1777 if (!cs) {
1778 dbg("gcin_FocusOut is null\n");
1779 return FALSE;
1780 }
1781
1782 if (!cs->client_win)
1783 return FALSE;
1784
1785 #if UNIX
1786 if (is_tip_window(cs->client_win)) {
1787 return FALSE;
1788 }
1789 #endif
1790
1791
1792 if (t - last_focus_out_time < 100000) {
1793 last_focus_out_time = t;
1794 return FALSE;
1795 }
1796
1797 last_focus_out_time = t;
1798
1799 if (cs == current_CS) {
1800 hide_in_win(cs);
1801 }
1802
1803 reset_current_in_win_xy();
1804
1805 if (cs == current_CS)
1806 temp_CS = *current_CS;
1807
1808 #if 0
1809 dbg("focus out\n");
1810 #endif
1811
1812 return True;
1813 }
1814
1815 int tsin_get_preedit(char *str, GCIN_PREEDIT_ATTR attr[], int *cursor, int *sub_comp_len);
1816 int gtab_get_preedit(char *str, GCIN_PREEDIT_ATTR attr[], int *pcursor, int *sub_comp_len);
1817 int int_get_preedit(char *str, GCIN_PREEDIT_ATTR attr[], int *cursor, int *sub_comp_len);
1818 int pho_get_preedit(char *str, GCIN_PREEDIT_ATTR attr[], int *cursor, int *sub_comp_len);
1819
gcin_get_preedit(ClientState * cs,char * str,GCIN_PREEDIT_ATTR attr[],int * cursor,int * comp_flag)1820 int gcin_get_preedit(ClientState *cs, char *str, GCIN_PREEDIT_ATTR attr[], int *cursor, int *comp_flag)
1821 {
1822 // dbg("gcin_get_preedit %x\n", current_CS);
1823 if (!current_CS) {
1824 empty:
1825 // dbg("empty\n");
1826 str[0]=0;
1827 *cursor=0;
1828 return 0;
1829 }
1830
1831 str[0]=0;
1832 *comp_flag=0;
1833
1834 // cs->use_preedit = TRUE;
1835
1836 switch(current_method_type()) {
1837 case method_type_PHO:
1838 return pho_get_preedit(str, attr, cursor, comp_flag);
1839 #if USE_TSIN
1840 case method_type_TSIN:
1841 return tsin_get_preedit(str, attr, cursor, comp_flag);
1842 #endif
1843 case method_type_MODULE:
1844 if (inmd[current_CS->in_method].mod_cb_funcs)
1845 return module_cb()->module_get_preedit(str, attr, cursor, comp_flag);
1846 default:
1847 return gtab_get_preedit(str, attr, cursor, comp_flag);
1848 // dbg("metho %d\n", current_CS->in_method);
1849 }
1850
1851 return 0;
1852 }
1853
1854 void pho_reset();
1855 int tsin_reset();
1856 void gtab_reset();
1857
gcin_reset()1858 void gcin_reset()
1859 {
1860 #if 1
1861 if (!current_CS)
1862 return;
1863 // dbg("gcin_reset\n");
1864
1865 switch(current_method_type()) {
1866 case method_type_PHO:
1867 pho_reset();
1868 return;
1869 #if USE_TSIN
1870 case method_type_TSIN:
1871 tsin_reset();
1872 return;
1873 #endif
1874 case method_type_MODULE:
1875 if (inmd[current_CS->in_method].mod_cb_funcs)
1876 module_cb()->module_reset();
1877 return;
1878 default:
1879 gtab_reset();
1880 // dbg("metho %d\n", current_CS->in_method);
1881 }
1882 #endif
1883 }
1884
1885 #if WIN32
1886 void show_tsin_stat();
gcin_set_tsin_pho_mode(ClientState * cs,gboolean pho_mode)1887 void gcin_set_tsin_pho_mode(ClientState *cs, gboolean pho_mode)
1888 {
1889 set_tsin_pho_mode0(cs, pho_mode);
1890
1891 if (!pho_mode) {
1892 cs->b_half_full_char = 0;
1893 tss.tsin_half_full = 0;
1894 }
1895 show_tsin_stat();
1896 }
1897 #endif
1898
1899 #if USE_XIM
xim_gcin_FocusOut(IMChangeFocusStruct * call_data)1900 int xim_gcin_FocusOut(IMChangeFocusStruct *call_data)
1901 {
1902 IC *ic = FindIC(call_data->icid);
1903 ClientState *cs = &ic->cs;
1904
1905 gcin_FocusOut(cs);
1906
1907 return True;
1908 }
1909 #endif
1910
1911
gcin_edit_display_ap_only()1912 gboolean gcin_edit_display_ap_only()
1913 {
1914 #if WIN32
1915 if (test_mode)
1916 return TRUE;
1917 #endif
1918 if (!current_CS)
1919 return FALSE;
1920 // dbg("gcin_edit_display_ap_only %d\n", current_CS->use_preedit)
1921 return current_CS->use_preedit && gcin_edit_display==GCIN_EDIT_DISPLAY_ON_THE_SPOT;
1922 }
1923
1924
gcin_display_on_the_spot_key()1925 gboolean gcin_display_on_the_spot_key()
1926 {
1927 return gcin_edit_display_ap_only() && gcin_on_the_spot_key;
1928 }
1929
flush_edit_buffer()1930 void flush_edit_buffer()
1931 {
1932 // dbg("flush_edit_buffer\n");
1933 if (!current_CS)
1934 return;
1935 #if WIN32
1936 if (test_mode)
1937 return;
1938 #endif
1939
1940 // dbg("gcin_reset\n");
1941 switch(current_method_type()) {
1942 #if USE_TSIN
1943 case method_type_TSIN:
1944 flush_tsin_buffer();
1945 break;
1946 #endif
1947 case method_type_MODULE:
1948 if (inmd[current_CS->in_method].mod_cb_funcs)
1949 module_cb()->module_flush_input();
1950 break;
1951 default:
1952 output_gbuf();
1953 // dbg("metho %d\n", current_CS->in_method);
1954 }
1955 }
1956
1957 #if WIN32
1958 void pho_save_gst(), tsin_save_gst(), gtab_save_gst();
1959 void pho_restore_gst(), tsin_restore_gst(), gtab_restore_gst();
1960
ProcessTestKeyPress(KeySym keysym,u_int kev_state)1961 gboolean ProcessTestKeyPress(KeySym keysym, u_int kev_state)
1962 {
1963 if (!current_CS)
1964 return TRUE;
1965 gboolean v;
1966
1967 test_mode= TRUE;
1968 #if 0
1969 switch(current_method_type()) {
1970 case method_type_PHO:
1971 pho_save_gst();
1972 v = ProcessKeyPress(keysym, kev_state);
1973 pho_restore_gst();
1974 break;
1975 case method_type_TSIN:
1976 tsin_save_gst();
1977 v = ProcessKeyPress(keysym, kev_state);
1978 tsin_restore_gst();
1979 break;
1980 case method_type_MODULE:
1981 break;
1982 default:
1983 gtab_save_gst();
1984 v = ProcessKeyPress(keysym, kev_state);
1985 gtab_restore_gst();
1986 }
1987 #endif
1988 pho_save_gst();
1989 tsin_save_gst();
1990 gtab_save_gst();
1991 v = ProcessKeyPress(keysym, kev_state);
1992 pho_restore_gst();
1993 tsin_restore_gst();
1994 gtab_restore_gst();
1995 test_mode= FALSE;
1996
1997 dbg("ProcessTestKeyPress %d\n", v);
1998
1999 return v;
2000 }
2001
2002 #if 0
2003 gboolean Process2KeyPress(KeySym keysym, u_int kev_state)
2004 {
2005 gboolean tv = ProcessTestKeyPress(keysym, kev_state);
2006 gboolean v = ProcessKeyPress(keysym, kev_state);
2007
2008 if (tv != v)
2009 dbg("ProcessKeyPress %x -> %d %d\n",keysym, tv, v);
2010
2011 return v;
2012 }
2013 #endif
2014
ProcessTestKeyRelease(KeySym keysym,u_int kev_state)2015 gboolean ProcessTestKeyRelease(KeySym keysym, u_int kev_state)
2016 {
2017 test_mode = TRUE;
2018 gboolean v = ProcessKeyRelease(keysym, kev_state);
2019 test_mode = FALSE;
2020 return v;
2021 }
2022
2023 #if 0
2024 gboolean Process2KeyRelease(KeySym keysym, u_int kev_state)
2025 {
2026 gboolean tv = ProcessTestKeyRelease(keysym, kev_state);
2027 gboolean v = ProcessKeyRelease(keysym, kev_state);
2028
2029 if (tv != v)
2030 dbg("ProcessKeyRelease %x -> %d %d\n",keysym, tv, v);
2031
2032 return v;
2033 }
2034 #endif
2035 #endif
2036