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