xref: /minix3/external/mit/xorg/tools/xkbcomp/xkbcomp-KeyBind.c (revision 971bb1a5878d19f91739f74fd389e6c5108cb7fa)
1 /*	$NetBSD: xkbcomp-KeyBind.c,v 1.1.1.1 2008/07/29 05:01:23 mrg Exp $	*/
2 
3 /* $Xorg: KeyBind.c,v 1.4 2001/02/09 02:03:34 xorgcvs Exp $ */
4 /*
5 
6 Copyright 1985, 1987, 1998  The Open Group
7 
8 Permission to use, copy, modify, distribute, and sell this software and its
9 documentation for any purpose is hereby granted without fee, provided that
10 the above copyright notice appear in all copies and that both that
11 copyright notice and this permission notice appear in supporting
12 documentation.
13 
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
20 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 
24 Except as contained in this notice, the name of The Open Group shall not be
25 used in advertising or otherwise to promote the sale, use or other dealings
26 in this Software without prior written authorization from The Open Group.
27 
28 */
29 /* $XFree86: xc/lib/X11/KeyBind.c,v 1.5 2001/12/14 19:54:02 dawes Exp $ */
30 
31 /* Beware, here be monsters (still under construction... - JG */
32 
33 #define NEED_EVENTS
34 #include <X11/Xlibint.h>
35 #include <X11/Xutil.h>
36 #define XK_MISCELLANY
37 #define XK_LATIN1
38 #define XK_LATIN2
39 #define XK_LATIN3
40 #define XK_LATIN4
41 #define XK_CYRILLIC
42 #define XK_GREEK
43 #define XK_ARMENIAN
44 #define XK_XKB_KEYS
45 #include <X11/keysymdef.h>
46 #include <stdio.h>
47 
48 #include "XKBlib.h"
49 
50 #ifdef USE_OWN_COMPOSE
51 #include "imComp.h"
52 
53 #endif
54 
55 #ifdef XKB
56 #define	XKeycodeToKeysym	_XKeycodeToKeysym
57 #define	XKeysymToKeycode	_XKeysymToKeycode
58 #define	XLookupKeysym		_XLookupKeysym
59 #define	XRefreshKeyboardMapping	_XRefreshKeyboardMapping
60 #define	XLookupString		_XLookupString
61 /* XKBBind.c */
62 #else
63 #define	XkbKeysymToModifiers	_XKeysymToModifiers
64 #endif
65 
66 #define AllMods (ShiftMask|LockMask|ControlMask| \
67 		 Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)
68 
69 #if 0	/* { */
70 
71 static void ComputeMaskFromKeytrans();
72 int _XKeyInitialize();
73 
74 struct _XKeytrans {
75 	struct _XKeytrans *next;/* next on list */
76 	char *string;		/* string to return when the time comes */
77 	int len;		/* length of string (since NULL is legit)*/
78 	KeySym key;		/* keysym rebound */
79 	unsigned int state;	/* modifier state */
80 	KeySym *modifiers;	/* modifier keysyms you want */
81 	int mlen;		/* length of modifier list */
82 };
83 
84 static KeySym
85 #if NeedFunctionPrototypes
86 KeyCodetoKeySym(register Display *dpy, KeyCode keycode, int col)
87 #else
88 KeyCodetoKeySym(dpy, keycode, col)
89     register Display *dpy;
90     KeyCode keycode;
91     int col;
92 #endif
93 {
94     register int per = dpy->keysyms_per_keycode;
95     register KeySym *syms;
96     KeySym lsym, usym;
97 
98     if ((col < 0) || ((col >= per) && (col > 3)) ||
99 	((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode))
100       return NoSymbol;
101 
102     syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per];
103     if (col < 4) {
104 	if (col > 1) {
105 	    while ((per > 2) && (syms[per - 1] == NoSymbol))
106 		per--;
107 	    if (per < 3)
108 		col -= 2;
109 	}
110 	if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
111 	    XConvertCase(syms[col&~1], &lsym, &usym);
112 	    if (!(col & 1))
113 		return lsym;
114 	    else if (usym == lsym)
115 		return NoSymbol;
116 	    else
117 		return usym;
118 	}
119     }
120     return syms[col];
121 }
122 
123 #if NeedFunctionPrototypes
124 KeySym
125 XKeycodeToKeysym(Display *dpy,
126 #if NeedWidePrototypes
127 		 unsigned int kc,
128 #else
129 		 KeyCode kc,
130 #endif
131 		 int col)
132 #else
133 KeySym
134 XKeycodeToKeysym(dpy, kc, col)
135     Display *dpy;
136     KeyCode kc;
137     int col;
138 #endif
139 {
140     if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
141 	return NoSymbol;
142     return KeyCodetoKeySym(dpy, kc, col);
143 }
144 
145 KeyCode
146 XKeysymToKeycode(dpy, ks)
147     Display *dpy;
148     KeySym ks;
149 {
150     register int i, j;
151 
152     if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
153 	return (KeyCode) 0;
154     for (j = 0; j < dpy->keysyms_per_keycode; j++) {
155 	for (i = dpy->min_keycode; i <= dpy->max_keycode; i++) {
156 	    if (KeyCodetoKeySym(dpy, (KeyCode) i, j) == ks)
157 		return i;
158 	}
159     }
160     return 0;
161 }
162 
163 KeySym
164 XLookupKeysym(event, col)
165     register XKeyEvent *event;
166     int col;
167 {
168     if ((! event->display->keysyms) && (! _XKeyInitialize(event->display)))
169 	return NoSymbol;
170     return KeyCodetoKeySym(event->display, event->keycode, col);
171 }
172 
173 static void
174 ResetModMap(dpy)
175     Display *dpy;
176 {
177     register XModifierKeymap *map;
178     register int i, j, n;
179     KeySym sym;
180     register struct _XKeytrans *p;
181 
182     map = dpy->modifiermap;
183     /* If any Lock key contains Caps_Lock, then interpret as Caps_Lock,
184      * else if any contains Shift_Lock, then interpret as Shift_Lock,
185      * else ignore Lock altogether.
186      */
187     dpy->lock_meaning = NoSymbol;
188     /* Lock modifiers are in the second row of the matrix */
189     n = 2 * map->max_keypermod;
190     for (i = map->max_keypermod; i < n; i++) {
191 	for (j = 0; j < dpy->keysyms_per_keycode; j++) {
192 	    sym = KeyCodetoKeySym(dpy, map->modifiermap[i], j);
193 	    if (sym == XK_Caps_Lock) {
194 		dpy->lock_meaning = XK_Caps_Lock;
195 		break;
196 	    } else if (sym == XK_Shift_Lock) {
197 		dpy->lock_meaning = XK_Shift_Lock;
198 	    }
199 	    else if (sym == XK_ISO_Lock) {
200 		dpy->lock_meaning = XK_Caps_Lock;
201 		break;
202 	    }
203 	}
204     }
205     /* Now find any Mod<n> modifier acting as the Group or Numlock modifier */
206     dpy->mode_switch = 0;
207     dpy->num_lock = 0;
208     n *= 4;
209     for (i = 3*map->max_keypermod; i < n; i++) {
210 	for (j = 0; j < dpy->keysyms_per_keycode; j++) {
211 	    sym = KeyCodetoKeySym(dpy, map->modifiermap[i], j);
212 	    if (sym == XK_Mode_switch)
213 		dpy->mode_switch |= 1 << (i / map->max_keypermod);
214 	    if (sym == XK_Num_Lock)
215 		dpy->num_lock |= 1 << (i / map->max_keypermod);
216 	}
217     }
218     for (p = dpy->key_bindings; p; p = p->next)
219 	ComputeMaskFromKeytrans(dpy, p);
220 }
221 
222 static int
223 InitModMap(dpy)
224     Display *dpy;
225 {
226     register XModifierKeymap *map;
227 
228     if (! (map = XGetModifierMapping(dpy)))
229 	return 0;
230     LockDisplay(dpy);
231     if (dpy->modifiermap)
232 	XFreeModifiermap(dpy->modifiermap);
233     dpy->modifiermap = map;
234     dpy->free_funcs->modifiermap = XFreeModifiermap;
235     if (dpy->keysyms)
236 	ResetModMap(dpy);
237     UnlockDisplay(dpy);
238     return 1;
239 }
240 
241 int
242 XRefreshKeyboardMapping(event)
243     register XMappingEvent *event;
244 {
245 
246     if(event->request == MappingKeyboard) {
247 	/* XXX should really only refresh what is necessary
248 	 * for now, make initialize test fail
249 	 */
250 	LockDisplay(event->display);
251 	if (event->display->keysyms) {
252 	     Xfree ((char *)event->display->keysyms);
253 	     event->display->keysyms = NULL;
254 	}
255 	UnlockDisplay(event->display);
256     }
257     if(event->request == MappingModifier) {
258 	LockDisplay(event->display);
259 	if (event->display->modifiermap) {
260 	    XFreeModifiermap(event->display->modifiermap);
261 	    event->display->modifiermap = NULL;
262 	}
263 	UnlockDisplay(event->display);
264 	/* go ahead and get it now, since initialize test may not fail */
265 	if (event->display->keysyms)
266 	    (void) InitModMap(event->display);
267     }
268     return 1;
269 }
270 
271 int
272 _XKeyInitialize(dpy)
273     Display *dpy;
274 {
275     int per, n;
276     KeySym *keysyms;
277 
278     /*
279      * lets go get the keysyms from the server.
280      */
281     if (!dpy->keysyms) {
282 	n = dpy->max_keycode - dpy->min_keycode + 1;
283 	keysyms = XGetKeyboardMapping (dpy, (KeyCode) dpy->min_keycode,
284 				       n, &per);
285 	/* keysyms may be NULL */
286 	if (! keysyms) return 0;
287 
288 	LockDisplay(dpy);
289 	if (dpy->keysyms)
290 	    Xfree ((char *)dpy->keysyms);
291 	dpy->keysyms = keysyms;
292 	dpy->keysyms_per_keycode = per;
293 	if (dpy->modifiermap)
294 	    ResetModMap(dpy);
295 	UnlockDisplay(dpy);
296     }
297     if (!dpy->modifiermap)
298         return InitModMap(dpy);
299     return 1;
300 }
301 
302 #endif	/* } */
303 
304 void
XConvertCase(sym,lower,upper)305 XConvertCase(sym, lower, upper)
306     register KeySym sym;
307     KeySym *lower;
308     KeySym *upper;
309 {
310     *lower = sym;
311     *upper = sym;
312     switch(sym >> 8) {
313     case 0: /* Latin 1 */
314 	if ((sym >= XK_A) && (sym <= XK_Z))
315 	    *lower += (XK_a - XK_A);
316 	else if ((sym >= XK_a) && (sym <= XK_z))
317 	    *upper -= (XK_a - XK_A);
318 	else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
319 	    *lower += (XK_agrave - XK_Agrave);
320 	else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
321 	    *upper -= (XK_agrave - XK_Agrave);
322 	else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
323 	    *lower += (XK_oslash - XK_Ooblique);
324 	else if ((sym >= XK_oslash) && (sym <= XK_thorn))
325 	    *upper -= (XK_oslash - XK_Ooblique);
326 	break;
327     case 1: /* Latin 2 */
328 	/* Assume the KeySym is a legal value (ignore discontinuities) */
329 	if (sym == XK_Aogonek)
330 	    *lower = XK_aogonek;
331 	else if (sym >= XK_Lstroke && sym <= XK_Sacute)
332 	    *lower += (XK_lstroke - XK_Lstroke);
333 	else if (sym >= XK_Scaron && sym <= XK_Zacute)
334 	    *lower += (XK_scaron - XK_Scaron);
335 	else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
336 	    *lower += (XK_zcaron - XK_Zcaron);
337 	else if (sym == XK_aogonek)
338 	    *upper = XK_Aogonek;
339 	else if (sym >= XK_lstroke && sym <= XK_sacute)
340 	    *upper -= (XK_lstroke - XK_Lstroke);
341 	else if (sym >= XK_scaron && sym <= XK_zacute)
342 	    *upper -= (XK_scaron - XK_Scaron);
343 	else if (sym >= XK_zcaron && sym <= XK_zabovedot)
344 	    *upper -= (XK_zcaron - XK_Zcaron);
345 	else if (sym >= XK_Racute && sym <= XK_Tcedilla)
346 	    *lower += (XK_racute - XK_Racute);
347 	else if (sym >= XK_racute && sym <= XK_tcedilla)
348 	    *upper -= (XK_racute - XK_Racute);
349 	break;
350     case 2: /* Latin 3 */
351 	/* Assume the KeySym is a legal value (ignore discontinuities) */
352 	if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
353 	    *lower += (XK_hstroke - XK_Hstroke);
354 	else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
355 	    *lower += (XK_gbreve - XK_Gbreve);
356 	else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
357 	    *upper -= (XK_hstroke - XK_Hstroke);
358 	else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
359 	    *upper -= (XK_gbreve - XK_Gbreve);
360 	else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
361 	    *lower += (XK_cabovedot - XK_Cabovedot);
362 	else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
363 	    *upper -= (XK_cabovedot - XK_Cabovedot);
364 	break;
365     case 3: /* Latin 4 */
366 	/* Assume the KeySym is a legal value (ignore discontinuities) */
367 	if (sym >= XK_Rcedilla && sym <= XK_Tslash)
368 	    *lower += (XK_rcedilla - XK_Rcedilla);
369 	else if (sym >= XK_rcedilla && sym <= XK_tslash)
370 	    *upper -= (XK_rcedilla - XK_Rcedilla);
371 	else if (sym == XK_ENG)
372 	    *lower = XK_eng;
373 	else if (sym == XK_eng)
374 	    *upper = XK_ENG;
375 	else if (sym >= XK_Amacron && sym <= XK_Umacron)
376 	    *lower += (XK_amacron - XK_Amacron);
377 	else if (sym >= XK_amacron && sym <= XK_umacron)
378 	    *upper -= (XK_amacron - XK_Amacron);
379 	break;
380     case 6: /* Cyrillic */
381 	/* Assume the KeySym is a legal value (ignore discontinuities) */
382 	if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
383 	    *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
384 	else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
385 	    *upper += (XK_Serbian_DJE - XK_Serbian_dje);
386 	else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
387 	    *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
388 	else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
389 	    *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
390         break;
391     case 7: /* Greek */
392 	/* Assume the KeySym is a legal value (ignore discontinuities) */
393 	if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
394 	    *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
395 	else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
396 		 sym != XK_Greek_iotaaccentdieresis &&
397 		 sym != XK_Greek_upsilonaccentdieresis)
398 	    *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
399 	else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
400 	    *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
401 	else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
402 		 sym != XK_Greek_finalsmallsigma)
403 	    *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
404         break;
405     case 0x14: /* Armenian */
406 	if (sym >= XK_Armenian_AYB && sym <= XK_Armenian_fe) {
407 	    *lower = sym | 1;
408 	    *upper = sym & ~1;
409 	}
410         break;
411     }
412 }
413 
414 #if __disabled_for_imakeicide__	/* { */
415 
416 int
417 #if NeedFunctionPrototypes
_XTranslateKey(register Display * dpy,KeyCode keycode,register unsigned int modifiers,unsigned int * modifiers_return,KeySym * keysym_return)418 _XTranslateKey(	register Display *dpy,
419 		KeyCode keycode,
420 		register unsigned int modifiers,
421 		unsigned int *modifiers_return,
422 		KeySym *keysym_return)
423 #else
424 _XTranslateKey(dpy, keycode, modifiers, modifiers_return, keysym_return)
425     register Display *dpy;
426     KeyCode keycode;
427     register unsigned int modifiers;
428     unsigned int *modifiers_return;
429     KeySym *keysym_return;
430 #endif
431 {
432     int per;
433     register KeySym *syms;
434     KeySym sym, lsym, usym;
435 
436     if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
437 	return 0;
438     *modifiers_return = ((ShiftMask|LockMask)
439 			 | dpy->mode_switch | dpy->num_lock);
440     if (((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode))
441     {
442 	*keysym_return = NoSymbol;
443 	return 1;
444     }
445     per = dpy->keysyms_per_keycode;
446     syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per];
447     while ((per > 2) && (syms[per - 1] == NoSymbol))
448 	per--;
449     if ((per > 2) && (modifiers & dpy->mode_switch)) {
450 	syms += 2;
451 	per -= 2;
452     }
453     if ((modifiers & dpy->num_lock) &&
454 	(per > 1 && (IsKeypadKey(syms[1]) || IsPrivateKeypadKey(syms[1])))) {
455 	if ((modifiers & ShiftMask) ||
456 	    ((modifiers & LockMask) && (dpy->lock_meaning == XK_Shift_Lock)))
457 	    *keysym_return = syms[0];
458 	else
459 	    *keysym_return = syms[1];
460     } else if (!(modifiers & ShiftMask) &&
461 	(!(modifiers & LockMask) || (dpy->lock_meaning == NoSymbol))) {
462 	if ((per == 1) || (syms[1] == NoSymbol))
463 	    XConvertCase(syms[0], keysym_return, &usym);
464 	else
465 	    *keysym_return = syms[0];
466     } else if (!(modifiers & LockMask) ||
467 	       (dpy->lock_meaning != XK_Caps_Lock)) {
468 	if ((per == 1) || ((usym = syms[1]) == NoSymbol))
469 	    XConvertCase(syms[0], &lsym, &usym);
470 	*keysym_return = usym;
471     } else {
472 	if ((per == 1) || ((sym = syms[1]) == NoSymbol))
473 	    sym = syms[0];
474 	XConvertCase(sym, &lsym, &usym);
475 	if (!(modifiers & ShiftMask) && (sym != syms[0]) &&
476 	    ((sym != usym) || (lsym == usym)))
477 	    XConvertCase(syms[0], &lsym, &usym);
478 	*keysym_return = usym;
479     }
480     if (*keysym_return == XK_VoidSymbol)
481 	*keysym_return = NoSymbol;
482     return 1;
483 }
484 
485 int
_XTranslateKeySym(dpy,symbol,modifiers,buffer,nbytes)486 _XTranslateKeySym(dpy, symbol, modifiers, buffer, nbytes)
487     Display *dpy;
488     register KeySym symbol;
489     unsigned int modifiers;
490     char *buffer;
491     int nbytes;
492 {
493     register struct _XKeytrans *p;
494     int length;
495     unsigned long hiBytes;
496     register unsigned char c;
497 
498     if (!symbol)
499 	return 0;
500     /* see if symbol rebound, if so, return that string. */
501     for (p = dpy->key_bindings; p; p = p->next) {
502 	if (((modifiers & AllMods) == p->state) && (symbol == p->key)) {
503 	    length = p->len;
504 	    if (length > nbytes) length = nbytes;
505 	    memcpy (buffer, p->string, length);
506 	    return length;
507 	}
508     }
509     /* try to convert to Latin-1, handling control */
510     hiBytes = symbol >> 8;
511     if (!(nbytes &&
512 	  ((hiBytes == 0) ||
513 	   ((hiBytes == 0xFF) &&
514 	    (((symbol >= XK_BackSpace) && (symbol <= XK_Clear)) ||
515 	     (symbol == XK_Return) ||
516 	     (symbol == XK_Escape) ||
517 	     (symbol == XK_KP_Space) ||
518 	     (symbol == XK_KP_Tab) ||
519 	     (symbol == XK_KP_Enter) ||
520 	     ((symbol >= XK_KP_Multiply) && (symbol <= XK_KP_9)) ||
521 	     (symbol == XK_KP_Equal) ||
522 	     (symbol == XK_Delete))))))
523 	return 0;
524 
525     /* if X keysym, convert to ascii by grabbing low 7 bits */
526     if (symbol == XK_KP_Space)
527 	c = XK_space & 0x7F; /* patch encoding botch */
528     else if (hiBytes == 0xFF)
529 	c = symbol & 0x7F;
530     else
531 	c = symbol & 0xFF;
532     /* only apply Control key if it makes sense, else ignore it */
533     if (modifiers & ControlMask) {
534 	if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
535 	else if (c == '2') c = '\000';
536 	else if (c >= '3' && c <= '7') c -= ('3' - '\033');
537 	else if (c == '8') c = '\177';
538 	else if (c == '/') c = '_' & 0x1F;
539     }
540     buffer[0] = c;
541     return 1;
542 }
543 
544 /*ARGSUSED*/
545 int
XLookupString(event,buffer,nbytes,keysym,status)546 XLookupString (event, buffer, nbytes, keysym, status)
547     register XKeyEvent *event;
548     char *buffer;	/* buffer */
549     int nbytes;	/* space in buffer for characters */
550     KeySym *keysym;
551     XComposeStatus *status;	/* not implemented */
552 {
553     unsigned int modifiers;
554     KeySym symbol;
555 
556     if (! _XTranslateKey(event->display, event->keycode, event->state,
557 		  &modifiers, &symbol))
558 	return 0;
559 
560 #ifdef USE_OWN_COMPOSE
561     if ( status ) {
562 	static int been_here= 0;
563 	if ( !been_here ) {
564 	    XimCompInitTables();
565 	    been_here = 1;
566 	}
567 	if ( !XimCompLegalStatus(status) ) {
568 	    status->compose_ptr = NULL;
569 	    status->chars_matched = 0;
570 	}
571 	if ( ((status->chars_matched>0)&&(status->compose_ptr!=NULL)) ||
572 		XimCompIsComposeKey(symbol,event->keycode,status) ) {
573 	    XimCompRtrn rtrn;
574 	    switch (XimCompProcessSym(status,symbol,&rtrn)) {
575 		case XIM_COMP_IGNORE:
576 		    break;
577 		case XIM_COMP_IN_PROGRESS:
578 		    if ( keysym!=NULL )
579 			*keysym = NoSymbol;
580 		    return 0;
581 		case XIM_COMP_FAIL:
582 		{
583 		    int n = 0, len= 0;
584 		    for (n=len=0;rtrn.sym[n]!=XK_VoidSymbol;n++) {
585 			if ( nbytes-len > 0 ) {
586 			    len+= _XTranslateKeySym(event->display,rtrn.sym[n],
587 							event->state,
588 							buffer+len,nbytes-len);
589 			}
590 		    }
591 		    if ( keysym!=NULL ) {
592 			if ( n==1 )	*keysym = rtrn.sym[0];
593 			else		*keysym = NoSymbol;
594 		    }
595 		    return len;
596 		}
597 		case XIM_COMP_SUCCEED:
598 		{
599 		    int len,n = 0;
600 
601 		    symbol = rtrn.matchSym;
602 		    if ( keysym!=NULL )	*keysym = symbol;
603 		    if ( rtrn.str[0]!='\0' ) {
604 			strncpy(buffer,rtrn.str,nbytes-1);
605 			buffer[nbytes-1]= '\0';
606 			len = strlen(buffer);
607 		    }
608 		    else {
609 			len = _XTranslateKeySym(event->display,symbol,
610 							event->state,
611 							buffer,nbytes);
612 		    }
613 		    for (n=0;rtrn.sym[n]!=XK_VoidSymbol;n++) {
614 			if ( nbytes-len > 0 ) {
615 			    len+= _XTranslateKeySym(event->display,rtrn.sym[n],
616 							event->state,
617 							buffer+len,nbytes-len);
618 			}
619 		    }
620 		    return len;
621 		}
622 	    }
623 	}
624     }
625 #endif
626 
627     if (keysym)
628 	*keysym = symbol;
629     /* arguable whether to use (event->state & ~modifiers) here */
630     return _XTranslateKeySym(event->display, symbol, event->state,
631 			     buffer, nbytes);
632 }
633 
634 static void
_XFreeKeyBindings(dpy)635 _XFreeKeyBindings (dpy)
636     Display *dpy;
637 {
638     register struct _XKeytrans *p, *np;
639 
640     for (p = dpy->key_bindings; p; p = np) {
641 	np = p->next;
642 	Xfree(p->string);
643 	Xfree((char *)p->modifiers);
644 	Xfree((char *)p);
645     }
646 }
647 
648 int
649 #if NeedFunctionPrototypes
XRebindKeysym(Display * dpy,KeySym keysym,KeySym * mlist,int nm,_Xconst unsigned char * str,int nbytes)650 XRebindKeysym (
651     Display *dpy,
652     KeySym keysym,
653     KeySym *mlist,
654     int nm,		/* number of modifiers in mlist */
655     _Xconst unsigned char *str,
656     int nbytes)
657 #else
658 XRebindKeysym (dpy, keysym, mlist, nm, str, nbytes)
659     Display *dpy;
660     KeySym keysym;
661     KeySym *mlist;
662     int nm;		/* number of modifiers in mlist */
663     unsigned char *str;
664     int nbytes;
665 #endif
666 {
667     register struct _XKeytrans *tmp, *p;
668     int nb;
669 
670     if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
671 	return 0;
672     LockDisplay(dpy);
673     tmp = dpy->key_bindings;
674     nb = sizeof(KeySym) * nm;
675 
676     if ((! (p = (struct _XKeytrans *) Xmalloc( sizeof(struct _XKeytrans)))) ||
677 	((! (p->string = (char *) Xmalloc( (unsigned) nbytes))) &&
678 	 (nbytes > 0)) ||
679 	((! (p->modifiers = (KeySym *) Xmalloc( (unsigned) nb))) &&
680 	 (nb > 0))) {
681 	if (p) {
682 	    if (p->string) Xfree(p->string);
683 	    if (p->modifiers) Xfree((char *) p->modifiers);
684 	    Xfree((char *) p);
685 	}
686 	UnlockDisplay(dpy);
687 	return 0;
688     }
689 
690     dpy->key_bindings = p;
691     dpy->free_funcs->key_bindings = _XFreeKeyBindings;
692     p->next = tmp;	/* chain onto list */
693     memcpy (p->string, (char *) str, nbytes);
694     p->len = nbytes;
695     memcpy ((char *) p->modifiers, (char *) mlist, nb);
696     p->key = keysym;
697     p->mlen = nm;
698     ComputeMaskFromKeytrans(dpy, p);
699     UnlockDisplay(dpy);
700     return 0;
701 }
702 
703 unsigned
_XKeysymToModifiers(dpy,ks)704 _XKeysymToModifiers(dpy,ks)
705     Display *dpy;
706     KeySym ks;
707 {
708     CARD8 code,mods;
709     register KeySym *kmax;
710     register KeySym *k;
711     register XModifierKeymap *m;
712 
713     if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
714 	return 0;
715     kmax = dpy->keysyms +
716 	   (dpy->max_keycode - dpy->min_keycode + 1) * dpy->keysyms_per_keycode;
717     k = dpy->keysyms;
718     m = dpy->modifiermap;
719     mods= 0;
720     while (k<kmax) {
721 	if (*k == ks ) {
722 	    register int j = m->max_keypermod<<3;
723 
724 	    code=(((k-dpy->keysyms)/dpy->keysyms_per_keycode)+dpy->min_keycode);
725 
726 	    while (--j >= 0) {
727 		if (code == m->modifiermap[j])
728 		    mods|= (1<<(j/m->max_keypermod));
729 	    }
730 	}
731 	k++;
732     }
733     return mods;
734 }
735 
736 /*
737  * given a list of modifiers, computes the mask necessary for later matching.
738  * This routine must lookup the key in the Keymap and then search to see
739  * what modifier it is bound to, if any.  Sets the AnyModifier bit if it
740  * can't map some keysym to a modifier.
741  */
742 static void
ComputeMaskFromKeytrans(dpy,p)743 ComputeMaskFromKeytrans(dpy, p)
744     Display *dpy;
745     register struct _XKeytrans *p;
746 {
747     register int i;
748 
749     p->state = AnyModifier;
750     for (i = 0; i < p->mlen; i++) {
751 	p->state|= XkbKeysymToModifiers(dpy,p->modifiers[i]);
752     }
753     p->state &= AllMods;
754 }
755 
756 #endif	/* __disabled_for_imakeicide__ } */
757