1
/* $Xorg: KeyBind.c,v 1.4 2001/02/09 02:03:34 xorgcvs Exp $ */
4
Copyright 1985, 1987, 1998 The Open Group
6
Permission to use, copy, modify, distribute, and sell this software and its
7
documentation for any purpose is hereby granted without fee, provided that
8
the above copyright notice appear in all copies and that both that
9
copyright notice and this permission notice appear in supporting
12
The above copyright notice and this permission notice shall be included in
13
all copies or substantial portions of the Software.
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
Except as contained in this notice, the name of The Open Group shall not be
23
used in advertising or otherwise to promote the sale, use or other dealings
24
in this Software without prior written authorization from The Open Group.
27
/* $XFree86: xc/lib/X11/KeyBind.c,v 1.5 2001/12/14 19:54:02 dawes Exp $ */
29
/* Beware, here be monsters (still under construction... - JG */
32
#include <X11/Xlibint.h>
33
#include <X11/Xutil.h>
43
#include <X11/keysymdef.h>
48
#ifdef USE_OWN_COMPOSE
54
#define XKeycodeToKeysym _XKeycodeToKeysym
55
#define XKeysymToKeycode _XKeysymToKeycode
56
#define XLookupKeysym _XLookupKeysym
57
#define XRefreshKeyboardMapping _XRefreshKeyboardMapping
58
#define XLookupString _XLookupString
61
#define XkbKeysymToModifiers _XKeysymToModifiers
64
#define AllMods (ShiftMask|LockMask|ControlMask| \
65
Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)
67
static void ComputeMaskFromKeytrans();
68
int _XKeyInitialize();
71
struct _XKeytrans *next;/* next on list */
72
char *string; /* string to return when the time comes */
73
int len; /* length of string (since NULL is legit)*/
74
KeySym key; /* keysym rebound */
75
unsigned int state; /* modifier state */
76
KeySym *modifiers; /* modifier keysyms you want */
77
int mlen; /* length of modifier list */
81
#if NeedFunctionPrototypes
82
KeyCodetoKeySym(register Display *dpy, KeyCode keycode, int col)
84
KeyCodetoKeySym(dpy, keycode, col)
85
register Display *dpy;
90
register int per = dpy->keysyms_per_keycode;
91
register KeySym *syms;
94
if ((col < 0) || ((col >= per) && (col > 3)) ||
95
((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode))
98
syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per];
101
while ((per > 2) && (syms[per - 1] == NoSymbol))
106
if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
107
XConvertCase(syms[col&~1], &lsym, &usym);
110
else if (usym == lsym)
119
#if NeedFunctionPrototypes
121
XKeycodeToKeysym(Display *dpy,
122
#if NeedWidePrototypes
130
XKeycodeToKeysym(dpy, kc, col)
136
if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
138
return KeyCodetoKeySym(dpy, kc, col);
142
XKeysymToKeycode(dpy, ks)
148
if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
150
for (j = 0; j < dpy->keysyms_per_keycode; j++) {
151
for (i = dpy->min_keycode; i <= dpy->max_keycode; i++) {
152
if (KeyCodetoKeySym(dpy, (KeyCode) i, j) == ks)
160
XLookupKeysym(event, col)
161
register XKeyEvent *event;
164
if ((! event->display->keysyms) && (! _XKeyInitialize(event->display)))
166
return KeyCodetoKeySym(event->display, event->keycode, col);
173
register XModifierKeymap *map;
174
register int i, j, n;
176
register struct _XKeytrans *p;
178
map = dpy->modifiermap;
179
/* If any Lock key contains Caps_Lock, then interpret as Caps_Lock,
180
* else if any contains Shift_Lock, then interpret as Shift_Lock,
181
* else ignore Lock altogether.
183
dpy->lock_meaning = NoSymbol;
184
/* Lock modifiers are in the second row of the matrix */
185
n = 2 * map->max_keypermod;
186
for (i = map->max_keypermod; i < n; i++) {
187
for (j = 0; j < dpy->keysyms_per_keycode; j++) {
188
sym = KeyCodetoKeySym(dpy, map->modifiermap[i], j);
189
if (sym == XK_Caps_Lock) {
190
dpy->lock_meaning = XK_Caps_Lock;
192
} else if (sym == XK_Shift_Lock) {
193
dpy->lock_meaning = XK_Shift_Lock;
195
else if (sym == XK_ISO_Lock) {
196
dpy->lock_meaning = XK_Caps_Lock;
201
/* Now find any Mod<n> modifier acting as the Group or Numlock modifier */
202
dpy->mode_switch = 0;
205
for (i = 3*map->max_keypermod; i < n; i++) {
206
for (j = 0; j < dpy->keysyms_per_keycode; j++) {
207
sym = KeyCodetoKeySym(dpy, map->modifiermap[i], j);
208
if (sym == XK_Mode_switch)
209
dpy->mode_switch |= 1 << (i / map->max_keypermod);
210
if (sym == XK_Num_Lock)
211
dpy->num_lock |= 1 << (i / map->max_keypermod);
214
for (p = dpy->key_bindings; p; p = p->next)
215
ComputeMaskFromKeytrans(dpy, p);
222
register XModifierKeymap *map;
224
if (! (map = XGetModifierMapping(dpy)))
227
if (dpy->modifiermap)
228
XFreeModifiermap(dpy->modifiermap);
229
dpy->modifiermap = map;
230
dpy->free_funcs->modifiermap = XFreeModifiermap;
238
XRefreshKeyboardMapping(event)
239
register XMappingEvent *event;
242
if(event->request == MappingKeyboard) {
243
/* XXX should really only refresh what is necessary
244
* for now, make initialize test fail
246
LockDisplay(event->display);
247
if (event->display->keysyms) {
248
Xfree ((char *)event->display->keysyms);
249
event->display->keysyms = NULL;
251
UnlockDisplay(event->display);
253
if(event->request == MappingModifier) {
254
LockDisplay(event->display);
255
if (event->display->modifiermap) {
256
XFreeModifiermap(event->display->modifiermap);
257
event->display->modifiermap = NULL;
259
UnlockDisplay(event->display);
260
/* go ahead and get it now, since initialize test may not fail */
261
if (event->display->keysyms)
262
(void) InitModMap(event->display);
275
* lets go get the keysyms from the server.
278
n = dpy->max_keycode - dpy->min_keycode + 1;
279
keysyms = XGetKeyboardMapping (dpy, (KeyCode) dpy->min_keycode,
281
/* keysyms may be NULL */
282
if (! keysyms) return 0;
286
Xfree ((char *)dpy->keysyms);
287
dpy->keysyms = keysyms;
288
dpy->keysyms_per_keycode = per;
289
if (dpy->modifiermap)
293
if (!dpy->modifiermap)
294
return InitModMap(dpy);
299
XConvertCase(sym, lower, upper)
307
case 0: /* Latin 1 */
308
if ((sym >= XK_A) && (sym <= XK_Z))
309
*lower += (XK_a - XK_A);
310
else if ((sym >= XK_a) && (sym <= XK_z))
311
*upper -= (XK_a - XK_A);
312
else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
313
*lower += (XK_agrave - XK_Agrave);
314
else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
315
*upper -= (XK_agrave - XK_Agrave);
316
else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
317
*lower += (XK_oslash - XK_Ooblique);
318
else if ((sym >= XK_oslash) && (sym <= XK_thorn))
319
*upper -= (XK_oslash - XK_Ooblique);
321
case 1: /* Latin 2 */
322
/* Assume the KeySym is a legal value (ignore discontinuities) */
323
if (sym == XK_Aogonek)
325
else if (sym >= XK_Lstroke && sym <= XK_Sacute)
326
*lower += (XK_lstroke - XK_Lstroke);
327
else if (sym >= XK_Scaron && sym <= XK_Zacute)
328
*lower += (XK_scaron - XK_Scaron);
329
else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
330
*lower += (XK_zcaron - XK_Zcaron);
331
else if (sym == XK_aogonek)
333
else if (sym >= XK_lstroke && sym <= XK_sacute)
334
*upper -= (XK_lstroke - XK_Lstroke);
335
else if (sym >= XK_scaron && sym <= XK_zacute)
336
*upper -= (XK_scaron - XK_Scaron);
337
else if (sym >= XK_zcaron && sym <= XK_zabovedot)
338
*upper -= (XK_zcaron - XK_Zcaron);
339
else if (sym >= XK_Racute && sym <= XK_Tcedilla)
340
*lower += (XK_racute - XK_Racute);
341
else if (sym >= XK_racute && sym <= XK_tcedilla)
342
*upper -= (XK_racute - XK_Racute);
344
case 2: /* Latin 3 */
345
/* Assume the KeySym is a legal value (ignore discontinuities) */
346
if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
347
*lower += (XK_hstroke - XK_Hstroke);
348
else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
349
*lower += (XK_gbreve - XK_Gbreve);
350
else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
351
*upper -= (XK_hstroke - XK_Hstroke);
352
else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
353
*upper -= (XK_gbreve - XK_Gbreve);
354
else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
355
*lower += (XK_cabovedot - XK_Cabovedot);
356
else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
357
*upper -= (XK_cabovedot - XK_Cabovedot);
359
case 3: /* Latin 4 */
360
/* Assume the KeySym is a legal value (ignore discontinuities) */
361
if (sym >= XK_Rcedilla && sym <= XK_Tslash)
362
*lower += (XK_rcedilla - XK_Rcedilla);
363
else if (sym >= XK_rcedilla && sym <= XK_tslash)
364
*upper -= (XK_rcedilla - XK_Rcedilla);
365
else if (sym == XK_ENG)
367
else if (sym == XK_eng)
369
else if (sym >= XK_Amacron && sym <= XK_Umacron)
370
*lower += (XK_amacron - XK_Amacron);
371
else if (sym >= XK_amacron && sym <= XK_umacron)
372
*upper -= (XK_amacron - XK_Amacron);
374
case 6: /* Cyrillic */
375
/* Assume the KeySym is a legal value (ignore discontinuities) */
376
if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
377
*lower -= (XK_Serbian_DJE - XK_Serbian_dje);
378
else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
379
*upper += (XK_Serbian_DJE - XK_Serbian_dje);
380
else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
381
*lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
382
else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
383
*upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
386
/* Assume the KeySym is a legal value (ignore discontinuities) */
387
if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
388
*lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
389
else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
390
sym != XK_Greek_iotaaccentdieresis &&
391
sym != XK_Greek_upsilonaccentdieresis)
392
*upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
393
else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
394
*lower += (XK_Greek_alpha - XK_Greek_ALPHA);
395
else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
396
sym != XK_Greek_finalsmallsigma)
397
*upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
399
case 0x14: /* Armenian */
400
if (sym >= XK_Armenian_AYB && sym <= XK_Armenian_fe) {
409
#if NeedFunctionPrototypes
410
_XTranslateKey( register Display *dpy,
412
register unsigned int modifiers,
413
unsigned int *modifiers_return,
414
KeySym *keysym_return)
416
_XTranslateKey(dpy, keycode, modifiers, modifiers_return, keysym_return)
417
register Display *dpy;
419
register unsigned int modifiers;
420
unsigned int *modifiers_return;
421
KeySym *keysym_return;
425
register KeySym *syms;
426
KeySym sym, lsym, usym;
428
if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
430
*modifiers_return = ((ShiftMask|LockMask)
431
| dpy->mode_switch | dpy->num_lock);
432
if (((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode))
434
*keysym_return = NoSymbol;
437
per = dpy->keysyms_per_keycode;
438
syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per];
439
while ((per > 2) && (syms[per - 1] == NoSymbol))
441
if ((per > 2) && (modifiers & dpy->mode_switch)) {
445
if ((modifiers & dpy->num_lock) &&
446
(per > 1 && (IsKeypadKey(syms[1]) || IsPrivateKeypadKey(syms[1])))) {
447
if ((modifiers & ShiftMask) ||
448
((modifiers & LockMask) && (dpy->lock_meaning == XK_Shift_Lock)))
449
*keysym_return = syms[0];
451
*keysym_return = syms[1];
452
} else if (!(modifiers & ShiftMask) &&
453
(!(modifiers & LockMask) || (dpy->lock_meaning == NoSymbol))) {
454
if ((per == 1) || (syms[1] == NoSymbol))
455
XConvertCase(syms[0], keysym_return, &usym);
457
*keysym_return = syms[0];
458
} else if (!(modifiers & LockMask) ||
459
(dpy->lock_meaning != XK_Caps_Lock)) {
460
if ((per == 1) || ((usym = syms[1]) == NoSymbol))
461
XConvertCase(syms[0], &lsym, &usym);
462
*keysym_return = usym;
464
if ((per == 1) || ((sym = syms[1]) == NoSymbol))
466
XConvertCase(sym, &lsym, &usym);
467
if (!(modifiers & ShiftMask) && (sym != syms[0]) &&
468
((sym != usym) || (lsym == usym)))
469
XConvertCase(syms[0], &lsym, &usym);
470
*keysym_return = usym;
472
if (*keysym_return == XK_VoidSymbol)
473
*keysym_return = NoSymbol;
478
_XTranslateKeySym(dpy, symbol, modifiers, buffer, nbytes)
480
register KeySym symbol;
481
unsigned int modifiers;
485
register struct _XKeytrans *p;
487
unsigned long hiBytes;
488
register unsigned char c;
492
/* see if symbol rebound, if so, return that string. */
493
for (p = dpy->key_bindings; p; p = p->next) {
494
if (((modifiers & AllMods) == p->state) && (symbol == p->key)) {
496
if (length > nbytes) length = nbytes;
497
memcpy (buffer, p->string, length);
501
/* try to convert to Latin-1, handling control */
502
hiBytes = symbol >> 8;
505
((hiBytes == 0xFF) &&
506
(((symbol >= XK_BackSpace) && (symbol <= XK_Clear)) ||
507
(symbol == XK_Return) ||
508
(symbol == XK_Escape) ||
509
(symbol == XK_KP_Space) ||
510
(symbol == XK_KP_Tab) ||
511
(symbol == XK_KP_Enter) ||
512
((symbol >= XK_KP_Multiply) && (symbol <= XK_KP_9)) ||
513
(symbol == XK_KP_Equal) ||
514
(symbol == XK_Delete))))))
517
/* if X keysym, convert to ascii by grabbing low 7 bits */
518
if (symbol == XK_KP_Space)
519
c = XK_space & 0x7F; /* patch encoding botch */
520
else if (hiBytes == 0xFF)
524
/* only apply Control key if it makes sense, else ignore it */
525
if (modifiers & ControlMask) {
526
if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
527
else if (c == '2') c = '\000';
528
else if (c >= '3' && c <= '7') c -= ('3' - '\033');
529
else if (c == '8') c = '\177';
530
else if (c == '/') c = '_' & 0x1F;
538
XLookupString (event, buffer, nbytes, keysym, status)
539
register XKeyEvent *event;
540
char *buffer; /* buffer */
541
int nbytes; /* space in buffer for characters */
543
XComposeStatus *status; /* not implemented */
545
unsigned int modifiers;
548
if (! _XTranslateKey(event->display, event->keycode, event->state,
549
&modifiers, &symbol))
552
#ifdef USE_OWN_COMPOSE
554
static int been_here= 0;
559
if ( !XimCompLegalStatus(status) ) {
560
status->compose_ptr = NULL;
561
status->chars_matched = 0;
563
if ( ((status->chars_matched>0)&&(status->compose_ptr!=NULL)) ||
564
XimCompIsComposeKey(symbol,event->keycode,status) ) {
566
switch (XimCompProcessSym(status,symbol,&rtrn)) {
567
case XIM_COMP_IGNORE:
569
case XIM_COMP_IN_PROGRESS:
576
for (n=len=0;rtrn.sym[n]!=XK_VoidSymbol;n++) {
577
if ( nbytes-len > 0 ) {
578
len+= _XTranslateKeySym(event->display,rtrn.sym[n],
580
buffer+len,nbytes-len);
583
if ( keysym!=NULL ) {
584
if ( n==1 ) *keysym = rtrn.sym[0];
585
else *keysym = NoSymbol;
589
case XIM_COMP_SUCCEED:
593
symbol = rtrn.matchSym;
594
if ( keysym!=NULL ) *keysym = symbol;
595
if ( rtrn.str[0]!='\0' ) {
596
strncpy(buffer,rtrn.str,nbytes-1);
597
buffer[nbytes-1]= '\0';
598
len = strlen(buffer);
601
len = _XTranslateKeySym(event->display,symbol,
605
for (n=0;rtrn.sym[n]!=XK_VoidSymbol;n++) {
606
if ( nbytes-len > 0 ) {
607
len+= _XTranslateKeySym(event->display,rtrn.sym[n],
609
buffer+len,nbytes-len);
621
/* arguable whether to use (event->state & ~modifiers) here */
622
return _XTranslateKeySym(event->display, symbol, event->state,
627
_XFreeKeyBindings (dpy)
630
register struct _XKeytrans *p, *np;
632
for (p = dpy->key_bindings; p; p = np) {
635
Xfree((char *)p->modifiers);
641
#if NeedFunctionPrototypes
646
int nm, /* number of modifiers in mlist */
647
_Xconst unsigned char *str,
650
XRebindKeysym (dpy, keysym, mlist, nm, str, nbytes)
654
int nm; /* number of modifiers in mlist */
659
register struct _XKeytrans *tmp, *p;
662
if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
665
tmp = dpy->key_bindings;
666
nb = sizeof(KeySym) * nm;
668
if ((! (p = (struct _XKeytrans *) Xmalloc( sizeof(struct _XKeytrans)))) ||
669
((! (p->string = (char *) Xmalloc( (unsigned) nbytes))) &&
671
((! (p->modifiers = (KeySym *) Xmalloc( (unsigned) nb))) &&
674
if (p->string) Xfree(p->string);
675
if (p->modifiers) Xfree((char *) p->modifiers);
682
dpy->key_bindings = p;
683
dpy->free_funcs->key_bindings = _XFreeKeyBindings;
684
p->next = tmp; /* chain onto list */
685
memcpy (p->string, (char *) str, nbytes);
687
memcpy ((char *) p->modifiers, (char *) mlist, nb);
690
ComputeMaskFromKeytrans(dpy, p);
696
_XKeysymToModifiers(dpy,ks)
701
register KeySym *kmax;
703
register XModifierKeymap *m;
705
if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
707
kmax = dpy->keysyms +
708
(dpy->max_keycode - dpy->min_keycode + 1) * dpy->keysyms_per_keycode;
710
m = dpy->modifiermap;
714
register int j = m->max_keypermod<<3;
716
code=(((k-dpy->keysyms)/dpy->keysyms_per_keycode)+dpy->min_keycode);
719
if (code == m->modifiermap[j])
720
mods|= (1<<(j/m->max_keypermod));
729
* given a list of modifiers, computes the mask necessary for later matching.
730
* This routine must lookup the key in the Keymap and then search to see
731
* what modifier it is bound to, if any. Sets the AnyModifier bit if it
732
* can't map some keysym to a modifier.
735
ComputeMaskFromKeytrans(dpy, p)
737
register struct _XKeytrans *p;
741
p->state = AnyModifier;
742
for (i = 0; i < p->mlen; i++) {
743
p->state|= XkbKeysymToModifiers(dpy,p->modifiers[i]);