1 /*
2  * $Id: do_xjplib.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  *
32  * Last modified date: 8,Feb.1999
33  *
34  * Code:
35  *
36  */
37 
38 #ifdef  XJPLIB
39 
40 #include "do_xjplib.h"
41 
42 #define XJPLIB_PORT_IN  (0x9494)
43 #define UNIX_PATH       "/tmp/xwnmo.V2"
44 #define UNIX_ACPT       0
45 #define INET_ACPT       1
46 
47 #define XIMCLIENT       (xim->root_pointer[xim->default_screen]->ximclient)
48 
49 static Atom xjp_select_id = (Atom) 0;
50 
51 XJpClientRec *xjp_clients = NULL;
52 XJpClientRec *xjp_cur_client = NULL;
53 XJpInputRec *xjp_inputs = NULL;
54 XJpInputRec *xjp_cur_input = NULL;
55 
56 char *def_escape[4] = {
57   "(J",
58   "$B",
59   "(I",
60   "$0"
61 };
62 
63 #define vname_size      128
64 #define hname_size      128
65 #define XWNMO_XJP_NAME  "xwnmo.V2"
66 void
XJp_init()67 XJp_init ()
68 {
69   char name[hname_size];
70   unsigned char buffer[hname_size * 2 + 10];
71   register unsigned char *p;
72   long pnumber = 0L;
73   extern int gethostname ();
74 
75   if (!(xjp_select_id = XInternAtom (dpy, "XJPFRONTEND", True)))
76     {
77       xjp_select_id = XInternAtom (dpy, "XJPFRONTEND", False);
78     }
79 #ifdef  XJPLIB_DIRECT
80   pnumber = (long) XJp_get_xjp_port ();
81 #endif /* XJPLIB_DIRECT */
82   gethostname (name, hname_size);
83   p = buffer;
84   strcpy (p, XWNMO_XJP_NAME);
85   p += vname_size;
86   strcpy (p, name);
87   bcopy (&pnumber, (p += hname_size), sizeof (long));
88   *(p += sizeof (long)) = '\0';
89   XChangeProperty (dpy, xim->root_pointer[xim->default_screen]->root_window, xjp_select_id, XA_STRING, 8, PropModeReplace, buffer, p - buffer);
90   XSetSelectionOwner (dpy, xjp_select_id, XIMCLIENT->w, 0L);
91 }
92 
93 static void
xjp_send_open(xjp,w)94 xjp_send_open (xjp, w)
95      XJpClientRec *xjp;
96      Window w;
97 {
98   XEvent event;
99 
100   event.type = ClientMessage;
101   event.xclient.format = 32;
102   event.xclient.window = w;
103   event.xclient.data.l[0] = XJP_OPEN;
104   event.xclient.data.l[1] = w;
105   if (xjp->dispmode == XJP_ROOT)
106     {
107       event.xclient.data.l[2] = FontWidth (XIMCLIENT->xl[0]);
108       event.xclient.data.l[3] = FontHeight (XIMCLIENT->xl[0]);
109     }
110   else
111     {
112       event.xclient.data.l[2] = FontWidth (xjp->xim_client->xl[0]);
113       event.xclient.data.l[3] = FontHeight (xjp->xim_client->xl[0]);
114     }
115   XSendEvent (dpy, xjp->w, False, NoEventMask, &event);
116   XFlush (dpy);
117 }
118 
119 static void
xjp_send_err(w,err)120 xjp_send_err (w, err)
121      Window w;
122      int err;
123 {
124   XEvent event;
125 
126   event.type = ClientMessage;
127   event.xclient.format = 32;
128   event.xclient.window = XIMCLIENT->w;
129   event.xclient.data.l[0] = XJP_ERROR;
130   event.xclient.data.l[1] = err;
131   XSendEvent (dpy, w, False, NoEventMask, &event);
132   XFlush (dpy);
133 }
134 
135 void
XJp_end()136 XJp_end ()
137 {
138   XEvent event;
139   XJpClientRec *p;
140 
141   if (dpy)
142     {
143       event.type = ClientMessage;
144       event.xclient.format = 32;
145       event.xclient.message_type = xjp_select_id;
146       event.xclient.data.l[0] = XJP_ERROR;
147       event.xclient.data.l[1] = 0;
148       for (p = xjp_clients; p; p = p->next)
149         {
150 #ifdef  XJPLIB_DIRECT
151           if (p->direct_fd == -1)
152             {
153 #endif /* XJPLIB_DIRECT */
154               XSendEvent (dpy, p->w, False, NoEventMask, &event);
155               XFlush (dpy);
156 #ifdef  XJPLIB_DIRECT
157             }
158 #endif /* XJPLIB_DIRECT */
159         }
160     }
161   XDeleteProperty (dpy, XIMCLIENT->w, xjp_select_id);
162 }
163 
164 static char *
xjp_get_xim_fontname(xjp,p,cs)165 xjp_get_xim_fontname (xjp, p, cs)
166      XJpClientRec *xjp;
167      register char *p;
168      XCharStruct *cs;
169 {
170   register char *s, *ss, *xim_font;
171   char save_escape[10];
172   int char_set;
173   register int i;
174   int get_height = 0;
175   XFontStruct *font;
176 
177   if ((xim_font = Malloc (strlen (p))) == NULL)
178     {
179       malloc_error ("allocation of work area");
180       return (NULL);
181     }
182 
183   s = xim_font;
184   for (; *p; s++)
185     {
186       for (i = 0; *p && *p != 0x09; i++, p++)
187         save_escape[i] = *p;
188       save_escape[i] = '\0';
189       p++;
190       ss = s;
191       for (; *p && *p != 0x0a; s++, p++)
192         {
193           *s = *p;
194         }
195       p++;
196       if (!get_height)
197         {
198           *s = '\0';
199           if (font = XLoadQueryFont (dpy, ss))
200             {
201               cs->ascent = font->ascent;
202               cs->descent = font->descent;
203               cs->width = font->max_bounds.width;
204               get_height = 1;
205               XFreeFont (dpy, font);
206             }
207         }
208       *s = ',';
209       if (save_escape[0] == '(')
210         {
211           if (save_escape[1] == 'I')
212             {
213               char_set = 2;
214             }
215           else
216             {
217               char_set = 0;
218             }
219         }
220       else if (save_escape[0] == '$')
221         {
222           if (save_escape[1] == 'B')
223             {
224               char_set = 1;
225             }
226           else
227             {
228               char_set = 3;
229             }
230         }
231       else
232         {
233           char_set = 0;
234         }
235       strcpy (xjp->escape[char_set], save_escape);
236     }
237   *s = '\0';
238   return (xim_font);
239 }
240 
241 void
XJp_xjp_to_xim(xjp,ic_req,pre_req,st_req,cs)242 XJp_xjp_to_xim (xjp, ic_req, pre_req, st_req, cs)
243      XJpClientRec *xjp;
244      ximICValuesReq *ic_req;
245      ximICAttributesReq *pre_req, *st_req;
246      XCharStruct *cs;
247 {
248   XWindowAttributes attr;
249   int height = cs->ascent + cs->descent;
250   int min_keycode, max_keycode;
251 
252   XDisplayKeycodes (dpy, &min_keycode, &max_keycode);
253   ic_req->c_window = ic_req->focus_window = xjp->w;
254   ic_req->max_keycode = max_keycode;
255   ic_req->mask = (1 << ICClientWindow);
256   ic_req->mask |= (1 << ICFocusWindow);
257 
258   switch (xjp->dispmode)
259     {
260     case XJP_UNDER:
261       ic_req->input_style = (XIMPreeditArea | XIMStatusArea);
262       ic_req->mask |= (1 << (ICInputStyle));
263       ic_req->mask |= (1 << (ICArea));
264       ic_req->mask |= (1 << (ICForeground));
265       ic_req->mask |= (1 << (ICBackground));
266       ic_req->mask |= (1 << (ICFontSet));
267       ic_req->mask |= (1 << (ICArea + StatusOffset));
268       ic_req->mask |= (1 << (ICForeground + StatusOffset));
269       ic_req->mask |= (1 << (ICBackground + StatusOffset));
270       ic_req->mask |= (1 << (ICFontSet + StatusOffset));
271       pre_req->area_x = xjp->x + cs->width * MHL0;
272       pre_req->area_y = xjp->y + (xjp->height - height) / 2;
273       pre_req->area_width = xjp->width - cs->width * MHL0;
274       pre_req->area_height = xjp->height;
275       pre_req->foreground = xjp->fg;
276       pre_req->background = xjp->bg;
277       st_req->area_x = xjp->x;
278       st_req->area_y = xjp->y + (xjp->height - height) / 2;
279       st_req->area_width = cs->width * MHL0;
280       st_req->area_height = xjp->height;
281       st_req->foreground = xjp->fg;
282       st_req->background = xjp->bg;
283       break;
284     case XJP_XY:
285       ic_req->input_style = (XIMPreeditPosition | XIMStatusArea);
286       ic_req->mask |= (1 << (ICInputStyle));
287       ic_req->mask |= (1 << (ICArea));
288       ic_req->mask |= (1 << (ICForeground));
289       ic_req->mask |= (1 << (ICBackground));
290       ic_req->mask |= (1 << (ICSpotLocation));
291       ic_req->mask |= (1 << (ICFontSet));
292       ic_req->mask |= (1 << (ICArea + StatusOffset));
293       ic_req->mask |= (1 << (ICForeground + StatusOffset));
294       ic_req->mask |= (1 << (ICBackground + StatusOffset));
295       ic_req->mask |= (1 << (ICFontSet + StatusOffset));
296       XGetWindowAttributes (dpy, xjp->w, &attr);
297       pre_req->area_x = attr.x;
298       pre_req->area_y = attr.y;
299       pre_req->area_width = attr.width;
300       pre_req->area_height = attr.height;
301       pre_req->spot_x = xjp->x;
302       pre_req->spot_y = xjp->y + cs->ascent;
303       pre_req->foreground = xjp->fg;
304       pre_req->background = xjp->bg;
305       st_req->area_x = xjp->status_x;
306       st_req->area_y = xjp->status_y;
307       st_req->area_width = cs->width * MHL0;
308       st_req->area_height = xjp->height;
309       st_req->foreground = xjp->fg;
310       st_req->background = xjp->bg;
311       break;
312     case XJP_ROOT:
313       ic_req->input_style = (XIMPreeditNothing | XIMStatusNothing);
314       ic_req->mask |= (1 << (ICInputStyle));
315       break;
316     }
317 }
318 
319 static void
xjp_open(ev)320 xjp_open (ev)
321      XClientMessageEvent *ev;
322 {
323   XJpClientRec *xjp, *p;
324   XIMClientRec *xc = NULL;
325   Atom client_atom = (Atom) ev->data.l[2];
326   Window client_window = (Window) ev->data.l[1];
327   Atom actual_type;
328   int actual_format;
329   unsigned long nitems, leftover;
330   unsigned char *data;
331   ximICValuesReq ic_req;
332   ximICAttributesReq pre_req, st_req;
333   XIMNestLangList lc_list = NULL;
334   char *font = NULL;
335   XCharStruct cs;
336   short detail;
337   int err_code = 0, i;
338 
339   if ((xjp = (XJpClientRec *) Malloc (sizeof (XJpClientRec))) == NULL)
340     {
341       malloc_error ("allocation of client data(XJp)");
342       return;
343     }
344   XGetWindowProperty (dpy, client_window, client_atom, 0L, 1000000L, False, XA_STRING, &actual_type, &actual_format, &nitems, &leftover, &data);
345   if (nitems < 184)
346     {
347       print_out ("XJp_open data was bad format.");
348       return;
349     }
350   bcopy ((char *) data, (char *) xjp, 184);
351   data += 184;
352   for (p = xjp_clients; p; p = p->next)
353     {
354       if (p->w == xjp->w)
355         {
356           p->ref_count++;
357           if (xjp->dispmode == XJP_ROOT)
358             {
359               xjp_send_open (xjp, XIMCLIENT->xl[0]->wp[0]);
360             }
361           else
362             {
363               xjp_send_open (xjp, p->xim_client->xl[0]->wp[0]);
364             }
365           Free ((char *) xjp);
366           return;
367         }
368     }
369   for (i = 0; i < 4; i++)
370     {
371       xjp->escape[i][0] = '\0';
372     }
373   if (xjp->dispmode != XJP_ROOT)
374     {
375       font = xjp_get_xim_fontname (xjp, data, &cs);
376       if ((xjp->mask & XJP_FG) == 0)
377         xjp->fg = XIMCLIENT->pe.fg;
378       if ((xjp->mask & XJP_BG) == 0)
379         xjp->bg = XIMCLIENT->pe.bg;
380       if (xjp->dispmode == XJP_UNDER)
381         {
382           if ((xjp->mask & XJP_BP) == 0)
383             xjp->bp = 1;
384           if ((xjp->mask & XJP_WIDTH) == 0)
385             xjp->width = xjp->p_width;
386           if ((xjp->mask & XJP_HEIGHT) == 0)
387             xjp->height = cs.ascent + cs.descent;
388           if ((xjp->mask & XJP_X) == 0)
389             xjp->x = 0;
390           if ((xjp->mask & XJP_Y) == 0)
391             xjp->y = xjp->p_height - (xjp->height + xjp->bp);
392         }
393       else if (xjp->dispmode == XJP_XY)
394         {
395           if ((xjp->mask & XJP_BP) == 0)
396             xjp->bp = 1;
397           if ((xjp->mask & XJP_HEIGHT) == 0)
398             xjp->height = cs.ascent + cs.descent;
399         }
400     }
401   for (i = 0; i < 4; i++)
402     {
403       if (xjp->escape[i][0] == '\0')
404         strcpy (xjp->escape[i], def_escape[i]);
405     }
406   XJp_xjp_to_xim (xjp, &ic_req, &pre_req, &st_req, &cs);
407   if (get_langlist (def_locale, &lc_list) >= 0 && lc_list)
408     {
409       xc = create_client (&ic_req, &pre_req, &st_req, lc_list, lc_list, 0, 0, font, font, xjp->c_data, &detail);
410     }
411   if (font)
412     Free (font);
413   if (lc_list)
414     free_langlist (lc_list);
415   if (xc == NULL)
416     {
417       switch (detail)
418         {
419         case BadStyle:
420           err_code = XJP_F_OPEN_NOT_SUPPORT;
421           break;
422         case BadFontSet:
423           err_code = XJP_F_OPEN_BAD_FN;
424           break;
425         case BadClientWindow:
426         case BadFocusWindow:
427           err_code = XJP_F_OPEN_BAD_WID;
428           break;
429         case BadSpotLocation:
430           err_code = XJP_F_OPEN_BAD_SZ;
431           break;
432         case BadSomething:
433         default:
434           err_code = XJP_F_OPEN_NOT_WIN;
435           break;
436         }
437       xjp_send_err (xjp->w, err_code);
438       Free ((char *) xjp);
439       return;
440     }
441   else
442     {
443       xc->xjp = 1;
444       xjp->xim_client = xc;
445 #ifdef  XJPLIB_DIRECT
446       xjp->direct_fd = -1;
447 #endif /* XJPLIB_DIRECT */
448       xjp->next = xjp_clients;
449       xjp->ref_count = 0;
450       xjp_clients = xjp;
451       XSelectInput (dpy, xjp->w, StructureNotifyMask);
452       if (xjp->dispmode == XJP_ROOT)
453         {
454           xjp_send_open (xjp, XIMCLIENT->xl[0]->wp[0]);
455         }
456       else
457         {
458           xjp_send_open (xjp, xc->xl[0]->wp[0]);
459         }
460     }
461 }
462 
463 static void
xjp_close(ev)464 xjp_close (ev)
465      XClientMessageEvent *ev;
466 {
467   Window client_window = ev->window;
468   XJpClientRec *p, **prev_p;
469   XJpInputRec *i, **prev_i;
470 
471   for (prev_p = &xjp_clients; p = *prev_p; prev_p = &p->next)
472     {
473       if (client_window == p->w)
474         {
475           if (p->ref_count)
476             {
477               p->ref_count--;
478               return;
479             }
480           if (p == xjp_cur_client)
481             {
482               xjp_cur_client = NULL;
483               xjp_cur_input = NULL;
484             }
485           destroy_client (p->xim_client);
486           for (prev_i = &xjp_inputs; i = *prev_i;)
487             {
488               if (i->pclient == p)
489                 {
490                   XSelectInput (dpy, i->w, NoEventMask);
491                   *prev_i = i->next;
492                   Free ((char *) i);
493                 }
494               else
495                 {
496                   prev_i = &i->next;
497                 }
498             }
499           XSelectInput (dpy, p->w, NoEventMask);
500           *prev_p = p->next;
501           Free ((char *) p);
502           return;
503         }
504     }
505 }
506 
507 static void
xjp_begin(ev)508 xjp_begin (ev)
509      XClientMessageEvent *ev;
510 {
511   register XJpClientRec *xjp = NULL, *p;
512   register XJpInputRec *i;
513   Window grab_window = ev->data.l[2];
514   Window client_window = ev->window;
515 
516   for (p = xjp_clients; p; p = p->next)
517     {
518       if (p->w == client_window)
519         {
520           xjp = p;
521           break;
522         }
523     }
524   if (p == NULL)
525     return;
526 
527   for (p = xjp_clients; p; p = p->next)
528     {
529       if (p->w == grab_window)
530         {
531           XSelectInput (dpy, grab_window, (KeyPressMask | StructureNotifyMask));
532           break;
533         }
534     }
535   if (p == NULL)
536     {
537       XSelectInput (dpy, grab_window, KeyPressMask);
538     }
539   XFlush (dpy);
540   for (i = xjp_inputs; i; i = i->next)
541     {
542       if (i->w == grab_window)
543         {
544           if (i->pclient != xjp)
545             {
546               i->pclient = xjp;
547               cur_input = NULL;
548             }
549           return;
550         }
551     }
552   if ((i = (XJpInputRec *) Malloc (sizeof (XJpInputRec))) == NULL)
553     {
554       if (p)
555         {
556           XSelectInput (dpy, grab_window, StructureNotifyMask);
557         }
558       else
559         {
560           XSelectInput (dpy, grab_window, NoEventMask);
561         }
562       return;
563     }
564   i->w = grab_window;
565   i->pclient = xjp;
566   i->save_event = 0;
567   i->next = xjp_inputs;
568   xjp_inputs = i;
569 }
570 
571 static void
xjp_end(ev)572 xjp_end (ev)
573      XClientMessageEvent *ev;
574 {
575   register XJpClientRec *p;
576   Window grab_window = ev->data.l[2];
577 
578   for (p = xjp_clients; p; p = p->next)
579     {
580       if (p->w == grab_window)
581         {
582           XSelectInput (dpy, grab_window, StructureNotifyMask);
583           break;
584         }
585     }
586   if (p == NULL)
587     XSelectInput (dpy, grab_window, NoEventMask);
588   cur_input = NULL;
589   XFlush (dpy);
590 }
591 
592 static void
xjp_change(ev)593 xjp_change (ev)
594      XClientMessageEvent *ev;
595 {
596   register XJpClientRec *xjp = NULL, *p;
597   register XIMClientRec *xc = NULL;
598   Window pre_window = (Window) ev->data.l[1];
599   XJpClientRec savexjp;
600   Atom client_atom;
601   Atom actual_type;
602   int actual_format;
603   unsigned long nitems, leftover;
604   unsigned char *data;
605   ximICValuesReq ic_req;
606   ximICAttributesReq pre_req, st_req;
607   short detail;
608   unsigned long mask, xim_mask = 0;
609 
610   for (p = xjp_clients; p; p = p->next)
611     {
612       if (IsPreeditNothing (p->xim_client))
613         continue;
614       if (p->xim_client->xl[0]->wp[0] == pre_window)
615         {
616           xjp = p;
617           xc = p->xim_client;
618           break;
619         }
620     }
621   if (xjp == NULL)
622     return;
623   if (!(client_atom = XInternAtom (dpy, "XJPCLIENT", True)))
624     return;
625   XGetWindowProperty (dpy, p->w, client_atom, 0L, 1000000L, False, XA_STRING, &actual_type, &actual_format, &nitems, &leftover, &data);
626   if (nitems < 184)
627     return;
628 
629   bcopy ((char *) data, (char *) &savexjp, 184);
630   mask = savexjp.mask;
631 
632   if (mask & XJP_FG)
633     {
634       if (xjp->fg != savexjp.fg)
635         {
636           xjp->fg = savexjp.fg;
637           xim_mask |= ((1 << ICForeground) | (1 << (ICForeground + StatusOffset)));
638         }
639       xjp->mask |= XJP_FG;
640     }
641   if (mask & XJP_BG)
642     {
643       if (xjp->bg != savexjp.bg)
644         {
645           xjp->bg = savexjp.bg;
646           xim_mask |= ((1 << ICBackground) | (1 << (ICBackground + StatusOffset)));
647         }
648       xjp->mask |= XJP_BG;
649     }
650   if ((mask & XJP_WIDTH) /* && xjp->dispmode == XJP_XY */ )
651     {
652       if (xjp->width != savexjp.width)
653         {
654           xjp->width = savexjp.width;
655           xim_mask |= (1 << ICArea);
656         }
657       xjp->mask |= XJP_WIDTH;
658     }
659   if (mask & XJP_HEIGHT)
660     {
661       if (xjp->height != savexjp.height)
662         {
663           xjp->height = savexjp.height;
664           xim_mask |= (1 << ICArea);
665         }
666       xjp->mask |= XJP_HEIGHT;
667     }
668   if ((mask & XJP_X) && xjp->dispmode == XJP_XY)
669     {
670       if (xjp->x != savexjp.x)
671         {
672           xjp->x = savexjp.x;
673           xim_mask |= (1 << ICSpotLocation);
674         }
675       xjp->mask |= XJP_X;
676     }
677   if ((mask & XJP_Y) && xjp->dispmode == XJP_XY)
678     {
679       if (xjp->y != savexjp.y)
680         {
681           xjp->y = savexjp.y;
682           xim_mask |= (1 << ICSpotLocation);
683         }
684       xjp->mask |= XJP_Y;
685     }
686   if (mask & XJP_PWIDTH)
687     {
688       if (xjp->p_width != savexjp.p_width)
689         {
690           xjp->p_width = savexjp.p_width;
691           if (xjp->dispmode == XJP_UNDER && !(xjp->mask & XJP_WIDTH))
692             {
693               xjp->width = xjp->p_width;
694               xim_mask |= (1 << ICArea);
695             }
696         }
697       xjp->mask |= XJP_PWIDTH;
698     }
699   if (mask & XJP_PHEIGHT)
700     {
701       if (xjp->p_height != savexjp.p_height)
702         {
703           xjp->p_height = savexjp.p_height;
704           if (xjp->dispmode == XJP_UNDER /* && !(xjp->mask & XJP_HEIGHT) */ )
705             {
706               xjp->y = xjp->p_height - xjp->height;
707               xim_mask |= ((1 << ICArea) | (1 << (ICArea + StatusOffset)));
708             }
709         }
710       xjp->mask |= XJP_HEIGHT;
711     }
712   if (mask & XJP_STATUS)
713     {
714       if (xjp->dispmode == XJP_XY)
715         {
716           xjp->status_x = savexjp.status_x;
717           xjp->status_y = savexjp.status_y;
718           xim_mask |= (1 << (ICArea + StatusOffset));
719         }
720       xjp->mask |= XJP_STATUS;
721     }
722 
723   XJp_xjp_to_xim (xjp, &ic_req, &pre_req, &st_req, xc->xl[0]->pe_b_char);
724   ic_req.mask = xim_mask;
725   change_client (xc, &ic_req, &pre_req, &st_req, NULL, NULL, NULL, &detail);
726 }
727 
728 static void
xjp_move(ev)729 xjp_move (ev)
730      XClientMessageEvent *ev;
731 {
732   register XJpClientRec *p;
733   Window pre_window = (Window) ev->data.l[1];
734   int x = (int) ev->data.l[2];
735   int y = (int) ev->data.l[3];
736 
737   for (p = xjp_clients; p; p = p->next)
738     {
739       if (IsPreeditNothing (p->xim_client))
740         continue;
741       if (p->xim_client->xl[0]->wp[0] == pre_window)
742         {
743           p->x = x;
744           p->y = y + FontAscent (p->xim_client->cur_xl);
745           change_spotlocation (p->xim_client, p->x, p->y);
746           return;
747         }
748     }
749 }
750 
751 static void
xjp_visible(ev,visible)752 xjp_visible (ev, visible)
753      XClientMessageEvent *ev;
754      int visible;
755 {
756   Window visible_window = ev->window;
757   register XJpClientRec *p;
758   register XIMClientRec *xc;
759   XIMClientRec *save_cur_p, *save_cur_x;
760   WnnClientRec *save_c_c;
761 
762   for (p = xjp_clients; p; p = p->next)
763     {
764       if (p->w == visible_window)
765         {
766           break;
767         }
768     }
769   if (p == NULL)
770     return;
771   xc = p->xim_client;
772   save_cur_p = cur_p;
773   save_cur_x = cur_x;
774   save_c_c = c_c;
775   cur_x = xc;
776   if (IsPreeditNothing (xc))
777     {
778       cur_p = XIMCLIENT;
779     }
780   else
781     {
782       cur_p = cur_x;
783     }
784   c_c = cur_p->cur_xl->w_c;
785   cur_rk = c_c->rk;
786   cur_rk_table = cur_rk->rk_table;
787   if (IsPreeditPosition (xc) || IsPreeditArea (xc))
788     {
789       if (visible)
790         {
791           reset_preedit (xc);
792         }
793       else
794         {
795           invisual_window ();
796         }
797     }
798   if (IsStatusArea (xc))
799     {
800       if (visible)
801         {
802           visual_status ();
803         }
804       else
805         {
806           invisual_status ();
807         }
808     }
809   cur_p = save_cur_p;
810   cur_x = save_cur_x;
811   c_c = save_c_c;
812   if (c_c)
813     {
814       cur_rk = c_c->rk;
815       cur_rk_table = cur_rk->rk_table;
816     }
817 }
818 
819 static void
xjp_indicator(ev)820 xjp_indicator (ev)
821      XClientMessageEvent *ev;
822 {
823   register XJpClientRec *p;
824   Window pre_window = (Window) ev->data.l[1];
825   Window window = (Window) ev->data.l[2];
826   int x = (int) ev->data.l[3];
827   int y = (int) ev->data.l[4];
828 
829   for (p = xjp_clients; p; p = p->next)
830     {
831       if (p->dispmode == XJP_ROOT)
832         continue;
833       if (p->xim_client->xl[0]->wp[0] == pre_window)
834         {
835           p->x = x;
836           p->y = y;
837           XReparentWindow (dpy, p->xim_client->xl[0]->ws, window, x, y);
838           return;
839         }
840     }
841 }
842 
843 void
XJp_event_dispatch(ev)844 XJp_event_dispatch (ev)
845      XClientMessageEvent *ev;
846 {
847   switch (ev->data.l[0])
848     {
849     case XJP_OPEN:
850       xjp_open (ev);
851       break;
852     case XJP_CLOSE:
853       xjp_close (ev);
854       break;
855     case XJP_BEGIN:
856       xjp_begin (ev);
857       break;
858     case XJP_END:
859       xjp_end (ev);
860       break;
861     case XJP_CHANGE:
862       xjp_change (ev);
863       break;
864     case XJP_MOVE:
865       xjp_move (ev);
866       break;
867     case XJP_VISIBLE:
868       xjp_visible (ev, 1);
869       break;
870     case XJP_INVISIBLE:
871       xjp_visible (ev, 0);
872       break;
873     case XJP_INDICATOR:
874       xjp_indicator (ev);
875       break;
876     }
877 
878 }
879 
880 XIMClientRec *
XJp_cur_cl_set(set_window)881 XJp_cur_cl_set (set_window)
882      Window set_window;
883 {
884   register XJpInputRec *i;
885 
886   if (set_window == (Window) 0)
887     {
888       xjp_cur_input = NULL;
889       xjp_cur_client = NULL;
890       return (NULL);
891     }
892   for (i = xjp_inputs; i; i = i->next)
893     {
894       if (i->w == set_window)
895         {
896           xjp_cur_input = i;
897           xjp_cur_client = i->pclient;
898           cur_input = NULL;
899           return (i->pclient->xim_client);
900         }
901     }
902   return (NULL);
903 }
904 
905 int
XJp_check_cur_input(w)906 XJp_check_cur_input (w)
907      Window w;
908 {
909   if (xjp_cur_input && w == xjp_cur_input->w)
910     return (0);
911   return (1);
912 }
913 
914 static void
xjp_send_cl_key(ev)915 xjp_send_cl_key (ev)
916      XKeyEvent *ev;
917 {
918 #ifdef  XJPLIB_DIRECT
919   if (xjp_cur_client && xjp_cur_client->direct_fd != -1)
920     {
921       XJp_direct_send_cl_key ();
922       return;
923     }
924 #endif /* XJPLIB_DIRECT */
925   if (!xjp_cur_input)
926     return;
927   ev->window = xjp_cur_input->w;
928   XSendEvent (dpy, xjp_cur_input->w, False, NoEventMask, (XEvent *) ev);
929   XFlush (dpy);
930 }
931 
932 void
XJp_check_send_cl_key(ev)933 XJp_check_send_cl_key (ev)
934      XKeyEvent *ev;
935 {
936   if (xjp_cur_input == NULL || xjp_cur_client == NULL)
937     return;
938   if (ifempty () || henkan_off_flag)
939     xjp_send_cl_key (ev);
940 }
941 
942 static void
xjp_save_event(ev)943 xjp_save_event (ev)
944      XKeyEvent *ev;
945 {
946   if (!xjp_cur_input)
947     return;
948   ev->window = xjp_cur_input->w;
949   bcopy ((char *) ev, (char *) &(xjp_cur_input->ev), sizeof (XKeyEvent));
950   xjp_cur_input->save_event = 1;
951 }
952 
953 void
XJp_check_save_event(ev,must)954 XJp_check_save_event (ev, must)
955      XKeyEvent *ev;
956      int must;
957 {
958   if (xjp_cur_input == NULL || xjp_cur_client == NULL)
959     return;
960   if (must || ifempty () || henkan_off_flag)
961     xjp_save_event (ev);
962 }
963 
964 void
XJp_return_cl_it()965 XJp_return_cl_it ()
966 {
967 #ifdef  XJPLIB_DIRECT
968   if (xjp_cur_client && xjp_cur_client->direct_fd != -1)
969     {
970       XJp_direct_send_cl_key ();
971       return;
972     }
973 #endif /* XJPLIB_DIRECT */
974   if (!xjp_cur_input || !xjp_cur_input->save_event)
975     return;
976   xjp_send_cl_key (&(xjp_cur_input->ev));
977   xjp_cur_input->save_event = 0;
978 }
979 
980 static void
xjp_send_buf(ptr,len,cs)981 xjp_send_buf (ptr, len, cs)
982      register unsigned char *ptr;
983      int len;
984      int cs;
985 {
986   XEvent ev;
987   register int i;
988 
989   ev.type = ClientMessage;
990   ev.xclient.format = 8;
991   ev.xclient.message_type = xjp_select_id;
992   ev.xclient.window = xjp_cur_input->w;
993   bcopy (xjp_cur_client->escape[cs], ev.xclient.data.b, 2);
994   while (len > 0)
995     {
996       for (i = 4; i < 4 + len && i < 20; i++, ptr++)
997         {
998           ev.xclient.data.b[i] = *ptr;
999         }
1000       ev.xclient.data.b[3] = (char) (i - 4);
1001       XSendEvent (dpy, xjp_cur_input->w, False, NoEventMask, &ev);
1002       len -= 16;
1003     }
1004 }
1005 
1006 void
XJp_xw_write(w_buf,size)1007 XJp_xw_write (w_buf, size)
1008      register w_char *w_buf;
1009      register int size;
1010 {
1011   unsigned char *ptr, *send_ptr, *save_ptr, buf[512], send_buf[512];
1012   int len, send_len = 0;
1013   int cs = 0;
1014 
1015   if (henkan_off_flag)
1016     {
1017       XJp_return_cl_it ();
1018       return;
1019     }
1020 
1021   if ((len = w_char_to_char (w_buf, buf, size)) <= 0)
1022     return;
1023   buf[len] = '\0';
1024 
1025 #ifdef  XJPLIB_DIRECT
1026   if (xjp_cur_client->direct_fd != -1)
1027     {
1028       XJp_return_sock ((short) 0, (short) len, 0, (KeySym) 0, buf);
1029       return;
1030     }
1031 #endif /* XJPLIB_DIRECT */
1032 
1033   for (ptr = buf, send_ptr = save_ptr = send_buf; *ptr;)
1034     {
1035       if (*ptr >= 0xa1 && *ptr <= 0xfe)
1036         {
1037           if (cs != 1 && send_len > 0)
1038             {
1039               xjp_send_buf (save_ptr, send_len, cs);
1040               save_ptr = send_ptr;
1041               send_len = 0;
1042             }
1043           *send_ptr++ = *ptr++ & 0x7f;
1044           *send_ptr++ = *ptr++ & 0x7f;
1045           cs = 1;
1046           send_len += 2;
1047         }
1048       else if (*ptr == SS2)
1049         {
1050           if (cs != 2 && send_len > 0)
1051             {
1052               xjp_send_buf (save_ptr, send_len, cs);
1053               save_ptr = send_ptr;
1054               send_len = 0;
1055             }
1056           ptr++;
1057           *send_ptr++ = *ptr++ &= 0x7f;
1058           cs = 2;
1059           send_len += 1;
1060         }
1061       else if (*ptr == SS3)
1062         {
1063           if (cs != 3 && send_len > 0)
1064             {
1065               xjp_send_buf (save_ptr, send_len, cs);
1066               save_ptr = send_ptr;
1067               send_len = 0;
1068             }
1069           ptr++;
1070           *send_ptr++ = *ptr++ &= 0x7f;
1071           *send_ptr++ = *ptr++ &= 0x7f;
1072           cs = 2;
1073           send_len += 2;
1074         }
1075       else
1076         {
1077           if (*ptr == 0xd || *ptr == 0xa)
1078             {
1079               if (send_len > 0)
1080                 {
1081                   xjp_send_buf (save_ptr, send_len, cs);
1082                   save_ptr = send_ptr;
1083                   send_len = 0;
1084                 }
1085               XJp_return_cl_it ();
1086               ptr++;
1087             }
1088           else
1089             {
1090               if (cs != 0 && send_len > 0)
1091                 {
1092                   xjp_send_buf (save_ptr, send_len, cs);
1093                   save_ptr = send_ptr;
1094                   send_len = 0;
1095                 }
1096               *send_ptr++ = *ptr++;
1097               cs = 0;
1098               send_len += 1;
1099             }
1100         }
1101     }
1102   xjp_send_buf (save_ptr, send_len, cs);
1103 }
1104 
1105 int
XJp_xw_destroy(ev)1106 XJp_xw_destroy (ev)
1107      register XDestroyWindowEvent *ev;
1108 {
1109   Window client_window = ev->window;
1110   XJpClientRec *p, **prev_p;
1111   XJpInputRec *i, **prev_i;
1112 
1113   for (prev_p = &xjp_clients; p = *prev_p; prev_p = &p->next)
1114     {
1115       if (client_window == p->w)
1116         {
1117           if (p == xjp_cur_client)
1118             {
1119               xjp_cur_client = NULL;
1120               xjp_cur_input = NULL;
1121             }
1122           destroy_client (p->xim_client);
1123           for (prev_i = &xjp_inputs; i = *prev_i;)
1124             {
1125               if (i->pclient == p)
1126                 {
1127                   XSelectInput (dpy, i->w, NoEventMask);
1128                   *prev_i = i->next;
1129                   Free ((char *) i);
1130                 }
1131               else
1132                 {
1133                   prev_i = &i->next;
1134                 }
1135             }
1136           XSelectInput (dpy, p->w, NoEventMask);
1137           *prev_p = p->next;
1138           Free ((char *) p);
1139           return (1);
1140         }
1141     }
1142   return (0);
1143 }
1144 
1145 int
XJp_check_map(xc)1146 XJp_check_map (xc)
1147      register XIMClientRec *xc;
1148 {
1149   register XJpInputRec *i;
1150 
1151   for (i = xjp_inputs; i != NULL; i = i->next)
1152     {
1153       if (i->pclient && i->pclient->xim_client == xc)
1154         return (1);
1155     }
1156   return (0);
1157 }
1158 
1159 int
XJp_get_client_cnt()1160 XJp_get_client_cnt ()
1161 {
1162   register XJpClientRec *p;
1163   register int i;
1164 
1165   for (i = 0, p = xjp_clients; p; p = p->next)
1166     i++;
1167   return (i);
1168 }
1169 #endif
1170