~ubuntu-branches/ubuntu/trusty/hime/trusty

« back to all changes in this revision

Viewing changes to src/IMdkit/lib/i18nX.c

  • Committer: Package Import Robot
  • Author(s): Yao Wei (魏銘廷)
  • Date: 2012-01-14 00:24:08 UTC
  • Revision ID: package-import@ubuntu.com-20120114002408-e79gagbeg1rt8npv
Tags: upstream-0.9.9
Import upstream version 0.9.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
}