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

« back to all changes in this revision

Viewing changes to qt/immodule-quiminputcontext_compose.cpp

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