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
******************************************************************/
33
#include <X11/Xatom.h>
40
extern Xi18nClient *_Xi18nFindClient(Xi18n, CARD16);
41
extern Xi18nClient *_Xi18nNewClient(Xi18n);
42
extern void _Xi18nDeleteClient(Xi18n, CARD16);
43
static Bool WaitXConnectMessage(Display*, Window,
45
static Bool WaitXIMProtocol(Display*, Window, XEvent*, XPointer);
47
static XClient *NewXClient (Xi18n i18n_core, Window new_client)
49
Display *dpy = i18n_core->address.dpy;
50
Xi18nClient *client = _Xi18nNewClient (i18n_core);
53
x_client = (XClient *) malloc (sizeof (XClient));
54
x_client->client_win = new_client;
55
x_client->accept_win = XCreateSimpleWindow (dpy,
56
DefaultRootWindow(dpy),
64
client->trans_rec = x_client;
65
return ((XClient *) x_client);
68
static unsigned char *ReadXIMMessage (XIMS ims,
69
XClientMessageEvent *ev,
72
Xi18n i18n_core = ims->protocol;
73
Xi18nClient *client = i18n_core->address.clients;
74
XClient *x_client = NULL;
76
extern XimFrameRec packet_header_fr[];
77
unsigned char *p = NULL;
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;
86
client = client->next;
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;
97
extern int _Xi18nNeedSwap (Xi18n, CARD16);
99
if (client->byte_order == '?')
101
if (hdr->major_opcode != XIM_CONNECT)
102
return (unsigned char *) NULL; /* can do nothing */
103
client->byte_order = (CARD8) rec[0];
106
fm = FrameMgrInit (packet_header_fr,
108
_Xi18nNeedSwap (i18n_core, *connect_id));
109
total_size = FrameMgrGetTotalSize (fm);
111
FrameMgrGetToken (fm, major_opcode);
112
FrameMgrGetToken (fm, minor_opcode);
113
FrameMgrGetToken (fm, length);
116
if ((p = (unsigned char *) malloc (total_size + length * 4)) == NULL)
117
return (unsigned char *) NULL;
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);
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];
133
Atom actual_type_ret;
134
int actual_format_ret;
135
unsigned long bytes_after_ret;
137
unsigned long nitems;
139
return_code = XGetWindowProperty (i18n_core->address.dpy,
140
x_client->accept_win,
151
if (return_code != Success || actual_format_ret == 0 || nitems == 0) {
152
if (return_code == Success)
154
return (unsigned char *) NULL;
156
if (length != nitems)
158
if (actual_format_ret == 16)
160
else if (actual_format_ret == 32)
163
/* if hit, it might be an error */
164
if ((p = (unsigned char *) malloc (length)) == NULL)
165
return (unsigned char *) NULL;
167
memmove (p, prop, length);
170
return (unsigned char *) p;
173
static void ReadXConnectMessage (XIMS ims, XClientMessageEvent *ev)
175
Xi18n i18n_core = ims->protocol;
176
XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
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);
184
if (ev->window != i18n_core->address.im_window)
185
return; /* incorrect connection request */
187
if (major_version != 0 || minor_version != 0)
191
/* Only supporting only-CM & Property-with-CM method */
194
_XRegisterFilterByType (dpy,
195
x_client->accept_win,
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;
218
static Bool Xi18nXBegin (XIMS ims)
220
Xi18n i18n_core = ims->protocol;
221
Display *dpy = i18n_core->address.dpy;
222
XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
224
spec->xim_request = XInternAtom (i18n_core->address.dpy,
227
spec->connect_request = XInternAtom (i18n_core->address.dpy,
231
_XRegisterFilterByType (dpy,
232
i18n_core->address.im_window,
240
static Bool Xi18nXEnd(XIMS ims)
242
Xi18n i18n_core = ims->protocol;
243
Display *dpy = i18n_core->address.dpy;
245
_XUnregisterFilter (dpy,
246
i18n_core->address.im_window,
252
static char *MakeNewAtom (CARD16 connect_id, char *atomName)
254
static int sequence = 0;
259
((sequence > 20) ? (sequence = 0) : sequence++));
263
static Bool Xi18nXSend (XIMS ims,
265
unsigned char *reply,
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;
274
event.type = ClientMessage;
275
event.xclient.window = x_client->client_win;
276
event.xclient.message_type = spec->xim_request;
278
if (length > XCM_DATA_LIMIT)
282
Atom actual_type_ret;
283
int actual_format_ret;
285
unsigned long nitems_ret;
286
unsigned long bytes_after_ret;
287
unsigned char *win_data;
289
event.xclient.format = 32;
290
atom = XInternAtom (i18n_core->address.dpy,
291
MakeNewAtom (connect_id, atomName),
293
return_code = XGetWindowProperty (i18n_core->address.dpy,
294
x_client->client_win,
305
if (return_code != Success)
309
XFree ((char *) win_data);
311
XChangeProperty (i18n_core->address.dpy,
312
x_client->client_win,
317
(unsigned char *) reply,
319
event.xclient.data.l[0] = length;
320
event.xclient.data.l[1] = atom;
324
unsigned char buffer[XCM_DATA_LIMIT];
327
event.xclient.format = 8;
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;
334
length = XCM_DATA_LIMIT;
335
memmove (event.xclient.data.b, buffer, length);
337
XSendEvent (i18n_core->address.dpy,
338
x_client->client_win,
342
XFlush (i18n_core->address.dpy);
346
static Bool CheckCMEvent (Display *display, XEvent *event, XPointer xi18n_core)
348
Xi18n i18n_core = (Xi18n) ((void *) xi18n_core);
349
XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
351
if ((event->type == ClientMessage)
353
(event->xclient.message_type == spec->xim_request))
361
static Bool Xi18nXWait (XIMS ims,
366
Xi18n i18n_core = ims->protocol;
368
Xi18nClient *client = _Xi18nFindClient (i18n_core, connect_id);
369
XClient *x_client = (XClient *) client->trans_rec;
373
unsigned char *packet;
377
XIfEvent (i18n_core->address.dpy,
380
(XPointer) i18n_core);
381
if (event.xclient.window == x_client->accept_win)
383
if ((packet = ReadXIMMessage (ims,
384
(XClientMessageEvent *) & event,
386
== (unsigned char*) NULL)
391
hdr = (XimProtoHdr *)packet;
393
if ((hdr->major_opcode == major_opcode)
395
(hdr->minor_opcode == minor_opcode))
399
else if (hdr->major_opcode == XIM_ERROR)
410
static Bool Xi18nXDisconnect (XIMS ims, CARD16 connect_id)
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;
417
XDestroyWindow (dpy, x_client->accept_win);
418
_XUnregisterFilter (dpy,
419
x_client->accept_win,
423
_Xi18nDeleteClient (i18n_core, connect_id);
427
Bool _Xi18nCheckXAddress (Xi18n i18n_core,
428
TransportSW *transSW,
433
if (!(spec = (XSpecRec *) malloc (sizeof (XSpecRec))))
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;
446
static Bool WaitXConnectMessage (Display *dpy,
449
XPointer client_data)
451
XIMS ims = (XIMS)client_data;
452
Xi18n i18n_core = ims->protocol;
453
XSpecRec *spec = (XSpecRec *) i18n_core->address.connect_addr;
455
if (((XClientMessageEvent *) ev)->message_type
456
== spec->connect_request)
458
ReadXConnectMessage (ims, (XClientMessageEvent *) ev);
465
static Bool WaitXIMProtocol (Display *dpy,
468
XPointer client_data)
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;
475
unsigned char *packet;
478
if (((XClientMessageEvent *) ev)->message_type
479
== spec->xim_request)
481
if ((packet = ReadXIMMessage (ims,
482
(XClientMessageEvent *) ev,
484
== (unsigned char *) NULL)
489
_Xi18nMessageHandler (ims, connect_id, packet, &delete);