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);