Home | History | Annotate | Line # | Download | only in xkb
      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