~ubuntu-branches/ubuntu/maverick/uim/maverick

« back to all changes in this revision

Viewing changes to gtk/compose.c

  • Committer: Bazaar Package Importer
  • Author(s): Masahito Omote
  • Date: 2006-11-23 15:10:53 UTC
  • mfrom: (3.1.8 edgy)
  • Revision ID: james.westby@ubuntu.com-20061123151053-q42sk1lvks41xpfx
Tags: 1:1.2.1-9
uim-gtk2.0.postinst: Don't call update-gtk-immodules on purge.
(closes: Bug#398530)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
  Copyright (c) 2003-2006 uim Project http://uim.freedesktop.org/
 
4
 
 
5
  All rights reserved.
 
6
 
 
7
  Redistribution and use in source and binary forms, with or without
 
8
  modification, are permitted provided that the following conditions
 
9
  are met:
 
10
 
 
11
  1. Redistributions of source code must retain the above copyright
 
12
     notice, this list of conditions and the following disclaimer.
 
13
  2. Redistributions in binary form must reproduce the above copyright
 
14
     notice, this list of conditions and the following disclaimer in the
 
15
     documentation and/or other materials provided with the distribution.
 
16
  3. Neither the name of authors nor the names of its contributors
 
17
     may be used to endorse or promote products derived from this software
 
18
     without specific prior written permission.
 
19
 
 
20
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
 
21
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
22
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
23
  ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
 
24
  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
25
  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
26
  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
27
  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
28
  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
29
  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
30
  SUCH DAMAGE.
 
31
*/
 
32
 
 
33
#include <config.h>
 
34
 
 
35
#include <stdio.h>
 
36
#include <ctype.h>
 
37
#include <stdlib.h>
 
38
#include <string.h>
 
39
#include <sys/stat.h>
 
40
#include <locale.h>
 
41
#include <errno.h>
 
42
 
 
43
#include <X11/keysym.h>
 
44
#include <X11/Xlib.h>
 
45
#include <X11/Xutil.h>
 
46
 
 
47
#include <glib.h>
 
48
 
 
49
#include "gtk-im-uim.h"
 
50
#include "compose.h"
 
51
 
 
52
#define COMPOSE_FILE    "Compose"
 
53
#define COMPOSE_DIR_FILE        "X11/locale/compose.dir"
 
54
#define XLOCALE_DIR     "X11/locale"
 
55
#define FALLBACK_XLIB_DIR       "/usr/X11R6/lib"
 
56
 
 
57
#define XLC_BUFSIZE     256
 
58
#define iscomment(ch)   ((ch) == '#' || (ch) == '\0')
 
59
 
 
60
#ifdef GDK_WINDOWING_X11
 
61
int compose_handle_key(GdkEventKey *event, IMUIMContext *uic);
 
62
 
 
63
static int parse_line(char *line, char **argv, int argsize);
 
64
static unsigned int KeySymToUcs4(KeySym keysym);
 
65
static char *get_compose_filename(void);
 
66
static void ParseComposeStringFile(FILE *fp);
 
67
static char *get_lang_region(void);
 
68
 
 
69
static DefTree *g_tree;
 
70
 
 
71
Compose *
 
72
im_uim_compose_new()
 
73
{
 
74
    DefTree *top = g_tree;
 
75
    Compose *p;
 
76
 
 
77
    p = malloc(sizeof(Compose));
 
78
    if (p) {
 
79
        p->m_composed = NULL;
 
80
        p->m_top = top;
 
81
        p->m_context = top;
 
82
    }
 
83
 
 
84
    return p;
 
85
}
 
86
 
 
87
static int
 
88
handleKey(unsigned int xkeysym, unsigned int xkeystate, int is_push,
 
89
                     IMUIMContext *uic)
 
90
{
 
91
    DefTree *p;
 
92
    DefTree *m_top = uic->compose->m_top;
 
93
    DefTree *m_context = uic->compose->m_context;
 
94
 
 
95
    if ((is_push == 0)  || m_top == NULL)
 
96
        return 0;
 
97
 
 
98
    if (IsModifierKey(xkeysym))
 
99
        return 0;
 
100
 
 
101
    for (p = m_context; p ; p = p->next) {
 
102
        if (((xkeystate & p->modifier_mask) == p->modifier) &&
 
103
                (xkeysym == p->keysym)) {
 
104
            break;
 
105
        }
 
106
    }
 
107
 
 
108
    if (p) { /* Matched */
 
109
        if (p->succession) { /* Intermediate */
 
110
            uic->compose->m_context = p->succession;
 
111
            return 1;
 
112
        } else { /* Terminate (reached to leaf) */
 
113
            uic->compose->m_composed = p;
 
114
            /* commit string here */
 
115
            im_uim_commit_string(uic, uic->compose->m_composed->utf8);
 
116
            /* initialize internal state for next key sequence */
 
117
            uic->compose->m_context = m_top;
 
118
            return 1;
 
119
        }
 
120
    } else { /* Unmatched */
 
121
        if (m_context == m_top)
 
122
            return 0;
 
123
        /* Error (Sequence Unmatch occurred) */
 
124
        uic->compose->m_context = m_top;
 
125
        return 1;
 
126
    }
 
127
}
 
128
 
 
129
void
 
130
im_uim_compose_reset(Compose *compose)
 
131
{
 
132
    compose->m_context = compose->m_top;
 
133
    compose->m_composed = NULL;
 
134
}
 
135
 
 
136
static int
 
137
nextch(FILE *fp, int *lastch)
 
138
{
 
139
    int c;
 
140
 
 
141
    if (*lastch != 0) {
 
142
        c = *lastch;
 
143
        *lastch = 0;
 
144
    } else {
 
145
        c = getc(fp);
 
146
        if (c == '\\') {
 
147
            c = getc(fp);
 
148
            if (c == '\n') {
 
149
                c = getc(fp);
 
150
            } else {
 
151
                ungetc(c, fp);
 
152
                c = '\\';
 
153
            }
 
154
        }
 
155
    }
 
156
    return(c);
 
157
}
 
158
 
 
159
static void
 
160
putbackch(int c, int *lastch)
 
161
{
 
162
    *lastch = c;
 
163
}
 
164
 
 
165
 
 
166
#define ENDOFFILE 0
 
167
#define ENDOFLINE 1
 
168
#define COLON 2
 
169
#define LESS 3
 
170
#define GREATER 4
 
171
#define EXCLAM 5
 
172
#define TILDE 6
 
173
#define STRING 7
 
174
#define KEY 8
 
175
#define ERROR 9
 
176
 
 
177
 
 
178
#ifndef isalnum
 
179
#define isalnum(c)      \
 
180
    (('0' <= (c) && (c) <= '9')  || \
 
181
     ('A' <= (c) && (c) <= 'Z')  || \
 
182
     ('a' <= (c) && (c) <= 'z'))
 
183
#endif
 
184
 
 
185
static int
 
186
nexttoken(FILE *fp, char *tokenbuf, int *lastch)
 
187
{
 
188
    int c;
 
189
    int token;
 
190
    char *p;
 
191
    int i, j;
 
192
 
 
193
    while ((c = nextch(fp, lastch)) == ' ' || c == '\t') {
 
194
    }
 
195
    switch (c) {
 
196
    case EOF:
 
197
        token = ENDOFFILE;
 
198
        break;
 
199
    case '\n':
 
200
        token = ENDOFLINE;
 
201
        break;
 
202
    case '<':
 
203
        token = LESS;
 
204
        break;
 
205
    case '>':
 
206
        token = GREATER;
 
207
        break;
 
208
    case ':':
 
209
        token = COLON;
 
210
        break;
 
211
    case '!':
 
212
        token = EXCLAM;
 
213
        break;
 
214
    case '~':
 
215
        token = TILDE;
 
216
        break;
 
217
    case '"':
 
218
        p = tokenbuf;
 
219
        while ((c = nextch(fp, lastch)) != '"') {
 
220
            if (c == '\n' || c == EOF) {
 
221
                putbackch(c, lastch);
 
222
                token = ERROR;
 
223
                goto string_error;
 
224
            } else if (c == '\\') {
 
225
                c = nextch(fp, lastch);
 
226
                switch (c) {
 
227
                case '\\':
 
228
                case '"':
 
229
                    *p++ = c;
 
230
                    break;
 
231
                case 'n':
 
232
                    *p++ = '\n';
 
233
                    break;
 
234
                case 'r':
 
235
                    *p++ = '\r';
 
236
                    break;
 
237
                case 't':
 
238
                    *p++ = '\t';
 
239
                    break;
 
240
                case '0':
 
241
                case '1':
 
242
                case '2':
 
243
                case '3':
 
244
                case '4':
 
245
                case '5':
 
246
                case '6':
 
247
                case '7':
 
248
                    i = c - '0';
 
249
                    c = nextch(fp, lastch);
 
250
                    for (j = 0; j < 2 && c >= '0' && c <= '7'; j++) {
 
251
                        i <<= 3;
 
252
                        i += c - '0';
 
253
                        c = nextch(fp, lastch);
 
254
                    }
 
255
                    putbackch(c, lastch);
 
256
                    *p++ = (char)i;
 
257
                    break;
 
258
                case 'X':
 
259
                case 'x':
 
260
                    i = 0;
 
261
                    for (j = 0; j < 2; j++) {
 
262
                        c = nextch(fp, lastch);
 
263
                        i <<= 4;
 
264
                        if (c >= '0' && c <= '9') {
 
265
                            i += c - '0';
 
266
                        } else if (c >= 'A' && c <= 'F') {
 
267
                            i += c - 'A' + 10;
 
268
                        } else if (c >= 'a' && c <= 'f') {
 
269
                            i += c - 'a' + 10;
 
270
                        } else {
 
271
                            putbackch(c, lastch);
 
272
                            i >>= 4;
 
273
                            break;
 
274
                        }
 
275
                    }
 
276
                    if (j == 0) {
 
277
                        token = ERROR;
 
278
                        goto string_error;
 
279
                    }
 
280
                    *p++ = (char)i;
 
281
                    break;
 
282
                case EOF:
 
283
                    putbackch(c, lastch);
 
284
                    token = ERROR;
 
285
                    goto string_error;
 
286
                default:
 
287
                    *p++ = c;
 
288
                    break;
 
289
                }
 
290
            } else {
 
291
                *p++ = c;
 
292
            }
 
293
        }
 
294
        *p = '\0';
 
295
        token = STRING;
 
296
        break;
 
297
    case '#':
 
298
        while ((c = nextch(fp, lastch)) != '\n' && c != EOF) {
 
299
        }
 
300
        if (c == '\n') {
 
301
            token = ENDOFLINE;
 
302
        } else {
 
303
            token = ENDOFFILE;
 
304
        }
 
305
        break;
 
306
    default:
 
307
        if (isalnum(c) || c == '_' || c == '-') {
 
308
            p = tokenbuf;
 
309
            *p++ = c;
 
310
            c = nextch(fp, lastch);
 
311
            while (isalnum(c) || c == '_' || c == '-') {
 
312
                *p++ = c;
 
313
                c = nextch(fp, lastch);
 
314
            }
 
315
            *p = '\0';
 
316
            putbackch(c, lastch);
 
317
            token = KEY;
 
318
        } else {
 
319
            token = ERROR;
 
320
        }
 
321
        break;
 
322
    }
 
323
string_error:
 
324
    return(token);
 
325
}
 
326
 
 
327
static long
 
328
modmask(char *name)
 
329
{
 
330
    long mask;
 
331
 
 
332
    struct _modtbl {
 
333
        const char *name;
 
334
        long mask;
 
335
    };
 
336
    struct _modtbl *p;
 
337
 
 
338
    static struct _modtbl tbl[] = {
 
339
        { "Ctrl",       ControlMask     },
 
340
        { "Lock",       LockMask        },
 
341
        { "Caps",       LockMask        },
 
342
        { "Shift",      ShiftMask       },
 
343
        { "Alt",        Mod1Mask        },
 
344
        { "Meta",       Mod1Mask        },
 
345
        { NULL,  0             }};
 
346
 
 
347
    p = tbl;
 
348
    mask = 0;
 
349
    for (p = tbl; p->name != NULL; p++) {
 
350
        if (strcmp(name, p->name) == 0) {
 
351
            mask = p->mask;
 
352
            break;
 
353
        }
 
354
    }
 
355
    return(mask);
 
356
}
 
357
 
 
358
static char *
 
359
TransFileName(char *name)
 
360
{
 
361
    char *home = NULL, *lcCompose = NULL;
 
362
    char *i = name, *ret, *j;
 
363
    int l = 0;
 
364
 
 
365
    while (*i) {
 
366
        if (*i == '%') {
 
367
            i++;
 
368
            switch (*i) {
 
369
            case '%':
 
370
                l++;
 
371
                break;
 
372
            case 'H':
 
373
                home = getenv("HOME");
 
374
                if (home)
 
375
                    l += strlen(home);
 
376
                break;
 
377
            case 'L':
 
378
                lcCompose = get_compose_filename();
 
379
                if (lcCompose)
 
380
                    l += strlen(lcCompose);
 
381
                break;
 
382
            }
 
383
        } else {
 
384
            l++;
 
385
        }
 
386
        i++;
 
387
    }
 
388
 
 
389
    j = ret = (char *)malloc(l + 1);
 
390
    if (ret == NULL)
 
391
        return ret;
 
392
    i = name;
 
393
    while (*i) {
 
394
        if (*i == '%') {
 
395
            i++;
 
396
            switch (*i) {
 
397
            case '%':
 
398
                *j++ = '%';
 
399
                break;
 
400
            case 'H':
 
401
                if (home) {
 
402
                    strcpy(j, home);
 
403
                    j += strlen(home);
 
404
                }
 
405
                break;
 
406
            case 'L':
 
407
                if (lcCompose) {
 
408
                    strcpy(j, lcCompose);
 
409
                    j += strlen(lcCompose);
 
410
                    free(lcCompose);
 
411
                }
 
412
                break;
 
413
            }
 
414
            i++;
 
415
        } else {
 
416
            *j++ = *i++;
 
417
        }
 
418
    }
 
419
    *j = '\0';
 
420
    return ret;
 
421
}
 
422
 
 
423
#ifndef MB_LEN_MAX
 
424
#define MB_LEN_MAX 6
 
425
#endif
 
426
 
 
427
static int
 
428
get_mb_string(char *buf, KeySym ks)
 
429
{
 
430
    int len;
 
431
    char local_buf[MB_LEN_MAX];
 
432
    char *mb;
 
433
    unsigned int ucs;
 
434
 
 
435
    ucs = KeySymToUcs4(ks);
 
436
    len = g_unichar_to_utf8(ucs, local_buf);
 
437
    local_buf[len] = '\0';
 
438
    mb = g_locale_from_utf8(local_buf, -1, NULL, NULL, NULL);
 
439
    if (!mb)
 
440
        return 0;
 
441
    len = strlen(mb);
 
442
    strlcpy(buf, mb, MB_LEN_MAX + 1);
 
443
    free(mb);
 
444
 
 
445
    return len;
 
446
}
 
447
 
 
448
#define AllMask (ShiftMask | LockMask | ControlMask | Mod1Mask)
 
449
#define LOCAL_UTF8_BUFSIZE 256
 
450
#define SEQUENCE_MAX    10
 
451
 
 
452
static int
 
453
parse_compose_line(FILE *fp, char* tokenbuf)
 
454
{
 
455
    int token;
 
456
    unsigned modifier_mask;
 
457
    unsigned modifier;
 
458
    unsigned tmp;
 
459
    KeySym keysym = NoSymbol;
 
460
    DefTree **top = &g_tree;
 
461
    DefTree *p = NULL;
 
462
    Bool exclam, tilde;
 
463
    KeySym rhs_keysym = 0;
 
464
    char *rhs_string_mb;
 
465
    int l = 0;
 
466
    int lastch = 0;
 
467
    char local_mb_buf[MB_LEN_MAX + 1];
 
468
    char *rhs_string_utf8;
 
469
 
 
470
    struct DefBuffer {
 
471
        unsigned modifier_mask;
 
472
        unsigned modifier;
 
473
        KeySym keysym;
 
474
    };
 
475
 
 
476
    struct DefBuffer buf[SEQUENCE_MAX];
 
477
    int i, n;
 
478
    const char *encoding;
 
479
    g_get_charset(&encoding);
 
480
 
 
481
    do {
 
482
        token = nexttoken(fp, tokenbuf, &lastch);
 
483
    } while (token == ENDOFLINE);
 
484
 
 
485
    if (token == ENDOFFILE) {
 
486
        return(-1);
 
487
    }
 
488
 
 
489
    n = 0;
 
490
    do {
 
491
        if ((token == KEY) && (strcmp("include", tokenbuf) == 0)) {
 
492
            char *filename;
 
493
            FILE *infp;
 
494
            token = nexttoken(fp, tokenbuf, &lastch);
 
495
            if (token != KEY && token != STRING)
 
496
                goto error;
 
497
 
 
498
            if ((filename = TransFileName(tokenbuf)) == NULL)
 
499
                goto error;
 
500
            infp = fopen(filename, "r");
 
501
            free(filename);
 
502
            if (infp == NULL)
 
503
                goto error;
 
504
            ParseComposeStringFile(infp);
 
505
            return (0);
 
506
        } else if ((token == KEY) && (strcmp("None", tokenbuf) == 0)) {
 
507
            modifier = 0;
 
508
            modifier_mask = AllMask;
 
509
            token = nexttoken(fp, tokenbuf, &lastch);
 
510
        } else {
 
511
            modifier_mask = modifier = 0;
 
512
            exclam = False;
 
513
            if (token == EXCLAM) {
 
514
                exclam = True;
 
515
                token = nexttoken(fp, tokenbuf, &lastch);
 
516
            }
 
517
            while (token == TILDE || token == KEY) {
 
518
                tilde = False;
 
519
                if (token == TILDE) {
 
520
                    tilde = True;
 
521
                    token = nexttoken(fp, tokenbuf, &lastch);
 
522
                    if (token != KEY)
 
523
                        goto error;
 
524
                }
 
525
                tmp = modmask(tokenbuf);
 
526
                if (!tmp) {
 
527
                    goto error;
 
528
                }
 
529
                modifier_mask |= tmp;
 
530
                if (tilde) {
 
531
                    modifier &= ~tmp;
 
532
                } else {
 
533
                    modifier |= tmp;
 
534
                }
 
535
                token = nexttoken(fp, tokenbuf, &lastch);
 
536
            }
 
537
            if (exclam) {
 
538
                modifier_mask = AllMask;
 
539
 
 
540
            }
 
541
        }
 
542
 
 
543
        if (token != LESS) {
 
544
            goto error;
 
545
        }
 
546
 
 
547
        token = nexttoken(fp, tokenbuf, &lastch);
 
548
        if (token != KEY) {
 
549
            goto error;
 
550
        }
 
551
 
 
552
        token = nexttoken(fp, tokenbuf, &lastch);
 
553
        if (token != GREATER) {
 
554
            goto error;
 
555
        }
 
556
 
 
557
        keysym = XStringToKeysym(tokenbuf);
 
558
        if (keysym == NoSymbol) {
 
559
            goto error;
 
560
        }
 
561
 
 
562
        buf[n].keysym = keysym;
 
563
        buf[n].modifier = modifier;
 
564
        buf[n].modifier_mask = modifier_mask;
 
565
        n++;
 
566
        if (n >= SEQUENCE_MAX)
 
567
            goto error;
 
568
        token = nexttoken(fp, tokenbuf, &lastch);
 
569
    } while (token != COLON);
 
570
 
 
571
    token = nexttoken(fp, tokenbuf, &lastch);
 
572
    if (token == STRING) {
 
573
        if ((rhs_string_mb = (char *)malloc(strlen(tokenbuf) + 1)) == NULL)
 
574
            goto error;
 
575
        strcpy(rhs_string_mb, tokenbuf);
 
576
        token = nexttoken(fp, tokenbuf, &lastch);
 
577
        if (token == KEY) {
 
578
            rhs_keysym = XStringToKeysym(tokenbuf);
 
579
            if (rhs_keysym == NoSymbol) {
 
580
                free(rhs_string_mb);
 
581
                goto error;
 
582
            }
 
583
            token = nexttoken(fp, tokenbuf, &lastch);
 
584
        }
 
585
        if (token != ENDOFLINE && token != ENDOFFILE) {
 
586
            free(rhs_string_mb);
 
587
            goto error;
 
588
        }
 
589
    } else if (token == KEY) {
 
590
        rhs_keysym = XStringToKeysym(tokenbuf);
 
591
        if (rhs_keysym == NoSymbol) {
 
592
            goto error;
 
593
        }
 
594
        token = nexttoken(fp, tokenbuf, &lastch);
 
595
        if (token != ENDOFLINE && token != ENDOFFILE) {
 
596
            goto error;
 
597
        }
 
598
 
 
599
        l = get_mb_string(local_mb_buf, rhs_keysym);
 
600
        if (l == 0) {
 
601
            rhs_string_mb = (char *)malloc(1);
 
602
        } else {
 
603
            rhs_string_mb = (char *)malloc(l + 1);
 
604
        }
 
605
        if (rhs_string_mb == NULL) {
 
606
            goto error;
 
607
        }
 
608
        memcpy(rhs_string_mb, local_mb_buf, l);
 
609
        rhs_string_mb[l] = '\0';
 
610
    } else {
 
611
        goto error;
 
612
    }
 
613
 
 
614
    rhs_string_utf8 = g_locale_to_utf8(rhs_string_mb, -1, NULL, NULL, NULL);
 
615
 
 
616
    for (i = 0; i < n; i++) {
 
617
        for (p = *top; p; p = p->next) {
 
618
            if (buf[i].keysym == p->keysym &&
 
619
                buf[i].modifier == p->modifier &&
 
620
                buf[i].modifier_mask == p->modifier_mask) {
 
621
                break;
 
622
            }
 
623
        }
 
624
        if (p) {
 
625
            top = &p->succession;
 
626
        } else {
 
627
            if ((p = (DefTree*)malloc(sizeof(DefTree))) == NULL) {
 
628
                free(rhs_string_mb);
 
629
                goto error;
 
630
            }
 
631
            p->keysym = buf[i].keysym;
 
632
            p->modifier = buf[i].modifier;
 
633
            p->modifier_mask = buf[i].modifier_mask;
 
634
            p->succession = NULL;
 
635
            p->next = *top;
 
636
            p->mb = NULL;
 
637
            p->utf8 = NULL;
 
638
            p->ks = NoSymbol;
 
639
            *top = p;
 
640
            top = &p->succession;
 
641
        }
 
642
    }
 
643
 
 
644
    if (p->mb != NULL)
 
645
        free(p->mb);
 
646
    p->mb = rhs_string_mb;
 
647
    if (p->utf8 != NULL)
 
648
        free(p->utf8);
 
649
    p->utf8 = rhs_string_utf8;
 
650
    p->ks = rhs_keysym;
 
651
    return n;
 
652
error:
 
653
    while (token != ENDOFLINE && token != ENDOFFILE) {
 
654
        token = nexttoken(fp, tokenbuf, &lastch);
 
655
    }
 
656
    return 0;
 
657
}
 
658
 
 
659
static void
 
660
ParseComposeStringFile(FILE *fp)
 
661
{
 
662
    char tb[8192];
 
663
    char* tbp;
 
664
    struct stat st;
 
665
 
 
666
    if (fstat(fileno(fp), &st) != -1) {
 
667
        unsigned long size = (unsigned long)st.st_size;
 
668
        if (size <= sizeof tb)
 
669
            tbp = tb;
 
670
        else
 
671
            tbp = (char *)malloc(size);
 
672
 
 
673
        if (tbp != NULL) {
 
674
            while (parse_compose_line(fp, tbp) >= 0) {
 
675
            }
 
676
            if (tbp != tb)
 
677
                free (tbp);
 
678
        }
 
679
    }
 
680
}
 
681
 
 
682
static char *
 
683
get_lang_region()
 
684
{
 
685
    char *locale, *p;
 
686
 
 
687
    locale = setlocale(LC_CTYPE, NULL);
 
688
    if (locale) {
 
689
        locale = strdup(locale);
 
690
    } else {
 
691
        return NULL;
 
692
    }
 
693
 
 
694
    p = strrchr(locale, '.');
 
695
    if (p)
 
696
        *p = '\0';
 
697
 
 
698
    return locale;
 
699
}
 
700
 
 
701
void im_uim_create_compose_tree()
 
702
{
 
703
    FILE *fp = NULL;
 
704
    char *name, *tmpname = NULL;
 
705
    char *lang_region;
 
706
    const char *encoding;
 
707
 
 
708
    name = getenv("XCOMPOSEFILE");
 
709
 
 
710
    if (name == NULL) {
 
711
        char *home = getenv("HOME");
 
712
        if (home != NULL) {
 
713
            int hl = strlen(home);
 
714
            tmpname = name = (char *)malloc(hl + 10 + 1);
 
715
            if (name != NULL) {
 
716
                strcpy(name, home);
 
717
                strcpy(name + hl, "/.XCompose");
 
718
                fp = fopen(name, "r");
 
719
                if (fp == NULL) {
 
720
                    free(name);
 
721
                    name = tmpname = NULL;
 
722
                }
 
723
            }
 
724
        }
 
725
    }
 
726
 
 
727
    if (name == NULL) {
 
728
        tmpname = name = get_compose_filename();
 
729
    }
 
730
 
 
731
    if (name == NULL)
 
732
        return;
 
733
    if (fp == NULL) {
 
734
        fp = fopen(name, "r");
 
735
    }
 
736
    if (tmpname != NULL) {
 
737
        free(tmpname);
 
738
    }
 
739
    if (fp == NULL)
 
740
        return;
 
741
 
 
742
    lang_region = get_lang_region();
 
743
    g_get_charset(&encoding);
 
744
    if (lang_region == NULL || encoding == NULL) {
 
745
        fprintf(stderr, "Warning: locale name is NULL\n");
 
746
        free(lang_region);
 
747
        fclose(fp);
 
748
        return;
 
749
    }
 
750
 
 
751
    ParseComposeStringFile(fp);
 
752
    fclose(fp);
 
753
    free(lang_region);
 
754
}
 
755
 
 
756
static void
 
757
FreeComposeTree(DefTree *top)
 
758
{
 
759
    if (!top)
 
760
        return;
 
761
 
 
762
    if (top->succession)
 
763
        FreeComposeTree(top->succession);
 
764
    if (top->next)
 
765
        FreeComposeTree(top->next);
 
766
    free(top->mb);
 
767
    free(top->utf8);
 
768
    free(top);
 
769
}
 
770
 
 
771
void
 
772
im_uim_release_compose_tree()
 
773
{
 
774
    FreeComposeTree(g_tree);
 
775
}
 
776
 
 
777
static char *
 
778
get_compose_filename()
 
779
{
 
780
    char *compose_dir_file;
 
781
    char *locale;
 
782
    const char *encoding;
 
783
    char *lang_region;
 
784
 
 
785
    FILE *fp;
 
786
    char buf[XLC_BUFSIZE], *name = NULL, *filename = NULL;
 
787
    const char *xlib_dir = XLIB_DIR ;
 
788
 
 
789
    lang_region = get_lang_region();
 
790
    g_get_charset(&encoding);
 
791
 
 
792
    if (lang_region == NULL || encoding == NULL) {
 
793
        free(lang_region);
 
794
        return NULL;
 
795
    }
 
796
 
 
797
    locale = (char *)malloc(strlen(lang_region) + strlen(encoding) + 2);
 
798
    if (locale == NULL) {
 
799
        free(lang_region);
 
800
        return NULL;
 
801
    }
 
802
    sprintf(locale, "%s.%s", lang_region, encoding);
 
803
    free(lang_region);
 
804
 
 
805
    compose_dir_file = (char *)malloc(strlen(XLIB_DIR) + strlen(COMPOSE_DIR_FILE) + 2);
 
806
    if (compose_dir_file == NULL) {
 
807
        free(locale);
 
808
        return NULL;
 
809
    }
 
810
    sprintf(compose_dir_file, "%s/%s", XLIB_DIR, COMPOSE_DIR_FILE);
 
811
 
 
812
    fp = fopen(compose_dir_file, "r");
 
813
    if (fp == NULL) {
 
814
        /* retry with fallback file */
 
815
        if (strcmp(FALLBACK_XLIB_DIR, XLIB_DIR)) {
 
816
            compose_dir_file = (char *)realloc(compose_dir_file,
 
817
                            strlen(FALLBACK_XLIB_DIR) +
 
818
                            strlen(COMPOSE_DIR_FILE) + 2);
 
819
            if (compose_dir_file == NULL) {
 
820
                free(locale);
 
821
                return NULL;
 
822
            }
 
823
            sprintf(compose_dir_file, "%s/%s",
 
824
                            FALLBACK_XLIB_DIR, COMPOSE_DIR_FILE);
 
825
            fp = fopen(compose_dir_file, "r");
 
826
            if (fp == NULL) {
 
827
                free(locale);
 
828
                free(compose_dir_file);
 
829
                return NULL;
 
830
            }
 
831
            xlib_dir = FALLBACK_XLIB_DIR;
 
832
        } else {
 
833
            free(locale);
 
834
            free(compose_dir_file);
 
835
            return NULL;
 
836
        }
 
837
    }
 
838
 
 
839
    while (fgets(buf, XLC_BUFSIZE, fp) != NULL) {
 
840
        char *p = buf;
 
841
        int n;
 
842
        char *args[2], *from, *to;
 
843
        while (isspace(*p)) {
 
844
            ++p;
 
845
        }
 
846
        if (iscomment(*p)) {
 
847
            continue;
 
848
        }
 
849
        n = parse_line(p, args, 2);
 
850
        if (n != 2) {
 
851
            continue;
 
852
        }
 
853
        from = args[1], to = args[0];
 
854
        if (!strcmp(from, locale)) {
 
855
            name = (char *)malloc(strlen(to) + 1);
 
856
            if (name != NULL) {
 
857
                strcpy(name, to);
 
858
            }
 
859
            break;
 
860
        }
 
861
    }
 
862
    fclose(fp);
 
863
    free(locale);
 
864
    free(compose_dir_file);
 
865
 
 
866
    if (name == NULL)
 
867
        return NULL;
 
868
 
 
869
    filename = (char *)malloc(strlen(xlib_dir) + strlen(XLOCALE_DIR) +
 
870
                    strlen(name) + 3);
 
871
    if (filename == NULL)
 
872
        return NULL;
 
873
    sprintf(filename, "%s/%s/%s", xlib_dir, XLOCALE_DIR, name);
 
874
    free(name);
 
875
 
 
876
    return filename;
 
877
}
 
878
 
 
879
static int
 
880
parse_line(char *line, char **argv, int argsize)
 
881
{
 
882
    int argc = 0;
 
883
    char *p = line;
 
884
 
 
885
    while (argc < argsize) {
 
886
        while (isspace(*p)) {
 
887
            ++p;
 
888
        }
 
889
        if (*p == '\0') {
 
890
            break;
 
891
        }
 
892
        argv[argc++] = p;
 
893
        while (*p != ':' && *p != '\n' && *p != '\0') {
 
894
            ++p;
 
895
        }
 
896
        if (*p == '\0') {
 
897
            break;
 
898
        }
 
899
        *p++ = '\0';
 
900
    }
 
901
 
 
902
    return argc;
 
903
}
 
904
 
 
905
static unsigned short const keysym_to_unicode_1a1_1ff[] = {
 
906
            0x0104, 0x02d8, 0x0141, 0x0000, 0x013d, 0x015a, 0x0000, /* 0x01a0-0x01a7 */
 
907
    0x0000, 0x0160, 0x015e, 0x0164, 0x0179, 0x0000, 0x017d, 0x017b, /* 0x01a8-0x01af */
 
908
    0x0000, 0x0105, 0x02db, 0x0142, 0x0000, 0x013e, 0x015b, 0x02c7, /* 0x01b0-0x01b7 */
 
909
    0x0000, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, /* 0x01b8-0x01bf */
 
910
    0x0154, 0x0000, 0x0000, 0x0102, 0x0000, 0x0139, 0x0106, 0x0000, /* 0x01c0-0x01c7 */
 
911
    0x010c, 0x0000, 0x0118, 0x0000, 0x011a, 0x0000, 0x0000, 0x010e, /* 0x01c8-0x01cf */
 
912
    0x0110, 0x0143, 0x0147, 0x0000, 0x0000, 0x0150, 0x0000, 0x0000, /* 0x01d0-0x01d7 */
 
913
    0x0158, 0x016e, 0x0000, 0x0170, 0x0000, 0x0000, 0x0162, 0x0000, /* 0x01d8-0x01df */
 
914
    0x0155, 0x0000, 0x0000, 0x0103, 0x0000, 0x013a, 0x0107, 0x0000, /* 0x01e0-0x01e7 */
 
915
    0x010d, 0x0000, 0x0119, 0x0000, 0x011b, 0x0000, 0x0000, 0x010f, /* 0x01e8-0x01ef */
 
916
    0x0111, 0x0144, 0x0148, 0x0000, 0x0000, 0x0151, 0x0000, 0x0000, /* 0x01f0-0x01f7 */
 
917
    0x0159, 0x016f, 0x0000, 0x0171, 0x0000, 0x0000, 0x0163, 0x02d9  /* 0x01f8-0x01ff */
 
918
};
 
919
 
 
920
static unsigned short const keysym_to_unicode_2a1_2fe[] = {
 
921
            0x0126, 0x0000, 0x0000, 0x0000, 0x0000, 0x0124, 0x0000, /* 0x02a0-0x02a7 */
 
922
    0x0000, 0x0130, 0x0000, 0x011e, 0x0134, 0x0000, 0x0000, 0x0000, /* 0x02a8-0x02af */
 
923
    0x0000, 0x0127, 0x0000, 0x0000, 0x0000, 0x0000, 0x0125, 0x0000, /* 0x02b0-0x02b7 */
 
924
    0x0000, 0x0131, 0x0000, 0x011f, 0x0135, 0x0000, 0x0000, 0x0000, /* 0x02b8-0x02bf */
 
925
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x010a, 0x0108, 0x0000, /* 0x02c0-0x02c7 */
 
926
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x02c8-0x02cf */
 
927
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0120, 0x0000, 0x0000, /* 0x02d0-0x02d7 */
 
928
    0x011c, 0x0000, 0x0000, 0x0000, 0x0000, 0x016c, 0x015c, 0x0000, /* 0x02d8-0x02df */
 
929
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x010b, 0x0109, 0x0000, /* 0x02e0-0x02e7 */
 
930
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x02e8-0x02ef */
 
931
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0121, 0x0000, 0x0000, /* 0x02f0-0x02f7 */
 
932
    0x011d, 0x0000, 0x0000, 0x0000, 0x0000, 0x016d, 0x015d        /* 0x02f8-0x02ff */
 
933
};
 
934
 
 
935
static unsigned short const keysym_to_unicode_3a2_3fe[] = {
 
936
                    0x0138, 0x0156, 0x0000, 0x0128, 0x013b, 0x0000, /* 0x03a0-0x03a7 */
 
937
    0x0000, 0x0000, 0x0112, 0x0122, 0x0166, 0x0000, 0x0000, 0x0000, /* 0x03a8-0x03af */
 
938
    0x0000, 0x0000, 0x0000, 0x0157, 0x0000, 0x0129, 0x013c, 0x0000, /* 0x03b0-0x03b7 */
 
939
    0x0000, 0x0000, 0x0113, 0x0123, 0x0167, 0x014a, 0x0000, 0x014b, /* 0x03b8-0x03bf */
 
940
    0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x012e, /* 0x03c0-0x03c7 */
 
941
    0x0000, 0x0000, 0x0000, 0x0000, 0x0116, 0x0000, 0x0000, 0x012a, /* 0x03c8-0x03cf */
 
942
    0x0000, 0x0145, 0x014c, 0x0136, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x03d0-0x03d7 */
 
943
    0x0000, 0x0172, 0x0000, 0x0000, 0x0000, 0x0168, 0x016a, 0x0000, /* 0x03d8-0x03df */
 
944
    0x0101, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x012f, /* 0x03e0-0x03e7 */
 
945
    0x0000, 0x0000, 0x0000, 0x0000, 0x0117, 0x0000, 0x0000, 0x012b, /* 0x03e8-0x03ef */
 
946
    0x0000, 0x0146, 0x014d, 0x0137, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x03f0-0x03f7 */
 
947
    0x0000, 0x0173, 0x0000, 0x0000, 0x0000, 0x0169, 0x016b        /* 0x03f8-0x03ff */
 
948
};
 
949
 
 
950
static unsigned short const keysym_to_unicode_4a1_4df[] = {
 
951
            0x3002, 0x3008, 0x3009, 0x3001, 0x30fb, 0x30f2, 0x30a1, /* 0x04a0-0x04a7 */
 
952
    0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3, /* 0x04a8-0x04af */
 
953
    0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad, /* 0x04b0-0x04b7 */
 
954
    0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd, /* 0x04b8-0x04bf */
 
955
    0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc, /* 0x04c0-0x04c7 */
 
956
    0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de, /* 0x04c8-0x04cf */
 
957
    0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9, /* 0x04d0-0x04d7 */
 
958
    0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c  /* 0x04d8-0x04df */
 
959
};
 
960
 
 
961
static unsigned short const keysym_to_unicode_590_5fe[] = {
 
962
    0x06f0, 0x06f1, 0x06f2, 0x06f3, 0x06f4, 0x06f5, 0x06f6, 0x06f7, /* 0x0590-0x0597 */
 
963
    0x06f8, 0x06f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x0598-0x059f */
 
964
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x066a, 0x0670, 0x0679, /* 0x05a0-0x05a7 */
 
965
        
 
966
    0x067e, 0x0686, 0x0688, 0x0691, 0x060c, 0x0000, 0x06d4, 0x0000, /* 0x05ac-0x05af */
 
967
    0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, /* 0x05b0-0x05b7 */
 
968
    0x0668, 0x0669, 0x0000, 0x061b, 0x0000, 0x0000, 0x0000, 0x061f, /* 0x05b8-0x05bf */
 
969
    0x0000, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, /* 0x05c0-0x05c7 */
 
970
    0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, /* 0x05c8-0x05cf */
 
971
    0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, /* 0x05d0-0x05d7 */
 
972
    0x0638, 0x0639, 0x063a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x05d8-0x05df */
 
973
    0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, /* 0x05e0-0x05e7 */
 
974
    0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d, 0x064e, 0x064f, /* 0x05e8-0x05ef */
 
975
    0x0650, 0x0651, 0x0652, 0x0653, 0x0654, 0x0655, 0x0698, 0x06a4, /* 0x05f0-0x05f7 */
 
976
    0x06a9, 0x06af, 0x06ba, 0x06be, 0x06cc, 0x06d2, 0x06c1        /* 0x05f8-0x05fe */
 
977
};
 
978
 
 
979
static unsigned short keysym_to_unicode_680_6ff[] = {
 
980
    0x0492, 0x0496, 0x049a, 0x049c, 0x04a2, 0x04ae, 0x04b0, 0x04b2, /* 0x0680-0x0687 */
 
981
    0x04b6, 0x04b8, 0x04ba, 0x0000, 0x04d8, 0x04e2, 0x04e8, 0x04ee, /* 0x0688-0x068f */
 
982
    0x0493, 0x0497, 0x049b, 0x049d, 0x04a3, 0x04af, 0x04b1, 0x04b3, /* 0x0690-0x0697 */
 
983
    0x04b7, 0x04b9, 0x04bb, 0x0000, 0x04d9, 0x04e3, 0x04e9, 0x04ef, /* 0x0698-0x069f */
 
984
    0x0000, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457, /* 0x06a0-0x06a7 */
 
985
    0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x0491, 0x045e, 0x045f, /* 0x06a8-0x06af */
 
986
    0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407, /* 0x06b0-0x06b7 */
 
987
    0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x0490, 0x040e, 0x040f, /* 0x06b8-0x06bf */
 
988
    0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, /* 0x06c0-0x06c7 */
 
989
    0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, /* 0x06c8-0x06cf */
 
990
    0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, /* 0x06d0-0x06d7 */
 
991
    0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a, /* 0x06d8-0x06df */
 
992
    0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, /* 0x06e0-0x06e7 */
 
993
    0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, /* 0x06e8-0x06ef */
 
994
    0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, /* 0x06f0-0x06f7 */
 
995
    0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a  /* 0x06f8-0x06ff */
 
996
};
 
997
 
 
998
static unsigned short const keysym_to_unicode_7a1_7f9[] = {
 
999
            0x0386, 0x0388, 0x0389, 0x038a, 0x03aa, 0x0000, 0x038c, /* 0x07a0-0x07a7 */
 
1000
    0x038e, 0x03ab, 0x0000, 0x038f, 0x0000, 0x0000, 0x0385, 0x2015, /* 0x07a8-0x07af */
 
1001
    0x0000, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03ca, 0x0390, 0x03cc, /* 0x07b0-0x07b7 */
 
1002
    0x03cd, 0x03cb, 0x03b0, 0x03ce, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x07b8-0x07bf */
 
1003
    0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, /* 0x07c0-0x07c7 */
 
1004
    0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, /* 0x07c8-0x07cf */
 
1005
    0x03a0, 0x03a1, 0x03a3, 0x0000, 0x03a4, 0x03a5, 0x03a6, 0x03a7, /* 0x07d0-0x07d7 */
 
1006
    0x03a8, 0x03a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x07d8-0x07df */
 
1007
    0x0000, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, /* 0x07e0-0x07e7 */
 
1008
    0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, /* 0x07e8-0x07ef */
 
1009
    0x03c0, 0x03c1, 0x03c3, 0x03c2, 0x03c4, 0x03c5, 0x03c6, 0x03c7, /* 0x07f0-0x07f7 */
 
1010
    0x03c8, 0x03c9                                                /* 0x07f8-0x07ff */
 
1011
};
 
1012
 
 
1013
static unsigned short const keysym_to_unicode_8a4_8fe[] = {
 
1014
                                    0x2320, 0x2321, 0x0000, 0x231c, /* 0x08a0-0x08a7 */
 
1015
    0x231d, 0x231e, 0x231f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08a8-0x08af */
 
1016
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08b0-0x08b7 */
 
1017
    0x0000, 0x0000, 0x0000, 0x0000, 0x2264, 0x2260, 0x2265, 0x222b, /* 0x08b8-0x08bf */
 
1018
    0x2234, 0x0000, 0x221e, 0x0000, 0x0000, 0x2207, 0x0000, 0x0000, /* 0x08c0-0x08c7 */
 
1019
    0x2245, 0x2246, 0x0000, 0x0000, 0x0000, 0x0000, 0x22a2, 0x0000, /* 0x08c8-0x08cf */
 
1020
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x221a, 0x0000, /* 0x08d0-0x08d7 */
 
1021
    0x0000, 0x0000, 0x2282, 0x2283, 0x2229, 0x222a, 0x2227, 0x2228, /* 0x08d8-0x08df */
 
1022
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08e0-0x08e7 */
 
1023
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08e8-0x08ef */
 
1024
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192, 0x0000, /* 0x08f0-0x08f7 */
 
1025
    0x0000, 0x0000, 0x0000, 0x2190, 0x2191, 0x2192, 0x2193        /* 0x08f8-0x08ff */
 
1026
};
 
1027
 
 
1028
static unsigned short const keysym_to_unicode_9df_9f8[] = {
 
1029
                                                            0x2422, /* 0x09d8-0x09df */
 
1030
    0x2666, 0x25a6, 0x2409, 0x240c, 0x240d, 0x240a, 0x0000, 0x0000, /* 0x09e0-0x09e7 */
 
1031
    0x240a, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x2500, /* 0x09e8-0x09ef */
 
1032
    0x0000, 0x0000, 0x0000, 0x0000, 0x251c, 0x2524, 0x2534, 0x252c, /* 0x09f0-0x09f7 */
 
1033
    0x2502                                                        /* 0x09f8-0x09ff */
 
1034
};
 
1035
 
 
1036
static unsigned short const keysym_to_unicode_aa1_afe[] = {
 
1037
            0x2003, 0x2002, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009, /* 0x0aa0-0x0aa7 */
 
1038
    0x200a, 0x2014, 0x2013, 0x0000, 0x0000, 0x0000, 0x2026, 0x2025, /* 0x0aa8-0x0aaf */
 
1039
    0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a, /* 0x0ab0-0x0ab7 */
 
1040
    0x2105, 0x0000, 0x0000, 0x2012, 0x2039, 0x2024, 0x203a, 0x0000, /* 0x0ab8-0x0abf */
 
1041
    0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e, 0x0000, /* 0x0ac0-0x0ac7 */
 
1042
    0x0000, 0x2122, 0x2120, 0x0000, 0x25c1, 0x25b7, 0x25cb, 0x25ad, /* 0x0ac8-0x0acf */
 
1043
    0x2018, 0x2019, 0x201c, 0x201d, 0x211e, 0x0000, 0x2032, 0x2033, /* 0x0ad0-0x0ad7 */
 
1044
    0x0000, 0x271d, 0x0000, 0x220e, 0x25c2, 0x2023, 0x25cf, 0x25ac, /* 0x0ad8-0x0adf */
 
1045
    0x25e6, 0x25ab, 0x25ae, 0x25b5, 0x25bf, 0x2606, 0x2022, 0x25aa, /* 0x0ae0-0x0ae7 */
 
1046
    0x25b4, 0x25be, 0x261a, 0x261b, 0x2663, 0x2666, 0x2665, 0x0000, /* 0x0ae8-0x0aef */
 
1047
    0x2720, 0x2020, 0x2021, 0x2713, 0x2612, 0x266f, 0x266d, 0x2642, /* 0x0af0-0x0af7 */
 
1048
    0x2640, 0x2121, 0x2315, 0x2117, 0x2038, 0x201a, 0x201e        /* 0x0af8-0x0aff */
 
1049
};
 
1050
 
 
1051
/* none of the APL keysyms match the Unicode characters */
 
1052
 
 
1053
static unsigned short const keysym_to_unicode_cdf_cfa[] = {
 
1054
                                                            0x2017, /* 0x0cd8-0x0cdf */
 
1055
    0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, /* 0x0ce0-0x0ce7 */
 
1056
    0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, /* 0x0ce8-0x0cef */
 
1057
    0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, /* 0x0cf0-0x0cf7 */
 
1058
    0x05e8, 0x05e9, 0x05ea                                        /* 0x0cf8-0x0cff */
 
1059
};
 
1060
 
 
1061
static unsigned short const keysym_to_unicode_da1_df9[] = {
 
1062
            0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, /* 0x0da0-0x0da7 */
 
1063
    0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, /* 0x0da8-0x0daf */
 
1064
    0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, /* 0x0db0-0x0db7 */
 
1065
    0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, /* 0x0db8-0x0dbf */
 
1066
    0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, /* 0x0dc0-0x0dc7 */
 
1067
    0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, /* 0x0dc8-0x0dcf */
 
1068
    0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, /* 0x0dd0-0x0dd7 */
 
1069
    0x0e38, 0x0e39, 0x0e3a, 0x0000, 0x0000, 0x0000, 0x0e3e, 0x0e3f, /* 0x0dd8-0x0ddf */
 
1070
    0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, /* 0x0de0-0x0de7 */
 
1071
    0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0000, 0x0000, /* 0x0de8-0x0def */
 
1072
    0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, /* 0x0df0-0x0df7 */
 
1073
    0x0e58, 0x0e59                                                /* 0x0df8-0x0dff */
 
1074
};
 
1075
 
 
1076
static unsigned short const keysym_to_unicode_ea0_eff[] = {
 
1077
    0x0000, 0x1101, 0x1101, 0x11aa, 0x1102, 0x11ac, 0x11ad, 0x1103, /* 0x0ea0-0x0ea7 */
 
1078
    0x1104, 0x1105, 0x11b0, 0x11b1, 0x11b2, 0x11b3, 0x11b4, 0x11b5, /* 0x0ea8-0x0eaf */
 
1079
    0x11b6, 0x1106, 0x1107, 0x1108, 0x11b9, 0x1109, 0x110a, 0x110b, /* 0x0eb0-0x0eb7 */
 
1080
    0x110c, 0x110d, 0x110e, 0x110f, 0x1110, 0x1111, 0x1112, 0x1161, /* 0x0eb8-0x0ebf */
 
1081
    0x1162, 0x1163, 0x1164, 0x1165, 0x1166, 0x1167, 0x1168, 0x1169, /* 0x0ec0-0x0ec7 */
 
1082
    0x116a, 0x116b, 0x116c, 0x116d, 0x116e, 0x116f, 0x1170, 0x1171, /* 0x0ec8-0x0ecf */
 
1083
    0x1172, 0x1173, 0x1174, 0x1175, 0x11a8, 0x11a9, 0x11aa, 0x11ab, /* 0x0ed0-0x0ed7 */
 
1084
    0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, 0x11b3, /* 0x0ed8-0x0edf */
 
1085
    0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, 0x11bb, /* 0x0ee0-0x0ee7 */
 
1086
    0x11bc, 0x11bd, 0x11be, 0x11bf, 0x11c0, 0x11c1, 0x11c2, 0x0000, /* 0x0ee8-0x0eef */
 
1087
    0x0000, 0x0000, 0x1140, 0x0000, 0x0000, 0x1159, 0x119e, 0x0000, /* 0x0ef0-0x0ef7 */
 
1088
    0x11eb, 0x0000, 0x11f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x20a9, /* 0x0ef8-0x0eff */
 
1089
};
 
1090
 
 
1091
static unsigned short keysym_to_unicode_12a1_12fe[] = {
 
1092
            0x1e02, 0x1e03, 0x0000, 0x0000, 0x0000, 0x1e0a, 0x0000, /* 0x12a0-0x12a7 */
 
1093
    0x1e80, 0x0000, 0x1e82, 0x1e0b, 0x1ef2, 0x0000, 0x0000, 0x0000, /* 0x12a8-0x12af */
 
1094
    0x1e1e, 0x1e1f, 0x0000, 0x0000, 0x1e40, 0x1e41, 0x0000, 0x1e56, /* 0x12b0-0x12b7 */
 
1095
    0x1e81, 0x1e57, 0x1e83, 0x1e60, 0x1ef3, 0x1e84, 0x1e85, 0x1e61, /* 0x12b8-0x12bf */
 
1096
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12c0-0x12c7 */
 
1097
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12c8-0x12cf */
 
1098
    0x0174, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e6a, /* 0x12d0-0x12d7 */
 
1099
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0176, 0x0000, /* 0x12d8-0x12df */
 
1100
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12e0-0x12e7 */
 
1101
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12e8-0x12ef */
 
1102
    0x0175, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e6b, /* 0x12f0-0x12f7 */
 
1103
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0177        /* 0x12f0-0x12ff */
 
1104
};
 
1105
                
 
1106
static unsigned short const keysym_to_unicode_13bc_13be[] = {
 
1107
                                    0x0152, 0x0153, 0x0178        /* 0x13b8-0x13bf */
 
1108
};
 
1109
 
 
1110
static unsigned short keysym_to_unicode_14a1_14ff[] = {
 
1111
            0x2741, 0x00a7, 0x0589, 0x0029, 0x0028, 0x00bb, 0x00ab, /* 0x14a0-0x14a7 */
 
1112
    0x2014, 0x002e, 0x055d, 0x002c, 0x2013, 0x058a, 0x2026, 0x055c, /* 0x14a8-0x14af */
 
1113
    0x055b, 0x055e, 0x0531, 0x0561, 0x0532, 0x0562, 0x0533, 0x0563, /* 0x14b0-0x14b7 */
 
1114
    0x0534, 0x0564, 0x0535, 0x0565, 0x0536, 0x0566, 0x0537, 0x0567, /* 0x14b8-0x14bf */
 
1115
    0x0538, 0x0568, 0x0539, 0x0569, 0x053a, 0x056a, 0x053b, 0x056b, /* 0x14c0-0x14c7 */
 
1116
    0x053c, 0x056c, 0x053d, 0x056d, 0x053e, 0x056e, 0x053f, 0x056f, /* 0x14c8-0x14cf */
 
1117
    0x0540, 0x0570, 0x0541, 0x0571, 0x0542, 0x0572, 0x0543, 0x0573, /* 0x14d0-0x14d7 */
 
1118
    0x0544, 0x0574, 0x0545, 0x0575, 0x0546, 0x0576, 0x0547, 0x0577, /* 0x14d8-0x14df */
 
1119
    0x0548, 0x0578, 0x0549, 0x0579, 0x054a, 0x057a, 0x054b, 0x057b, /* 0x14e0-0x14e7 */
 
1120
    0x054c, 0x057c, 0x054d, 0x057d, 0x054e, 0x057e, 0x054f, 0x057f, /* 0x14e8-0x14ef */
 
1121
    0x0550, 0x0580, 0x0551, 0x0581, 0x0552, 0x0582, 0x0553, 0x0583, /* 0x14f0-0x14f7 */
 
1122
    0x0554, 0x0584, 0x0555, 0x0585, 0x0556, 0x0586, 0x2019, 0x0027, /* 0x14f8-0x14ff */
 
1123
};
 
1124
 
 
1125
static unsigned short keysym_to_unicode_15d0_15f6[] = {
 
1126
    0x10d0, 0x10d1, 0x10d2, 0x10d3, 0x10d4, 0x10d5, 0x10d6, 0x10d7, /* 0x15d0-0x15d7 */
 
1127
    0x10d8, 0x10d9, 0x10da, 0x10db, 0x10dc, 0x10dd, 0x10de, 0x10df, /* 0x15d8-0x15df */
 
1128
    0x10e0, 0x10e1, 0x10e2, 0x10e3, 0x10e4, 0x10e5, 0x10e6, 0x10e7, /* 0x15e0-0x15e7 */
 
1129
    0x10e8, 0x10e9, 0x10ea, 0x10eb, 0x10ec, 0x10ed, 0x10ee, 0x10ef, /* 0x15e8-0x15ef */
 
1130
    0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6        /* 0x15f0-0x15f7 */
 
1131
};
 
1132
 
 
1133
static unsigned short keysym_to_unicode_16a0_16f6[] = {
 
1134
    0x0000, 0x0000, 0xf0a2, 0x1e8a, 0x0000, 0xf0a5, 0x012c, 0xf0a7, /* 0x16a0-0x16a7 */
 
1135
    0xf0a8, 0x01b5, 0x01e6, 0x0000, 0x0000, 0x0000, 0x0000, 0x019f, /* 0x16a8-0x16af */
 
1136
    0x0000, 0x0000, 0xf0b2, 0x1e8b, 0x01d1, 0xf0b5, 0x012d, 0xf0b7, /* 0x16b0-0x16b7 */
 
1137
    0xf0b8, 0x01b6, 0x01e7, 0x0000, 0x0000, 0x01d2, 0x0000, 0x0275, /* 0x16b8-0x16bf */
 
1138
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x018f, 0x0000, /* 0x16c0-0x16c7 */
 
1139
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16c8-0x16cf */
 
1140
    0x0000, 0x1e36, 0xf0d2, 0xf0d3, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16d0-0x16d7 */
 
1141
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16d8-0x16df */
 
1142
    0x0000, 0x1e37, 0xf0e2, 0xf0e3, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16e0-0x16e7 */
 
1143
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16e8-0x16ef */
 
1144
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0259        /* 0x16f0-0x16f6 */
 
1145
};
 
1146
 
 
1147
static unsigned short const keysym_to_unicode_1e9f_1eff[] = {
 
1148
                                                            0x0303,
 
1149
    0x1ea0, 0x1ea1, 0x1ea2, 0x1ea3, 0x1ea4, 0x1ea5, 0x1ea6, 0x1ea7, /* 0x1ea0-0x1ea7 */
 
1150
    0x1ea8, 0x1ea9, 0x1eaa, 0x1eab, 0x1eac, 0x1ead, 0x1eae, 0x1eaf, /* 0x1ea8-0x1eaf */
 
1151
    0x1eb0, 0x1eb1, 0x1eb2, 0x1eb3, 0x1eb4, 0x1eb5, 0x1eb6, 0x1eb7, /* 0x1eb0-0x1eb7 */
 
1152
    0x1eb8, 0x1eb9, 0x1eba, 0x1ebb, 0x1ebc, 0x1ebd, 0x1ebe, 0x1ebf, /* 0x1eb8-0x1ebf */
 
1153
    0x1ec0, 0x1ec1, 0x1ec2, 0x1ec3, 0x1ec4, 0x1ec5, 0x1ec6, 0x1ec7, /* 0x1ec0-0x1ec7 */
 
1154
    0x1ec8, 0x1ec9, 0x1eca, 0x1ecb, 0x1ecc, 0x1ecd, 0x1ece, 0x1ecf, /* 0x1ec8-0x1ecf */
 
1155
    0x1ed0, 0x1ed1, 0x1ed2, 0x1ed3, 0x1ed4, 0x1ed5, 0x1ed6, 0x1ed7, /* 0x1ed0-0x1ed7 */
 
1156
    0x1ed8, 0x1ed9, 0x1eda, 0x1edb, 0x1edc, 0x1edd, 0x1ede, 0x1edf, /* 0x1ed8-0x1edf */
 
1157
    0x1ee0, 0x1ee1, 0x1ee2, 0x1ee3, 0x1ee4, 0x1ee5, 0x1ee6, 0x1ee7, /* 0x1ee0-0x1ee7 */
 
1158
    0x1ee8, 0x1ee9, 0x1eea, 0x1eeb, 0x1eec, 0x1eed, 0x1eee, 0x1eef, /* 0x1ee8-0x1eef */
 
1159
    0x1ef0, 0x1ef1, 0x0300, 0x0301, 0x1ef4, 0x1ef5, 0x1ef6, 0x1ef7, /* 0x1ef0-0x1ef7 */
 
1160
    0x1ef8, 0x1ef9, 0x01a0, 0x01a1, 0x01af, 0x01b0, 0x0309, 0x0323  /* 0x1ef8-0x1eff */
 
1161
};
 
1162
 
 
1163
static unsigned short const keysym_to_unicode_20a0_20ac[] = {
 
1164
    0x20a0, 0x20a1, 0x20a2, 0x20a3, 0x20a4, 0x20a5, 0x20a6, 0x20a7, /* 0x20a0-0x20a7 */
 
1165
    0x20a8, 0x20a9, 0x20aa, 0x20ab, 0x20ac                        /* 0x20a8-0x20af */
 
1166
};
 
1167
 
 
1168
static unsigned int
 
1169
KeySymToUcs4(KeySym keysym)
 
1170
{
 
1171
    /* 'Unicode keysym' */
 
1172
    if ((keysym & 0xff000000) == 0x01000000)
 
1173
        return (keysym & 0x00ffffff);
 
1174
 
 
1175
    if (keysym > 0 && keysym < 0x100)
 
1176
        return keysym;
 
1177
    else if (keysym > 0x1a0 && keysym < 0x200)
 
1178
        return keysym_to_unicode_1a1_1ff[keysym - 0x1a1];
 
1179
    else if (keysym > 0x2a0 && keysym < 0x2ff)
 
1180
        return keysym_to_unicode_2a1_2fe[keysym - 0x2a1];
 
1181
    else if (keysym > 0x3a1 && keysym < 0x3ff)
 
1182
        return keysym_to_unicode_3a2_3fe[keysym - 0x3a2];
 
1183
    else if (keysym > 0x4a0 && keysym < 0x4e0)
 
1184
        return keysym_to_unicode_4a1_4df[keysym - 0x4a1];
 
1185
    else if (keysym > 0x589 && keysym < 0x5ff)
 
1186
        return keysym_to_unicode_590_5fe[keysym - 0x590];
 
1187
    else if (keysym > 0x67f && keysym < 0x700)
 
1188
        return keysym_to_unicode_680_6ff[keysym - 0x680];
 
1189
    else if (keysym > 0x7a0 && keysym < 0x7fa)
 
1190
        return keysym_to_unicode_7a1_7f9[keysym - 0x7a1];
 
1191
    else if (keysym > 0x8a3 && keysym < 0x8ff)
 
1192
        return keysym_to_unicode_8a4_8fe[keysym - 0x8a4];
 
1193
    else if (keysym > 0x9de && keysym < 0x9f9)
 
1194
        return keysym_to_unicode_9df_9f8[keysym - 0x9df];
 
1195
    else if (keysym > 0xaa0 && keysym < 0xaff)
 
1196
        return keysym_to_unicode_aa1_afe[keysym - 0xaa1];
 
1197
    else if (keysym > 0xcde && keysym < 0xcfb)
 
1198
        return keysym_to_unicode_cdf_cfa[keysym - 0xcdf];
 
1199
    else if (keysym > 0xda0 && keysym < 0xdfa)
 
1200
        return keysym_to_unicode_da1_df9[keysym - 0xda1];
 
1201
    else if (keysym > 0xe9f && keysym < 0xf00)
 
1202
        return keysym_to_unicode_ea0_eff[keysym - 0xea0];
 
1203
    else if (keysym > 0x12a0 && keysym < 0x12ff)
 
1204
        return keysym_to_unicode_12a1_12fe[keysym - 0x12a1];
 
1205
    else if (keysym > 0x13bb && keysym < 0x13bf)
 
1206
        return keysym_to_unicode_13bc_13be[keysym - 0x13bc];
 
1207
    else if (keysym > 0x14a0 && keysym < 0x1500)
 
1208
        return keysym_to_unicode_14a1_14ff[keysym - 0x14a1];
 
1209
    else if (keysym > 0x15cf && keysym < 0x15f7)
 
1210
        return keysym_to_unicode_15d0_15f6[keysym - 0x15d0];
 
1211
    else if (keysym > 0x169f && keysym < 0x16f7)
 
1212
        return keysym_to_unicode_16a0_16f6[keysym - 0x16a0];
 
1213
    else if (keysym > 0x1e9e && keysym < 0x1f00)
 
1214
        return keysym_to_unicode_1e9f_1eff[keysym - 0x1e9f];
 
1215
    else if (keysym > 0x209f && keysym < 0x20ad)
 
1216
        return keysym_to_unicode_20a0_20ac[keysym - 0x20a0];
 
1217
    else 
 
1218
        return 0;
 
1219
}
 
1220
 
 
1221
int compose_handle_key(GdkEventKey *event, IMUIMContext *uic)
 
1222
{
 
1223
    unsigned int keysym, mod;
 
1224
    int is_push, rv;
 
1225
 
 
1226
    keysym = event->keyval;
 
1227
    mod = event->state;
 
1228
    is_push = event->type == GDK_KEY_PRESS ? 1 : 0;
 
1229
    rv = handleKey(keysym, mod, is_push, uic);
 
1230
 
 
1231
    return rv ? 0 : 1;
 
1232
}
 
1233
#endif /* GDK_WINDOWING_X11 */
 
1234
 
 
1235
/*
 
1236
 * Local variables:
 
1237
 *  c-indent-level: 4
 
1238
 *  c-basic-offset: 4
 
1239
 * End:
 
1240
 */