0
|
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
|
|
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
|
|
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
|
|
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
|
|
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 *
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 *
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|