XKBBind.c revision 9c019ec5
1/* 2 3Copyright 1985, 1987, 1994, 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 12in all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall 23not be used in advertising or otherwise to promote the sale, use or 24other dealings in this Software without prior written authorization 25from The Open Group. 26 27*/ 28 29 /* the new monsters ate the old ones */ 30 31#ifdef HAVE_CONFIG_H 32#include <config.h> 33#endif 34#include "XKBlib.h" 35#include <X11/Xlibint.h> 36#include <X11/Xutil.h> 37#include <X11/keysym.h> 38#include <stdio.h> 39#include <ctype.h> 40 41#include <X11/extensions/XKBproto.h> 42#include "XKBlibint.h" 43 44#define AllMods (ShiftMask|LockMask|ControlMask| \ 45 Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask) 46 47static int _XkbLoadDpy(Display *dpy); 48 49struct _XKeytrans { 50 struct _XKeytrans *next; /* next on list */ 51 char *string; /* string to return when the time comes */ 52 int len; /* length of string (since NULL is legit) */ 53 KeySym key; /* keysym rebound */ 54 unsigned int state; /* modifier state */ 55 KeySym *modifiers; /* modifier keysyms you want */ 56 int mlen; /* length of modifier list */ 57}; 58 59KeySym 60XkbKeycodeToKeysym(Display *dpy, 61#if NeedWidePrototypes 62 unsigned int kc, 63#else 64 KeyCode kc, 65#endif 66 int group, 67 int level) 68{ 69 XkbDescRec *xkb; 70 71 if (_XkbUnavailable(dpy)) 72 return NoSymbol; 73 74 _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 75 76 xkb = dpy->xkb_info->desc; 77 if ((kc < xkb->min_key_code) || (kc > xkb->max_key_code)) 78 return NoSymbol; 79 80 if ((group < 0) || (level < 0) || (group >= XkbKeyNumGroups(xkb, kc))) 81 return NoSymbol; 82 if (level >= XkbKeyGroupWidth(xkb, kc, group)) { 83 /* for compatibility with the core protocol, _always_ allow */ 84 /* two symbols in the first two groups. If either of the */ 85 /* two is of type ONE_LEVEL, just replicate the first symbol */ 86 if ((group > XkbGroup2Index) || (XkbKeyGroupWidth(xkb, kc, group) != 1) 87 || (level != 1)) { 88 return NoSymbol; 89 } 90 level = 0; 91 } 92 return XkbKeySymEntry(xkb, kc, level, group); 93} 94 95KeySym 96XKeycodeToKeysym(Display *dpy, 97#if NeedWidePrototypes 98 unsigned int kc, 99#else 100 KeyCode kc, 101#endif 102 int col) 103{ 104 XkbDescRec *xkb; 105 106 if (_XkbUnavailable(dpy)) 107 return _XKeycodeToKeysym(dpy, kc, col); 108 109 _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 110 111 xkb = dpy->xkb_info->desc; 112 if ((kc < xkb->min_key_code) || (kc > xkb->max_key_code)) 113 return NoSymbol; 114 115 if (col > 3) { 116 int lastSym, tmp, nGrp; 117 118 lastSym = 3; 119 nGrp = XkbKeyNumGroups(xkb, kc); 120 if ((nGrp > 0) && 121 ((tmp = XkbKeyGroupWidth(xkb, kc, XkbGroup1Index)) > 2)) { 122 if (col <= (lastSym + tmp - 2)) 123 return XkbKeycodeToKeysym(dpy, kc, XkbGroup1Index, 124 col - lastSym + 2); 125 lastSym += tmp - 2; 126 } 127 if ((nGrp > 1) && 128 ((tmp = XkbKeyGroupWidth(xkb, kc, XkbGroup2Index)) > 2)) { 129 if (col <= (lastSym + tmp - 2)) 130 return XkbKeycodeToKeysym(dpy, kc, XkbGroup2Index, 131 col - lastSym + 2); 132 lastSym += tmp - 2; 133 } 134 if (nGrp > 2) { 135 tmp = XkbKeyGroupWidth(xkb, kc, XkbGroup3Index); 136 if (col <= lastSym + tmp) 137 return XkbKeycodeToKeysym(dpy, kc, XkbGroup3Index, 138 col - lastSym); 139 lastSym += tmp; 140 } 141 if (nGrp > 3) { 142 tmp = XkbKeyGroupWidth(xkb, kc, XkbGroup4Index); 143 if (col <= lastSym + tmp) 144 return XkbKeycodeToKeysym(dpy, kc, XkbGroup4Index, 145 col - lastSym); 146 } 147 return NoSymbol; 148 } 149 return XkbKeycodeToKeysym(dpy, kc, (col >> 1), (col & 1)); 150} 151 152KeyCode 153XKeysymToKeycode(Display *dpy, KeySym ks) 154{ 155 register int i, j, gotOne; 156 157 if (_XkbUnavailable(dpy)) 158 return _XKeysymToKeycode(dpy, ks); 159 _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 160 161 j = 0; 162 do { 163 register XkbDescRec *xkb = dpy->xkb_info->desc; 164 gotOne = 0; 165 for (i = dpy->min_keycode; i <= dpy->max_keycode; i++) { 166 if (j < (int) XkbKeyNumSyms(xkb, i)) { 167 gotOne = 1; 168 if ((XkbKeySym(xkb, i, j) == ks)) 169 return i; 170 } 171 } 172 j++; 173 } while (gotOne); 174 return 0; 175} 176 177static int 178_XkbComputeModmap(Display *dpy) 179{ 180 register XkbDescPtr xkb; 181 182 xkb = dpy->xkb_info->desc; 183 if (XkbGetUpdatedMap(dpy, XkbModifierMapMask, xkb) == Success) 184 return 1; 185 return 0; 186} 187 188unsigned 189XkbKeysymToModifiers(Display *dpy, KeySym ks) 190{ 191 XkbDescRec *xkb; 192 register int i, j; 193 register KeySym *pSyms; 194 CARD8 mods; 195 196 if (_XkbUnavailable(dpy)) 197 return _XKeysymToModifiers(dpy, ks); 198 _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 199 200 if (_XkbNeedModmap(dpy->xkb_info) && (!_XkbComputeModmap(dpy))) 201 return _XKeysymToModifiers(dpy, ks); 202 203 xkb = dpy->xkb_info->desc; 204 mods = 0; 205 for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) { 206 pSyms = XkbKeySymsPtr(xkb, i); 207 for (j = XkbKeyNumSyms(xkb, i) - 1; j >= 0; j--) { 208 if (pSyms[j] == ks) { 209 mods |= xkb->map->modmap[i]; 210 break; 211 } 212 } 213 } 214 return mods; 215} 216 217KeySym 218XLookupKeysym(register XKeyEvent * event, int col) 219{ 220 Display *dpy = event->display; 221 222 if (_XkbUnavailable(dpy)) 223 return _XLookupKeysym(event, col); 224 _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 225 return XKeycodeToKeysym(dpy, event->keycode, col); 226} 227 228 /* 229 * Not a public entry point -- XkbTranslateKey is an obsolete name 230 * that is preserved here so that functions linked against the old 231 * version will continue to work in a shared library environment. 232 */ 233int 234XkbTranslateKey(register Display *dpy, 235 KeyCode key, 236 register unsigned int mods, 237 unsigned int *mods_rtrn, 238 KeySym *keysym_rtrn); 239 240int 241XkbTranslateKey(register Display *dpy, 242 KeyCode key, 243 register unsigned int mods, 244 unsigned int *mods_rtrn, 245 KeySym *keysym_rtrn) 246{ 247 return XkbLookupKeySym(dpy, key, mods, mods_rtrn, keysym_rtrn); 248} 249 250Bool 251XkbLookupKeySym(register Display *dpy, 252 KeyCode key, 253 register unsigned int mods, 254 unsigned int *mods_rtrn, 255 KeySym *keysym_rtrn) 256{ 257 if (_XkbUnavailable(dpy)) 258 return _XTranslateKey(dpy, key, mods, mods_rtrn, keysym_rtrn); 259 _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 260 return XkbTranslateKeyCode(dpy->xkb_info->desc, key, mods, mods_rtrn, 261 keysym_rtrn); 262} 263 264Bool 265XkbTranslateKeyCode(register XkbDescPtr xkb, 266 KeyCode key, 267 register unsigned int mods, 268 unsigned int *mods_rtrn, 269 KeySym *keysym_rtrn) 270{ 271 XkbKeyTypeRec *type; 272 int col, nKeyGroups; 273 unsigned preserve, effectiveGroup; 274 KeySym *syms; 275 276 if (mods_rtrn != NULL) 277 *mods_rtrn = 0; 278 279 nKeyGroups = XkbKeyNumGroups(xkb, key); 280 if ((!XkbKeycodeInRange(xkb, key)) || (nKeyGroups == 0)) { 281 if (keysym_rtrn != NULL) 282 *keysym_rtrn = NoSymbol; 283 return False; 284 } 285 286 syms = XkbKeySymsPtr(xkb, key); 287 288 /* find the offset of the effective group */ 289 col = 0; 290 effectiveGroup = XkbGroupForCoreState(mods); 291 if (effectiveGroup >= nKeyGroups) { 292 unsigned groupInfo = XkbKeyGroupInfo(xkb, key); 293 294 switch (XkbOutOfRangeGroupAction(groupInfo)) { 295 default: 296 effectiveGroup %= nKeyGroups; 297 break; 298 case XkbClampIntoRange: 299 effectiveGroup = nKeyGroups - 1; 300 break; 301 case XkbRedirectIntoRange: 302 effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo); 303 if (effectiveGroup >= nKeyGroups) 304 effectiveGroup = 0; 305 break; 306 } 307 } 308 col = effectiveGroup * XkbKeyGroupsWidth(xkb, key); 309 type = XkbKeyKeyType(xkb, key, effectiveGroup); 310 311 preserve = 0; 312 if (type->map) { /* find the column (shift level) within the group */ 313 register int i; 314 register XkbKTMapEntryPtr entry; 315 316 for (i = 0, entry = type->map; i < type->map_count; i++, entry++) { 317 if ((entry->active) && 318 ((mods & type->mods.mask) == entry->mods.mask)) { 319 col += entry->level; 320 if (type->preserve) 321 preserve = type->preserve[i].mask; 322 break; 323 } 324 } 325 } 326 327 if (keysym_rtrn != NULL) 328 *keysym_rtrn = syms[col]; 329 if (mods_rtrn) { 330 *mods_rtrn = type->mods.mask & (~preserve); 331 /* The Motif VTS doesn't get the help callback called if help 332 * is bound to Shift+<whatever>, and it appears as though it 333 * is XkbTranslateKeyCode that is causing the problem. The 334 * core X version of XTranslateKey always OR's in ShiftMask 335 * and LockMask for mods_rtrn, so this "fix" keeps this behavior 336 * and solves the VTS problem. 337 */ 338 if ((xkb->dpy) && (xkb->dpy->xkb_info) && 339 (xkb->dpy->xkb_info-> 340 xlib_ctrls & XkbLC_AlwaysConsumeShiftAndLock)) { 341 *mods_rtrn |= (ShiftMask | LockMask); 342 } 343 } 344 return (syms[col] != NoSymbol); 345} 346 347Status 348XkbRefreshKeyboardMapping(register XkbMapNotifyEvent * event) 349{ 350 Display *dpy = event->display; 351 XkbInfoPtr xkbi; 352 353 if (_XkbUnavailable(dpy)) { 354 _XRefreshKeyboardMapping((XMappingEvent *) event); 355 return Success; 356 } 357 xkbi = dpy->xkb_info; 358 359 if (((event->type & 0x7f) - xkbi->codes->first_event) != XkbEventCode) 360 return BadMatch; 361 if (event->xkb_type == XkbNewKeyboardNotify) { 362 _XkbReloadDpy(dpy); 363 return Success; 364 } 365 if (event->xkb_type == XkbMapNotify) { 366 XkbMapChangesRec changes; 367 Status rtrn; 368 369 if (xkbi->flags & XkbMapPending) 370 changes = xkbi->changes; 371 else 372 bzero(&changes, sizeof(changes)); 373 XkbNoteMapChanges(&changes, event, XKB_XLIB_MAP_MASK); 374 if ((rtrn = XkbGetMapChanges(dpy, xkbi->desc, &changes)) != Success) { 375#ifdef DEBUG 376 fprintf(stderr, "Internal Error! XkbGetMapChanges failed:\n"); 377#endif 378 xkbi->changes = changes; 379 } 380 else if (xkbi->flags & XkbMapPending) { 381 xkbi->flags &= ~XkbMapPending; 382 bzero(&xkbi->changes, sizeof(XkbMapChangesRec)); 383 } 384 return rtrn; 385 } 386 return BadMatch; 387} 388 389int 390XRefreshKeyboardMapping(register XMappingEvent * event) 391{ 392 XkbEvent *xkbevent = (XkbEvent *) event; 393 Display *dpy = event->display; 394 XkbMapChangesRec changes; 395 XkbInfoPtr xkbi; 396 397 /* always do this for input methods, which still use the old keymap */ 398 (void) _XRefreshKeyboardMapping(event); 399 400 if (_XkbUnavailable(dpy)) 401 return 1; 402 403 xkbi = dpy->xkb_info; 404 405 if (((event->type & 0x7f) - xkbi->codes->first_event) == XkbEventCode) 406 return XkbRefreshKeyboardMapping(&xkbevent->map); 407 408 if (xkbi->flags & XkbXlibNewKeyboard) { 409 _XkbReloadDpy(dpy); 410 return 1; 411 } 412 413 if ((xkbi->flags & XkbMapPending) || (event->request == MappingKeyboard)) { 414 if (xkbi->flags & XkbMapPending) { 415 changes = xkbi->changes; 416 _XkbNoteCoreMapChanges(&changes, event, XKB_XLIB_MAP_MASK); 417 } 418 else { 419 bzero(&changes, sizeof(changes)); 420 changes.changed = XkbKeySymsMask; 421 if (xkbi->desc->min_key_code < xkbi->desc->max_key_code) { 422 changes.first_key_sym = xkbi->desc->min_key_code; 423 changes.num_key_syms = xkbi->desc->max_key_code - 424 xkbi->desc->min_key_code + 1; 425 } 426 else { 427 changes.first_key_sym = event->first_keycode; 428 changes.num_key_syms = event->count; 429 } 430 } 431 432 if (XkbGetMapChanges(dpy, xkbi->desc, &changes) != Success) { 433#ifdef DEBUG 434 fprintf(stderr, "Internal Error! XkbGetMapChanges failed:\n"); 435 if (changes.changed & XkbKeyTypesMask) { 436 int first = changes.first_type; 437 int last = changes.first_type + changes.num_types - 1; 438 439 fprintf(stderr, " types: %d..%d\n", first, last); 440 } 441 if (changes.changed & XkbKeySymsMask) { 442 int first = changes.first_key_sym; 443 int last = changes.first_key_sym + changes.num_key_syms - 1; 444 445 fprintf(stderr, " symbols: %d..%d\n", first, last); 446 } 447 if (changes.changed & XkbKeyActionsMask) { 448 int first = changes.first_key_act; 449 int last = changes.first_key_act + changes.num_key_acts - 1; 450 451 fprintf(stderr, " acts: %d..%d\n", first, last); 452 } 453 if (changes.changed & XkbKeyBehaviorsMask) { 454 int first = changes.first_key_behavior; 455 int last = first + changes.num_key_behaviors - 1; 456 457 fprintf(stderr, " behaviors: %d..%d\n", first, last); 458 } 459 if (changes.changed & XkbVirtualModsMask) { 460 fprintf(stderr, "virtual mods: 0x%04x\n", changes.vmods); 461 } 462 if (changes.changed & XkbExplicitComponentsMask) { 463 int first = changes.first_key_explicit; 464 int last = first + changes.num_key_explicit - 1; 465 466 fprintf(stderr, " explicit: %d..%d\n", first, last); 467 } 468#endif 469 } 470 LockDisplay(dpy); 471 if (xkbi->flags & XkbMapPending) { 472 xkbi->flags &= ~XkbMapPending; 473 bzero(&xkbi->changes, sizeof(XkbMapChangesRec)); 474 } 475 UnlockDisplay(dpy); 476 } 477 if (event->request == MappingModifier) { 478 LockDisplay(dpy); 479 if (xkbi->desc->map->modmap) { 480 _XkbFree(xkbi->desc->map->modmap); 481 xkbi->desc->map->modmap = NULL; 482 } 483 if (dpy->key_bindings) { 484 register struct _XKeytrans *p; 485 486 for (p = dpy->key_bindings; p; p = p->next) { 487 register int i; 488 489 p->state = 0; 490 if (p->mlen > 0) { 491 for (i = 0; i < p->mlen; i++) { 492 p->state |= XkbKeysymToModifiers(dpy, p->modifiers[i]); 493 } 494 if (p->state) 495 p->state &= AllMods; 496 else 497 p->state = AnyModifier; 498 } 499 } 500 } 501 UnlockDisplay(dpy); 502 } 503 return 1; 504} 505 506static int 507_XkbLoadDpy(Display *dpy) 508{ 509 XkbInfoPtr xkbi; 510 unsigned query, oldEvents; 511 XkbDescRec *desc; 512 513 if (!XkbUseExtension(dpy, NULL, NULL)) 514 return 0; 515 516 xkbi = dpy->xkb_info; 517 query = XkbAllClientInfoMask; 518 desc = XkbGetMap(dpy, query, XkbUseCoreKbd); 519 if (!desc) { 520#ifdef DEBUG 521 fprintf(stderr, "Warning! XkbGetMap failed!\n"); 522#endif 523 return 0; 524 } 525 LockDisplay(dpy); 526 xkbi->desc = desc; 527 528 UnlockDisplay(dpy); 529 oldEvents = xkbi->selected_events; 530 if (!(xkbi->xlib_ctrls & XkbLC_IgnoreNewKeyboards)) { 531 XkbSelectEventDetails(dpy, xkbi->desc->device_spec, 532 XkbNewKeyboardNotify, 533 XkbNKN_KeycodesMask | XkbNKN_DeviceIDMask, 534 XkbNKN_KeycodesMask | XkbNKN_DeviceIDMask); 535 } 536 XkbSelectEventDetails(dpy, xkbi->desc->device_spec, XkbMapNotify, 537 XkbAllClientInfoMask, XkbAllClientInfoMask); 538 LockDisplay(dpy); 539 xkbi->selected_events = oldEvents; 540 UnlockDisplay(dpy); 541 return 1; 542} 543 544void 545_XkbReloadDpy(Display *dpy) 546{ 547 XkbInfoPtr xkbi; 548 XkbDescRec *desc; 549 unsigned oldDeviceID; 550 551 if (_XkbUnavailable(dpy)) 552 return; 553 554 xkbi = dpy->xkb_info; 555 LockDisplay(dpy); 556 if (xkbi->desc) { 557 oldDeviceID = xkbi->desc->device_spec; 558 XkbFreeKeyboard(xkbi->desc, XkbAllComponentsMask, True); 559 xkbi->desc = NULL; 560 xkbi->flags &= ~(XkbMapPending | XkbXlibNewKeyboard); 561 xkbi->changes.changed = 0; 562 } 563 else 564 oldDeviceID = XkbUseCoreKbd; 565 UnlockDisplay(dpy); 566 desc = XkbGetMap(dpy, XkbAllClientInfoMask, XkbUseCoreKbd); 567 if (!desc) 568 return; 569 LockDisplay(dpy); 570 xkbi->desc = desc; 571 UnlockDisplay(dpy); 572 573 if (desc->device_spec != oldDeviceID) { 574 /* transfer(?) event masks here */ 575#ifdef NOTYET 576 unsigned oldEvents; 577 578 oldEvents = xkbi->selected_events; 579 XkbSelectEventDetails(dpy, xkbi->desc->device_spec, XkbMapNotify, 580 XkbAllMapComponentsMask, XkbAllClientInfoMask); 581 LockDisplay(dpy); 582 xkbi->selected_events = oldEvents; 583 UnlockDisplay(dpy); 584#endif 585 } 586 return; 587} 588 589int 590XkbTranslateKeySym(register Display *dpy, 591 register KeySym *sym_rtrn, 592 unsigned int mods, 593 char *buffer, 594 int nbytes, 595 int *extra_rtrn) 596{ 597 register XkbInfoPtr xkb; 598 XkbKSToMBFunc cvtr; 599 XPointer priv; 600 char tmp[4]; 601 int n; 602 603 xkb = dpy->xkb_info; 604 if (!xkb->cvt.KSToMB) { 605 _XkbGetConverters(_XkbGetCharset(), &xkb->cvt); 606 _XkbGetConverters("ISO8859-1", &xkb->latin1cvt); 607 } 608 609 if (extra_rtrn) 610 *extra_rtrn = 0; 611 612 if ((buffer == NULL) || (nbytes == 0)) { 613 buffer = tmp; 614 nbytes = 4; 615 } 616 617 /* see if symbol rebound, if so, return that string. */ 618 n = XkbLookupKeyBinding(dpy, *sym_rtrn, mods, buffer, nbytes, extra_rtrn); 619 if (n) 620 return n; 621 622 if (nbytes > 0) 623 buffer[0] = '\0'; 624 625 if (xkb->cvt.KSToUpper && (mods & LockMask)) { 626 *sym_rtrn = (*xkb->cvt.KSToUpper) (*sym_rtrn); 627 } 628 if (xkb->xlib_ctrls & XkbLC_ForceLatin1Lookup) { 629 cvtr = xkb->latin1cvt.KSToMB; 630 priv = xkb->latin1cvt.KSToMBPriv; 631 } 632 else { 633 cvtr = xkb->cvt.KSToMB; 634 priv = xkb->cvt.KSToMBPriv; 635 } 636 637 n = (*cvtr) (priv, *sym_rtrn, buffer, nbytes, extra_rtrn); 638 639 if ((!xkb->cvt.KSToUpper) && (mods & LockMask)) { 640 register int i; 641 int change; 642 643 for (i = change = 0; i < n; i++) { 644 char ch = toupper(buffer[i]); 645 change = (change || (buffer[i] != ch)); 646 buffer[i] = ch; 647 } 648 if (change) { 649 if (n == 1) 650 *sym_rtrn = 651 (*xkb->cvt.MBToKS) (xkb->cvt.MBToKSPriv, buffer, n, NULL); 652 else 653 *sym_rtrn = NoSymbol; 654 } 655 } 656 657 if (mods & ControlMask) { 658 if (n == 1) { 659 buffer[0] = XkbToControl(buffer[0]); 660 if (nbytes > 1) 661 buffer[1] = '\0'; 662 return 1; 663 } 664 if (nbytes > 0) 665 buffer[0] = '\0'; 666 return 0; 667 } 668 return n; 669} 670 671int 672XLookupString(register XKeyEvent *event, 673 char *buffer, 674 int nbytes, 675 KeySym *keysym, 676 XComposeStatus *status) 677{ 678 KeySym dummy; 679 int rtrnLen; 680 unsigned int new_mods; 681 Display *dpy = event->display; 682 683 if (keysym == NULL) 684 keysym = &dummy; 685 if (!XkbLookupKeySym(dpy, event->keycode, event->state, &new_mods, keysym)) 686 return 0; 687 new_mods = (event->state & (~new_mods)); 688 689 /* find the group where a symbol can be converted to control one */ 690 if (new_mods & ControlMask && *keysym > 0x7F && 691 (dpy->xkb_info->xlib_ctrls & XkbLC_ControlFallback)) { 692 XKeyEvent tmp_ev = *event; 693 KeySym tmp_keysym; 694 unsigned int tmp_new_mods; 695 696 if (_XkbUnavailable(dpy)) { 697 tmp_ev.state = event->state ^ dpy->mode_switch; 698 if (XkbLookupKeySym(dpy, tmp_ev.keycode, tmp_ev.state, 699 &tmp_new_mods, &tmp_keysym) && 700 tmp_keysym != NoSymbol && tmp_keysym < 0x80) { 701 *keysym = tmp_keysym; 702 } 703 } 704 else { 705 int n = XkbKeyNumGroups(dpy->xkb_info->desc, tmp_ev.keycode); 706 int i; 707 708 for (i = 0; i < n; i++) { 709 if (XkbGroupForCoreState(event->state) == i) 710 continue; 711 tmp_ev.state = XkbBuildCoreState(tmp_ev.state, i); 712 if (XkbLookupKeySym(dpy, tmp_ev.keycode, tmp_ev.state, 713 &tmp_new_mods, &tmp_keysym) && 714 tmp_keysym != NoSymbol && tmp_keysym < 0x80) { 715 *keysym = tmp_keysym; 716 new_mods = (event->state & (~tmp_new_mods)); 717 break; 718 } 719 } 720 } 721 } 722 723 /* We *should* use the new_mods (which does not contain any modifiers */ 724 /* that were used to compute the symbol here, but pre-XKB XLookupString */ 725 /* did not and we have to remain compatible. Sigh. */ 726 if (_XkbUnavailable(dpy) || 727 (dpy->xkb_info->xlib_ctrls & XkbLC_ConsumeLookupMods) == 0) 728 new_mods = event->state; 729 730 rtrnLen = XkbLookupKeyBinding(dpy, *keysym, new_mods, buffer, nbytes, NULL); 731 if (rtrnLen > 0) 732 return rtrnLen; 733 734 return XkbTranslateKeySym(dpy, keysym, new_mods, buffer, nbytes, NULL); 735} 736 737 738int 739XkbLookupKeyBinding(Display *dpy, 740 register KeySym sym, 741 unsigned int mods, 742 char *buffer, 743 int nbytes, 744 int *extra_rtrn) 745{ 746 register struct _XKeytrans *p; 747 748 if (extra_rtrn) 749 *extra_rtrn = 0; 750 for (p = dpy->key_bindings; p; p = p->next) { 751 if (((mods & AllMods) == p->state) && (sym == p->key)) { 752 int tmp = p->len; 753 754 if (tmp > nbytes) { 755 if (extra_rtrn) 756 *extra_rtrn = (tmp - nbytes); 757 tmp = nbytes; 758 } 759 memcpy(buffer, p->string, (size_t) tmp); 760 if (tmp < nbytes) 761 buffer[tmp] = '\0'; 762 return tmp; 763 } 764 } 765 return 0; 766} 767 768char 769XkbToControl(char ch) 770{ 771 register char c = ch; 772 773 if ((c >= '@' && c < '\177') || c == ' ') 774 c &= 0x1F; 775 else if (c == '2') 776 c = '\000'; 777 else if (c >= '3' && c <= '7') 778 c -= ('3' - '\033'); 779 else if (c == '8') 780 c = '\177'; 781 else if (c == '/') 782 c = '_' & 0x1F; 783 return c; 784} 785