1 /*
2  * $Id: do_xjutil.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 /*      Version 4.0
38  */
39 #ifdef  USING_XJUTIL
40 
41 #include <stdio.h>
42 #include <sys/wait.h>
43 #include <signal.h>
44 #include <X11/Xos.h>
45 #include "config.h"
46 #include "commonhd.h"
47 #include "sdefine.h"
48 #include "xim.h"
49 #include "sheader.h"
50 #include "proto.h"
51 #include "ext.h"
52 
53 #define ROOT_WINDOW     (xim->root_pointer[xim->default_screen]->root_window)
54 static int seq_xjutil_fs_id = 0;
55 
56 static XIMLangDataBase *
set_xjutil(prop_name)57 set_xjutil (prop_name)
58      char *prop_name;
59 {
60   register int i, nbytes;
61   register unsigned char *p;
62   register Xjutil_startRec *xj;
63   XFontStruct **font_struct_list;
64   char **font_name_list;
65   int num;
66   Atom id;
67   register XIMLangRec *xl = cur_p->cur_xl;
68   Xjutil_startRec xjutil_start;
69   XIMLangDataBase *ld;
70   WnnEnv *we;
71   unsigned char tmp_buf[256];
72 
73   if (!(ld = xl->lang_db) || (ld->xjutil_pid))
74     return (NULL);
75 
76   xj = &xjutil_start;
77   if (uumkeyname && *uumkeyname)
78     strcpy (xj->uumkey_name, uumkeyname);
79   else
80     xj->uumkey_name[0] = '\0';
81   if (ld->rkfile_name && *ld->rkfile_name)
82     strcpy (xj->rkfile_name, ld->rkfile_name);
83   else
84     xj->rkfile_name[0] = '\0';
85   if (cvt_key_file && *cvt_key_file)
86     strcpy (xj->cvtkey_name, cvt_key_file);
87   else
88     xj->cvtfun_name[0] = '\0';
89   if (cvt_fun_file && *cvt_fun_file)
90     strcpy (xj->cvtfun_name, cvt_fun_file);
91   else
92     xj->cvtfun_name[0] = '\0';
93   if (cvt_meta_file && *cvt_meta_file)
94     strcpy (xj->cvtmeta_name, cvt_meta_file);
95   else
96     xj->cvtmeta_name[0] = '\0';
97   if (username && *username)
98     strcpy (xj->user_name, username);
99   else
100     xj->user_name[0] = '\0';
101   if (ld->lang && *ld->lang)
102     strcpy (xj->lang, ld->lang);
103   else
104     xj->lang[0] = '\0';
105   if (ld->lc_name && *ld->lc_name)
106     strcpy (xj->lc_name, ld->lc_name);
107   else
108     xj->lc_name[0] = '\0';
109   strcpy (xj->f_name, ld->f_table->name);
110   if (ld->jishopath && *ld->jishopath)
111     strcpy (xj->jishopath, ld->jishopath);
112   else
113     xj->jishopath[0] = '\0';
114   if (ld->hindopath && *ld->hindopath)
115     strcpy (xj->hindopath, ld->hindopath);
116   else
117     xj->hindopath[0] = '\0';
118   if (ld->fuzokugopath && *ld->fuzokugopath)
119     strcpy (xj->fuzokugopath, ld->fuzokugopath);
120   else
121     xj->fuzokugopath[0] = '\0';
122   nbytes = 0;
123   num = XFontsOfFontSet (xl->pe_fs, &font_struct_list, &font_name_list);
124   for (i = 0; i < num; i++)
125     {
126       nbytes += (strlen (font_name_list[i]) + 1);
127     }
128   if (!(p = (unsigned char *) Malloc ((unsigned) (nbytes + 1))))
129     {
130       malloc_error ("allocation of work area for xjutil");
131       return (NULL);
132     }
133   p[0] = '\0';
134   for (i = 0; i < num; i++)
135     {
136       strcat ((char *) p, font_name_list[i]);
137       strcat ((char *) p, ",");
138     }
139   p[nbytes - 1] = '\0';
140   xj->fn_len = nbytes - 1;
141   xj->rubout_code = rubout_code;
142   xj->cswidth_id = ld->cswidth_id;
143 
144   if (xim->save_under)
145     {
146       xj->save_under = 1;
147     }
148   else
149     {
150       xj->save_under = 0;
151     }
152 
153   for (i = 0, we = c_c->normal_env; we; we = we->next, i++);
154   xj->max_env = i;
155   for (i = 0, we = c_c->reverse_env; we; we = we->next, i++);
156   xj->max_reverse_env = i;
157 
158   strcpy (prop_name, XJUTIL_START_PRO);
159   strcat (prop_name, ld->lang);
160   id = XInternAtom (dpy, prop_name, False);
161   XChangeProperty (dpy, ROOT_WINDOW, id, XA_STRING, 8, PropModeReplace, (unsigned char *) xj, sizeof (Xjutil_startRec));
162 
163   for (i = 0; i < xim->screen_count; i++)
164     {
165       XChangeProperty (dpy, ROOT_WINDOW, id, XA_STRING, 8, PropModeAppend, (unsigned char *) &cur_p->pe.fg, sizeof (unsigned long));
166       XChangeProperty (dpy, ROOT_WINDOW, id, XA_STRING, 8, PropModeAppend, (unsigned char *) &cur_p->pe.bg, sizeof (unsigned long));
167       XChangeProperty (dpy, ROOT_WINDOW, id, XA_STRING, 8, PropModeAppend, (unsigned char *) &cur_p->root_pointer->bw, sizeof (unsigned int));
168     }
169   for (i = 0, we = c_c->normal_env; we; we = we->next, i++)
170     {
171       tmp_buf[0] = '\0';
172       if (we->host_name)
173         strcpy ((char *) tmp_buf, we->host_name);
174       XChangeProperty (dpy, ROOT_WINDOW, id, XA_STRING, 8, PropModeAppend, tmp_buf, 256);
175       tmp_buf[0] = '\0';
176       if (we->envrc_name)
177         strcpy ((char *) tmp_buf, we->envrc_name);
178       XChangeProperty (dpy, ROOT_WINDOW, id, XA_STRING, 8, PropModeAppend, tmp_buf, 256);
179       tmp_buf[0] = '\0';
180       strcpy ((char *) tmp_buf, we->env_name_str);
181       XChangeProperty (dpy, ROOT_WINDOW, id, XA_STRING, 8, PropModeAppend, tmp_buf, 32);
182     }
183   for (i = 0, we = c_c->reverse_env; we; we = we->next, i++)
184     {
185       tmp_buf[0] = '\0';
186       if (we->host_name)
187         strcpy ((char *) tmp_buf, we->host_name);
188       XChangeProperty (dpy, ROOT_WINDOW, id, XA_STRING, 8, PropModeAppend, tmp_buf, 256);
189       tmp_buf[0] = '\0';
190       if (we->envrc_name)
191         strcpy ((char *) tmp_buf, we->envrc_name);
192       XChangeProperty (dpy, ROOT_WINDOW, id, XA_STRING, 8, PropModeAppend, tmp_buf, 256);
193       tmp_buf[0] = '\0';
194       strcpy ((char *) tmp_buf, we->env_name_str);
195       XChangeProperty (dpy, ROOT_WINDOW, id, XA_STRING, 8, PropModeAppend, tmp_buf, 32);
196     }
197   XChangeProperty (dpy, ROOT_WINDOW, id, XA_STRING, 8, PropModeAppend, p, strlen ((char *) p));
198   XSetSelectionOwner (dpy, id, xim->root_pointer[xim->default_screen]->ximclient->w, 0L);
199   XFlush (dpy);
200   Free (p);
201   return (ld);
202 }
203 
204 #ifndef NOTFORK_XJUTIL
205 static void
kill_old_xjutil()206 kill_old_xjutil ()
207 {
208   char tmp_buf[256];
209   XIMLangDataBase *ld;
210   XEvent event;
211   Window w;
212   Atom ret;
213 
214   for (ld = language_db; ld != NULL; ld = ld->next)
215     {
216       strcpy (tmp_buf, XJUTIL_START_PRO);
217       strcat (tmp_buf, ld->lang);
218       strcat (tmp_buf, "_OK");
219       if (ret = XInternAtom (dpy, tmp_buf, True))
220         {
221           if (w = XGetSelectionOwner (dpy, ret))
222             {
223               event.type = ClientMessage;
224               event.xclient.format = 32;
225               event.xclient.window = w;
226               event.xclient.data.l[0] = DIC_KILL;
227               XSendEvent (dpy, w, False, NoEventMask, &event);
228               XFlush (dpy);
229             }
230         }
231     }
232 }
233 
234 static void
exec_xjutil(prop_name,counter)235 exec_xjutil (prop_name, counter)
236      char *prop_name;
237      int counter;
238 {
239   char tmp[2];
240   unsigned char *p, tmp_buf[256];
241 
242   tmp[0] = (char) counter;
243   tmp[1] = '\0';
244   if (xjutil_name == NULL)
245     {
246       strcpy ((char *) tmp_buf, XJUTILBINDIR);
247       strcat ((char *) tmp_buf, "/");
248       strcat ((char *) tmp_buf, XJUTIL_NAME);
249       p = tmp_buf;
250     }
251   else
252     {
253       p = (unsigned char *) xjutil_name;
254     }
255   execlp ((char *) p, (char *) p, DisplayString (dpy), prop_name, tmp, 0);
256 }
257 
258 static void
catch_sigchld()259 catch_sigchld ()
260 {
261   XIMLangDataBase *ld;
262 #ifdef SYSVR2
263   int status;
264 #else
265   union wait status;
266 #endif
267   int pid;
268 
269 #ifdef SYSVR2
270   pid = wait (&status);
271 #else
272   pid = wait3 (&status, WNOHANG, 0);
273 #endif
274   for (ld = language_db; ld != NULL; ld = ld->next)
275     {
276       if (ld->xjutil_pid == pid)
277         {
278           ld->xjutil_id = 0;
279           ld->xjutil_pid = 0;
280           return;
281         }
282     }
283   return;
284 }
285 #endif /* !NOTFORK_XJUTIL */
286 
287 void
xjutil_start()288 xjutil_start ()
289 {
290   char prop_name[32];
291   static int counter = 1;
292   XIMLangDataBase *ld;
293 
294   if (!(ld = set_xjutil (prop_name)))
295     {
296       print_out ("Could not exec xjutil");
297       return;
298     }
299   ld->xjutil_act = counter++;
300 #ifndef NOTFORK_XJUTIL
301   signal (SIGCHLD, catch_sigchld);
302   if ((ld->xjutil_pid = fork ()) == 0)
303     {
304       close (ConnectionNumber (dpy));
305       exec_xjutil (prop_name, ld->xjutil_act);
306       print_out ("Could not execute xjutil");
307       exit (1);
308     }
309 #endif /* NOTFORK_XJUTIL */
310 }
311 
312 void
kill_xjutil(ld)313 kill_xjutil (ld)
314      XIMLangDataBase *ld;
315 {
316   extern int kill ();
317 
318   if (ld->xjutil_pid > 0)
319     {
320       kill (ld->xjutil_pid, SIGTERM);
321       ld->xjutil_act = 0;
322       ld->xjutil_id = 0;
323       ld->xjutil_pid = 0;
324     }
325 }
326 
327 void
kill_all_xjutil()328 kill_all_xjutil ()
329 {
330   XIMLangDataBase *ld;
331 
332   for (ld = language_db; ld; ld = ld->next)
333     {
334       if (ld->xjutil_pid > 0)
335         {
336           kill_xjutil (ld);
337         }
338     }
339   return;
340 }
341 
342 static void
send_xjutil_event(id)343 send_xjutil_event (id)
344      int id;
345 {
346   XEvent event;
347 
348   event.type = ClientMessage;
349   event.xclient.format = 32;
350   event.xclient.window = xim->root_pointer[xim->default_screen]->ximclient->w;
351   event.xclient.data.l[0] = id;
352   XSendEvent (dpy, cur_p->cur_xl->lang_db->xjutil_id, False, NoEventMask, &event);
353   XFlush (dpy);
354   return;
355 }
356 
357 static int
check_cur_xjutil()358 check_cur_xjutil ()
359 {
360   register XIMLangRec *xl = cur_p->cur_xl;
361 
362   if (xl->lang_db->xjutil_id == 0 || xl->lang_db->xjutil_use)
363     return (-1);
364   xl->working_xjutil = 1;
365   xl->lang_db->xjutil_use = cur_p;
366   return (0);
367 }
368 
369 void
xjutil_send_key_event(ev)370 xjutil_send_key_event (ev)
371      XKeyEvent *ev;
372 {
373   XSendEvent (dpy, cur_p->cur_xl->lang_db->xjutil_id, False, NoEventMask, (XEvent *) ev);
374   XFlush (dpy);
375   return;
376 }
377 
378 void
set_xjutil_id(w,act,error)379 set_xjutil_id (w, act, error)
380      Window w;
381      int act;
382      char error;
383 {
384   XIMLangDataBase *ld;
385 
386   for (ld = language_db; ld != NULL; ld = ld->next)
387     {
388       if (ld->xjutil_act == act)
389         {
390           if (error)
391             {
392               ld->xjutil_id = 0;
393               ld->xjutil_pid = 0;
394             }
395           else
396             {
397               ld->xjutil_id = w;
398               XSelectInput (dpy, w, StructureNotifyMask);
399             }
400           return;
401         }
402     }
403   return;
404 }
405 
406 void
reset_xjutil_fs_id(id,act)407 reset_xjutil_fs_id (id, act)
408      int id;
409      int act;
410 {
411   register int i;
412   XIMLangDataBase *ld;
413   XIMClientList xc = ximclient_list;
414   XIMLangRec **xl;
415 
416   for (ld = language_db; ld; ld = ld->next)
417     {
418       if (ld->xjutil_act == act)
419         break;
420     }
421   if (ld == NULL)
422     return;
423   for (; xc != NULL; xc = xc->next)
424     {
425       for (i = 0, xl = xc->xl; i < xc->lang_num; i++)
426         {
427           if ((xl[i]->lang_db == ld) && (xl[i]->xjutil_fs_id == id))
428             {
429               xl[i]->xjutil_fs_id = -1;
430               return;
431             }
432         }
433     }
434   return;
435 }
436 
437 int
isstart_xjutil(lang)438 isstart_xjutil (lang)
439      char *lang;
440 {
441   Atom ret;
442   char tmp[64];
443 
444   strcpy (tmp, XJUTIL_START_PRO);
445   strcat (tmp, lang);
446   strcat (tmp, "_OK");
447   if (ret = XInternAtom (dpy, tmp, True))
448     {
449       if (XGetSelectionOwner (dpy, ret))
450         {
451           return (1);
452         }
453     }
454   return (0);
455 }
456 
457 void
end_xjutil_work(act)458 end_xjutil_work (act)
459      int act;
460 {
461   register XIMLangDataBase *ld;
462 
463   for (ld = language_db; ld; ld = ld->next)
464     {
465       if (ld->xjutil_act == act)
466         {
467           if (ld->xjutil_use)
468             {
469               ld->xjutil_use->cur_xl->working_xjutil = 0;
470               ld->xjutil_use = NULL;
471             }
472           break;
473         }
474     }
475 }
476 
477 int
xjutil_destroy(ev)478 xjutil_destroy (ev)
479      register XDestroyWindowEvent *ev;
480 {
481   Window window = ev->window;
482   register XIMClientList xc;
483   register XIMLangDataBase *ld;
484   register int i;
485 
486   for (ld = language_db; ld; ld = ld->next)
487     {
488       if (ld->xjutil_id == window)
489         break;
490     }
491   if (!ld)
492     return (0);
493   ld->xjutil_id = (Window) 0;
494   ld->xjutil_pid = 0;
495   ld->xjutil_use = NULL;
496   XSelectInput (dpy, window, NoEventMask);
497   for (xc = ximclient_list; xc; xc = xc->next)
498     {
499       for (i = 0; i < xc->lang_num; i++)
500         {
501           if (xc->xl[i]->lang_db == ld)
502             {
503               xc->xl[i]->xjutil_fs_id = -1;
504               xc->xl[i]->working_xjutil = 0;
505             }
506         }
507     }
508   return (1);
509 }
510 
511 static Atom
set_uum_env()512 set_uum_env ()
513 {
514   Atom id;
515   Xjutil_envRec xjutil_env;
516   register int i, nbytes = 0;
517   register unsigned char *p = NULL;
518   XFontStruct **font_struct_list;
519   char **font_name_list;
520   int num;
521   WnnEnv *we;
522   char prop_name[32];
523 
524   strcpy (prop_name, XJUTIL_ENV_PRO);
525   strcat (prop_name, cur_p->cur_xl->lang_db->lang);
526   if ((id = XInternAtom (dpy, prop_name, True)) == 0)
527     {
528       id = XInternAtom (dpy, prop_name, False);
529     }
530   xjutil_env.screen = cur_p->root_pointer->screen;
531   if (cur_p->cur_xl->xjutil_fs_id == -1)
532     {
533       nbytes = 0;
534       num = XFontsOfFontSet (cur_p->cur_xl->pe_fs, &font_struct_list, &font_name_list);
535       for (i = 0; i < num; i++)
536         {
537           nbytes += (strlen (font_name_list[i]) + 1);
538         }
539       if (!(p = (unsigned char *) Malloc ((unsigned) (nbytes + 1))))
540         {
541           malloc_error ("Allocation of work area for xjutil");
542           return ((Atom) 0);
543         }
544       p[0] = '\0';
545       for (i = 0; i < num; i++)
546         {
547           strcat ((char *) p, font_name_list[i]);
548           strcat ((char *) p, ",");
549         }
550       p[nbytes - 1] = '\0';
551       xjutil_env.fs_id = cur_p->cur_xl->xjutil_fs_id = seq_xjutil_fs_id++;
552       xjutil_env.fn_len = nbytes - 1;
553     }
554   else
555     {
556       xjutil_env.fs_id = cur_p->cur_xl->xjutil_fs_id;
557       xjutil_env.fn_len = 0;
558     }
559   xjutil_env.fore_ground = cur_p->pe.fg;
560   xjutil_env.back_ground = cur_p->pe.bg;
561   xjutil_env.cur_env_id = -1;
562   xjutil_env.cur_env_reverse_id = -1;
563   if (c_c->cur_normal_env && c_c->cur_normal_env->env)
564     xjutil_env.cur_env_id = c_c->cur_normal_env->env->env_id;
565   if (c_c->cur_reverse_env && c_c->cur_reverse_env->env)
566     xjutil_env.cur_env_reverse_id = c_c->cur_reverse_env->env->env_id;
567   for (i = 0, we = c_c->normal_env; we; we = we->next, i++)
568     {
569       if (we->env)
570         xjutil_env.env_id[i] = we->env->env_id;
571       else
572         xjutil_env.env_id[i] = -1;
573     }
574   for (i = 0, we = c_c->reverse_env; we; we = we->next, i++)
575     {
576       if (we->env)
577         xjutil_env.env_reverse_id[i] = we->env->env_id;
578       else
579         xjutil_env.env_reverse_id[i] = -1;
580     }
581   if (c_c->cur_reverse_env && jl_env_get (bun_data_) == c_c->cur_reverse_env->env)
582     xjutil_env.env_is_reverse = 1;
583   else
584     xjutil_env.env_is_reverse = 0;
585   strcpy (xjutil_env.lc_name, cur_lang->lc_name);
586   xjutil_env.cswidth_id = cur_lang->cswidth_id;
587   XChangeProperty (dpy, ROOT_WINDOW, id, XA_STRING, 8, PropModeReplace, (unsigned char *) &xjutil_env, sizeof (Xjutil_envRec));
588   if (nbytes > 0)
589     {
590       XChangeProperty (dpy, ROOT_WINDOW, id, XA_STRING, 8, PropModeAppend, p, strlen ((char *) p));
591       Free (p);
592     }
593   XFlush (dpy);
594   return (id);
595 }
596 
597 static void
set_uum_touroku(start)598 set_uum_touroku (start)
599      int start;
600 {
601   Atom id;
602 
603   if ((id = set_uum_env ()) == 0)
604     return;
605   XChangeProperty (dpy, ROOT_WINDOW, id, XA_STRING, 8, PropModeAppend, (unsigned char *) &start, sizeof (int));
606   XChangeProperty (dpy, ROOT_WINDOW, id, XA_STRING, 8, PropModeAppend, (unsigned char *) c_b->buffer, Strlen (c_b->buffer) * 2);
607   XFlush (dpy);
608 }
609 
610 void
xw_jishoadd()611 xw_jishoadd ()
612 {
613   if (check_cur_xjutil ())
614     return;
615   if (set_uum_env () == 0)
616     return;
617   send_xjutil_event (DIC_ADD);
618 }
619 
620 void
xw_kensaku()621 xw_kensaku ()
622 {
623   if (check_cur_xjutil ())
624     return;
625   if (set_uum_env () == 0)
626     return;
627   send_xjutil_event (DIC_KENSAKU);
628 }
629 
630 void
xw_select_one_dict9()631 xw_select_one_dict9 ()
632 {
633   if (check_cur_xjutil ())
634     return;
635   if (set_uum_env () == 0)
636     return;
637   send_xjutil_event (DIC_ICHIRAN);
638 }
639 
640 void
xw_paramchg()641 xw_paramchg ()
642 {
643   if (check_cur_xjutil ())
644     return;
645   if (set_uum_env () == 0)
646     return;
647   send_xjutil_event (DIC_PARAM);
648 }
649 
650 void
xw_dicinfoout()651 xw_dicinfoout ()
652 {
653   if (check_cur_xjutil ())
654     return;
655   if (set_uum_env () == 0)
656     return;
657   send_xjutil_event (DIC_INFO);
658 }
659 
660 void
xw_fuzoku_set()661 xw_fuzoku_set ()
662 {
663   if (check_cur_xjutil ())
664     return;
665   if (set_uum_env () == 0)
666     return;
667   send_xjutil_event (DIC_FZK);
668 }
669 
670 void
xw_touroku(s)671 xw_touroku (s)
672      int s;
673 {
674   if (check_cur_xjutil ())
675     return;
676   set_uum_touroku (s);
677   send_xjutil_event (DIC_TOUROKU);
678 }
679 
680 void
call_kill_old_xjutil()681 call_kill_old_xjutil ()
682 {
683 #ifndef NOTFORK_XJUTIL
684   kill_old_xjutil ();
685 #endif /* !NOTFORK_XJUTIL */
686 }
687 
688 #endif /* USING_XJUTIL */
689