1 /******************************************************************
2
3 Copyright 1994, 1995 by Sun Microsystems, Inc.
4 Copyright 1993, 1994 by Hewlett-Packard Company
5
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.
16
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.
25
26 Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc.
27
28 This version tidied and debugged by Steve Underwood May 1999
29
30 ******************************************************************/
31
32 #include <X11/Xlib.h>
33 #include <X11/Xatom.h>
34 #include "FrameMgr.h"
35 #include "IMdkit.h"
36 #include "Xi18n.h"
37 #include "Xi18nX.h"
38 #include "XimFunc.h"
39
40 extern Xi18nClient *_Xi18nFindClient(Xi18n, CARD16);
41 extern Xi18nClient *_Xi18nNewClient(Xi18n);
42 extern void _Xi18nDeleteClient(Xi18n, CARD16);
43 static Bool WaitXConnectMessage(Display*, Window,
44 XEvent*, XPointer);
45 static Bool WaitXIMProtocol(Display*, Window, XEvent*, XPointer);
46
NewXClient(Xi18n i18n_core,Window new_client)47 static XClient *NewXClient (Xi18n i18n_core, Window new_client)
48 {
49 Display *dpy = i18n_core->address.dpy;
50 Xi18nClient *client = _Xi18nNewClient (i18n_core);
51 XClient *x_client;
52
53 x_client = (XClient *) malloc (sizeof (XClient));
54 x_client->client_win = new_client;
55 x_client->accept_win = XCreateSimpleWindow (dpy,
56 DefaultRootWindow(dpy),
57 0,
58 0,
59 1,
60 1,
61 1,
62 0,
63 0);
64 client->trans_rec = x_client;
65 return ((XClient *) x_client);
66 }
67
ReadXIMMessage(XIMS ims,XClientMessageEvent * ev,int * connect_id)68 static unsigned char *ReadXIMMessage (XIMS ims,
69 XClientMessageEvent *ev,
70 int *connect_id)
71 {
72 Xi18n i18n_core = ims->protocol;
73 Xi18nClient *client = i18n_core->address.clients;
74 XClient *x_client = NULL;
75 FrameMgr fm;
76 extern XimFrameRec packet_header_fr[];
77 unsigned char *p = NULL;
78 unsigned char *p1;
79
80 while (client != NULL) {
81 x_client = (XClient *) client->trans_rec;
82 if (x_client->accept_win == ev->window) {
83 *connect_id = client->connect_id;
84 break;
85 }
86 client = client->next;
87 }
88
89 if (ev->format == 8) {
90 /* ClientMessage only */
91 XimProtoHdr *hdr = (XimProtoHdr *) ev->data.b;
92 unsigned char *rec = (unsigned char *) (hdr + 1);
93 register int total_size;
94 CARD8 major_opcode;
95 CARD8 minor_opcode;
96 CARD16 length;
97 extern int _Xi18nNeedSwap (Xi18n, CARD16);
98
99 if (client->byte_order == '?')
100 {
101 if (hdr->major_opcode != XIM_CONNECT)
102 return (unsigned char *) NULL; /* can do nothing */
103 client->byte_order = (CARD8) rec[0];
104 }
105
106 fm = FrameMgrInit (packet_header_fr,
107 (char *) hdr,
108 _Xi18nNeedSwap (i18n_core, *connect_id));
109 total_size = FrameMgrGetTotalSize (fm);
110 /* get data */
111 FrameMgrGetToken (fm, major_opcode);
112 FrameMgrGetToken (fm, minor_opcode);
113 FrameMgrGetToken (fm, length);
114 FrameMgrFree (fm);
115
116 if ((p = (unsigned char *) malloc (total_size + length * 4)) == NULL)
117 return (unsigned char *) NULL;
118
119 p1 = p;
120 memmove (p1, &major_opcode, sizeof (CARD8));
121 p1 += sizeof (CARD8);
122 memmove (p1, &minor_opcode, sizeof (CARD8));
123 p1 += sizeof (CARD8);
124 memmove (p1, &length, sizeof (CARD16));
125 p1 += sizeof (CARD16);
126 memmove (p1, rec, length * 4);
127 }
128 else if (ev->format == 32) {
129 /* ClientMessage and WindowProperty */
130 unsigned long length = (unsigned long) ev->data.l[0];
131 Atom atom = (Atom) ev->data.l[1];
132 int return_code;
133 Atom actual_type_ret;
134 int actual_format_ret;
135 unsigned long bytes_after_ret;
136 unsigned char *prop;
137 unsigned long nitems;
138
139 return_code = XGetWindowProperty (i18n_core->address.dpy,
140 x_client->accept_win,
141 atom,
142 0L,
143 length,
144 True,
145 AnyPropertyType,
146 &actual_type_ret,
147 &actual_format_ret,
148 &nitems,
149 &bytes_after_ret,
150 &prop);
151 if (return_code != Success || actual_format_ret == 0 || nitems == 0) {
152 if (return_code == Success)
153 XFree (prop);
154 return (unsigned char *) NULL;
155 }
156 if (length != nitems)
157 length = nitems;
158 if (actual_format_ret == 16)
159 length *= 2;
160 else if (actual_format_ret == 32)
161 length *= 4;
162
163 /* if hit, it might be an error */
164 if ((p = (unsigned char *) malloc (length)) == NULL)
165 return (unsigned char *) NULL;
166
167 memmove (p, prop, length);
168 XFree (prop);
169 }
170 return (unsigned char *) p;
171 }
172
ReadXConnectMessage(XIMS ims,XClientMessageEvent * ev)173 static void ReadXConnectMessage (XIMS ims, XClientMessageEvent *ev)
174 {
175 Xi18n i18n_core = ims->protocol;
176 XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
177 XEvent event;
178 Display *dpy = i18n_core->address.dpy;
179 Window new_client = ev->data.l[0];
180 CARD32 major_version = ev->data.l[1];
181 CARD32 minor_version = ev->data.l[2];
182 XClient *x_client = NewXClient (i18n_core, new_client);
183
184 if (ev->window != i18n_core->address.im_window)
185 return; /* incorrect connection request */
186 /*endif*/
187 if (major_version != 0 || minor_version != 0)
188 {
189 major_version =
190 minor_version = 0;
191 /* Only supporting only-CM & Property-with-CM method */
192 }
193 /*endif*/
194 _XRegisterFilterByType (dpy,
195 x_client->accept_win,
196 ClientMessage,
197 ClientMessage,
198 WaitXIMProtocol,
199 (XPointer)ims);
200 event.xclient.type = ClientMessage;
201 event.xclient.display = dpy;
202 event.xclient.window = new_client;
203 event.xclient.message_type = spec->connect_request;
204 event.xclient.format = 32;
205 event.xclient.data.l[0] = x_client->accept_win;
206 event.xclient.data.l[1] = major_version;
207 event.xclient.data.l[2] = minor_version;
208 event.xclient.data.l[3] = XCM_DATA_LIMIT;
209
210 XSendEvent (dpy,
211 new_client,
212 False,
213 NoEventMask,
214 &event);
215 XFlush (dpy);
216 }
217
Xi18nXBegin(XIMS ims)218 static Bool Xi18nXBegin (XIMS ims)
219 {
220 Xi18n i18n_core = ims->protocol;
221 Display *dpy = i18n_core->address.dpy;
222 XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
223
224 spec->xim_request = XInternAtom (i18n_core->address.dpy,
225 _XIM_PROTOCOL,
226 False);
227 spec->connect_request = XInternAtom (i18n_core->address.dpy,
228 _XIM_XCONNECT,
229 False);
230
231 _XRegisterFilterByType (dpy,
232 i18n_core->address.im_window,
233 ClientMessage,
234 ClientMessage,
235 WaitXConnectMessage,
236 (XPointer)ims);
237 return True;
238 }
239
Xi18nXEnd(XIMS ims)240 static Bool Xi18nXEnd(XIMS ims)
241 {
242 Xi18n i18n_core = ims->protocol;
243 Display *dpy = i18n_core->address.dpy;
244
245 _XUnregisterFilter (dpy,
246 i18n_core->address.im_window,
247 WaitXConnectMessage,
248 (XPointer)ims);
249 return True;
250 }
251
MakeNewAtom(CARD16 connect_id,char * atomName)252 static char *MakeNewAtom (CARD16 connect_id, char *atomName)
253 {
254 static int sequence = 0;
255
256 sprintf (atomName,
257 "_server%d_%d",
258 connect_id,
259 ((sequence > 20) ? (sequence = 0) : sequence++));
260 return atomName;
261 }
262
Xi18nXSend(XIMS ims,CARD16 connect_id,unsigned char * reply,long length)263 static Bool Xi18nXSend (XIMS ims,
264 CARD16 connect_id,
265 unsigned char *reply,
266 long length)
267 {
268 Xi18n i18n_core = ims->protocol;
269 Xi18nClient *client = _Xi18nFindClient (i18n_core, connect_id);
270 XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
271 XClient *x_client = (XClient *) client->trans_rec;
272 XEvent event;
273
274 event.type = ClientMessage;
275 event.xclient.window = x_client->client_win;
276 event.xclient.message_type = spec->xim_request;
277
278 if (length > XCM_DATA_LIMIT)
279 {
280 Atom atom;
281 char atomName[16];
282 Atom actual_type_ret;
283 int actual_format_ret;
284 int return_code;
285 unsigned long nitems_ret;
286 unsigned long bytes_after_ret;
287 unsigned char *win_data;
288
289 event.xclient.format = 32;
290 atom = XInternAtom (i18n_core->address.dpy,
291 MakeNewAtom (connect_id, atomName),
292 False);
293 return_code = XGetWindowProperty (i18n_core->address.dpy,
294 x_client->client_win,
295 atom,
296 0L,
297 10000L,
298 False,
299 XA_STRING,
300 &actual_type_ret,
301 &actual_format_ret,
302 &nitems_ret,
303 &bytes_after_ret,
304 &win_data);
305 if (return_code != Success)
306 return False;
307 /*endif*/
308 if (win_data)
309 XFree ((char *) win_data);
310 /*endif*/
311 XChangeProperty (i18n_core->address.dpy,
312 x_client->client_win,
313 atom,
314 XA_STRING,
315 8,
316 PropModeAppend,
317 (unsigned char *) reply,
318 length);
319 event.xclient.data.l[0] = length;
320 event.xclient.data.l[1] = atom;
321 }
322 else
323 {
324 unsigned char buffer[XCM_DATA_LIMIT];
325 int i;
326
327 event.xclient.format = 8;
328
329 /* Clear unused field with NULL */
330 memmove(buffer, reply, length);
331 for (i = length; i < XCM_DATA_LIMIT; i++)
332 buffer[i] = (char) 0;
333 /*endfor*/
334 length = XCM_DATA_LIMIT;
335 memmove (event.xclient.data.b, buffer, length);
336 }
337 XSendEvent (i18n_core->address.dpy,
338 x_client->client_win,
339 False,
340 NoEventMask,
341 &event);
342 XFlush (i18n_core->address.dpy);
343 return True;
344 }
345
CheckCMEvent(Display * display,XEvent * event,XPointer xi18n_core)346 static Bool CheckCMEvent (Display *display, XEvent *event, XPointer xi18n_core)
347 {
348 Xi18n i18n_core = (Xi18n) ((void *) xi18n_core);
349 XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
350
351 if ((event->type == ClientMessage)
352 &&
353 (event->xclient.message_type == spec->xim_request))
354 {
355 return True;
356 }
357 /*endif*/
358 return False;
359 }
360
Xi18nXWait(XIMS ims,CARD16 connect_id,CARD8 major_opcode,CARD8 minor_opcode)361 static Bool Xi18nXWait (XIMS ims,
362 CARD16 connect_id,
363 CARD8 major_opcode,
364 CARD8 minor_opcode)
365 {
366 Xi18n i18n_core = ims->protocol;
367 XEvent event;
368 Xi18nClient *client = _Xi18nFindClient (i18n_core, connect_id);
369 XClient *x_client = (XClient *) client->trans_rec;
370
371 for (;;)
372 {
373 unsigned char *packet;
374 XimProtoHdr *hdr;
375 int connect_id_ret;
376
377 XIfEvent (i18n_core->address.dpy,
378 &event,
379 CheckCMEvent,
380 (XPointer) i18n_core);
381 if (event.xclient.window == x_client->accept_win)
382 {
383 if ((packet = ReadXIMMessage (ims,
384 (XClientMessageEvent *) & event,
385 &connect_id_ret))
386 == (unsigned char*) NULL)
387 {
388 return False;
389 }
390 /*endif*/
391 hdr = (XimProtoHdr *)packet;
392
393 if ((hdr->major_opcode == major_opcode)
394 &&
395 (hdr->minor_opcode == minor_opcode))
396 {
397 return True;
398 }
399 else if (hdr->major_opcode == XIM_ERROR)
400 {
401 return False;
402 }
403 /*endif*/
404 }
405 /*endif*/
406 }
407 /*endfor*/
408 }
409
Xi18nXDisconnect(XIMS ims,CARD16 connect_id)410 static Bool Xi18nXDisconnect (XIMS ims, CARD16 connect_id)
411 {
412 Xi18n i18n_core = ims->protocol;
413 Display *dpy = i18n_core->address.dpy;
414 Xi18nClient *client = _Xi18nFindClient (i18n_core, connect_id);
415 XClient *x_client = (XClient *) client->trans_rec;
416
417 XDestroyWindow (dpy, x_client->accept_win);
418 _XUnregisterFilter (dpy,
419 x_client->accept_win,
420 WaitXIMProtocol,
421 (XPointer)ims);
422 XFree (x_client);
423 _Xi18nDeleteClient (i18n_core, connect_id);
424 return True;
425 }
426
_Xi18nCheckXAddress(Xi18n i18n_core,TransportSW * transSW,char * address)427 Bool _Xi18nCheckXAddress (Xi18n i18n_core,
428 TransportSW *transSW,
429 char *address)
430 {
431 XSpecRec *spec;
432
433 if (!(spec = (XSpecRec *) malloc (sizeof (XSpecRec))))
434 return False;
435 /*endif*/
436
437 i18n_core->address.connect_addr = (XSpecRec *) spec;
438 i18n_core->methods.begin = Xi18nXBegin;
439 i18n_core->methods.end = Xi18nXEnd;
440 i18n_core->methods.send = Xi18nXSend;
441 i18n_core->methods.wait = Xi18nXWait;
442 i18n_core->methods.disconnect = Xi18nXDisconnect;
443 return True;
444 }
445
WaitXConnectMessage(Display * dpy,Window win,XEvent * ev,XPointer client_data)446 static Bool WaitXConnectMessage (Display *dpy,
447 Window win,
448 XEvent *ev,
449 XPointer client_data)
450 {
451 XIMS ims = (XIMS)client_data;
452 Xi18n i18n_core = ims->protocol;
453 XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
454
455 if (((XClientMessageEvent *) ev)->message_type
456 == spec->connect_request)
457 {
458 ReadXConnectMessage (ims, (XClientMessageEvent *) ev);
459 return True;
460 }
461 /*endif*/
462 return False;
463 }
464
WaitXIMProtocol(Display * dpy,Window win,XEvent * ev,XPointer client_data)465 static Bool WaitXIMProtocol (Display *dpy,
466 Window win,
467 XEvent *ev,
468 XPointer client_data)
469 {
470 extern void _Xi18nMessageHandler (XIMS, CARD16, unsigned char *, Bool *);
471 XIMS ims = (XIMS) client_data;
472 Xi18n i18n_core = ims->protocol;
473 XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
474 Bool delete = True;
475 unsigned char *packet;
476 int connect_id;
477
478 if (((XClientMessageEvent *) ev)->message_type
479 == spec->xim_request)
480 {
481 if ((packet = ReadXIMMessage (ims,
482 (XClientMessageEvent *) ev,
483 &connect_id))
484 == (unsigned char *) NULL)
485 {
486 return False;
487 }
488 /*endif*/
489 _Xi18nMessageHandler (ims, connect_id, packet, &delete);
490 if (delete == True)
491 XFree (packet);
492 /*endif*/
493 return True;
494 }
495 /*endif*/
496 return False;
497 }
498