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