1 /*
2 * $Id: do_xjpdrct.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 #if defined(XJPLIB) && defined(XJPLIB_DIRECT)
39
40 #include <stdio.h>
41 #include <X11/Xlib.h>
42 #ifdef X11R4
43 #define NEED_EVENTS 1
44 #include <X11/Xlibos.h>
45 #else /* X11R4 */
46 #include "Xlibnet.h"
47
48 #ifndef X11R5
49 /* followings were included in Xlibnet.h, but none in X11R6 */
50 #include <netinet/in.h>
51 #include <sys/ioctl.h>
52 #include <netdb.h>
53 /* end */
54 #endif /* !X11R5 */
55
56 #endif /* X11R4 */
57 #include <X11/Xos.h>
58 #if defined(TCPCONN) || defined(UNIXCONN)
59 #include <sys/socket.h>
60 #endif /* defined(TCPCONN) || defined(UNIXCONN) */
61 #ifdef TCPCONN
62 #define XJP_PORT_IN 0x9494
63 #endif /* TCPCONN */
64
65 #ifdef UNIXCONN
66 #include <sys/un.h>
67 #ifndef XJP_UNIX_PATH
68 #define XJP_UNIX_PATH "/tmp/xwnmo.V2"
69 #endif /* XJP_UNIX_PATH */
70 #endif /* UNIXCONN */
71
72 #include "do_xjplib.h"
73
74 #define XJP_UNIX_ACPT 3
75 #define XJP_INET_ACPT 4
76
77 extern XIMCmblk accept_blk[];
78 extern XIMCmblk *cblk;
79 extern XIMCmblk *cur_cblk;
80
81 extern int *all_socks;
82 extern int *ready_socks;
83
84 extern int max_client;
85 extern int cur_sock;
86
87 #define BINTSIZE (sizeof(int)*8)
88 #define sock_set(array,pos) (array[pos/BINTSIZE] |= (1<<(pos%BINTSIZE)))
89 #define sock_clr(array,pos) (array[pos/BINTSIZE] &= ~(1<<(pos%BINTSIZE)))
90 #define sock_tst(array,pos) (array[pos/BINTSIZE] & (1<<(pos%BINTSIZE)))
91
92 extern XJpClientRec *xjp_clients;
93 extern XJpClientRec *xjp_cur_client;
94 extern XJpInputRec *xjp_inputs;
95 extern XJpInputRec *xjp_cur_input;
96
97 static int need_write = 0;
98
99 static int real_port = 0;
100
101 int
XJp_get_xjp_port()102 XJp_get_xjp_port ()
103 {
104 return (real_port);
105 }
106
107 static void
xjp_init_net_area()108 xjp_init_net_area ()
109 {
110 #ifdef UNIXCONN
111 accept_blk[XJP_UNIX_ACPT].sd = -1;
112 #endif /* UNIXCONN */
113 #ifdef TCPCONN
114 accept_blk[XJP_INET_ACPT].sd = -1;
115 #endif /* TCPCONN */
116 }
117
118 #ifdef UNIXCONN
119 static int
xjp_init_net_un()120 xjp_init_net_un ()
121 {
122 int so;
123 struct sockaddr_un saddr_un;
124 extern int unlink (), socket (), bind (), shutdown (), listen ();
125
126 unlink (XJP_UNIX_PATH);
127 saddr_un.sun_family = AF_UNIX;
128 strcpy (saddr_un.sun_path, XJP_UNIX_PATH);
129
130 if ((so = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
131 {
132 return (-1);
133 }
134 if (bind (so, (struct sockaddr *) &saddr_un, strlen (saddr_un.sun_path) + 2) < 0)
135 {
136 shutdown (so, 2);
137 return (-1);
138 }
139 if (listen (so, 5) < 0)
140 {
141 shutdown (so, 2);
142 return (-1);
143 }
144 accept_blk[XJP_UNIX_ACPT].sd = so;
145 sock_set (all_socks, so);
146 return (0);
147 }
148 #endif /* UNIXCONN */
149
150 #ifdef TCPCONN
151 static int
xjp_init_net_in()152 xjp_init_net_in ()
153 {
154 int so;
155 struct servent *sp;
156 struct sockaddr_in saddr_in;
157 unsigned short port;
158 #ifndef SOLARIS
159 int on = 1;
160 #else /* SOLARIS */
161 int on = 0;
162 #endif /* SOLARIS */
163 int i, ok = 0;
164 extern int setsockopt ();
165
166 if ((sp = getservbyname ("xwnmo", "tcp")) == NULL)
167 {
168 real_port = port = XJP_PORT_IN;
169 }
170 else
171 {
172 real_port = port = ntohs (sp->s_port);
173 }
174 saddr_in.sin_family = AF_INET;
175 saddr_in.sin_port = htons (port);
176 saddr_in.sin_addr.s_addr = htonl (INADDR_ANY);
177
178 for (i = 0; i < MAX_PORT_NUMBER; i++)
179 {
180 if ((so = socket (AF_INET, SOCK_STREAM, 0)) < 0)
181 {
182 return (-1);
183 }
184 setsockopt (so, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (int));
185 if (bind (so, (struct sockaddr *) &saddr_in, sizeof (struct sockaddr_in)) == 0)
186 {
187 ok = 1;
188 break;
189 }
190 shutdown (so, 2);
191 if (port == real_port)
192 port += 0x10;
193 else
194 port += 1;
195 saddr_in.sin_port = htons (port);
196 }
197 if (ok == 0)
198 {
199 return (-1);
200 }
201 real_port = port;
202 if (listen (so, 5) < 0)
203 {
204 shutdown (so, 2);
205 return (-1);
206 }
207 accept_blk[XJP_INET_ACPT].sd = so;
208 sock_set (all_socks, so);
209 return (0);
210 }
211 #endif /* TCPCONN */
212
213 void
XJp_init_net()214 XJp_init_net ()
215 {
216 xjp_init_net_area ();
217 #ifdef UNIXCONN
218 if (xjp_init_net_un () < 0)
219 {
220 print_out ("Could not open UNIX domain socket for XJp protocol.");
221 }
222 #endif /* UNIXCONN */
223 #ifdef TCPCONN
224 if (xjp_init_net_in () < 0)
225 {
226 print_out ("Could not open INET domain socket for XJp protocol.");
227 }
228 #endif /* TCPCONN */
229 }
230
231 void
XJp_close_net()232 XJp_close_net ()
233 {
234 int trueFlag = 1;
235 #ifdef UNIXCONN
236 struct sockaddr_un addr_un;
237 #endif /* UNIXCONN */
238 #ifdef TCPCONN
239 struct sockaddr_in addr_in;
240 #endif /* TCPCONN */
241 #if defined(UNIXCONN) || defined(TCPCONN)
242 int addrlen;
243 extern int accept (), close ();
244 #endif
245
246 #ifdef UNIXCONN
247 if (accept_blk[XJP_UNIX_ACPT].sd != -1)
248 {
249 #ifndef SOLARIS
250 #if defined(FIONBIO)
251 ioctl (accept_blk[XJP_UNIX_ACPT].sd, FIONBIO, &trueFlag);
252 #endif
253 #else /* !SOLARIS */
254 fcntl (accept_blk[XJP_UNIX_ACPT].sd, F_SETFL, F_UNLCK);
255 #endif /* !SOLARIS */
256 for (;;)
257 {
258 addrlen = sizeof (addr_un);
259 if (accept (accept_blk[XJP_UNIX_ACPT].sd, (struct sockaddr *) &addr_un, &addrlen) < 0)
260 break;
261 }
262 shutdown (accept_blk[XJP_UNIX_ACPT].sd, 2);
263 close (accept_blk[XJP_UNIX_ACPT].sd);
264 }
265 #endif /* UNIXCONN */
266
267 #ifdef TCPCONN
268 if (accept_blk[XJP_INET_ACPT].sd != -1)
269 {
270 #ifndef SOLARIS
271 #if defined(FIONBIO)
272 ioctl (accept_blk[XJP_INET_ACPT].sd, FIONBIO, &trueFlag);
273 #endif
274 #else /* !SOLARIS */
275 fcntl (accept_blk[XJP_INET_ACPT].sd, F_SETFL, F_UNLCK);
276 #endif /* !SOLARIS */
277 for (;;)
278 {
279 addrlen = sizeof (addr_in);
280 if (accept (accept_blk[XJP_INET_ACPT].sd, (struct sockaddr *) &addr_in, &addrlen) < 0)
281 break;
282 }
283 shutdown (accept_blk[XJP_INET_ACPT].sd, 2);
284 close (accept_blk[XJP_INET_ACPT].sd);
285 }
286 #endif /* TCPCONN */
287 }
288
289 int
XJp_return_sock(state,detail,open,keysym,string)290 XJp_return_sock (state, detail, open, keysym, string)
291 short state, detail;
292 int open;
293 KeySym keysym;
294 char *string;
295 {
296 unsigned short tmp_short;
297 unsigned long tmp_long;
298
299 tmp_short = (unsigned short) htons (state);
300 if (_WriteToClient (&tmp_short, sizeof (short)) == -1)
301 return (-1);
302 tmp_short = (unsigned short) htons (detail);
303 if (_WriteToClient (&tmp_short, sizeof (short)) == -1)
304 return (-1);
305
306 if (open == 0 && state == (short) 0)
307 {
308 tmp_long = (unsigned long) htonl (keysym);
309 if (_WriteToClient (&tmp_long, sizeof (KeySym)) == -1)
310 return (-1);
311 if (detail > (short) 0)
312 {
313 if (_WriteToClient (string, (int) detail) == -1)
314 return (-1);
315 }
316 need_write = 0;
317 }
318 if (_Send_Flush () == -1)
319 return (-1);
320 return (0);
321 }
322
323 static int
xjp_new_cl_sock(fd)324 xjp_new_cl_sock (fd)
325 int fd;
326 {
327 register XJpClientRec *xjp;
328 register XIMClientRec *xc;
329 short detail;
330 char buf[32];
331 ximICValuesReq ic_req;
332 ximICAttributesReq pre_req, st_req;
333 XCharStruct cs;
334
335 if ((_ReadFromClient (buf, 2) == -1) || (_ReadFromClient (buf, (int) buf[1]) == -1))
336 {
337 return (-1);
338 }
339 if ((xjp = (XJpClientRec *) Malloc (sizeof (XJpClientRec))) == NULL)
340 {
341 XJp_return_sock ((short) -1, (short) 7, 1, (KeySym) 0, NULL);
342 return (-1);
343 }
344 xjp->dispmode = XJP_ROOT;
345 xjp->w = 0;
346 XJp_xjp_to_xim (xjp, &ic_req, &pre_req, &st_req, &cs);
347 if ((xc = create_client (&ic_req, &pre_req, &st_req, NULL, NULL, 0, 0, NULL, NULL, NULL, &detail)) == NULL)
348 {
349 Free ((char *) xjp);
350 XJp_return_sock ((short) -1, (short) 7, 1, (KeySym) 0, NULL);
351 return (-1);
352 }
353 if (XJp_return_sock ((short) 0, (short) 0, 1, (KeySym) 0, NULL) < 0)
354 {
355 Free ((char *) xjp);
356 return (-1);
357 }
358 xc->xjp = 1;
359 xjp->xim_client = xc;
360 xjp->direct_fd = fd;
361 xjp->next = xjp_clients;
362 xjp->ref_count = 0;
363 xjp_clients = xjp;
364 return (0);
365 }
366
367 static int
xjp_new_client_acpt(fd)368 xjp_new_client_acpt (fd)
369 int fd;
370 {
371 #ifdef UNIXCONN
372 struct sockaddr_un addr_un;
373 #endif /* UNIXCONN */
374 #ifdef TCPCONN
375 struct sockaddr_in addr_in;
376 #endif /* TCPCONN */
377 #if defined(UNIXCONN) || defined(TCPCONN)
378 register int i;
379 int addrlen;
380 #endif
381
382 #ifdef UNIXCONN
383 if (accept_blk[XJP_UNIX_ACPT].sd != -1)
384 {
385 if (fd == accept_blk[XJP_UNIX_ACPT].sd)
386 {
387 for (i = 0; i < max_client; i++)
388 {
389 if (cblk[i].use == 0)
390 {
391 addrlen = sizeof (addr_un);
392 if ((cblk[i].sd = accept (fd, (struct sockaddr *) &addr_un, &addrlen)) < 0)
393 {
394 return (-1);
395 }
396 cur_cblk = &cblk[i];
397 cur_cblk->use = 1;
398 cur_cblk->xjp = 1;
399 cur_cblk->byteOrder = False;
400 cur_sock = cur_cblk->sd;
401 if (xjp_new_cl_sock (cur_sock) == 0)
402 {
403 sock_set (all_socks, cur_sock);
404 }
405 return (0);
406 }
407 }
408 }
409 }
410 #endif /* UNIXCONN */
411 #ifdef TCPCONN
412 if (fd == accept_blk[XJP_INET_ACPT].sd)
413 {
414 for (i = 0; i < max_client; i++)
415 {
416 if (cblk[i].use == 0)
417 {
418 addrlen = sizeof (addr_in);
419 if ((cblk[i].sd = accept (fd, (struct sockaddr *) &addr_in, &addrlen)) < 0)
420 {
421 return (-1);
422 }
423 cur_cblk = &cblk[i];
424 cur_cblk->use = 1;
425 cur_cblk->xjp = 1;
426 cur_cblk->byteOrder = False;
427 cur_sock = cur_cblk->sd;
428 if (xjp_new_cl_sock (cur_sock) == 0)
429 {
430 sock_set (all_socks, cur_sock);
431 }
432 break;
433 }
434 }
435 }
436 #endif /* TCPCONN */
437 return (0);
438 }
439
440 int
XJp_wait_for_socket()441 XJp_wait_for_socket ()
442 {
443 #ifdef UNIXCONN
444 if (accept_blk[XJP_UNIX_ACPT].sd != -1)
445 {
446 if (sock_tst (ready_socks, accept_blk[XJP_UNIX_ACPT].sd))
447 {
448 sock_clr (ready_socks, accept_blk[XJP_UNIX_ACPT].sd);
449 cur_cblk = NULL;
450 cur_sock = -1;
451 xjp_new_client_acpt (accept_blk[XJP_UNIX_ACPT].sd);
452 return (XJP_DIRECT_TYPE);
453 }
454 }
455 #endif /* UNIXCONN */
456 #ifdef TCPCONN
457 if (accept_blk[XJP_INET_ACPT].sd != -1)
458 {
459 if (sock_tst (ready_socks, accept_blk[XJP_INET_ACPT].sd))
460 {
461 sock_clr (ready_socks, accept_blk[XJP_INET_ACPT].sd);
462 cur_cblk = NULL;
463 cur_sock = -1;
464 xjp_new_client_acpt (accept_blk[XJP_INET_ACPT].sd);
465 return (XJP_DIRECT_TYPE);
466 }
467 }
468 #endif /* TCPCONN */
469 return (0);
470 }
471
472 void
XJp_destroy_for_sock(fd)473 XJp_destroy_for_sock (fd)
474 int fd;
475 {
476 XJpClientRec *p, **prev_p;
477 XJpInputRec *i, **prev_i;
478
479 for (prev_p = &xjp_clients; p = *prev_p; prev_p = &p->next)
480 {
481 if (p->direct_fd != -1 && p->direct_fd == fd)
482 {
483 if (p == xjp_cur_client)
484 {
485 xjp_cur_client = NULL;
486 xjp_cur_input = NULL;
487 }
488 destroy_client (p->xim_client);
489 for (prev_i = &xjp_inputs; i = *prev_i;)
490 {
491 if (i->pclient == p)
492 {
493 *prev_i = i->next;
494 Free ((char *) i);
495 }
496 else
497 {
498 prev_i = &i->next;
499 }
500 }
501 *prev_p = p->next;
502 Free ((char *) p);
503 return;
504 }
505 }
506 }
507
508 static void
xjp_buffer_to_xevent(buf,ev)509 xjp_buffer_to_xevent (buf, ev)
510 char *buf;
511 XEvent *ev;
512 {
513 ev->xkey.display = dpy;
514 ev->xkey.type = (int) buf[0];
515 ev->xkey.state = (unsigned int) buf[1];
516 ev->xkey.serial = (unsigned long) ntohs (*(short *) (buf + 2));
517 ev->xkey.time = (Time) ntohl (*(Time *) (buf + 4));
518 ev->xkey.root = (Window) ntohl (*(Window *) (buf + 8));
519 ev->xkey.window = (Window) ntohl (*(Window *) (buf + 12));
520 ev->xkey.subwindow = (Window) ntohl (*(Window *) (buf + 16));
521 ev->xkey.x_root = (int) ntohs (*(short *) (buf + 20));
522 ev->xkey.y_root = (int) ntohs (*(short *) (buf + 22));
523 ev->xkey.x = (int) ntohs (*(short *) (buf + 24));
524 ev->xkey.y = (int) ntohs (*(short *) (buf + 26));
525 ev->xkey.keycode = (unsigned int) ntohs (*(short *) (buf + 28));
526 ev->xkey.same_screen = (Bool) buf[30];
527 }
528
529 static int
xjp_get_event(ev)530 xjp_get_event (ev)
531 XEvent *ev;
532 {
533 char readbuf[64];
534 register XJpClientRec *p;
535 register XJpInputRec *i;
536
537 if (_ReadFromClient (readbuf, 32) == -1)
538 {
539 return (-1);
540 }
541 xjp_buffer_to_xevent (readbuf, ev);
542 for (p = xjp_clients; p; p = p->next)
543 {
544 if (p->direct_fd != -1 && p->direct_fd == cur_sock)
545 {
546 if (p->w == (Window) 0)
547 {
548 p->w = ev->xkey.window;
549 }
550 for (i = xjp_inputs; i; i = i->next)
551 {
552 if (i->pclient == p && i->w == ev->xkey.window)
553 return (0);
554 }
555 if ((i = (XJpInputRec *) Malloc (sizeof (XJpInputRec))) == NULL)
556 {
557 malloc_error ("allocation of Focus data struct(XJp)");
558 return (-1);
559 }
560 i->w = ev->xkey.window;
561 i->pclient = p;
562 i->save_event = 0;
563 i->next = xjp_inputs;
564 xjp_inputs = i;
565 return (0);
566 }
567 }
568 return (-1);
569 }
570
571 void
XJp_Direct_Dispatch()572 XJp_Direct_Dispatch ()
573 {
574 XEvent ev;
575 int buff[32], in;
576 int ret, i, n_bytes;
577
578 if (xjp_get_event (&ev) == -1)
579 return;
580 ret = key_input (buff, &ev);
581 for (i = 0; i < ret;)
582 {
583 n_bytes = get_cswidth_by_char (in = buff[i++]);
584 for (; n_bytes > 1 && i < ret; n_bytes--, i++)
585 {
586 in = (in << 8) + buff[i];
587 }
588 in_put (in);
589 }
590 if (need_write)
591 {
592 XJp_return_sock ((short) 0, (short) 0, 0, (KeySym) 0, NULL);
593 }
594 return;
595 }
596
597 static KeySym save_sock_keysym = (KeySym) 0;
598 static unsigned char save_sock_str[32];
599 static unsigned int save_sock_str_len = 0;
600
601 void
XJp_save_sockbuf(len,str,keysym)602 XJp_save_sockbuf (len, str, keysym)
603 int len;
604 unsigned char *str;
605 KeySym keysym;
606 {
607 if (xjp_cur_client && xjp_cur_client->direct_fd != -1)
608 {
609 need_write = 1;
610 save_sock_keysym = keysym;
611 save_sock_str_len = len;
612 if (len > 0)
613 {
614 bcopy (str, save_sock_str, len);
615 }
616 }
617 }
618
619 void
XJp_direct_send_cl_key()620 XJp_direct_send_cl_key ()
621 {
622 XJp_return_sock ((short) 0, (short) save_sock_str_len, 0, save_sock_keysym, save_sock_str);
623 }
624
625 #endif /* defined(XJPLIB) && defined(XJPLIB_DIRECT) */
626