1 /******************************************************************
3 Copyright 1994, 1995 by Sun Microsystems, Inc.
4 Copyright 1993, 1994 by Hewlett-Packard Company
6 Permission to use, copy, modify, distribute, and sell this software
7 and its documentation for any purpose is hereby granted without fee,
8 provided that the above copyright notice appear in all copies and
9 that both that copyright notice and this permission notice appear
10 in supporting documentation, and that the name of Sun Microsystems, Inc.
11 and Hewlett-Packard not be used in advertising or publicity pertaining to
12 distribution of the software without specific, written prior permission.
13 Sun Microsystems, Inc. and Hewlett-Packard make no representations about
14 the suitability of this software for any purpose. It is provided "as is"
15 without express or implied warranty.
17 SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL
18 WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
20 SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY
21 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
22 RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
23 CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
24 IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc.
28 This version tidied and debugged by Steve Underwood May 1999
30 ******************************************************************/
34 #include <X11/Xatom.h>
41 extern Xi18nClient *_Xi18nFindClient(Xi18n, CARD16);
42 extern Xi18nClient *_Xi18nNewClient(Xi18n);
43 extern void _Xi18nDeleteClient(Xi18n, CARD16);
44 static Bool WaitXConnectMessage(Display*, Window,
46 static Bool WaitXIMProtocol(Display*, Window, XEvent*, XPointer);
48 static XClient *NewXClient (Xi18n i18n_core, Window new_client)
50 Display *dpy = i18n_core->address.dpy;
51 Xi18nClient *client = _Xi18nNewClient (i18n_core);
54 x_client = (XClient *) malloc (sizeof (XClient));
55 x_client->client_win = new_client;
56 x_client->accept_win = XCreateSimpleWindow (dpy,
57 DefaultRootWindow(dpy),
65 client->trans_rec = x_client;
66 return ((XClient *) x_client);
69 static unsigned char *ReadXIMMessage (XIMS ims,
70 XClientMessageEvent *ev,
73 Xi18n i18n_core = ims->protocol;
74 Xi18nClient *client = i18n_core->address.clients;
75 XClient *x_client = NULL;
77 extern XimFrameRec packet_header_fr[];
78 unsigned char *p = NULL;
81 while (client != NULL) {
82 x_client = (XClient *) client->trans_rec;
83 if (x_client->accept_win == ev->window) {
84 *connect_id = client->connect_id;
87 client = client->next;
90 if (ev->format == 8) {
91 /* ClientMessage only */
92 XimProtoHdr *hdr = (XimProtoHdr *) ev->data.b;
93 unsigned char *rec = (unsigned char *) (hdr + 1);
94 register int total_size;
98 extern int _Xi18nNeedSwap (Xi18n, CARD16);
100 if (client->byte_order == '?')
102 if (hdr->major_opcode != XIM_CONNECT)
103 return (unsigned char *) NULL; /* can do nothing */
104 client->byte_order = (CARD8) rec[0];
107 fm = FrameMgrInit (packet_header_fr,
109 _Xi18nNeedSwap (i18n_core, *connect_id));
110 total_size = FrameMgrGetTotalSize (fm);
112 FrameMgrGetToken (fm, major_opcode);
113 FrameMgrGetToken (fm, minor_opcode);
114 FrameMgrGetToken (fm, length);
117 if ((p = (unsigned char *) malloc (total_size + length * 4)) == NULL)
118 return (unsigned char *) NULL;
121 memmove (p1, &major_opcode, sizeof (CARD8));
122 p1 += sizeof (CARD8);
123 memmove (p1, &minor_opcode, sizeof (CARD8));
124 p1 += sizeof (CARD8);
125 memmove (p1, &length, sizeof (CARD16));
126 p1 += sizeof (CARD16);
127 memmove (p1, rec, length * 4);
129 else if (ev->format == 32) {
130 /* ClientMessage and WindowProperty */
131 unsigned long length = (unsigned long) ev->data.l[0];
132 unsigned long get_length;
133 Atom atom = (Atom) ev->data.l[1];
135 Atom actual_type_ret;
136 int actual_format_ret;
137 unsigned long bytes_after_ret;
139 unsigned long nitems;
141 /* Round up length to next 4 byte value. */
142 get_length = length + 3;
143 if (get_length > LONG_MAX)
144 get_length = LONG_MAX;
146 if (get_length == 0) {
147 fprintf(stderr, "%s: invalid length 0\n", __func__);
150 return_code = XGetWindowProperty (i18n_core->address.dpy,
151 x_client->accept_win,
153 client->property_offset / 4,
162 if (return_code != Success || actual_format_ret == 0 || nitems == 0) {
163 if (return_code == Success)
165 client->property_offset = 0;
166 return (unsigned char *) NULL;
168 /* Update the offset to read next time as needed */
169 if (bytes_after_ret > 0)
170 client->property_offset += length;
172 client->property_offset = 0;
173 switch (actual_format_ret) {
177 length = nitems * actual_format_ret / 8;
180 fprintf(stderr, "%s: unknown property return format: %d\n",
181 __func__, actual_format_ret);
183 client->property_offset = 0;
186 /* if hit, it might be an error */
187 if ((p = (unsigned char *) malloc (length)) == NULL)
188 return (unsigned char *) NULL;
190 memmove (p, prop, length);
193 return (unsigned char *) p;
196 static void ReadXConnectMessage (XIMS ims, XClientMessageEvent *ev)
198 Xi18n i18n_core = ims->protocol;
199 XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
201 Display *dpy = i18n_core->address.dpy;
202 Window new_client = ev->data.l[0];
203 CARD32 major_version = ev->data.l[1];
204 CARD32 minor_version = ev->data.l[2];
205 XClient *x_client = NewXClient (i18n_core, new_client);
207 if (ev->window != i18n_core->address.im_window)
208 return; /* incorrect connection request */
210 if (major_version != 0 || minor_version != 0)
214 /* Only supporting only-CM & Property-with-CM method */
217 _XRegisterFilterByType (dpy,
218 x_client->accept_win,
223 event.xclient.type = ClientMessage;
224 event.xclient.display = dpy;
225 event.xclient.window = new_client;
226 event.xclient.message_type = spec->connect_request;
227 event.xclient.format = 32;
228 event.xclient.data.l[0] = x_client->accept_win;
229 event.xclient.data.l[1] = major_version;
230 event.xclient.data.l[2] = minor_version;
231 event.xclient.data.l[3] = XCM_DATA_LIMIT;
241 static Bool Xi18nXBegin (XIMS ims)
243 Xi18n i18n_core = ims->protocol;
244 Display *dpy = i18n_core->address.dpy;
245 XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
247 spec->xim_request = XInternAtom (i18n_core->address.dpy,
250 spec->connect_request = XInternAtom (i18n_core->address.dpy,
254 _XRegisterFilterByType (dpy,
255 i18n_core->address.im_window,
263 static Bool Xi18nXEnd(XIMS ims)
265 Xi18n i18n_core = ims->protocol;
266 Display *dpy = i18n_core->address.dpy;
268 _XUnregisterFilter (dpy,
269 i18n_core->address.im_window,
275 static char *MakeNewAtom (CARD16 connect_id, char *atomName)
277 static int sequence = 0;
282 ((sequence > 20) ? (sequence = 0) : sequence++));
286 static Bool Xi18nXSend (XIMS ims,
288 unsigned char *reply,
291 Xi18n i18n_core = ims->protocol;
292 Xi18nClient *client = _Xi18nFindClient (i18n_core, connect_id);
293 XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
294 XClient *x_client = (XClient *) client->trans_rec;
297 memset(&event, 0, sizeof(XEvent));
298 event.type = ClientMessage;
299 event.xclient.serial = 0;
300 event.xclient.send_event = True;
301 event.xclient.display = i18n_core->address.dpy;
302 event.xclient.window = x_client->client_win;
303 event.xclient.message_type = spec->xim_request;
305 if (length > XCM_DATA_LIMIT)
309 Atom actual_type_ret;
310 int actual_format_ret;
312 unsigned long nitems_ret;
313 unsigned long bytes_after_ret;
314 unsigned char *win_data;
316 event.xclient.format = 32;
317 atom = XInternAtom (i18n_core->address.dpy,
318 MakeNewAtom (connect_id, atomName),
320 return_code = XGetWindowProperty (i18n_core->address.dpy,
321 x_client->client_win,
332 if (return_code != Success)
336 XFree ((char *) win_data);
338 XChangeProperty (i18n_core->address.dpy,
339 x_client->client_win,
344 (unsigned char *) reply,
346 event.xclient.data.l[0] = length;
347 event.xclient.data.l[1] = atom;
351 unsigned char buffer[XCM_DATA_LIMIT];
354 event.xclient.format = 8;
356 /* Clear unused field with NULL */
357 memmove(buffer, reply, length);
358 for (i = length; i < XCM_DATA_LIMIT; i++)
359 buffer[i] = (char) 0;
361 length = XCM_DATA_LIMIT;
362 memmove (event.xclient.data.b, buffer, length);
364 XSendEvent (i18n_core->address.dpy,
365 x_client->client_win,
369 XFlush (i18n_core->address.dpy);
373 static Bool CheckCMEvent (Display *display, XEvent *event, XPointer xi18n_core)
375 Xi18n i18n_core = (Xi18n) ((void *) xi18n_core);
376 XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
378 if ((event->type == ClientMessage)
380 (event->xclient.message_type == spec->xim_request))
388 static Bool Xi18nXWait (XIMS ims,
393 Xi18n i18n_core = ims->protocol;
395 Xi18nClient *client = _Xi18nFindClient (i18n_core, connect_id);
396 XClient *x_client = (XClient *) client->trans_rec;
400 unsigned char *packet;
404 XIfEvent (i18n_core->address.dpy,
407 (XPointer) i18n_core);
408 if (event.xclient.window == x_client->accept_win)
410 if ((packet = ReadXIMMessage (ims,
411 (XClientMessageEvent *) & event,
413 == (unsigned char*) NULL)
418 hdr = (XimProtoHdr *)packet;
420 if ((hdr->major_opcode == major_opcode)
422 (hdr->minor_opcode == minor_opcode))
426 else if (hdr->major_opcode == XIM_ERROR)
437 static Bool Xi18nXDisconnect (XIMS ims, CARD16 connect_id)
439 Xi18n i18n_core = ims->protocol;
440 Display *dpy = i18n_core->address.dpy;
441 Xi18nClient *client = _Xi18nFindClient (i18n_core, connect_id);
442 XClient *x_client = (XClient *) client->trans_rec;
444 XDestroyWindow (dpy, x_client->accept_win);
445 _XUnregisterFilter (dpy,
446 x_client->accept_win,
450 _Xi18nDeleteClient (i18n_core, connect_id);
454 Bool _Xi18nCheckXAddress (Xi18n i18n_core,
455 TransportSW *transSW,
460 if (!(spec = (XSpecRec *) malloc (sizeof (XSpecRec))))
464 i18n_core->address.connect_addr = (XSpecRec *) spec;
465 i18n_core->methods.begin = Xi18nXBegin;
466 i18n_core->methods.end = Xi18nXEnd;
467 i18n_core->methods.send = Xi18nXSend;
468 i18n_core->methods.wait = Xi18nXWait;
469 i18n_core->methods.disconnect = Xi18nXDisconnect;
473 static Bool WaitXConnectMessage (Display *dpy,
476 XPointer client_data)
478 XIMS ims = (XIMS)client_data;
479 Xi18n i18n_core = ims->protocol;
480 XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
482 if (((XClientMessageEvent *) ev)->message_type
483 == spec->connect_request)
485 ReadXConnectMessage (ims, (XClientMessageEvent *) ev);
492 static Bool WaitXIMProtocol (Display *dpy,
495 XPointer client_data)
497 extern void _Xi18nMessageHandler (XIMS, CARD16, unsigned char *, Bool *);
498 XIMS ims = (XIMS) client_data;
499 Xi18n i18n_core = ims->protocol;
500 XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
502 unsigned char *packet;
505 if (((XClientMessageEvent *) ev)->message_type
506 == spec->xim_request)
508 if ((packet = ReadXIMMessage (ims,
509 (XClientMessageEvent *) ev,
511 == (unsigned char *) NULL)
516 _Xi18nMessageHandler (ims, connect_id, packet, &delete);