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