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 //pklong
211 //fprintf(stderr, "ReadXConnectMessage Serial: %ld\n", event.xclient.serial);
212 //
213 XSendEvent (dpy,
214 new_client,
215 False,
216 NoEventMask,
217 &event);
218 XFlush (dpy);
219 }
220
Xi18nXBegin(XIMS ims)221 static Bool Xi18nXBegin (XIMS ims)
222 {
223 Xi18n i18n_core = ims->protocol;
224 Display *dpy = i18n_core->address.dpy;
225 XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
226
227 spec->xim_request = XInternAtom (i18n_core->address.dpy,
228 _XIM_PROTOCOL,
229 False);
230 spec->connect_request = XInternAtom (i18n_core->address.dpy,
231 _XIM_XCONNECT,
232 False);
233
234 _XRegisterFilterByType (dpy,
235 i18n_core->address.im_window,
236 ClientMessage,
237 ClientMessage,
238 WaitXConnectMessage,
239 (XPointer)ims);
240 return True;
241 }
242
Xi18nXEnd(XIMS ims)243 static Bool Xi18nXEnd(XIMS ims)
244 {
245 Xi18n i18n_core = ims->protocol;
246 Display *dpy = i18n_core->address.dpy;
247
248 _XUnregisterFilter (dpy,
249 i18n_core->address.im_window,
250 WaitXConnectMessage,
251 (XPointer)ims);
252 return True;
253 }
254
MakeNewAtom(CARD16 connect_id,char * atomName)255 static char *MakeNewAtom (CARD16 connect_id, char *atomName)
256 {
257 static int sequence = 0;
258
259 sprintf (atomName,
260 "_server%d_%d",
261 connect_id,
262 ((sequence > 20) ? (sequence = 0) : sequence++));
263 return atomName;
264 }
265
Xi18nXSend(XIMS ims,CARD16 connect_id,unsigned char * reply,long length)266 static Bool Xi18nXSend (XIMS ims,
267 CARD16 connect_id,
268 unsigned char *reply,
269 long length)
270 {
271 Xi18n i18n_core = ims->protocol;
272 Xi18nClient *client = _Xi18nFindClient (i18n_core, connect_id);
273 XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
274 XClient *x_client = (XClient *) client->trans_rec;
275 XEvent event;
276
277 event.type = ClientMessage;
278 event.xclient.window = x_client->client_win;
279 event.xclient.message_type = spec->xim_request;
280
281 if (length > XCM_DATA_LIMIT)
282 {
283 Atom atom;
284 char atomName[16];
285 Atom actual_type_ret;
286 int actual_format_ret;
287 int return_code;
288 unsigned long nitems_ret;
289 unsigned long bytes_after_ret;
290 unsigned char *win_data;
291
292 event.xclient.format = 32;
293 atom = XInternAtom (i18n_core->address.dpy,
294 MakeNewAtom (connect_id, atomName),
295 False);
296 return_code = XGetWindowProperty (i18n_core->address.dpy,
297 x_client->client_win,
298 atom,
299 0L,
300 10000L,
301 False,
302 XA_STRING,
303 &actual_type_ret,
304 &actual_format_ret,
305 &nitems_ret,
306 &bytes_after_ret,
307 &win_data);
308 if (return_code != Success)
309 return False;
310 /*endif*/
311 if (win_data)
312 XFree ((char *) win_data);
313 /*endif*/
314 XChangeProperty (i18n_core->address.dpy,
315 x_client->client_win,
316 atom,
317 XA_STRING,
318 8,
319 PropModeAppend,
320 (unsigned char *) reply,
321 length);
322 event.xclient.data.l[0] = length;
323 event.xclient.data.l[1] = atom;
324 }
325 else
326 {
327 unsigned char buffer[XCM_DATA_LIMIT];
328 int i;
329
330 event.xclient.format = 8;
331
332 /* Clear unused field with NULL */
333 memmove(buffer, reply, length);
334 for (i = length; i < XCM_DATA_LIMIT; i++)
335 buffer[i] = (char) 0;
336 /*endfor*/
337 length = XCM_DATA_LIMIT;
338 memmove (event.xclient.data.b, buffer, length);
339 }
340 XSendEvent (i18n_core->address.dpy,
341 x_client->client_win,
342 False,
343 NoEventMask,
344 &event);
345 XFlush (i18n_core->address.dpy);
346 return True;
347 }
348
CheckCMEvent(Display * display,XEvent * event,XPointer xi18n_core)349 static Bool CheckCMEvent (Display *display, XEvent *event, XPointer xi18n_core)
350 {
351 Xi18n i18n_core = (Xi18n) ((void *) xi18n_core);
352 XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
353
354 if ((event->type == ClientMessage)
355 &&
356 (event->xclient.message_type == spec->xim_request))
357 {
358 return True;
359 }
360 /*endif*/
361 return False;
362 }
363
Xi18nXWait(XIMS ims,CARD16 connect_id,CARD8 major_opcode,CARD8 minor_opcode)364 static Bool Xi18nXWait (XIMS ims,
365 CARD16 connect_id,
366 CARD8 major_opcode,
367 CARD8 minor_opcode)
368 {
369 Xi18n i18n_core = ims->protocol;
370 XEvent event;
371 Xi18nClient *client = _Xi18nFindClient (i18n_core, connect_id);
372 XClient *x_client = (XClient *) client->trans_rec;
373
374 for (;;)
375 {
376 unsigned char *packet;
377 XimProtoHdr *hdr;
378 int connect_id_ret;
379
380 XIfEvent (i18n_core->address.dpy,
381 &event,
382 CheckCMEvent,
383 (XPointer) i18n_core);
384 if (event.xclient.window == x_client->accept_win)
385 {
386 if ((packet = ReadXIMMessage (ims,
387 (XClientMessageEvent *) & event,
388 &connect_id_ret))
389 == (unsigned char*) NULL)
390 {
391 return False;
392 }
393 /*endif*/
394 hdr = (XimProtoHdr *)packet;
395
396 if ((hdr->major_opcode == major_opcode)
397 &&
398 (hdr->minor_opcode == minor_opcode))
399 {
400 return True;
401 }
402 else if (hdr->major_opcode == XIM_ERROR)
403 {
404 return False;
405 }
406 /*endif*/
407 }
408 /*endif*/
409 }
410 /*endfor*/
411 }
412
Xi18nXDisconnect(XIMS ims,CARD16 connect_id)413 static Bool Xi18nXDisconnect (XIMS ims, CARD16 connect_id)
414 {
415 Xi18n i18n_core = ims->protocol;
416 Display *dpy = i18n_core->address.dpy;
417 Xi18nClient *client = _Xi18nFindClient (i18n_core, connect_id);
418 XClient *x_client = (XClient *) client->trans_rec;
419
420 XDestroyWindow (dpy, x_client->accept_win);
421 _XUnregisterFilter (dpy,
422 x_client->accept_win,
423 WaitXIMProtocol,
424 (XPointer)ims);
425 XFree (x_client);
426 _Xi18nDeleteClient (i18n_core, connect_id);
427 return True;
428 }
429
_Xi18nCheckXAddress(Xi18n i18n_core,TransportSW * transSW,char * address)430 Bool _Xi18nCheckXAddress (Xi18n i18n_core,
431 TransportSW *transSW,
432 char *address)
433 {
434 XSpecRec *spec;
435
436 if (!(spec = (XSpecRec *) malloc (sizeof (XSpecRec))))
437 return False;
438 /*endif*/
439
440 i18n_core->address.connect_addr = (XSpecRec *) spec;
441 i18n_core->methods.begin = Xi18nXBegin;
442 i18n_core->methods.end = Xi18nXEnd;
443 i18n_core->methods.send = Xi18nXSend;
444 i18n_core->methods.wait = Xi18nXWait;
445 i18n_core->methods.disconnect = Xi18nXDisconnect;
446 return True;
447 }
448
WaitXConnectMessage(Display * dpy,Window win,XEvent * ev,XPointer client_data)449 static Bool WaitXConnectMessage (Display *dpy,
450 Window win,
451 XEvent *ev,
452 XPointer client_data)
453 {
454 XIMS ims = (XIMS)client_data;
455 Xi18n i18n_core = ims->protocol;
456 XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
457
458 if (((XClientMessageEvent *) ev)->message_type
459 == spec->connect_request)
460 {
461 ReadXConnectMessage (ims, (XClientMessageEvent *) ev);
462 return True;
463 }
464 /*endif*/
465 return False;
466 }
467
WaitXIMProtocol(Display * dpy,Window win,XEvent * ev,XPointer client_data)468 static Bool WaitXIMProtocol (Display *dpy,
469 Window win,
470 XEvent *ev,
471 XPointer client_data)
472 {
473 extern void _Xi18nMessageHandler (XIMS, CARD16, unsigned char *, Bool *);
474 XIMS ims = (XIMS) client_data;
475 Xi18n i18n_core = ims->protocol;
476 XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
477 Bool delete = True;
478 unsigned char *packet;
479 int connect_id;
480
481 if (((XClientMessageEvent *) ev)->message_type
482 == spec->xim_request)
483 {
484 if ((packet = ReadXIMMessage (ims,
485 (XClientMessageEvent *) ev,
486 &connect_id))
487 == (unsigned char *) NULL)
488 {
489 return False;
490 }
491 /*endif*/
492 _Xi18nMessageHandler (ims, connect_id, packet, &delete);
493 if (delete == True)
494 XFree (packet);
495 /*endif*/
496 return True;
497 }
498 /*endif*/
499 return False;
500 }
501