1 /*
2  * $Id: evdispatch.c,v 1.2 2001/06/14 18:16:15 ura Exp $
3  */
4 
5 /*
6  * FreeWnn is a network-extensible Kana-to-Kanji conversion system.
7  * This file is part of FreeWnn.
8  *
9  * Copyright OMRON Corporation. 1987, 1988, 1989, 1990, 1991, 1992, 1999
10  * Copyright 1991, 1992 by Massachusetts Institute of Technology
11  *
12  * Author: OMRON SOFTWARE Co., Ltd. <freewnn@rd.kyoto.omronsoft.co.jp>
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2, or (at your option)
17  * any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with GNU Emacs; see the file COPYING.  If not, write to the
26  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27  *
28  * Commentary:
29  *
30  * Change log:
31  *      '99/04/19       TAOKA Satoshi - �IJ� �һ�<taoka@infonets.hiroshima-u.ac.jp>
32  *              kill()��getpid() ����������ȥ����ȡ�
33  *
34  * Last modified date: 19,Apr.1999
35  *
36  * Code:
37  *
38  */
39 /*      Version 4.0
40  */
41 #include <stdio.h>
42 #include "commonhd.h"
43 #include "sdefine.h"
44 #include "xim.h"
45 #include "sheader.h"
46 #include "ext.h"
47 
48 #ifdef BC_X11R5
49 #define IS_NOT_FROM_XIMR5(ev)   ((ev).xselectionrequest.selection == server_id)
50 
51 int ximr5_client = 1;           /* True when XIM R5 client comes */
52 extern Atom server_id;          /* IM server of X11R6 */
53 #endif /* BC_X11R5 */
54 
55 static void
keyboard_mapping(ev)56 keyboard_mapping (ev)
57      XMappingEvent *ev;
58 {
59   XRefreshKeyboardMapping (ev);
60 }
61 
62 static int
motif_event(ev)63 motif_event (ev)
64      XClientMessageEvent *ev;
65 {
66   /* extern int kill(), getpid(); */
67 
68   if (ev->window == xim->root_pointer[xim->default_screen]->ximclient->w)
69     {
70       do_end ();
71     }
72   else if (xim->j_c && (ev->window == xim->cur_j_c_root->ichi->w || ev->window == xim->cur_j_c_root->inspect->w))
73     {
74       xim->sel_ret = -2;
75       cur_cl_change3 (xim->j_c);
76       return (0);
77     }
78   return (1);
79 }
80 
81 
82 static char *syuuryou_title = "X INPUT MANAGER";
83 static char *syuuryou_syuuryou = " EXIT ";
84 static void
syuuryou_menu(in)85 syuuryou_menu (in)
86      int in;
87 {
88   static char *buf[1];
89   int c;
90 
91   cur_x = xim->root_pointer[xim->default_screen]->ximclient;
92   cur_p = cur_x;
93   cur_lang = cur_p->cur_xl->lang_db;
94   c_c = cur_p->cur_xl->w_c;
95   cur_rk = c_c->rk;
96   cur_rk_table = cur_rk->rk_table;
97   cur_input = 0;
98   xim->exit_menu_flg = (char) 1;
99   buf[0] = syuuryou_syuuryou;
100   c = xw_select_one_element (buf, 1, -1, syuuryou_title, SENTAKU, main_table[4], in);
101   if (c == 0)
102     {
103       do_end ();
104     }
105   else if (c == BUFFER_IN_CONT)
106     {
107       return;
108     }
109   xim->exit_menu_flg = (char) 0;
110   return;
111 }
112 
113 
114 static void
search_expose(event)115 search_expose (event)
116      register XExposeEvent *event;
117 {
118   register XIMClientRec *xc;
119   register XIMLangRec *xl;
120   register BoxRec *p;
121   register Window window = event->window;
122 
123   for (xc = ximclient_list; xc != NULL; xc = xc->next)
124     {
125       if (IsPreeditArea (xc) || IsPreeditPosition (xc))
126         {
127           cur_p = cur_x = xc;
128           xl = cur_p->cur_xl;
129           cur_lang = xl->lang_db;
130           if (window == xl->w[0])
131             {
132               if (IsPreeditArea (cur_x))
133                 {
134                   redraw_window3 (event->x, event->width);
135                   return;
136                 }
137               else if (IsPreeditPosition (cur_x))
138                 {
139                   redraw_lines (event->x, event->width, 1);
140                   return;
141                 }
142             }
143           else if (window == xl->w[1])
144             {
145               redraw_lines (event->x, event->width, 2);
146               return;
147             }
148           else if (window == xl->w[2])
149             {
150               redraw_lines (event->x, event->width, 3);
151               return;
152             }
153           else if (window == xl->wn[0])
154             {
155               redraw_note (0);
156               return;
157             }
158           else if (window == xl->wn[1])
159             {
160               redraw_note (1);
161               return;
162             }
163         }
164 
165       if (IsStatusArea (xc))
166         {
167           if (window == cur_p->cur_xl->ws)
168             {
169               redraw_window0 ();
170               return;
171             }
172         }
173     }
174   for (p = box_list; p != NULL; p = p->next)
175     {
176       if (window == p->window)
177         {
178           if (p->redraw_cb)
179             (p->redraw_cb) (p->redraw_cb_data);
180           redraw_box (p);
181           return;
182         }
183     }
184   if (xim->j_c)
185     {
186       cur_cl_change3 (xim->j_c);
187       if (window == xim->cur_j_c_root->ichi->w1)
188         {
189           redraw_ichi_w ();
190           return;
191         }
192       else if (window == xim->cur_j_c_root->ichi->nyuu_w)
193         {
194           JW3Mputc (xim->cur_j_c_root->ichi->nyuu, xim->cur_j_c_root->ichi->nyuu_w, 0, 1, 0);
195           return;
196         }
197       if (window == xim->cur_j_c_root->inspect->w1)
198         {
199           JW3Mputc (xim->cur_j_c_root->inspect->msg, xim->cur_j_c_root->inspect->w1, 0, 0, IN_BORDER);
200           return;
201         }
202     }
203   return;
204 }
205 
206 static void
xw_expose(event)207 xw_expose (event)
208      register XExposeEvent *event;
209 {
210   register XIMClientRec *cur_x_sv, *cur_p_sv;
211   register XIMLangDataBase *cur_lang_sv;
212 
213   cur_x_sv = cur_x;
214   cur_p_sv = cur_p;
215   cur_lang_sv = cur_lang;
216   search_expose (event);
217   cur_p = cur_p_sv;
218   cur_x = cur_x_sv;
219   cur_lang = cur_lang_sv;
220 }
221 
222 static Status
xw_buttonpress(event)223 xw_buttonpress (event)
224      XButtonEvent *event;
225 {
226   register XIMClientRec *xc;
227   register BoxRec *p;
228   register Window window = event->window;
229 
230   xim->sel_ret = -1;
231   for (xc = ximclient_list; xc != NULL; xc = xc->next)
232     {
233       if (IsPreeditNothing (xc))
234         continue;
235       if (window == xc->cur_xl->ws)
236         {
237           if (xim->j_c == NULL)
238             {
239               xim->sel_button = 1;
240               cur_cl_change3 (xc);
241               if (event->button == Button1)
242                 {
243                   jutil_c ();
244                 }
245               else
246                 {
247                   lang_c ();
248                 }
249             }
250           return (False);
251         }
252     }
253 
254   for (p = box_list; p != NULL; p = p->next)
255     {
256       if (window == p->window)
257         {
258           if (p->freeze)
259             return (False);
260           xim->sel_ret = p->sel_ret;
261           if (p->cb)
262             (*p->cb) (p->cb_data);
263           return (p->do_ret);
264         }
265     }
266   if (xim->j_c)
267     {
268       if (window == xim->cur_j_c_root->ichi->w1)
269         {
270           xim->sel_button = 1;
271           if (xim->cur_j_c_root->ichi->mode == SENTAKU)
272             {
273               xw_select_button (event);
274             }
275           else
276             {
277               xw_select_jikouho_button (event);
278             }
279           cur_cl_change3 (xim->j_c);
280           return (True);
281         }
282     }
283   return (False);
284 }
285 
286 static void
xw_destroy(event)287 xw_destroy (event)
288      register XDestroyWindowEvent *event;
289 {
290   register XIMClientRec *xc;
291   register int i;
292 
293 #ifdef  XJPLIB
294   if (XJp_xw_destroy (event))
295     return;
296 #endif /* XJPLIB */
297 #ifdef  USING_XJUTIL
298   if (xjutil_destroy (event))
299     return;
300 #endif /* USING_XJUTIL */
301   for (xc = ximclient_list; xc != NULL; xc = xc->next)
302     {
303       if (event->window == xc->w)
304         {
305           for (i = 0; i < xim->screen_count; i++)
306             {
307               if (xc == xim->root_pointer[i]->ximclient)
308                 {
309                   create_xim_window (xim->root_pointer[i], xc);
310                   create_preedit (xc, xc->cur_xl, 1);
311                   create_status (xc, xc->cur_xl, 1);
312                   XMapWindow (dpy, xc->cur_xl->ws);
313                   return;
314                 }
315             }
316           destroy_client (xc);
317           return;
318         }
319     }
320 }
321 
322 static void
xw_mousemove(event)323 xw_mousemove (event)
324      XMotionEvent *event;
325 {
326   if (xim->j_c)
327     {
328       if (xim->cur_j_c_root->ichi->mode == SENTAKU)
329         {
330           xw_move_hilite (event->y);
331         }
332       else
333         {
334           xw_jikouho_move_hilite (event->x, event->y);
335         }
336     }
337 }
338 
339 static void
xw_enterleave(event,el)340 xw_enterleave (event, el)
341      XCrossingEvent *event;
342      char el;
343 {
344   register BoxRec *p;
345   register Window window = event->window;
346 
347   for (p = box_list; p != NULL; p = p->next)
348     {
349       if (window == p->window)
350         {
351           if (!p->freeze && p->reverse && el != p->in)
352             {
353               reverse_box (p, p->invertgc);
354               p->in = el;
355             }
356           return;
357         }
358     }
359   if (xim->j_c)
360     {
361       if (window == xim->cur_j_c_root->ichi->w1)
362         {
363           if (el)
364             {
365               xw_mousemove (event);
366             }
367           else
368             {
369               if (xim->cur_j_c_root->ichi->mode == SENTAKU)
370                 xw_mouseleave ();
371             }
372           return;
373         }
374     }
375   return;
376 }
377 
378 static void
xw_reparent(event)379 xw_reparent (event)
380      XReparentEvent *event;
381 {
382 /*
383     register XIMClientRec *xc;
384 
385     for (xc = ximclient_list; xc != NULL; xc = xc->next) {
386         if (xc->xl[0] && (xc->lang_num > 1)) {
387             if (event->window == xc->xl[0]->wp[0]) {
388                 reparent_preedit(xc, event->parent);
389                 return;
390             }
391             if (event->window == xc->xl[0]->ws) {
392                 reparent_status(xc, event->parent);
393                 return;
394             }
395         }
396     }
397 */
398   read_wm_id ();
399 }
400 
401 static void
xw_configure(ev)402 xw_configure (ev)
403      XConfigureEvent *ev;
404 {
405   register XIMClientRec *xc;
406 
407   for (xc = ximclient_list; xc != NULL; xc = xc->next)
408     {
409       if (xc->w == ev->window)
410         {
411           change_client_area (xc, ev->x, ev->y, ev->width, ev->height);
412           return;
413         }
414       else if (xc->focus_window == ev->window)
415         {
416           change_focus_area (xc, ev->x, ev->y, ev->width, ev->height);
417           return;
418         }
419     }
420 }
421 
422 void
X_flush()423 X_flush ()
424 {
425   if (cur_x && cur_p && IsPreeditPosition (cur_x) && cur_p->cur_xl->del_x >= cur_p->cur_xl->max_pos)
426     {
427       JWMline_clear1 ();
428     }
429   XFlush (dpy);
430 }
431 
432 static void
kill_xim(window,prop_id,force)433 kill_xim (window, prop_id, force)
434      Window window;
435      Atom prop_id;
436      int force;
437 {
438   XEvent event;
439   register int i, ok = 0;
440   register XIMClientRec *xc;
441   unsigned char *data;
442   Atom actual_type;
443   int actual_format;
444   unsigned long nitems, leftover;
445 
446   for (i = 0, xc = ximclient_list; xc; xc = xc->next)
447     i++;
448 #ifdef  XJPLIB
449   i += XJp_get_client_cnt ();
450 #endif /* XJPLIB */
451   event.type = ClientMessage;
452   event.xclient.format = 32;
453   event.xclient.window = xim->root_pointer[xim->default_screen]->ximclient->w;
454   event.xclient.data.l[0] = XWNMO_KILL;
455   if (prop_id)
456     {
457       XGetWindowProperty (dpy, xim->root_pointer[xim->default_screen]->root_window, prop_id, 0L, 1000000L, False, XA_STRING, &actual_type, &actual_format, &nitems, &leftover, &data);
458       if (nitems > 0 && data && *data && !strncmp (root_username, (char *) data, nitems))
459         {
460           if (force || i == 1)
461             {
462               ok = 1;
463               event.xclient.data.l[2] = 0;
464             }
465           else
466             {
467               event.xclient.data.l[2] = i - 1;
468             }
469         }
470       else
471         {
472           event.xclient.data.l[2] = -1;
473         }
474       XFree (data);
475     }
476   else
477     {
478       event.xclient.data.l[2] = -1;
479     }
480   if (ok)
481     {
482       event.xclient.data.l[1] = XWNMO_KILL_OK;
483     }
484   else
485     {
486       event.xclient.data.l[1] = XWNMO_KILL_NG;
487     }
488   XSendEvent (dpy, window, False, NoEventMask, &event);
489   XFlush (dpy);
490   if (ok)
491     {
492       do_end ();
493     }
494 }
495 
496 static Bool
dummy_proc(display,ev,arg)497 dummy_proc (display, ev, arg)
498      Display *display;
499      XEvent *ev;
500      char *arg;
501 {
502   return (True);
503 }
504 
505 void
XEventDispatch()506 XEventDispatch ()
507 {
508   int buff[32], in;
509   XEvent event;
510   int ret = 0, n_bytes;
511   register int i;
512   extern Atom wm_id;
513   extern Atom wm_id1;
514 
515 /*
516     while (XPending(dpy) > 0) {
517 */
518   do
519     {
520 /*
521         XNextEvent(dpy, &event);
522         if (XCheckMaskEvent(dpy, ~NoEventMask, &event) == False) return;
523 */
524       if (XCheckIfEvent (dpy, &event, dummy_proc, 0) == False)
525         return;
526       ret = 0;
527       switch (event.type)
528         {
529         case KeyPress:
530           xim->sel_button = (char) 0;
531           ret = key_input (buff, &event);
532           break;
533         case Expose:
534           xw_expose (&event);
535           break;
536         case ButtonRelease:
537           button.x = event.xbutton.x_root;
538           button.y = event.xbutton.y_root;
539           if (event.xbutton.window == xim->root_pointer[xim->default_screen]->ximclient->w)
540             {
541               if (xim->exit_menu)
542                 {
543                   xim->sel_button = 1;
544                   syuuryou_menu ();
545                 }
546             }
547           else
548             {
549               if (xw_buttonpress (&event) == True)
550                 {
551                   if (xim->exit_menu_flg && xim->j_c && ((event.xbutton.window == xim->cur_j_c_root->ichi->button[CANCEL_W]->window) || (event.xbutton.window == xim->cur_j_c_root->ichi->w1)))
552                     {
553                       syuuryou_menu ();
554                     }
555                   else
556                     {
557                       buff[0] = 0xd;
558                       ret = 1;
559                     }
560                 }
561             }
562           break;
563         case DestroyNotify:
564           xw_destroy (&event);
565           break;
566         case MotionNotify:
567           xw_mousemove (&event);
568           break;
569         case EnterNotify:
570           xw_enterleave (&event, 1);
571           break;
572         case LeaveNotify:
573           xw_enterleave (&event, 0);
574           break;
575         case ReparentNotify:
576           xw_reparent (&event);
577           break;
578         case MapNotify:
579           check_map (event.xmap.window);
580           break;
581         case MappingNotify:
582           keyboard_mapping (&event);
583           break;
584         case ConfigureNotify:
585           xw_configure (&event);
586           break;
587         case ClientMessage:
588           if (wm_id && (event.xclient.message_type == wm_id) && (event.xclient.data.l[0] == wm_id1))
589             {
590               motif_event (&event);
591               break;
592             }
593 #ifdef  USING_XJUTIL
594           if (event.xclient.data.l[0] == DIC_START)
595             {
596               set_xjutil_id (event.xclient.data.l[1], event.xclient.data.l[2], 0);
597             }
598           else if (event.xclient.data.l[0] == DIC_START_ER)
599             {
600               set_xjutil_id (event.xclient.data.l[1], event.xclient.data.l[2], 1);
601             }
602           else if (event.xclient.data.l[0] == DIC_FONTSET_ER)
603             {
604               reset_xjutil_fs_id (event.xclient.data.l[1], event.xclient.data.l[2]);
605             }
606           else if (event.xclient.data.l[0] == DIC_END)
607             {
608               end_xjutil_work (event.xclient.data.l[1]);
609             }
610 #endif /* USING_XJUTIL */
611           if (event.xclient.data.l[0] == XWNMO_KILL)
612             {
613               kill_xim (event.xclient.data.l[1], event.xclient.data.l[2], event.xclient.data.l[3]);
614             }
615 #ifdef  XJPLIB
616           else
617             {
618               XJp_event_dispatch (&event);
619             }
620 #endif
621           break;
622 #ifndef X11R5
623         case SelectionRequest:
624 #ifdef BC_X11R5
625           if (IS_NOT_FROM_XIMR5 (event))
626             ximr5_client = 0;
627 #endif /* BC_X11R5 */
628           XimConvertTarget (dpy, (XSelectionRequestEvent *) & event);
629           break;
630 #endif /* !X11R5 */
631         default:
632           break;
633         }
634       for (i = 0; i < ret;)
635         {
636           n_bytes = get_cswidth_by_char (in = buff[i++]);
637           for (; n_bytes > 1 && i < ret; n_bytes--, i++)
638             {
639               in = (in << 8) + buff[i];
640             }
641           in_put (in);
642         }
643 /*
644     }
645 */
646     }
647   while (XPending (dpy) > 0);
648 }
649 
650 static Bool
yes_no_proc(display,ev,arg)651 yes_no_proc (display, ev, arg)
652      Display *display;
653      XEvent *ev;
654      char *arg;
655 {
656   register Window w = ev->xany.window;
657 
658   if (w == cur_p->yes_no->w || w == cur_p->yes_no->title->window || w == cur_p->yes_no->button[0]->window || w == cur_p->yes_no->button[1]->window)
659     {
660       return (True);
661     }
662   return (False);
663 }
664 
665 int
get_yes_no_event()666 get_yes_no_event ()
667 {
668   int buff[16];
669   XEvent event;
670 
671   while (1)
672     {
673       XFlush (dpy);
674       XIfEvent (dpy, &event, yes_no_proc, 0);
675       switch (event.type)
676         {
677         case KeyPress:
678           if (key_input (buff, &event) > 0)
679             return (buff[0]);
680           break;
681         case Expose:
682           xw_expose (&event);
683           return (0);
684         case ButtonRelease:
685           button.x = event.xbutton.x_root;
686           button.y = event.xbutton.y_root;
687           if (xw_buttonpress (&event) == True)
688             {
689               return (0xd);
690             }
691           break;
692         case EnterNotify:
693           xw_enterleave (&event, 1);
694           break;
695         case LeaveNotify:
696           xw_enterleave (&event, 0);
697           break;
698         case MapNotify:
699           check_map (event.xmap.window);
700           return (0);
701         default:
702           break;
703         }
704     }
705 }
706