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