221cedd8cbbe77e8f2594e46f873b66713c0d2d0
[platform/upstream/libX11.git] / src / KeyBind.c
1 /*
2
3 Copyright 1985, 1987, 1998  The Open Group
4
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
24
25 */
26
27 /* Beware, here be monsters (still under construction... - JG */
28
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32 #include <X11/Xlibint.h>
33 #include <X11/Xutil.h>
34 #define XK_MISCELLANY
35 #define XK_LATIN1
36 #define XK_LATIN2
37 #define XK_LATIN3
38 #define XK_LATIN4
39 #define XK_LATIN8
40 #define XK_LATIN9
41 #define XK_CYRILLIC
42 #define XK_GREEK
43 #define XK_ARMENIAN
44 #define XK_CAUCASUS
45 #define XK_VIETNAMESE
46 #define XK_XKB_KEYS
47 #define XK_SINHALA
48 #include <X11/keysymdef.h>
49 #include <stdio.h>
50
51 #ifdef USE_OWN_COMPOSE
52 #include "imComp.h"
53
54 #endif
55
56 #include "Xresource.h"
57 #include "Key.h"
58
59 #ifdef XKB
60 #include "XKBlib.h"
61 #include "XKBlibint.h"
62 #define XKeycodeToKeysym        _XKeycodeToKeysym
63 #define XKeysymToKeycode        _XKeysymToKeycode
64 #define XLookupKeysym           _XLookupKeysym
65 #define XRefreshKeyboardMapping _XRefreshKeyboardMapping
66 #define XLookupString           _XLookupString
67 /* XKBBind.c */
68 #else
69 #define XkbKeysymToModifiers    _XKeysymToModifiers
70 #endif
71
72 #define AllMods (ShiftMask|LockMask|ControlMask| \
73                  Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)
74
75 static void
76 ComputeMaskFromKeytrans(
77     Display *dpy,
78     register struct _XKeytrans *p);
79
80 struct _XKeytrans {
81         struct _XKeytrans *next;/* next on list */
82         char *string;           /* string to return when the time comes */
83         int len;                /* length of string (since NULL is legit)*/
84         KeySym key;             /* keysym rebound */
85         unsigned int state;     /* modifier state */
86         KeySym *modifiers;      /* modifier keysyms you want */
87         int mlen;               /* length of modifier list */
88 };
89
90 static KeySym
91 KeyCodetoKeySym(register Display *dpy, KeyCode keycode, int col)
92 {
93     register int per = dpy->keysyms_per_keycode;
94     register KeySym *syms;
95     KeySym lsym, usym;
96
97     if ((col < 0) || ((col >= per) && (col > 3)) ||
98         ((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode))
99       return NoSymbol;
100
101     syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per];
102     if (col < 4) {
103         if (col > 1) {
104             while ((per > 2) && (syms[per - 1] == NoSymbol))
105                 per--;
106             if (per < 3)
107                 col -= 2;
108         }
109         if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
110             XConvertCase(syms[col&~1], &lsym, &usym);
111             if (!(col & 1))
112                 return lsym;
113             else if (usym == lsym)
114                 return NoSymbol;
115             else
116                 return usym;
117         }
118     }
119     return syms[col];
120 }
121
122 KeySym
123 XKeycodeToKeysym(Display *dpy,
124 #if NeedWidePrototypes
125                  unsigned int kc,
126 #else
127                  KeyCode kc,
128 #endif
129                  int col)
130 {
131     if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
132         return NoSymbol;
133     return KeyCodetoKeySym(dpy, kc, col);
134 }
135
136 KeyCode
137 XKeysymToKeycode(
138     Display *dpy,
139     KeySym ks)
140 {
141     register int i, j;
142
143     if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
144         return (KeyCode) 0;
145     for (j = 0; j < dpy->keysyms_per_keycode; j++) {
146         for (i = dpy->min_keycode; i <= dpy->max_keycode; i++) {
147             if (KeyCodetoKeySym(dpy, (KeyCode) i, j) == ks)
148                 return i;
149         }
150     }
151     return 0;
152 }
153
154 KeySym
155 XLookupKeysym(
156     register XKeyEvent *event,
157     int col)
158 {
159     if ((! event->display->keysyms) && (! _XKeyInitialize(event->display)))
160         return NoSymbol;
161     return KeyCodetoKeySym(event->display, event->keycode, col);
162 }
163
164 static void
165 ResetModMap(
166     Display *dpy)
167 {
168     register XModifierKeymap *map;
169     register int i, j, n;
170     KeySym sym;
171     register struct _XKeytrans *p;
172
173     map = dpy->modifiermap;
174     /* If any Lock key contains Caps_Lock, then interpret as Caps_Lock,
175      * else if any contains Shift_Lock, then interpret as Shift_Lock,
176      * else ignore Lock altogether.
177      */
178     dpy->lock_meaning = NoSymbol;
179     /* Lock modifiers are in the second row of the matrix */
180     n = 2 * map->max_keypermod;
181     for (i = map->max_keypermod; i < n; i++) {
182         for (j = 0; j < dpy->keysyms_per_keycode; j++) {
183             sym = KeyCodetoKeySym(dpy, map->modifiermap[i], j);
184             if (sym == XK_Caps_Lock) {
185                 dpy->lock_meaning = XK_Caps_Lock;
186                 break;
187             } else if (sym == XK_Shift_Lock) {
188                 dpy->lock_meaning = XK_Shift_Lock;
189             }
190             else if (sym == XK_ISO_Lock) {
191                 dpy->lock_meaning = XK_Caps_Lock;
192                 break;
193             }
194         }
195     }
196     /* Now find any Mod<n> modifier acting as the Group or Numlock modifier */
197     dpy->mode_switch = 0;
198     dpy->num_lock = 0;
199     n *= 4;
200     for (i = 3*map->max_keypermod; i < n; i++) {
201         for (j = 0; j < dpy->keysyms_per_keycode; j++) {
202             sym = KeyCodetoKeySym(dpy, map->modifiermap[i], j);
203             if (sym == XK_Mode_switch)
204                 dpy->mode_switch |= 1 << (i / map->max_keypermod);
205             if (sym == XK_Num_Lock)
206                 dpy->num_lock |= 1 << (i / map->max_keypermod);
207         }
208     }
209     for (p = dpy->key_bindings; p; p = p->next)
210         ComputeMaskFromKeytrans(dpy, p);
211 }
212
213 static int
214 InitModMap(
215     Display *dpy)
216 {
217     register XModifierKeymap *map;
218
219     if (! (map = XGetModifierMapping(dpy)))
220         return 0;
221     LockDisplay(dpy);
222     if (dpy->modifiermap)
223         XFreeModifiermap(dpy->modifiermap);
224     dpy->modifiermap = map;
225     dpy->free_funcs->modifiermap = XFreeModifiermap;
226     if (dpy->keysyms)
227         ResetModMap(dpy);
228     UnlockDisplay(dpy);
229     return 1;
230 }
231
232 int
233 XRefreshKeyboardMapping(register XMappingEvent *event)
234 {
235
236     if(event->request == MappingKeyboard) {
237         /* XXX should really only refresh what is necessary
238          * for now, make initialize test fail
239          */
240         LockDisplay(event->display);
241         if (event->display->keysyms) {
242              Xfree ((char *)event->display->keysyms);
243              event->display->keysyms = NULL;
244         }
245         UnlockDisplay(event->display);
246     }
247     if(event->request == MappingModifier) {
248         LockDisplay(event->display);
249         if (event->display->modifiermap) {
250             XFreeModifiermap(event->display->modifiermap);
251             event->display->modifiermap = NULL;
252         }
253         UnlockDisplay(event->display);
254         /* go ahead and get it now, since initialize test may not fail */
255         if (event->display->keysyms)
256             (void) InitModMap(event->display);
257     }
258     return 1;
259 }
260
261 int
262 _XKeyInitialize(
263     Display *dpy)
264 {
265     int per, n;
266     KeySym *keysyms;
267
268     /*
269      * lets go get the keysyms from the server.
270      */
271     if (!dpy->keysyms) {
272         n = dpy->max_keycode - dpy->min_keycode + 1;
273         keysyms = XGetKeyboardMapping (dpy, (KeyCode) dpy->min_keycode,
274                                        n, &per);
275         /* keysyms may be NULL */
276         if (! keysyms) return 0;
277
278         LockDisplay(dpy);
279         if (dpy->keysyms)
280             Xfree ((char *)dpy->keysyms);
281         dpy->keysyms = keysyms;
282         dpy->keysyms_per_keycode = per;
283         if (dpy->modifiermap)
284             ResetModMap(dpy);
285         UnlockDisplay(dpy);
286     }
287     if (!dpy->modifiermap)
288         return InitModMap(dpy);
289     return 1;
290 }
291
292 static void
293 UCSConvertCase( register unsigned code,
294                 KeySym *lower,
295                 KeySym *upper )
296 {
297     /* Case conversion for UCS, as in Unicode Data version 4.0.0 */
298     /* NB: Only converts simple one-to-one mappings. */
299
300     /* Tables are used where they take less space than     */
301     /* the code to work out the mappings. Zero values mean */
302     /* undefined code points.                              */
303
304     static unsigned short const IPAExt_upper_mapping[] = { /* part only */
305                             0x0181, 0x0186, 0x0255, 0x0189, 0x018A,
306     0x0258, 0x018F, 0x025A, 0x0190, 0x025C, 0x025D, 0x025E, 0x025F,
307     0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267,
308     0x0197, 0x0196, 0x026A, 0x026B, 0x026C, 0x026D, 0x026E, 0x019C,
309     0x0270, 0x0271, 0x019D, 0x0273, 0x0274, 0x019F, 0x0276, 0x0277,
310     0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F,
311     0x01A6, 0x0281, 0x0282, 0x01A9, 0x0284, 0x0285, 0x0286, 0x0287,
312     0x01AE, 0x0289, 0x01B1, 0x01B2, 0x028C, 0x028D, 0x028E, 0x028F,
313     0x0290, 0x0291, 0x01B7
314     };
315
316     static unsigned short const LatinExtB_upper_mapping[] = { /* first part only */
317     0x0180, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187,
318     0x0187, 0x0189, 0x018A, 0x018B, 0x018B, 0x018D, 0x018E, 0x018F,
319     0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01F6, 0x0196, 0x0197,
320     0x0198, 0x0198, 0x019A, 0x019B, 0x019C, 0x019D, 0x0220, 0x019F,
321     0x01A0, 0x01A0, 0x01A2, 0x01A2, 0x01A4, 0x01A4, 0x01A6, 0x01A7,
322     0x01A7, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AC, 0x01AE, 0x01AF,
323     0x01AF, 0x01B1, 0x01B2, 0x01B3, 0x01B3, 0x01B5, 0x01B5, 0x01B7,
324     0x01B8, 0x01B8, 0x01BA, 0x01BB, 0x01BC, 0x01BC, 0x01BE, 0x01F7,
325     0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C4, 0x01C4, 0x01C7,
326     0x01C7, 0x01C7, 0x01CA, 0x01CA, 0x01CA
327     };
328
329     static unsigned short const LatinExtB_lower_mapping[] = { /* first part only */
330     0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188,
331     0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259,
332     0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268,
333     0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275,
334     0x01A1, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x0280, 0x01A8,
335     0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01B0,
336     0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292,
337     0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF,
338     0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9,
339     0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC
340     };
341
342     static unsigned short const Greek_upper_mapping[] = {
343     0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000,
344     0x0000, 0x0000, 0x037A, 0x0000, 0x0000, 0x0000, 0x037E, 0x0000,
345     0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x0386, 0x0387,
346     0x0388, 0x0389, 0x038A, 0x0000, 0x038C, 0x0000, 0x038E, 0x038F,
347     0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
348     0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
349     0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
350     0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x0386, 0x0388, 0x0389, 0x038A,
351     0x03B0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
352     0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
353     0x03A0, 0x03A1, 0x03A3, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
354     0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x038C, 0x038E, 0x038F, 0x0000,
355     0x0392, 0x0398, 0x03D2, 0x03D3, 0x03D4, 0x03A6, 0x03A0, 0x03D7,
356     0x03D8, 0x03D8, 0x03DA, 0x03DA, 0x03DC, 0x03DC, 0x03DE, 0x03DE,
357     0x03E0, 0x03E0, 0x03E2, 0x03E2, 0x03E4, 0x03E4, 0x03E6, 0x03E6,
358     0x03E8, 0x03E8, 0x03EA, 0x03EA, 0x03EC, 0x03EC, 0x03EE, 0x03EE,
359     0x039A, 0x03A1, 0x03F9, 0x03F3, 0x03F4, 0x0395, 0x03F6, 0x03F7,
360     0x03F7, 0x03F9, 0x03FA, 0x03FA, 0x0000, 0x0000, 0x0000, 0x0000
361     };
362
363     static unsigned short const Greek_lower_mapping[] = {
364     0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000,
365     0x0000, 0x0000, 0x037A, 0x0000, 0x0000, 0x0000, 0x037E, 0x0000,
366     0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x03AC, 0x0387,
367     0x03AD, 0x03AE, 0x03AF, 0x0000, 0x03CC, 0x0000, 0x03CD, 0x03CE,
368     0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
369     0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
370     0x03C0, 0x03C1, 0x0000, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
371     0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
372     0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
373     0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
374     0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
375     0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000,
376     0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,
377     0x03D9, 0x03D9, 0x03DB, 0x03DB, 0x03DD, 0x03DD, 0x03DF, 0x03DF,
378     0x03E1, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7,
379     0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF,
380     0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03B8, 0x03F5, 0x03F6, 0x03F8,
381     0x03F8, 0x03F2, 0x03FB, 0x03FB, 0x0000, 0x0000, 0x0000, 0x0000
382     };
383
384     static unsigned short const GreekExt_lower_mapping[] = {
385     0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,
386     0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,
387     0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000,
388     0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000,
389     0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,
390     0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,
391     0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,
392     0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,
393     0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000,
394     0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000,
395     0x1F50, 0x1F51, 0x1F52, 0x1F53, 0x1F54, 0x1F55, 0x1F56, 0x1F57,
396     0x0000, 0x1F51, 0x0000, 0x1F53, 0x0000, 0x1F55, 0x0000, 0x1F57,
397     0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,
398     0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,
399     0x1F70, 0x1F71, 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1F76, 0x1F77,
400     0x1F78, 0x1F79, 0x1F7A, 0x1F7B, 0x1F7C, 0x1F7D, 0x0000, 0x0000,
401     0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,
402     0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,
403     0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,
404     0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,
405     0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,
406     0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,
407     0x1FB0, 0x1FB1, 0x1FB2, 0x1FB3, 0x1FB4, 0x0000, 0x1FB6, 0x1FB7,
408     0x1FB0, 0x1FB1, 0x1F70, 0x1F71, 0x1FB3, 0x1FBD, 0x1FBE, 0x1FBF,
409     0x1FC0, 0x1FC1, 0x1FC2, 0x1FC3, 0x1FC4, 0x0000, 0x1FC6, 0x1FC7,
410     0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1FC3, 0x1FCD, 0x1FCE, 0x1FCF,
411     0x1FD0, 0x1FD1, 0x1FD2, 0x1FD3, 0x0000, 0x0000, 0x1FD6, 0x1FD7,
412     0x1FD0, 0x1FD1, 0x1F76, 0x1F77, 0x0000, 0x1FDD, 0x1FDE, 0x1FDF,
413     0x1FE0, 0x1FE1, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FE5, 0x1FE6, 0x1FE7,
414     0x1FE0, 0x1FE1, 0x1F7A, 0x1F7B, 0x1FE5, 0x1FED, 0x1FEE, 0x1FEF,
415     0x0000, 0x0000, 0x1FF2, 0x1FF3, 0x1FF4, 0x0000, 0x1FF6, 0x1FF7,
416     0x1F78, 0x1F79, 0x1F7C, 0x1F7D, 0x1FF3, 0x1FFD, 0x1FFE, 0x0000
417     };
418
419     static unsigned short const GreekExt_upper_mapping[] = {
420     0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,
421     0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,
422     0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000,
423     0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000,
424     0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F,
425     0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F,
426     0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,
427     0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,
428     0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000,
429     0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000,
430     0x1F50, 0x1F59, 0x1F52, 0x1F5B, 0x1F54, 0x1F5D, 0x1F56, 0x1F5F,
431     0x0000, 0x1F59, 0x0000, 0x1F5B, 0x0000, 0x1F5D, 0x0000, 0x1F5F,
432     0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,
433     0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,
434     0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB,
435     0x1FF8, 0x1FF9, 0x1FEA, 0x1FEB, 0x1FFA, 0x1FFB, 0x0000, 0x0000,
436     0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F,
437     0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F,
438     0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,
439     0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,
440     0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF,
441     0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF,
442     0x1FB8, 0x1FB9, 0x1FB2, 0x1FBC, 0x1FB4, 0x0000, 0x1FB6, 0x1FB7,
443     0x1FB8, 0x1FB9, 0x1FBA, 0x1FBB, 0x1FBC, 0x1FBD, 0x0399, 0x1FBF,
444     0x1FC0, 0x1FC1, 0x1FC2, 0x1FCC, 0x1FC4, 0x0000, 0x1FC6, 0x1FC7,
445     0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FCC, 0x1FCD, 0x1FCE, 0x1FCF,
446     0x1FD8, 0x1FD9, 0x1FD2, 0x1FD3, 0x0000, 0x0000, 0x1FD6, 0x1FD7,
447     0x1FD8, 0x1FD9, 0x1FDA, 0x1FDB, 0x0000, 0x1FDD, 0x1FDE, 0x1FDF,
448     0x1FE8, 0x1FE9, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FEC, 0x1FE6, 0x1FE7,
449     0x1FE8, 0x1FE9, 0x1FEA, 0x1FEB, 0x1FEC, 0x1FED, 0x1FEE, 0x1FEF,
450     0x0000, 0x0000, 0x1FF2, 0x1FFC, 0x1FF4, 0x0000, 0x1FF6, 0x1FF7,
451     0x1FF8, 0x1FF9, 0x1FFA, 0x1FFB, 0x1FFC, 0x1FFD, 0x1FFE, 0x0000
452     };
453
454     *lower = code;
455     *upper = code;
456
457     /* Basic Latin and Latin-1 Supplement, U+0000 to U+00FF */
458     if (code <= 0x00ff) {
459         if (code >= 0x0041 && code <= 0x005a)             /* A-Z */
460             *lower += 0x20;
461         else if (code >= 0x0061 && code <= 0x007a)        /* a-z */
462             *upper -= 0x20;
463         else if ( (code >= 0x00c0 && code <= 0x00d6) ||
464                   (code >= 0x00d8 && code <= 0x00de) )
465             *lower += 0x20;
466         else if ( (code >= 0x00e0 && code <= 0x00f6) ||
467                   (code >= 0x00f8 && code <= 0x00fe) )
468             *upper -= 0x20;
469         else if (code == 0x00ff)      /* y with diaeresis */
470             *upper = 0x0178;
471         else if (code == 0x00b5)      /* micro sign */
472             *upper = 0x039c;
473         return;
474     }
475
476     /* Latin Extended-A, U+0100 to U+017F */
477     if (code >= 0x0100 && code <= 0x017f) {
478         if ( (code >= 0x0100 && code <= 0x012f) ||
479              (code >= 0x0132 && code <= 0x0137) ||
480              (code >= 0x014a && code <= 0x0177) ) {
481             *upper = code & ~1;
482             *lower = code | 1;
483         }
484         else if ( (code >= 0x0139 && code <= 0x0148) ||
485                   (code >= 0x0179 && code <= 0x017e) ) {
486             if (code & 1)
487                 *lower += 1;
488             else
489                 *upper -= 1;
490         }
491         else if (code == 0x0130)
492             *lower = 0x0069;
493         else if (code == 0x0131)
494             *upper = 0x0049;
495         else if (code == 0x0178)
496             *lower = 0x00ff;
497         else if (code == 0x017f)
498             *upper = 0x0053;
499         return;
500     }
501
502     /* Latin Extended-B, U+0180 to U+024F */
503     if (code >= 0x0180 && code <= 0x024f) {
504         if (code >= 0x01cd && code <= 0x01dc) {
505             if (code & 1)
506                *lower += 1;
507             else
508                *upper -= 1;
509         }
510         else if ( (code >= 0x01de && code <= 0x01ef) ||
511                   (code >= 0x01f4 && code <= 0x01f5) ||
512                   (code >= 0x01f8 && code <= 0x021f) ||
513                   (code >= 0x0222 && code <= 0x0233) ) {
514             *lower |= 1;
515             *upper &= ~1;
516         }
517         else if (code >= 0x0180 && code <= 0x01cc) {
518             *lower = LatinExtB_lower_mapping[code - 0x0180];
519             *upper = LatinExtB_upper_mapping[code - 0x0180];
520         }
521         else if (code == 0x01dd)
522             *upper = 0x018e;
523         else if (code == 0x01f1 || code == 0x01f2) {
524             *lower = 0x01f3;
525             *upper = 0x01f1;
526         }
527         else if (code == 0x01f3)
528             *upper = 0x01f1;
529         else if (code == 0x01f6)
530             *lower = 0x0195;
531         else if (code == 0x01f7)
532             *lower = 0x01bf;
533         else if (code == 0x0220)
534             *lower = 0x019e;
535         return;
536     }
537
538     /* IPA Extensions, U+0250 to U+02AF */
539     if (code >= 0x0253 && code <= 0x0292) {
540         *upper = IPAExt_upper_mapping[code - 0x0253];
541     }
542
543     /* Combining Diacritical Marks, U+0300 to U+036F */
544     if (code == 0x0345) {
545         *upper = 0x0399;
546     }
547
548     /* Greek and Coptic, U+0370 to U+03FF */
549     if (code >= 0x0370 && code <= 0x03ff) {
550         *lower = Greek_lower_mapping[code - 0x0370];
551         *upper = Greek_upper_mapping[code - 0x0370];
552         if (*upper == 0)
553             *upper = code;
554         if (*lower == 0)
555             *lower = code;
556     }
557
558     /* Cyrillic and Cyrillic Supplementary, U+0400 to U+052F */
559     if ( (code >= 0x0400 && code <= 0x04ff) ||
560          (code >= 0x0500 && code <= 0x052f) ) {
561         if (code >= 0x0400 && code <= 0x040f)
562             *lower += 0x50;
563         else if (code >= 0x0410 && code <= 0x042f)
564             *lower += 0x20;
565         else if (code >= 0x0430 && code <= 0x044f)
566             *upper -= 0x20;
567         else if (code >= 0x0450 && code <= 0x045f)
568             *upper -= 0x50;
569         else if ( (code >= 0x0460 && code <= 0x0481) ||
570                   (code >= 0x048a && code <= 0x04bf) ||
571                   (code >= 0x04d0 && code <= 0x04f5) ||
572                   (code >= 0x04f8 && code <= 0x04f9) ||
573                   (code >= 0x0500 && code <= 0x050f) ) {
574             *upper &= ~1;
575             *lower |= 1;
576         }
577         else if (code >= 0x04c1 && code <= 0x04ce) {
578             if (code & 1)
579                 *lower += 1;
580             else
581                 *upper -= 1;
582         }
583     }
584
585     /* Armenian, U+0530 to U+058F */
586     if (code >= 0x0530 && code <= 0x058f) {
587         if (code >= 0x0531 && code <= 0x0556)
588             *lower += 0x30;
589         else if (code >=0x0561 && code <= 0x0586)
590             *upper -= 0x30;
591     }
592
593     /* Latin Extended Additional, U+1E00 to U+1EFF */
594     if (code >= 0x1e00 && code <= 0x1eff) {
595         if ( (code >= 0x1e00 && code <= 0x1e95) ||
596              (code >= 0x1ea0 && code <= 0x1ef9) ) {
597             *upper &= ~1;
598             *lower |= 1;
599         }
600         else if (code == 0x1e9b)
601             *upper = 0x1e60;
602     }
603
604     /* Greek Extended, U+1F00 to U+1FFF */
605     if (code >= 0x1f00 && code <= 0x1fff) {
606         *lower = GreekExt_lower_mapping[code - 0x1f00];
607         *upper = GreekExt_upper_mapping[code - 0x1f00];
608         if (*upper == 0)
609             *upper = code;
610         if (*lower == 0)
611             *lower = code;
612     }
613
614     /* Letterlike Symbols, U+2100 to U+214F */
615     if (code >= 0x2100 && code <= 0x214f) {
616         switch (code) {
617         case 0x2126: *lower = 0x03c9; break;
618         case 0x212a: *lower = 0x006b; break;
619         case 0x212b: *lower = 0x00e5; break;
620         }
621     }
622     /* Number Forms, U+2150 to U+218F */
623     else if (code >= 0x2160 && code <= 0x216f)
624         *lower += 0x10;
625     else if (code >= 0x2170 && code <= 0x217f)
626         *upper -= 0x10;
627     /* Enclosed Alphanumerics, U+2460 to U+24FF */
628     else if (code >= 0x24b6 && code <= 0x24cf)
629         *lower += 0x1a;
630     else if (code >= 0x24d0 && code <= 0x24e9)
631         *upper -= 0x1a;
632     /* Halfwidth and Fullwidth Forms, U+FF00 to U+FFEF */
633     else if (code >= 0xff21 && code <= 0xff3a)
634         *lower += 0x20;
635     else if (code >= 0xff41 && code <= 0xff5a)
636         *upper -= 0x20;
637     /* Deseret, U+10400 to U+104FF */
638     else if (code >= 0x10400 && code <= 0x10427)
639         *lower += 0x28;
640     else if (code >= 0x10428 && code <= 0x1044f)
641         *upper -= 0x28;
642 }
643
644 void
645 XConvertCase(
646     register KeySym sym,
647     KeySym *lower,
648     KeySym *upper)
649 {
650     /* Latin 1 keysym */
651     if (sym < 0x100) {
652         UCSConvertCase(sym, lower, upper);
653         return;
654     }
655
656     /* Unicode keysym */
657     if ((sym & 0xff000000) == 0x01000000) {
658         UCSConvertCase((sym & 0x00ffffff), lower, upper);
659         *upper |= 0x01000000;
660         *lower |= 0x01000000;
661         return;
662     }
663
664     /* Legacy keysym */
665
666     *lower = sym;
667     *upper = sym;
668
669     switch(sym >> 8) {
670     case 1: /* Latin 2 */
671         /* Assume the KeySym is a legal value (ignore discontinuities) */
672         if (sym == XK_Aogonek)
673             *lower = XK_aogonek;
674         else if (sym >= XK_Lstroke && sym <= XK_Sacute)
675             *lower += (XK_lstroke - XK_Lstroke);
676         else if (sym >= XK_Scaron && sym <= XK_Zacute)
677             *lower += (XK_scaron - XK_Scaron);
678         else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
679             *lower += (XK_zcaron - XK_Zcaron);
680         else if (sym == XK_aogonek)
681             *upper = XK_Aogonek;
682         else if (sym >= XK_lstroke && sym <= XK_sacute)
683             *upper -= (XK_lstroke - XK_Lstroke);
684         else if (sym >= XK_scaron && sym <= XK_zacute)
685             *upper -= (XK_scaron - XK_Scaron);
686         else if (sym >= XK_zcaron && sym <= XK_zabovedot)
687             *upper -= (XK_zcaron - XK_Zcaron);
688         else if (sym >= XK_Racute && sym <= XK_Tcedilla)
689             *lower += (XK_racute - XK_Racute);
690         else if (sym >= XK_racute && sym <= XK_tcedilla)
691             *upper -= (XK_racute - XK_Racute);
692         break;
693     case 2: /* Latin 3 */
694         /* Assume the KeySym is a legal value (ignore discontinuities) */
695         if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
696             *lower += (XK_hstroke - XK_Hstroke);
697         else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
698             *lower += (XK_gbreve - XK_Gbreve);
699         else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
700             *upper -= (XK_hstroke - XK_Hstroke);
701         else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
702             *upper -= (XK_gbreve - XK_Gbreve);
703         else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
704             *lower += (XK_cabovedot - XK_Cabovedot);
705         else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
706             *upper -= (XK_cabovedot - XK_Cabovedot);
707         break;
708     case 3: /* Latin 4 */
709         /* Assume the KeySym is a legal value (ignore discontinuities) */
710         if (sym >= XK_Rcedilla && sym <= XK_Tslash)
711             *lower += (XK_rcedilla - XK_Rcedilla);
712         else if (sym >= XK_rcedilla && sym <= XK_tslash)
713             *upper -= (XK_rcedilla - XK_Rcedilla);
714         else if (sym == XK_ENG)
715             *lower = XK_eng;
716         else if (sym == XK_eng)
717             *upper = XK_ENG;
718         else if (sym >= XK_Amacron && sym <= XK_Umacron)
719             *lower += (XK_amacron - XK_Amacron);
720         else if (sym >= XK_amacron && sym <= XK_umacron)
721             *upper -= (XK_amacron - XK_Amacron);
722         break;
723     case 6: /* Cyrillic */
724         /* Assume the KeySym is a legal value (ignore discontinuities) */
725         if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
726             *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
727         else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
728             *upper += (XK_Serbian_DJE - XK_Serbian_dje);
729         else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
730             *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
731         else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
732             *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
733         break;
734     case 7: /* Greek */
735         /* Assume the KeySym is a legal value (ignore discontinuities) */
736         if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
737             *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
738         else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
739                  sym != XK_Greek_iotaaccentdieresis &&
740                  sym != XK_Greek_upsilonaccentdieresis)
741             *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
742         else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
743             *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
744         else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
745                  sym != XK_Greek_finalsmallsigma)
746             *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
747         break;
748     case 0x13: /* Latin 9 */
749         if (sym == XK_OE)
750             *lower = XK_oe;
751         else if (sym == XK_oe)
752             *upper = XK_OE;
753         else if (sym == XK_Ydiaeresis)
754             *lower = XK_ydiaeresis;
755         break;
756     }
757 }
758
759 int
760 _XTranslateKey( register Display *dpy,
761                 KeyCode keycode,
762                 register unsigned int modifiers,
763                 unsigned int *modifiers_return,
764                 KeySym *keysym_return)
765 {
766     int per;
767     register KeySym *syms;
768     KeySym sym, lsym, usym;
769
770     if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
771         return 0;
772     *modifiers_return = ((ShiftMask|LockMask)
773                          | dpy->mode_switch | dpy->num_lock);
774     if (((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode))
775     {
776         *keysym_return = NoSymbol;
777         return 1;
778     }
779     per = dpy->keysyms_per_keycode;
780     syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per];
781     while ((per > 2) && (syms[per - 1] == NoSymbol))
782         per--;
783     if ((per > 2) && (modifiers & dpy->mode_switch)) {
784         syms += 2;
785         per -= 2;
786     }
787     if ((modifiers & dpy->num_lock) &&
788         (per > 1 && (IsKeypadKey(syms[1]) || IsPrivateKeypadKey(syms[1])))) {
789         if ((modifiers & ShiftMask) ||
790             ((modifiers & LockMask) && (dpy->lock_meaning == XK_Shift_Lock)))
791             *keysym_return = syms[0];
792         else
793             *keysym_return = syms[1];
794     } else if (!(modifiers & ShiftMask) &&
795         (!(modifiers & LockMask) || (dpy->lock_meaning == NoSymbol))) {
796         if ((per == 1) || (syms[1] == NoSymbol))
797             XConvertCase(syms[0], keysym_return, &usym);
798         else
799             *keysym_return = syms[0];
800     } else if (!(modifiers & LockMask) ||
801                (dpy->lock_meaning != XK_Caps_Lock)) {
802         if ((per == 1) || ((usym = syms[1]) == NoSymbol))
803             XConvertCase(syms[0], &lsym, &usym);
804         *keysym_return = usym;
805     } else {
806         if ((per == 1) || ((sym = syms[1]) == NoSymbol))
807             sym = syms[0];
808         XConvertCase(sym, &lsym, &usym);
809         if (!(modifiers & ShiftMask) && (sym != syms[0]) &&
810             ((sym != usym) || (lsym == usym)))
811             XConvertCase(syms[0], &lsym, &usym);
812         *keysym_return = usym;
813     }
814     if (*keysym_return == XK_VoidSymbol)
815         *keysym_return = NoSymbol;
816     return 1;
817 }
818
819 int
820 _XTranslateKeySym(
821     Display *dpy,
822     register KeySym symbol,
823     unsigned int modifiers,
824     char *buffer,
825     int nbytes)
826 {
827     register struct _XKeytrans *p;
828     int length;
829     unsigned long hiBytes;
830     register unsigned char c;
831
832     if (!symbol)
833         return 0;
834     /* see if symbol rebound, if so, return that string. */
835     for (p = dpy->key_bindings; p; p = p->next) {
836         if (((modifiers & AllMods) == p->state) && (symbol == p->key)) {
837             length = p->len;
838             if (length > nbytes) length = nbytes;
839             memcpy (buffer, p->string, length);
840             return length;
841         }
842     }
843     /* try to convert to Latin-1, handling control */
844     hiBytes = symbol >> 8;
845     if (!(nbytes &&
846           ((hiBytes == 0) ||
847            ((hiBytes == 0xFF) &&
848             (((symbol >= XK_BackSpace) && (symbol <= XK_Clear)) ||
849              (symbol == XK_Return) ||
850              (symbol == XK_Escape) ||
851              (symbol == XK_KP_Space) ||
852              (symbol == XK_KP_Tab) ||
853              (symbol == XK_KP_Enter) ||
854              ((symbol >= XK_KP_Multiply) && (symbol <= XK_KP_9)) ||
855              (symbol == XK_KP_Equal) ||
856              (symbol == XK_Delete))))))
857         return 0;
858
859     /* if X keysym, convert to ascii by grabbing low 7 bits */
860     if (symbol == XK_KP_Space)
861         c = XK_space & 0x7F; /* patch encoding botch */
862     else if (hiBytes == 0xFF)
863         c = symbol & 0x7F;
864     else
865         c = symbol & 0xFF;
866     /* only apply Control key if it makes sense, else ignore it */
867     if (modifiers & ControlMask) {
868         if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
869         else if (c == '2') c = '\000';
870         else if (c >= '3' && c <= '7') c -= ('3' - '\033');
871         else if (c == '8') c = '\177';
872         else if (c == '/') c = '_' & 0x1F;
873     }
874     buffer[0] = c;
875     return 1;
876 }
877
878 /*ARGSUSED*/
879 int
880 XLookupString (
881     register XKeyEvent *event,
882     char *buffer,       /* buffer */
883     int nbytes, /* space in buffer for characters */
884     KeySym *keysym,
885     XComposeStatus *status)     /* not implemented */
886 {
887     unsigned int modifiers;
888     KeySym symbol;
889
890     if (! _XTranslateKey(event->display, event->keycode, event->state,
891                   &modifiers, &symbol))
892         return 0;
893
894 #ifdef USE_OWN_COMPOSE
895     if ( status ) {
896         static int been_here= 0;
897         if ( !been_here ) {
898             XimCompInitTables();
899             been_here = 1;
900         }
901         if ( !XimCompLegalStatus(status) ) {
902             status->compose_ptr = NULL;
903             status->chars_matched = 0;
904         }
905         if ( ((status->chars_matched>0)&&(status->compose_ptr!=NULL)) ||
906                 XimCompIsComposeKey(symbol,event->keycode,status) ) {
907             XimCompRtrn rtrn;
908             switch (XimCompProcessSym(status,symbol,&rtrn)) {
909                 case XIM_COMP_IGNORE:
910                     break;
911                 case XIM_COMP_IN_PROGRESS:
912                     if ( keysym!=NULL )
913                         *keysym = NoSymbol;
914                     return 0;
915                 case XIM_COMP_FAIL:
916                 {
917                     int n = 0, len= 0;
918                     for (n=len=0;rtrn.sym[n]!=XK_VoidSymbol;n++) {
919                         if ( nbytes-len > 0 ) {
920                             len+= _XTranslateKeySym(event->display,rtrn.sym[n],
921                                                         event->state,
922                                                         buffer+len,nbytes-len);
923                         }
924                     }
925                     if ( keysym!=NULL ) {
926                         if ( n==1 )     *keysym = rtrn.sym[0];
927                         else            *keysym = NoSymbol;
928                     }
929                     return len;
930                 }
931                 case XIM_COMP_SUCCEED:
932                 {
933                     int len,n = 0;
934
935                     symbol = rtrn.matchSym;
936                     if ( keysym!=NULL ) *keysym = symbol;
937                     if ( rtrn.str[0]!='\0' ) {
938                         strncpy(buffer,rtrn.str,nbytes-1);
939                         buffer[nbytes-1]= '\0';
940                         len = strlen(buffer);
941                     }
942                     else {
943                         len = _XTranslateKeySym(event->display,symbol,
944                                                         event->state,
945                                                         buffer,nbytes);
946                     }
947                     for (n=0;rtrn.sym[n]!=XK_VoidSymbol;n++) {
948                         if ( nbytes-len > 0 ) {
949                             len+= _XTranslateKeySym(event->display,rtrn.sym[n],
950                                                         event->state,
951                                                         buffer+len,nbytes-len);
952                         }
953                     }
954                     return len;
955                 }
956             }
957         }
958     }
959 #endif
960
961     if (keysym)
962         *keysym = symbol;
963     /* arguable whether to use (event->state & ~modifiers) here */
964     return _XTranslateKeySym(event->display, symbol, event->state,
965                              buffer, nbytes);
966 }
967
968 static void
969 _XFreeKeyBindings(
970     Display *dpy)
971 {
972     register struct _XKeytrans *p, *np;
973
974     for (p = dpy->key_bindings; p; p = np) {
975         np = p->next;
976         Xfree(p->string);
977         Xfree((char *)p->modifiers);
978         Xfree((char *)p);
979     }
980 }
981
982 int
983 XRebindKeysym (
984     Display *dpy,
985     KeySym keysym,
986     KeySym *mlist,
987     int nm,             /* number of modifiers in mlist */
988     _Xconst unsigned char *str,
989     int nbytes)
990 {
991     register struct _XKeytrans *tmp, *p;
992     int nb;
993
994     if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
995         return 0;
996     LockDisplay(dpy);
997     tmp = dpy->key_bindings;
998     nb = sizeof(KeySym) * nm;
999
1000     if ((! (p = (struct _XKeytrans *) Xcalloc( 1, sizeof(struct _XKeytrans)))) ||
1001         ((! (p->string = (char *) Xmalloc( (unsigned) nbytes))) &&
1002          (nbytes > 0)) ||
1003         ((! (p->modifiers = (KeySym *) Xmalloc( (unsigned) nb))) &&
1004          (nb > 0))) {
1005         if (p) {
1006             if (p->string) Xfree(p->string);
1007             if (p->modifiers) Xfree((char *) p->modifiers);
1008             Xfree((char *) p);
1009         }
1010         UnlockDisplay(dpy);
1011         return 0;
1012     }
1013
1014     dpy->key_bindings = p;
1015     dpy->free_funcs->key_bindings = _XFreeKeyBindings;
1016     p->next = tmp;      /* chain onto list */
1017     memcpy (p->string, (char *) str, nbytes);
1018     p->len = nbytes;
1019     memcpy ((char *) p->modifiers, (char *) mlist, nb);
1020     p->key = keysym;
1021     p->mlen = nm;
1022     ComputeMaskFromKeytrans(dpy, p);
1023     UnlockDisplay(dpy);
1024     return 0;
1025 }
1026
1027 unsigned
1028 _XKeysymToModifiers(
1029     Display *dpy,
1030     KeySym ks)
1031 {
1032     CARD8 code,mods;
1033     register KeySym *kmax;
1034     register KeySym *k;
1035     register XModifierKeymap *m;
1036
1037     if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
1038         return 0;
1039     kmax = dpy->keysyms +
1040            (dpy->max_keycode - dpy->min_keycode + 1) * dpy->keysyms_per_keycode;
1041     k = dpy->keysyms;
1042     m = dpy->modifiermap;
1043     mods= 0;
1044     while (k<kmax) {
1045         if (*k == ks ) {
1046             register int j = m->max_keypermod<<3;
1047
1048             code=(((k-dpy->keysyms)/dpy->keysyms_per_keycode)+dpy->min_keycode);
1049
1050             while (--j >= 0) {
1051                 if (code == m->modifiermap[j])
1052                     mods|= (1<<(j/m->max_keypermod));
1053             }
1054         }
1055         k++;
1056     }
1057     return mods;
1058 }
1059
1060 /*
1061  * given a list of modifiers, computes the mask necessary for later matching.
1062  * This routine must lookup the key in the Keymap and then search to see
1063  * what modifier it is bound to, if any.  Sets the AnyModifier bit if it
1064  * can't map some keysym to a modifier.
1065  */
1066 static void
1067 ComputeMaskFromKeytrans(
1068     Display *dpy,
1069     register struct _XKeytrans *p)
1070 {
1071     register int i;
1072
1073     p->state = AnyModifier;
1074     for (i = 0; i < p->mlen; i++) {
1075         p->state|= XkbKeysymToModifiers(dpy,p->modifiers[i]);
1076     }
1077     p->state &= AllMods;
1078 }