Mercurial > kinput2.yaz
comparison lib/imlib/imxport.c @ 0:92745d501b9a
initial import from kinput2-v3.1
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Mon, 08 Mar 2010 04:44:30 +0900 |
parents | |
children | 598fcbe482b5 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:92745d501b9a |
---|---|
1 #ifndef lint | |
2 static char *rcsid = "$Id: imxport.c,v 1.11 1999/05/04 05:44:11 ishisone Exp $"; | |
3 #endif | |
4 /* | |
5 * Copyright (c) 1994 Software Research Associates, Inc. | |
6 * | |
7 * Permission to use, copy, modify, and distribute this software and its | |
8 * documentation for any purpose and without fee is hereby granted, provided | |
9 * that the above copyright notice appear in all copies and that both that | |
10 * copyright notice and this permission notice appear in supporting | |
11 * documentation, and that the name of Software Research Associates not be | |
12 * used in advertising or publicity pertaining to distribution of the | |
13 * software without specific, written prior permission. Software Research | |
14 * Associates makes no representations about the suitability of this software | |
15 * for any purpose. It is provided "as is" without express or implied | |
16 * warranty. | |
17 * | |
18 * Author: Makoto Ishisone, Software Research Associates, Inc., Japan | |
19 */ | |
20 | |
21 #include "im.h" | |
22 | |
23 #include "MyDispatch.h" | |
24 | |
25 #include <X11/Xatom.h> | |
26 | |
27 #if (defined(IM_UNIX_TRANSPORT) || defined(IM_TCP_TRANSPORT)) | |
28 #include <sys/types.h> | |
29 #include <sys/socket.h> | |
30 #endif | |
31 | |
32 #ifdef IM_UNIX_TRANSPORT | |
33 #include <sys/un.h> | |
34 #endif | |
35 | |
36 #ifdef IM_TCP_TRANSPORT | |
37 #include <netinet/in.h> | |
38 #endif | |
39 | |
40 extern int errno; | |
41 | |
42 /* | |
43 * X transport version number | |
44 * This implementation uses: | |
45 * + ClientMessage (both single and multiple) | |
46 * + Property with notification by ClientMessage | |
47 * So the major version is 0, minor version is 2. | |
48 * | |
49 * X transport dividing size | |
50 * This size is the threshold between ClientMessage transfer | |
51 * and Property transfer. If the data to be sent is small, | |
52 * transfer via ClientMessage is faster. But since single | |
53 * ClientMessage can transfer only 20bytes, there must be a | |
54 * certain size above which the transfer via Property is | |
55 * faster. | |
56 */ | |
57 #define ServerMajorTransportVersion 0 | |
58 #define ServerMinorTransportVersion 2 | |
59 #define XTransportDividingSize (20 * 5) | |
60 | |
61 | |
62 static int dummyDispatcher _Pt_((IMConnection *conn)); | |
63 static void dumpBuf _Pt_((IMBuffer *ibp, char *title)); | |
64 static Window communicationWindow _Pt_((Widget w)); | |
65 static IMConnection *newConnection _Pt_((Widget protocol)); | |
66 | |
67 #if defined(IM_TCP_TRANSPORT) || defined(IM_UNIX_TRANSPORT) | |
68 static void socketinput _Pt_((XtPointer cldata, int *fdp, XtInputId *idp)); | |
69 static int socketFlush _Pt_((IMConnection *conn)); | |
70 static void socketShutdown _Pt_((IMConnection *conn)); | |
71 | |
72 static IMTransportOps SocketTransportOps = { | |
73 socketFlush, | |
74 socketShutdown, | |
75 }; | |
76 #endif /* IM_TCP_TRANSPORT || IM_UNIX_TRANSPORT */ | |
77 | |
78 #ifdef IM_X_TRANSPORT | |
79 static void xinput _Pt_((XEvent *ev, XtPointer cldata)); | |
80 static void xdestroy _Pt_((XEvent *ev, XtPointer cldata)); | |
81 static int xBrokenPipe _Pt_((Display *dpy, XErrorEvent *eev, | |
82 XPointer client_data)); | |
83 static int xFlush _Pt_((IMConnection *conn)); | |
84 static void xShutdown _Pt_((IMConnection *conn)); | |
85 | |
86 static IMTransportOps XTransportOps = { | |
87 xFlush, | |
88 xShutdown, | |
89 }; | |
90 #endif /* IM_X_TRANSPORT */ | |
91 | |
92 | |
93 /*- dummyDispatcher: dummy dispatcher routine -*/ | |
94 /* ARGSUSED */ | |
95 static int | |
96 dummyDispatcher(conn) | |
97 IMConnection *conn; | |
98 { | |
99 #ifdef DEBUG | |
100 printf("dummyDispatcher -- this function should not be called!\n"); | |
101 #endif | |
102 return 0; /* for lint */ | |
103 } | |
104 | |
105 /*- dumpBuf: dump input/output buffer (for debug) -*/ | |
106 static void | |
107 dumpBuf(ibp, title) | |
108 IMBuffer *ibp; | |
109 char *title; | |
110 { | |
111 int len = IMBUFLEN(ibp); | |
112 unsigned char *data = (unsigned char *)IMBUFDATA(ibp); | |
113 int i; | |
114 | |
115 printf("%s (%d bytes)", title, len); | |
116 for (i = 0; i < len; i++) { | |
117 if (i % 16 == 0) printf("\n\t"); | |
118 printf("%02x ", *data++); | |
119 } | |
120 printf("\n"); | |
121 } | |
122 | |
123 /*- communicationWindow: create a window for communication with client -*/ | |
124 static Window | |
125 communicationWindow(w) | |
126 Widget w; | |
127 { | |
128 return XCreateSimpleWindow(XtDisplay(w), XtWindow(w), 0, 0, 1, 1, 0, 0, 0); | |
129 } | |
130 | |
131 /*- newConnection: allocate IMConnection structure and initialize -*/ | |
132 static IMConnection * | |
133 newConnection(protocol) | |
134 Widget protocol; | |
135 { | |
136 IMConnection *conn; | |
137 static int connection_serial_number = 0; | |
138 | |
139 conn = (IMConnection *)XtMalloc(sizeof(IMConnection)); | |
140 | |
141 conn->serial = ++connection_serial_number; /* start from 1 */ | |
142 conn->dispatcher = dummyDispatcher; | |
143 | |
144 IMBufInit(&conn->in_buf); | |
145 IMBufInit(&conn->out_buf); | |
146 | |
147 conn->byte_order = ORDER_UNKNOWN; | |
148 conn->im_list = NULL; | |
149 conn->proto_widget = protocol; | |
150 | |
151 conn->schedule = 0; | |
152 conn->queue_next = NULL; | |
153 | |
154 conn->next = NULL; | |
155 | |
156 return conn; | |
157 } | |
158 | |
159 #if defined(IM_TCP_TRANSPORT) || defined(IM_UNIX_TRANSPORT) | |
160 /*- socketinput: handler for input from TCP/Unix socket -*/ | |
161 /* ARGSUSED */ | |
162 static void | |
163 socketinput(cldata, fdp, idp) | |
164 XtPointer cldata; | |
165 int *fdp; | |
166 XtInputId *idp; | |
167 { | |
168 IMConnection *conn = (IMConnection *)cldata; | |
169 int fd = conn->transport.priv.sock.fd; | |
170 char buf[4096]; | |
171 int n; | |
172 int cond; | |
173 | |
174 if ((n = read(fd, buf, sizeof(buf))) < 0) { | |
175 cond = TRANSPORT_ERROR; | |
176 } else if (n == 0) { | |
177 cond = TRANSPORT_EOF; | |
178 } else { | |
179 IMBufAdd(&conn->in_buf, buf, n); | |
180 cond = TRANSPORT_OK; | |
181 } | |
182 | |
183 if (DDEBUG_CONDITION(100)) dumpBuf(IM_INBUF(conn), "** input buffer"); | |
184 | |
185 IMDispatch(conn, cond); | |
186 } | |
187 | |
188 /*- socketFlush: output to socket -*/ | |
189 static int | |
190 socketFlush(conn) | |
191 IMConnection *conn; | |
192 { | |
193 int fd = conn->transport.priv.sock.fd; | |
194 IMBuffer *ibp = IM_OUTBUF(conn); | |
195 int n; | |
196 | |
197 if ((n = write(fd, ibp->buf, IMBUFLEN(ibp))) < 0) { | |
198 return TRANSPORT_ERROR; | |
199 } else { | |
200 IMBufDiscard(ibp, n); | |
201 return (IMBUFLEN(ibp) == 0) ? TRANSPORT_OK : TRANSPORT_PARTIAL; | |
202 } | |
203 } | |
204 | |
205 /*- socketShutdown: close socket and stop input callback associate with it -*/ | |
206 static void | |
207 socketShutdown(conn) | |
208 IMConnection *conn; | |
209 { | |
210 int fd = conn->transport.priv.sock.fd; | |
211 | |
212 (void)shutdown(fd, 2); | |
213 (void)close(fd); | |
214 XtRemoveInput(conn->transport.priv.sock.id); | |
215 } | |
216 #endif /* IM_TCP_TRANSPORT || IM_UNIX_TRANSPORT */ | |
217 | |
218 #ifdef IM_X_TRANSPORT | |
219 /*- xinput: handler for input via X inter-client communication -*/ | |
220 static void | |
221 xinput(ev, cldata) | |
222 XEvent *ev; | |
223 XtPointer cldata; | |
224 { | |
225 XClientMessageEvent *event = (XClientMessageEvent *)ev; | |
226 IMConnection *conn = (IMConnection *)cldata; | |
227 int cond; | |
228 Atom msg_type; | |
229 | |
230 TRACE(("imlib:xinput()\n")); | |
231 | |
232 if (event->type != ClientMessage || | |
233 event->window != conn->transport.priv.x.server) { | |
234 return; | |
235 } | |
236 | |
237 msg_type = event->message_type; | |
238 | |
239 if (event->format == 32) { | |
240 /* | |
241 * indirect reference -- data resides in a property, | |
242 * whose name is stored in the event. | |
243 */ | |
244 Atom propatom = event->data.l[1]; | |
245 long offset = 0; | |
246 unsigned long remain; | |
247 | |
248 if (msg_type != IMProtocolAtom(conn->proto_widget)) return; | |
249 | |
250 do { | |
251 Atom actualtype; | |
252 int actualformat; | |
253 unsigned long nitems; | |
254 char *data = NULL; | |
255 | |
256 XGetWindowProperty(event->display, event->window, propatom, | |
257 offset, 1000, True, AnyPropertyType, | |
258 &actualtype, &actualformat, &nitems, | |
259 &remain, (unsigned char **)&data); | |
260 if (data == NULL) return; | |
261 if (actualformat != 8) { | |
262 cond = TRANSPORT_ERROR; | |
263 } else { | |
264 IMBufAdd(&conn->in_buf, data, (int)nitems); | |
265 offset += nitems; | |
266 cond = TRANSPORT_OK; | |
267 } | |
268 XFree(data); | |
269 } while (remain > 0); | |
270 } else if (event->format == 8) { | |
271 if (msg_type != IMProtocolAtom(conn->proto_widget) && | |
272 msg_type != IMMoreDataAtom(conn->proto_widget)) { | |
273 return; | |
274 } | |
275 IMBufAdd(&conn->in_buf, event->data.b, 20); | |
276 cond = TRANSPORT_OK; | |
277 } else { | |
278 return; | |
279 } | |
280 | |
281 if (DDEBUG_CONDITION(100)) dumpBuf(IM_INBUF(conn), "** input buffer"); | |
282 | |
283 IMDispatch(conn, cond); | |
284 } | |
285 | |
286 /*- xdestroy: handler for client comm. window destruction -*/ | |
287 static void | |
288 xdestroy(ev, cldata) | |
289 XEvent *ev; | |
290 XtPointer cldata; | |
291 { | |
292 XDestroyWindowEvent *event = (XDestroyWindowEvent *)ev; | |
293 IMConnection *conn = (IMConnection *)cldata; | |
294 | |
295 TRACE(("imlib:xdestroy()\n")); | |
296 | |
297 if (event->type != DestroyNotify || | |
298 event->window != conn->transport.priv.x.client) { | |
299 return; | |
300 } | |
301 /* | |
302 * Call IMDispatch with TRANSPORT_ERROR, in order to | |
303 * shutdown connection and process queued operations. | |
304 */ | |
305 IMDispatch(conn, TRANSPORT_ERROR); | |
306 } | |
307 | |
308 /*- xBrokenPipe: asyncronous BadWindow error handler -*/ | |
309 /* ARGSUSED */ | |
310 static int | |
311 xBrokenPipe(dpy, eev, client_data) | |
312 Display *dpy; | |
313 XErrorEvent *eev; | |
314 XPointer client_data; | |
315 { | |
316 TRACE(("xBrokenPipe()\n")); | |
317 | |
318 if (eev->error_code == BadWindow) { | |
319 /* | |
320 * Search for the connection using window that caused the error. | |
321 * Note that we cannot pass the connection via client_data, | |
322 * Since the connection might be already destroyed by a previous | |
323 * error. | |
324 */ | |
325 Window bad_win = (Window)eev->resourceid; | |
326 IMConnection *conn; | |
327 | |
328 conn = IMConnectionList((Widget)client_data); | |
329 while (conn != NULL) { | |
330 if (bad_win == conn->transport.priv.x.client) { | |
331 DPRINT(("BadWindow on connection #%d\n", conn->serial)); | |
332 IMDispatch(conn, TRANSPORT_ERROR); | |
333 break; | |
334 } | |
335 conn = conn->next; | |
336 } | |
337 return 0; | |
338 } else { | |
339 return 1; | |
340 } | |
341 } | |
342 | |
343 /*- xFlush: output via X inter-client communication mechanism -*/ | |
344 static int | |
345 xFlush(conn) | |
346 IMConnection *conn; | |
347 { | |
348 IMBuffer *ibp = IM_OUTBUF(conn); | |
349 XClientMessageEvent repl; | |
350 Widget w = conn->proto_widget; | |
351 Window client_win = conn->transport.priv.x.client; | |
352 Display *dpy = XtDisplay(w); | |
353 int length; | |
354 XAEHandle handle; | |
355 | |
356 if ((length = IMBUFLEN(ibp)) == 0) return TRANSPORT_OK; | |
357 | |
358 repl.type = ClientMessage; | |
359 repl.window = client_win; | |
360 | |
361 handle = XAESet(dpy, xBrokenPipe, (void (*)())NULL, (XPointer)w); | |
362 | |
363 if (IMBUFLEN(ibp) < XTransportDividingSize) { | |
364 char *data = IMBUFDATA(ibp); | |
365 | |
366 repl.format = 8; | |
367 repl.message_type = IMMoreDataAtom(w); | |
368 while (length > 20) { | |
369 bcopy(data, repl.data.b, 20); | |
370 XSendEvent(dpy, client_win, False, NoEventMask, (XEvent *)&repl); | |
371 data += 20; | |
372 length -= 20; | |
373 } | |
374 repl.message_type = IMProtocolAtom(w); | |
375 bzero(repl.data.b, 20); | |
376 bcopy(data, repl.data.b, length); | |
377 XSendEvent(dpy, client_win, False, NoEventMask, (XEvent *)&repl); | |
378 } else { | |
379 repl.format = 32; | |
380 repl.message_type = IMProtocolAtom(w); | |
381 repl.data.l[0] = length; | |
382 repl.data.l[1] = IMKi2CommAtom(w); | |
383 XChangeProperty(dpy, client_win, IMKi2CommAtom(w), XA_STRING, | |
384 8, PropModeAppend, | |
385 (unsigned char *)IMBUFDATA(ibp), IMBUFLEN(ibp)); | |
386 XSendEvent(dpy, client_win, False, NoEventMask, (XEvent *)&repl); | |
387 } | |
388 | |
389 XFlush(dpy); | |
390 XAEUnset(handle); | |
391 | |
392 IMBufClear(ibp); | |
393 return TRANSPORT_OK; | |
394 } | |
395 | |
396 /*- xShutdown: close communication channel by destroying comm. window -*/ | |
397 static void | |
398 xShutdown(conn) | |
399 IMConnection *conn; | |
400 { | |
401 Display *dpy = XtDisplay(conn->proto_widget); | |
402 MyRemoveAllEventHandler(dpy, conn->transport.priv.x.client); | |
403 MyRemoveAllEventHandler(dpy, conn->transport.priv.x.server); | |
404 XDestroyWindow(dpy, conn->transport.priv.x.server); | |
405 } | |
406 #endif /* IM_X_TRANSPORT */ | |
407 | |
408 | |
409 /* | |
410 * Public functions | |
411 */ | |
412 | |
413 #ifdef IM_TCP_TRANSPORT | |
414 int | |
415 IMCreateTCPService(portp) | |
416 int *portp; | |
417 { | |
418 struct sockaddr_in addr; | |
419 int optval = 1; | |
420 int sock; | |
421 | |
422 TRACE(("IMCreateTCPService(port=%d)\n", *portp)); | |
423 | |
424 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) { | |
425 DPRINT(("socket(PF_INET) failed with %d\n", errno)); | |
426 return -1; | |
427 } | |
428 | |
429 #ifdef SO_REUSEADDR | |
430 (void)setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, | |
431 (char *)&optval, sizeof(optval)); | |
432 #endif /* SO_REUSEADDR */ | |
433 | |
434 bzero((char *)&addr, sizeof(addr)); | |
435 addr.sin_family = AF_INET; | |
436 addr.sin_port = htons(*portp); | |
437 | |
438 if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { | |
439 DPRINT(("bind() failed with %d\n", errno)); | |
440 return -1; | |
441 } | |
442 if (*portp == 0) { | |
443 int addr_len = sizeof(addr); | |
444 | |
445 if (getsockname(sock, (struct sockaddr *)&addr, &addr_len) < 0) { | |
446 DPRINT(("getsockname() failed with %d\n", errno)); | |
447 return -1; | |
448 } | |
449 *portp = ntohs(addr.sin_port); | |
450 TRACE(("\tport=%d\n", *portp)); | |
451 } | |
452 if (listen(sock, 4) < 0) { | |
453 DPRINT(("listen() failed with %d\n", errno)); | |
454 return -1; | |
455 } | |
456 return sock; | |
457 } | |
458 | |
459 IMConnection * | |
460 IMTCPConnection(protocol, wellknownfd) | |
461 Widget protocol; | |
462 int wellknownfd; | |
463 { | |
464 IMConnection *conn; | |
465 int fd; | |
466 struct sockaddr_in addr; | |
467 int addrlen = sizeof(addr); | |
468 XtInputId id; | |
469 | |
470 TRACE(("IMTCPConnection()\n")); | |
471 | |
472 if ((fd = accept(wellknownfd, (struct sockaddr *)&addr, &addrlen)) < 0) { | |
473 DPRINT(("accept() failed with %d\n", errno)); | |
474 return NULL; | |
475 } | |
476 conn = newConnection(protocol); | |
477 conn->transport.ops = &SocketTransportOps; | |
478 conn->transport.priv.sock.fd = fd; | |
479 DDPRINT(2, ("new connection #%d: transport=TCP socket=%d\n", | |
480 conn->serial, fd)); | |
481 | |
482 id = XtAppAddInput(XtWidgetToApplicationContext(protocol), fd, | |
483 (XtPointer)XtInputReadMask, socketinput, | |
484 (XtPointer)conn); | |
485 conn->transport.priv.sock.id = id; | |
486 | |
487 return conn; | |
488 } | |
489 #endif /* IM_TCP_TRANSPORT */ | |
490 | |
491 #ifdef IM_UNIX_TRANSPORT | |
492 int | |
493 IMCreateUnixService(path) | |
494 char *path; | |
495 { | |
496 struct sockaddr_un addr; | |
497 int sock; | |
498 | |
499 TRACE(("IMCreateUnixService(%s)\n", path)); | |
500 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { | |
501 DPRINT(("socket(PF_UNIX) failed with %d\n", errno)); | |
502 return -1; | |
503 } | |
504 | |
505 bzero((char *)&addr, sizeof(addr)); | |
506 addr.sun_family = AF_UNIX; | |
507 (void)strcpy(addr.sun_path, path); | |
508 | |
509 /* | |
510 * Remove socket which is created by the previous process. | |
511 */ | |
512 (void)unlink(path); | |
513 | |
514 if (bind(sock, (struct sockaddr *)&addr, strlen(path) + 2) < 0) { | |
515 DPRINT(("bind() failed with %d\n", errno)); | |
516 return -1; | |
517 } | |
518 if (listen(sock, 4) < 0) { | |
519 DPRINT(("listen() failed with %d\n", errno)); | |
520 return -1; | |
521 } | |
522 return sock; | |
523 } | |
524 | |
525 IMConnection * | |
526 IMUnixConnection(protocol, wellknownfd) | |
527 Widget protocol; | |
528 int wellknownfd; | |
529 { | |
530 IMConnection *conn; | |
531 int fd; | |
532 struct sockaddr_un addr; | |
533 int addrlen = sizeof(addr); | |
534 XtInputId id; | |
535 | |
536 TRACE(("IMUnixConnection()\n")); | |
537 | |
538 if ((fd = accept(wellknownfd, (struct sockaddr *)&addr, &addrlen)) < 0) { | |
539 DPRINT(("accept() failed with %d\n", errno)); | |
540 return NULL; | |
541 } | |
542 conn = newConnection(protocol); | |
543 conn->transport.ops = &SocketTransportOps; | |
544 conn->transport.priv.sock.fd = fd; | |
545 DDPRINT(2, ("new connection #%d: transport=UNIX socket=%d\n", | |
546 conn->serial, fd)); | |
547 | |
548 id = XtAppAddInput(XtWidgetToApplicationContext(protocol), fd, | |
549 (XtPointer)XtInputReadMask, socketinput, | |
550 (XtPointer)conn); | |
551 conn->transport.priv.sock.id = id; | |
552 | |
553 return conn; | |
554 } | |
555 #endif /* IM_UNIX_TRANSPORT */ | |
556 | |
557 #ifdef IM_X_TRANSPORT | |
558 IMConnection * | |
559 IMXConnection(protocol, xev) | |
560 Widget protocol; | |
561 XEvent *xev; | |
562 { | |
563 XClientMessageEvent *event = (XClientMessageEvent *)xev; | |
564 XClientMessageEvent repl; | |
565 Display *dpy = XtDisplay(protocol); | |
566 Window client_window; | |
567 IMConnection *conn; | |
568 XAEHandle h; | |
569 | |
570 TRACE(("IMXConnection()\n")); | |
571 | |
572 if (event->type != ClientMessage || | |
573 event->display != dpy || | |
574 event->window != XtWindow(protocol) || | |
575 event->message_type != IMXConnectAtom(protocol) || | |
576 event->format != 32) { | |
577 TRACE(("\tinvalid event\n")); | |
578 #ifdef DEBUG | |
579 if (event->type != ClientMessage) printf("not ClientMessage\n"); | |
580 if (event->display != dpy) printf("wrong display\n"); | |
581 if (event->window != XtWindow(protocol)) printf("wrong window\n"); | |
582 if (event->message_type != IMXConnectAtom(protocol)) { | |
583 printf("wrong message type (%ld should be %ld)\n", | |
584 event->message_type, IMXConnectAtom(protocol)); | |
585 } | |
586 if (event->format != 32) printf("wrong format\n"); | |
587 #endif | |
588 return NULL; | |
589 } | |
590 client_window = event->data.l[0]; | |
591 if (!IMValidateWindow(dpy, client_window, (IMWindowProfile *)NULL)) { | |
592 DPRINT(("client window %08lx does not exist\n", client_window)); | |
593 return NULL; | |
594 } | |
595 conn = newConnection(protocol); | |
596 conn->transport.ops = &XTransportOps; | |
597 conn->transport.priv.x.client = client_window; | |
598 conn->transport.priv.x.server = communicationWindow(protocol); | |
599 DDPRINT(2, ("new connection #%d: transport=X client=%08lx\n", | |
600 conn->serial, client_window)); | |
601 TRACE(("\ttransport version: %ld.%ld\n", | |
602 event->data.l[1], event->data.l[2])); | |
603 | |
604 repl.type = ClientMessage; | |
605 repl.window = client_window; | |
606 repl.message_type = IMXConnectAtom(protocol); | |
607 repl.format = 32; | |
608 repl.data.l[0] = conn->transport.priv.x.server; | |
609 repl.data.l[1] = ServerMajorTransportVersion; | |
610 repl.data.l[2] = ServerMinorTransportVersion; | |
611 repl.data.l[3] = XTransportDividingSize; | |
612 /* make it safe... */ | |
613 h = XAESetIgnoreErrors(dpy); | |
614 XSendEvent(dpy, client_window, False, NoEventMask, (XEvent *)&repl); | |
615 MyAddEventHandler(dpy, client_window, DestroyNotify, StructureNotifyMask, | |
616 xdestroy, (XtPointer)conn); | |
617 XAEUnset(h); | |
618 | |
619 MyAddEventHandler(dpy, conn->transport.priv.x.server, | |
620 ClientMessage, NoEventMask, xinput, (XtPointer)conn); | |
621 | |
622 return conn; | |
623 } | |
624 #endif /* IM_X_TRANSPORT */ | |
625 | |
626 int | |
627 IMFlush(conn) | |
628 IMConnection *conn; | |
629 { | |
630 TRACE(("IMFlush(#%d)\n", conn->serial)); | |
631 | |
632 if (DDEBUG_CONDITION(100)) dumpBuf(IM_OUTBUF(conn), "** output buffer"); | |
633 | |
634 return (*conn->transport.ops->flush)(conn); | |
635 } | |
636 | |
637 void | |
638 IMShutdown(conn) | |
639 IMConnection *conn; | |
640 { | |
641 TRACE(("IMShutdown(#%d)\n", conn->serial)); | |
642 (*conn->transport.ops->shutdown)(conn); | |
643 } | |
644 | |
645 void | |
646 IMCloseConnection(conn) | |
647 IMConnection *conn; | |
648 { | |
649 IMIM *imp; | |
650 | |
651 DDPRINT(2, ("IMCloseConnection(#%d)\n", conn->serial)); | |
652 | |
653 imp = conn->im_list; | |
654 while (imp != NULL) { | |
655 IMIM *next = imp->next; | |
656 | |
657 IMDestroyIM(imp); | |
658 imp = next; | |
659 } | |
660 | |
661 IMBufClear(&conn->in_buf); | |
662 IMBufClear(&conn->out_buf); | |
663 #ifdef notdef | |
664 destroyAuth(conn->server_auth); | |
665 destroyAuth(conn->client_auth); | |
666 #endif | |
667 IMShutdown(conn); | |
668 | |
669 IMUnregisterConnection(conn); | |
670 | |
671 XtFree((char *)conn); | |
672 } |