XKBBind.c revision 5efbdfc3
11ab64890Smrg/* 21ab64890Smrg 31ab64890SmrgCopyright 1985, 1987, 1994, 1998 The Open Group 41ab64890Smrg 51ab64890SmrgPermission to use, copy, modify, distribute, and sell this software and its 61ab64890Smrgdocumentation for any purpose is hereby granted without fee, provided that 71ab64890Smrgthe above copyright notice appear in all copies and that both that 81ab64890Smrgcopyright notice and this permission notice appear in supporting 91ab64890Smrgdocumentation. 101ab64890Smrg 111ab64890SmrgThe above copyright notice and this permission notice shall be included 121ab64890Smrgin all copies or substantial portions of the Software. 131ab64890Smrg 141ab64890SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 151ab64890SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 161ab64890SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 171ab64890SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 181ab64890SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 191ab64890SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 201ab64890SmrgOTHER DEALINGS IN THE SOFTWARE. 211ab64890Smrg 221ab64890SmrgExcept as contained in this notice, the name of The Open Group shall 231ab64890Smrgnot be used in advertising or otherwise to promote the sale, use or 241ab64890Smrgother dealings in this Software without prior written authorization 251ab64890Smrgfrom The Open Group. 261ab64890Smrg 271ab64890Smrg*/ 281ab64890Smrg 29818534a1Smrg /* the new monsters ate the old ones */ 301ab64890Smrg 311ab64890Smrg#ifdef HAVE_CONFIG_H 321ab64890Smrg#include <config.h> 331ab64890Smrg#endif 341ab64890Smrg#include "XKBlib.h" 351ab64890Smrg#include <X11/Xlibint.h> 361ab64890Smrg#include <X11/Xutil.h> 371ab64890Smrg#include <X11/keysym.h> 381ab64890Smrg#include <stdio.h> 391ab64890Smrg#include <ctype.h> 401ab64890Smrg 411ab64890Smrg#include <X11/extensions/XKBproto.h> 421ab64890Smrg#include "XKBlibint.h" 431ab64890Smrg 441ab64890Smrg#define AllMods (ShiftMask|LockMask|ControlMask| \ 45818534a1Smrg Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask) 461ab64890Smrg 47818534a1Smrgstatic int _XkbLoadDpy(Display *dpy); 481ab64890Smrg 491ab64890Smrgstruct _XKeytrans { 50818534a1Smrg struct _XKeytrans *next; /* next on list */ 51818534a1Smrg char *string; /* string to return when the time comes */ 52818534a1Smrg int len; /* length of string (since NULL is legit) */ 53818534a1Smrg KeySym key; /* keysym rebound */ 54818534a1Smrg unsigned int state; /* modifier state */ 55818534a1Smrg KeySym *modifiers; /* modifier keysyms you want */ 56818534a1Smrg int mlen; /* length of modifier list */ 571ab64890Smrg}; 581ab64890Smrg 591ab64890SmrgKeySym 601ab64890SmrgXkbKeycodeToKeysym(Display *dpy, 611ab64890Smrg#if NeedWidePrototypes 62818534a1Smrg unsigned int kc, 631ab64890Smrg#else 64818534a1Smrg KeyCode kc, 651ab64890Smrg#endif 66818534a1Smrg int group, 67818534a1Smrg int level) 681ab64890Smrg{ 69818534a1Smrg XkbDescRec *xkb; 7061b2299dSmrg 711ab64890Smrg if (_XkbUnavailable(dpy)) 72818534a1Smrg return NoSymbol; 731ab64890Smrg 74818534a1Smrg _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 751ab64890Smrg 761ab64890Smrg xkb = dpy->xkb_info->desc; 77818534a1Smrg if ((kc < xkb->min_key_code) || (kc > xkb->max_key_code)) 78818534a1Smrg return NoSymbol; 79818534a1Smrg 80818534a1Smrg if ((group < 0) || (level < 0) || (group >= XkbKeyNumGroups(xkb, kc))) 81818534a1Smrg return NoSymbol; 82818534a1Smrg if (level >= XkbKeyGroupWidth(xkb, kc, group)) { 83818534a1Smrg /* for compatibility with the core protocol, _always_ allow */ 84818534a1Smrg /* two symbols in the first two groups. If either of the */ 85818534a1Smrg /* two is of type ONE_LEVEL, just replicate the first symbol */ 86818534a1Smrg if ((group > XkbGroup2Index) || (XkbKeyGroupWidth(xkb, kc, group) != 1) 87818534a1Smrg || (level != 1)) { 88818534a1Smrg return NoSymbol; 89818534a1Smrg } 90818534a1Smrg level = 0; 911ab64890Smrg } 92818534a1Smrg return XkbKeySymEntry(xkb, kc, level, group); 931ab64890Smrg} 941ab64890Smrg 951ab64890SmrgKeySym 961ab64890SmrgXKeycodeToKeysym(Display *dpy, 971ab64890Smrg#if NeedWidePrototypes 98818534a1Smrg unsigned int kc, 991ab64890Smrg#else 100818534a1Smrg KeyCode kc, 1011ab64890Smrg#endif 102818534a1Smrg int col) 1031ab64890Smrg{ 104818534a1Smrg XkbDescRec *xkb; 10561b2299dSmrg 1061ab64890Smrg if (_XkbUnavailable(dpy)) 107818534a1Smrg return _XKeycodeToKeysym(dpy, kc, col); 1081ab64890Smrg 109818534a1Smrg _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 1101ab64890Smrg 1111ab64890Smrg xkb = dpy->xkb_info->desc; 112818534a1Smrg if ((kc < xkb->min_key_code) || (kc > xkb->max_key_code)) 113818534a1Smrg return NoSymbol; 114818534a1Smrg 115818534a1Smrg if (col > 3) { 1165efbdfc3Smrg int firstSym, nGrp, grp; 117818534a1Smrg 1185efbdfc3Smrg firstSym = 4; 119818534a1Smrg nGrp = XkbKeyNumGroups(xkb, kc); 1205efbdfc3Smrg for (grp = 0; grp < nGrp; grp++) { 1215efbdfc3Smrg int width = XkbKeyGroupWidth(xkb, kc, grp); 1225efbdfc3Smrg int skip = 0; 1235efbdfc3Smrg if (grp < 2) { 1245efbdfc3Smrg /* Skip the first two symbols in the first two groups, since we 1255efbdfc3Smrg * return them below for indexes 0-3. */ 1265efbdfc3Smrg skip = 2; 1275efbdfc3Smrg width -= skip; 1285efbdfc3Smrg if (width < 0) 1295efbdfc3Smrg width = 0; 1305efbdfc3Smrg } 1315efbdfc3Smrg if (col < firstSym + width) 1325efbdfc3Smrg return XkbKeycodeToKeysym(dpy, kc, grp, col - firstSym + skip); 1335efbdfc3Smrg firstSym += width; 134818534a1Smrg } 135818534a1Smrg return NoSymbol; 1361ab64890Smrg } 137818534a1Smrg return XkbKeycodeToKeysym(dpy, kc, (col >> 1), (col & 1)); 1381ab64890Smrg} 1391ab64890Smrg 1401ab64890SmrgKeyCode 1411ab64890SmrgXKeysymToKeycode(Display *dpy, KeySym ks) 1421ab64890Smrg{ 1431ab64890Smrg register int i, j, gotOne; 1441ab64890Smrg 1451ab64890Smrg if (_XkbUnavailable(dpy)) 146818534a1Smrg return _XKeysymToKeycode(dpy, ks); 147818534a1Smrg _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 1481ab64890Smrg 149818534a1Smrg j = 0; 1501ab64890Smrg do { 151818534a1Smrg register XkbDescRec *xkb = dpy->xkb_info->desc; 152818534a1Smrg gotOne = 0; 153818534a1Smrg for (i = dpy->min_keycode; i <= dpy->max_keycode; i++) { 154818534a1Smrg if (j < (int) XkbKeyNumSyms(xkb, i)) { 155818534a1Smrg gotOne = 1; 156818534a1Smrg if ((XkbKeySym(xkb, i, j) == ks)) 157818534a1Smrg return i; 158818534a1Smrg } 159818534a1Smrg } 160818534a1Smrg j++; 1611ab64890Smrg } while (gotOne); 1621ab64890Smrg return 0; 1631ab64890Smrg} 1641ab64890Smrg 1651ab64890Smrgstatic int 1661ab64890Smrg_XkbComputeModmap(Display *dpy) 1671ab64890Smrg{ 168818534a1Smrg register XkbDescPtr xkb; 1691ab64890Smrg 170818534a1Smrg xkb = dpy->xkb_info->desc; 171818534a1Smrg if (XkbGetUpdatedMap(dpy, XkbModifierMapMask, xkb) == Success) 172818534a1Smrg return 1; 1731ab64890Smrg return 0; 1741ab64890Smrg} 1751ab64890Smrg 1761ab64890Smrgunsigned 177818534a1SmrgXkbKeysymToModifiers(Display *dpy, KeySym ks) 1781ab64890Smrg{ 1791ab64890Smrg XkbDescRec *xkb; 180818534a1Smrg register int i, j; 1811ab64890Smrg register KeySym *pSyms; 1821ab64890Smrg CARD8 mods; 1831ab64890Smrg 1841ab64890Smrg if (_XkbUnavailable(dpy)) 185818534a1Smrg return _XKeysymToModifiers(dpy, ks); 186818534a1Smrg _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 187818534a1Smrg 188818534a1Smrg if (_XkbNeedModmap(dpy->xkb_info) && (!_XkbComputeModmap(dpy))) 189818534a1Smrg return _XKeysymToModifiers(dpy, ks); 190818534a1Smrg 191818534a1Smrg xkb = dpy->xkb_info->desc; 192818534a1Smrg mods = 0; 193818534a1Smrg for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) { 194818534a1Smrg pSyms = XkbKeySymsPtr(xkb, i); 195818534a1Smrg for (j = XkbKeyNumSyms(xkb, i) - 1; j >= 0; j--) { 196818534a1Smrg if (pSyms[j] == ks) { 197818534a1Smrg mods |= xkb->map->modmap[i]; 198818534a1Smrg break; 199818534a1Smrg } 200818534a1Smrg } 2011ab64890Smrg } 2021ab64890Smrg return mods; 2031ab64890Smrg} 2041ab64890Smrg 2051ab64890SmrgKeySym 206818534a1SmrgXLookupKeysym(register XKeyEvent * event, int col) 2071ab64890Smrg{ 2081ab64890Smrg Display *dpy = event->display; 209818534a1Smrg 2101ab64890Smrg if (_XkbUnavailable(dpy)) 211818534a1Smrg return _XLookupKeysym(event, col); 212818534a1Smrg _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 213d4a3aaf4Smrg 214d4a3aaf4Smrg#ifdef __clang__ 215d4a3aaf4Smrg#pragma clang diagnostic push 216d4a3aaf4Smrg#pragma clang diagnostic ignored "-Wdeprecated-declarations" 217d4a3aaf4Smrg#elif defined(__GNUC__) 218d4a3aaf4Smrg#pragma GCC diagnostic push 219d4a3aaf4Smrg#pragma GCC diagnostic ignored "-Wdeprecated-declarations" 220d4a3aaf4Smrg#endif 2211ab64890Smrg return XKeycodeToKeysym(dpy, event->keycode, col); 222d4a3aaf4Smrg#ifdef __clang__ 223d4a3aaf4Smrg#pragma clang diagnostic pop 224d4a3aaf4Smrg#elif defined(__GNUC__) 225d4a3aaf4Smrg#pragma GCC diagnostic pop 226d4a3aaf4Smrg#endif 227d4a3aaf4Smrg 2281ab64890Smrg} 2291ab64890Smrg 2301ab64890Smrg /* 23161b2299dSmrg * Not a public entry point -- XkbTranslateKey is an obsolete name 23261b2299dSmrg * that is preserved here so that functions linked against the old 2331ab64890Smrg * version will continue to work in a shared library environment. 2341ab64890Smrg */ 2351ab64890Smrgint 236818534a1SmrgXkbTranslateKey(register Display *dpy, 237818534a1Smrg KeyCode key, 238818534a1Smrg register unsigned int mods, 239818534a1Smrg unsigned int *mods_rtrn, 240818534a1Smrg KeySym *keysym_rtrn); 241818534a1Smrg 2421ab64890Smrgint 243818534a1SmrgXkbTranslateKey(register Display *dpy, 244818534a1Smrg KeyCode key, 245818534a1Smrg register unsigned int mods, 246818534a1Smrg unsigned int *mods_rtrn, 247818534a1Smrg KeySym *keysym_rtrn) 2481ab64890Smrg{ 249818534a1Smrg return XkbLookupKeySym(dpy, key, mods, mods_rtrn, keysym_rtrn); 2501ab64890Smrg} 2511ab64890Smrg 2521ab64890SmrgBool 253818534a1SmrgXkbLookupKeySym(register Display *dpy, 254818534a1Smrg KeyCode key, 255818534a1Smrg register unsigned int mods, 256818534a1Smrg unsigned int *mods_rtrn, 257818534a1Smrg KeySym *keysym_rtrn) 2581ab64890Smrg{ 2591ab64890Smrg if (_XkbUnavailable(dpy)) 260818534a1Smrg return _XTranslateKey(dpy, key, mods, mods_rtrn, keysym_rtrn); 261818534a1Smrg _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 262818534a1Smrg return XkbTranslateKeyCode(dpy->xkb_info->desc, key, mods, mods_rtrn, 263818534a1Smrg keysym_rtrn); 2641ab64890Smrg} 2651ab64890Smrg 2661ab64890SmrgBool 267818534a1SmrgXkbTranslateKeyCode(register XkbDescPtr xkb, 268818534a1Smrg KeyCode key, 269818534a1Smrg register unsigned int mods, 270818534a1Smrg unsigned int *mods_rtrn, 271818534a1Smrg KeySym *keysym_rtrn) 2721ab64890Smrg{ 2731ab64890Smrg XkbKeyTypeRec *type; 274818534a1Smrg int col, nKeyGroups; 275818534a1Smrg unsigned preserve, effectiveGroup; 2761ab64890Smrg KeySym *syms; 2771ab64890Smrg 278818534a1Smrg if (mods_rtrn != NULL) 279818534a1Smrg *mods_rtrn = 0; 2801ab64890Smrg 281818534a1Smrg nKeyGroups = XkbKeyNumGroups(xkb, key); 282818534a1Smrg if ((!XkbKeycodeInRange(xkb, key)) || (nKeyGroups == 0)) { 283818534a1Smrg if (keysym_rtrn != NULL) 284818534a1Smrg *keysym_rtrn = NoSymbol; 285818534a1Smrg return False; 2861ab64890Smrg } 2871ab64890Smrg 288818534a1Smrg syms = XkbKeySymsPtr(xkb, key); 2891ab64890Smrg 2901ab64890Smrg /* find the offset of the effective group */ 2911ab64890Smrg col = 0; 292818534a1Smrg effectiveGroup = XkbGroupForCoreState(mods); 293818534a1Smrg if (effectiveGroup >= nKeyGroups) { 294818534a1Smrg unsigned groupInfo = XkbKeyGroupInfo(xkb, key); 295818534a1Smrg 296818534a1Smrg switch (XkbOutOfRangeGroupAction(groupInfo)) { 297818534a1Smrg default: 298818534a1Smrg effectiveGroup %= nKeyGroups; 299818534a1Smrg break; 300818534a1Smrg case XkbClampIntoRange: 301818534a1Smrg effectiveGroup = nKeyGroups - 1; 302818534a1Smrg break; 303818534a1Smrg case XkbRedirectIntoRange: 304818534a1Smrg effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo); 305818534a1Smrg if (effectiveGroup >= nKeyGroups) 306818534a1Smrg effectiveGroup = 0; 307818534a1Smrg break; 308818534a1Smrg } 3091ab64890Smrg } 310818534a1Smrg col = effectiveGroup * XkbKeyGroupsWidth(xkb, key); 311818534a1Smrg type = XkbKeyKeyType(xkb, key, effectiveGroup); 312818534a1Smrg 313818534a1Smrg preserve = 0; 314818534a1Smrg if (type->map) { /* find the column (shift level) within the group */ 315818534a1Smrg register int i; 316818534a1Smrg register XkbKTMapEntryPtr entry; 317818534a1Smrg 318818534a1Smrg for (i = 0, entry = type->map; i < type->map_count; i++, entry++) { 319818534a1Smrg if ((entry->active) && 320818534a1Smrg ((mods & type->mods.mask) == entry->mods.mask)) { 321818534a1Smrg col += entry->level; 322818534a1Smrg if (type->preserve) 323818534a1Smrg preserve = type->preserve[i].mask; 324818534a1Smrg break; 325818534a1Smrg } 326818534a1Smrg } 3271ab64890Smrg } 3281ab64890Smrg 329818534a1Smrg if (keysym_rtrn != NULL) 330818534a1Smrg *keysym_rtrn = syms[col]; 3311ab64890Smrg if (mods_rtrn) { 332818534a1Smrg *mods_rtrn = type->mods.mask & (~preserve); 333818534a1Smrg /* The Motif VTS doesn't get the help callback called if help 334818534a1Smrg * is bound to Shift+<whatever>, and it appears as though it 335818534a1Smrg * is XkbTranslateKeyCode that is causing the problem. The 336818534a1Smrg * core X version of XTranslateKey always OR's in ShiftMask 337818534a1Smrg * and LockMask for mods_rtrn, so this "fix" keeps this behavior 338818534a1Smrg * and solves the VTS problem. 339818534a1Smrg */ 340818534a1Smrg if ((xkb->dpy) && (xkb->dpy->xkb_info) && 341818534a1Smrg (xkb->dpy->xkb_info-> 342818534a1Smrg xlib_ctrls & XkbLC_AlwaysConsumeShiftAndLock)) { 343818534a1Smrg *mods_rtrn |= (ShiftMask | LockMask); 344818534a1Smrg } 3451ab64890Smrg } 346818534a1Smrg return (syms[col] != NoSymbol); 3471ab64890Smrg} 3481ab64890Smrg 3491ab64890SmrgStatus 350818534a1SmrgXkbRefreshKeyboardMapping(register XkbMapNotifyEvent * event) 3511ab64890Smrg{ 3521ab64890Smrg Display *dpy = event->display; 3531ab64890Smrg XkbInfoPtr xkbi; 3541ab64890Smrg 3551ab64890Smrg if (_XkbUnavailable(dpy)) { 356818534a1Smrg _XRefreshKeyboardMapping((XMappingEvent *) event); 357818534a1Smrg return Success; 3581ab64890Smrg } 359818534a1Smrg xkbi = dpy->xkb_info; 3601ab64890Smrg 361818534a1Smrg if (((event->type & 0x7f) - xkbi->codes->first_event) != XkbEventCode) 362818534a1Smrg return BadMatch; 363818534a1Smrg if (event->xkb_type == XkbNewKeyboardNotify) { 364818534a1Smrg _XkbReloadDpy(dpy); 365818534a1Smrg return Success; 3661ab64890Smrg } 367818534a1Smrg if (event->xkb_type == XkbMapNotify) { 368818534a1Smrg XkbMapChangesRec changes; 369818534a1Smrg Status rtrn; 370818534a1Smrg 371818534a1Smrg if (xkbi->flags & XkbMapPending) 372818534a1Smrg changes = xkbi->changes; 373818534a1Smrg else 374818534a1Smrg bzero(&changes, sizeof(changes)); 375818534a1Smrg XkbNoteMapChanges(&changes, event, XKB_XLIB_MAP_MASK); 376818534a1Smrg if ((rtrn = XkbGetMapChanges(dpy, xkbi->desc, &changes)) != Success) { 3771ab64890Smrg#ifdef DEBUG 378818534a1Smrg fprintf(stderr, "Internal Error! XkbGetMapChanges failed:\n"); 3791ab64890Smrg#endif 380818534a1Smrg xkbi->changes = changes; 381818534a1Smrg } 382818534a1Smrg else if (xkbi->flags & XkbMapPending) { 383818534a1Smrg xkbi->flags &= ~XkbMapPending; 384818534a1Smrg bzero(&xkbi->changes, sizeof(XkbMapChangesRec)); 385818534a1Smrg } 386818534a1Smrg return rtrn; 3871ab64890Smrg } 3881ab64890Smrg return BadMatch; 3891ab64890Smrg} 3901ab64890Smrg 3911ab64890Smrgint 392818534a1SmrgXRefreshKeyboardMapping(register XMappingEvent * event) 3931ab64890Smrg{ 394818534a1Smrg XkbEvent *xkbevent = (XkbEvent *) event; 3951ab64890Smrg Display *dpy = event->display; 3961ab64890Smrg XkbMapChangesRec changes; 3971ab64890Smrg XkbInfoPtr xkbi; 3981ab64890Smrg 3991ab64890Smrg /* always do this for input methods, which still use the old keymap */ 4001ab64890Smrg (void) _XRefreshKeyboardMapping(event); 4011ab64890Smrg 4021ab64890Smrg if (_XkbUnavailable(dpy)) 403818534a1Smrg return 1; 4041ab64890Smrg 4051ab64890Smrg xkbi = dpy->xkb_info; 4061ab64890Smrg 407818534a1Smrg if (((event->type & 0x7f) - xkbi->codes->first_event) == XkbEventCode) 408818534a1Smrg return XkbRefreshKeyboardMapping(&xkbevent->map); 4091ab64890Smrg 410818534a1Smrg if (xkbi->flags & XkbXlibNewKeyboard) { 411818534a1Smrg _XkbReloadDpy(dpy); 412818534a1Smrg return 1; 4131ab64890Smrg } 4141ab64890Smrg 415818534a1Smrg if ((xkbi->flags & XkbMapPending) || (event->request == MappingKeyboard)) { 416818534a1Smrg if (xkbi->flags & XkbMapPending) { 417818534a1Smrg changes = xkbi->changes; 418818534a1Smrg _XkbNoteCoreMapChanges(&changes, event, XKB_XLIB_MAP_MASK); 419818534a1Smrg } 420818534a1Smrg else { 421818534a1Smrg bzero(&changes, sizeof(changes)); 422818534a1Smrg changes.changed = XkbKeySymsMask; 423818534a1Smrg if (xkbi->desc->min_key_code < xkbi->desc->max_key_code) { 424818534a1Smrg changes.first_key_sym = xkbi->desc->min_key_code; 425818534a1Smrg changes.num_key_syms = xkbi->desc->max_key_code - 426818534a1Smrg xkbi->desc->min_key_code + 1; 427818534a1Smrg } 428818534a1Smrg else { 429818534a1Smrg changes.first_key_sym = event->first_keycode; 430818534a1Smrg changes.num_key_syms = event->count; 431818534a1Smrg } 432818534a1Smrg } 433818534a1Smrg 434818534a1Smrg if (XkbGetMapChanges(dpy, xkbi->desc, &changes) != Success) { 4351ab64890Smrg#ifdef DEBUG 436818534a1Smrg fprintf(stderr, "Internal Error! XkbGetMapChanges failed:\n"); 437818534a1Smrg if (changes.changed & XkbKeyTypesMask) { 438818534a1Smrg int first = changes.first_type; 439818534a1Smrg int last = changes.first_type + changes.num_types - 1; 440818534a1Smrg 441818534a1Smrg fprintf(stderr, " types: %d..%d\n", first, last); 442818534a1Smrg } 443818534a1Smrg if (changes.changed & XkbKeySymsMask) { 444818534a1Smrg int first = changes.first_key_sym; 445818534a1Smrg int last = changes.first_key_sym + changes.num_key_syms - 1; 446818534a1Smrg 447818534a1Smrg fprintf(stderr, " symbols: %d..%d\n", first, last); 448818534a1Smrg } 449818534a1Smrg if (changes.changed & XkbKeyActionsMask) { 450818534a1Smrg int first = changes.first_key_act; 451818534a1Smrg int last = changes.first_key_act + changes.num_key_acts - 1; 452818534a1Smrg 453818534a1Smrg fprintf(stderr, " acts: %d..%d\n", first, last); 454818534a1Smrg } 455818534a1Smrg if (changes.changed & XkbKeyBehaviorsMask) { 456818534a1Smrg int first = changes.first_key_behavior; 457818534a1Smrg int last = first + changes.num_key_behaviors - 1; 458818534a1Smrg 459818534a1Smrg fprintf(stderr, " behaviors: %d..%d\n", first, last); 460818534a1Smrg } 461818534a1Smrg if (changes.changed & XkbVirtualModsMask) { 462818534a1Smrg fprintf(stderr, "virtual mods: 0x%04x\n", changes.vmods); 463818534a1Smrg } 464818534a1Smrg if (changes.changed & XkbExplicitComponentsMask) { 465818534a1Smrg int first = changes.first_key_explicit; 466818534a1Smrg int last = first + changes.num_key_explicit - 1; 467818534a1Smrg 468818534a1Smrg fprintf(stderr, " explicit: %d..%d\n", first, last); 469818534a1Smrg } 4701ab64890Smrg#endif 471818534a1Smrg } 472818534a1Smrg LockDisplay(dpy); 473818534a1Smrg if (xkbi->flags & XkbMapPending) { 474818534a1Smrg xkbi->flags &= ~XkbMapPending; 475818534a1Smrg bzero(&xkbi->changes, sizeof(XkbMapChangesRec)); 476818534a1Smrg } 477818534a1Smrg UnlockDisplay(dpy); 4781ab64890Smrg } 479818534a1Smrg if (event->request == MappingModifier) { 480818534a1Smrg LockDisplay(dpy); 481818534a1Smrg if (xkbi->desc->map->modmap) { 482818534a1Smrg _XkbFree(xkbi->desc->map->modmap); 483818534a1Smrg xkbi->desc->map->modmap = NULL; 484818534a1Smrg } 485818534a1Smrg if (dpy->key_bindings) { 486818534a1Smrg register struct _XKeytrans *p; 487818534a1Smrg 488818534a1Smrg for (p = dpy->key_bindings; p; p = p->next) { 489818534a1Smrg register int i; 490818534a1Smrg 491818534a1Smrg p->state = 0; 492818534a1Smrg if (p->mlen > 0) { 493818534a1Smrg for (i = 0; i < p->mlen; i++) { 494818534a1Smrg p->state |= XkbKeysymToModifiers(dpy, p->modifiers[i]); 495818534a1Smrg } 496818534a1Smrg if (p->state) 497818534a1Smrg p->state &= AllMods; 498818534a1Smrg else 499818534a1Smrg p->state = AnyModifier; 500818534a1Smrg } 501818534a1Smrg } 502818534a1Smrg } 503818534a1Smrg UnlockDisplay(dpy); 5041ab64890Smrg } 5051ab64890Smrg return 1; 5061ab64890Smrg} 5071ab64890Smrg 5081ab64890Smrgstatic int 5091ab64890Smrg_XkbLoadDpy(Display *dpy) 5101ab64890Smrg{ 5111ab64890Smrg XkbInfoPtr xkbi; 512818534a1Smrg unsigned query, oldEvents; 5131ab64890Smrg XkbDescRec *desc; 5141ab64890Smrg 515818534a1Smrg if (!XkbUseExtension(dpy, NULL, NULL)) 516818534a1Smrg return 0; 5171ab64890Smrg 5181ab64890Smrg xkbi = dpy->xkb_info; 5191ab64890Smrg query = XkbAllClientInfoMask; 520818534a1Smrg desc = XkbGetMap(dpy, query, XkbUseCoreKbd); 5211ab64890Smrg if (!desc) { 5221ab64890Smrg#ifdef DEBUG 523818534a1Smrg fprintf(stderr, "Warning! XkbGetMap failed!\n"); 5241ab64890Smrg#endif 525818534a1Smrg return 0; 5261ab64890Smrg } 5271ab64890Smrg LockDisplay(dpy); 5281ab64890Smrg xkbi->desc = desc; 5291ab64890Smrg 5301ab64890Smrg UnlockDisplay(dpy); 531818534a1Smrg oldEvents = xkbi->selected_events; 532818534a1Smrg if (!(xkbi->xlib_ctrls & XkbLC_IgnoreNewKeyboards)) { 533818534a1Smrg XkbSelectEventDetails(dpy, xkbi->desc->device_spec, 534818534a1Smrg XkbNewKeyboardNotify, 535818534a1Smrg XkbNKN_KeycodesMask | XkbNKN_DeviceIDMask, 536818534a1Smrg XkbNKN_KeycodesMask | XkbNKN_DeviceIDMask); 5371ab64890Smrg } 538818534a1Smrg XkbSelectEventDetails(dpy, xkbi->desc->device_spec, XkbMapNotify, 539818534a1Smrg XkbAllClientInfoMask, XkbAllClientInfoMask); 5401ab64890Smrg LockDisplay(dpy); 541818534a1Smrg xkbi->selected_events = oldEvents; 5421ab64890Smrg UnlockDisplay(dpy); 5431ab64890Smrg return 1; 5441ab64890Smrg} 5451ab64890Smrg 5461ab64890Smrgvoid 5471ab64890Smrg_XkbReloadDpy(Display *dpy) 5481ab64890Smrg{ 5491ab64890Smrg XkbInfoPtr xkbi; 5501ab64890Smrg XkbDescRec *desc; 551818534a1Smrg unsigned oldDeviceID; 5521ab64890Smrg 5531ab64890Smrg if (_XkbUnavailable(dpy)) 554818534a1Smrg return; 5551ab64890Smrg 5561ab64890Smrg xkbi = dpy->xkb_info; 5571ab64890Smrg LockDisplay(dpy); 5581ab64890Smrg if (xkbi->desc) { 559818534a1Smrg oldDeviceID = xkbi->desc->device_spec; 560818534a1Smrg XkbFreeKeyboard(xkbi->desc, XkbAllComponentsMask, True); 561818534a1Smrg xkbi->desc = NULL; 562818534a1Smrg xkbi->flags &= ~(XkbMapPending | XkbXlibNewKeyboard); 563818534a1Smrg xkbi->changes.changed = 0; 5641ab64890Smrg } 565818534a1Smrg else 566818534a1Smrg oldDeviceID = XkbUseCoreKbd; 5671ab64890Smrg UnlockDisplay(dpy); 568818534a1Smrg desc = XkbGetMap(dpy, XkbAllClientInfoMask, XkbUseCoreKbd); 5691ab64890Smrg if (!desc) 570818534a1Smrg return; 5711ab64890Smrg LockDisplay(dpy); 5721ab64890Smrg xkbi->desc = desc; 5731ab64890Smrg UnlockDisplay(dpy); 5741ab64890Smrg 575818534a1Smrg if (desc->device_spec != oldDeviceID) { 576818534a1Smrg /* transfer(?) event masks here */ 5771ab64890Smrg#ifdef NOTYET 578818534a1Smrg unsigned oldEvents; 579818534a1Smrg 580818534a1Smrg oldEvents = xkbi->selected_events; 581818534a1Smrg XkbSelectEventDetails(dpy, xkbi->desc->device_spec, XkbMapNotify, 582818534a1Smrg XkbAllMapComponentsMask, XkbAllClientInfoMask); 583818534a1Smrg LockDisplay(dpy); 584818534a1Smrg xkbi->selected_events = oldEvents; 585818534a1Smrg UnlockDisplay(dpy); 5861ab64890Smrg#endif 5871ab64890Smrg } 5881ab64890Smrg return; 5891ab64890Smrg} 5901ab64890Smrg 5911ab64890Smrgint 592d7c63e31SmrgXkbTranslateKeySym(Display *dpy, 593d7c63e31Smrg KeySym *sym_rtrn, 594818534a1Smrg unsigned int mods, 595818534a1Smrg char *buffer, 596818534a1Smrg int nbytes, 597818534a1Smrg int *extra_rtrn) 5981ab64890Smrg{ 599818534a1Smrg register XkbInfoPtr xkb; 6001ab64890Smrg XkbKSToMBFunc cvtr; 6011ab64890Smrg XPointer priv; 6021ab64890Smrg char tmp[4]; 6031ab64890Smrg int n; 6041ab64890Smrg 605818534a1Smrg xkb = dpy->xkb_info; 6061ab64890Smrg if (!xkb->cvt.KSToMB) { 607818534a1Smrg _XkbGetConverters(_XkbGetCharset(), &xkb->cvt); 608818534a1Smrg _XkbGetConverters("ISO8859-1", &xkb->latin1cvt); 6091ab64890Smrg } 6101ab64890Smrg 6111ab64890Smrg if (extra_rtrn) 612818534a1Smrg *extra_rtrn = 0; 6131ab64890Smrg 614818534a1Smrg if ((buffer == NULL) || (nbytes == 0)) { 615818534a1Smrg buffer = tmp; 616818534a1Smrg nbytes = 4; 6171ab64890Smrg } 6181ab64890Smrg 6191ab64890Smrg /* see if symbol rebound, if so, return that string. */ 620818534a1Smrg n = XkbLookupKeyBinding(dpy, *sym_rtrn, mods, buffer, nbytes, extra_rtrn); 6211ab64890Smrg if (n) 6221ab64890Smrg return n; 6231ab64890Smrg 624818534a1Smrg if (nbytes > 0) 625818534a1Smrg buffer[0] = '\0'; 6261ab64890Smrg 627818534a1Smrg if (xkb->cvt.KSToUpper && (mods & LockMask)) { 628818534a1Smrg *sym_rtrn = (*xkb->cvt.KSToUpper) (*sym_rtrn); 6291ab64890Smrg } 6301ab64890Smrg if (xkb->xlib_ctrls & XkbLC_ForceLatin1Lookup) { 631818534a1Smrg cvtr = xkb->latin1cvt.KSToMB; 632818534a1Smrg priv = xkb->latin1cvt.KSToMBPriv; 633818534a1Smrg } 634818534a1Smrg else { 635818534a1Smrg cvtr = xkb->cvt.KSToMB; 636818534a1Smrg priv = xkb->cvt.KSToMBPriv; 6371ab64890Smrg } 6381ab64890Smrg 639818534a1Smrg n = (*cvtr) (priv, *sym_rtrn, buffer, nbytes, extra_rtrn); 640818534a1Smrg 641818534a1Smrg if ((!xkb->cvt.KSToUpper) && (mods & LockMask)) { 642818534a1Smrg register int i; 643818534a1Smrg int change; 644818534a1Smrg 645818534a1Smrg for (i = change = 0; i < n; i++) { 646818534a1Smrg char ch = toupper(buffer[i]); 647818534a1Smrg change = (change || (buffer[i] != ch)); 648818534a1Smrg buffer[i] = ch; 649818534a1Smrg } 650818534a1Smrg if (change) { 651818534a1Smrg if (n == 1) 652818534a1Smrg *sym_rtrn = 653818534a1Smrg (*xkb->cvt.MBToKS) (xkb->cvt.MBToKSPriv, buffer, n, NULL); 654818534a1Smrg else 655818534a1Smrg *sym_rtrn = NoSymbol; 656818534a1Smrg } 6571ab64890Smrg } 6581ab64890Smrg 659818534a1Smrg if (mods & ControlMask) { 660818534a1Smrg if (n == 1) { 661818534a1Smrg buffer[0] = XkbToControl(buffer[0]); 662818534a1Smrg if (nbytes > 1) 663818534a1Smrg buffer[1] = '\0'; 664818534a1Smrg return 1; 665818534a1Smrg } 666818534a1Smrg if (nbytes > 0) 667818534a1Smrg buffer[0] = '\0'; 668818534a1Smrg return 0; 6691ab64890Smrg } 6701ab64890Smrg return n; 6711ab64890Smrg} 6721ab64890Smrg 6731ab64890Smrgint 674818534a1SmrgXLookupString(register XKeyEvent *event, 675818534a1Smrg char *buffer, 676818534a1Smrg int nbytes, 677818534a1Smrg KeySym *keysym, 678818534a1Smrg XComposeStatus *status) 6791ab64890Smrg{ 680818534a1Smrg KeySym dummy; 6811ab64890Smrg int rtrnLen; 6821ab64890Smrg unsigned int new_mods; 6831ab64890Smrg Display *dpy = event->display; 6841ab64890Smrg 685818534a1Smrg if (keysym == NULL) 686818534a1Smrg keysym = &dummy; 687818534a1Smrg if (!XkbLookupKeySym(dpy, event->keycode, event->state, &new_mods, keysym)) 688818534a1Smrg return 0; 689818534a1Smrg new_mods = (event->state & (~new_mods)); 6901ab64890Smrg 6911ab64890Smrg /* find the group where a symbol can be converted to control one */ 692818534a1Smrg if (new_mods & ControlMask && *keysym > 0x7F && 693818534a1Smrg (dpy->xkb_info->xlib_ctrls & XkbLC_ControlFallback)) { 694818534a1Smrg XKeyEvent tmp_ev = *event; 695818534a1Smrg KeySym tmp_keysym; 696818534a1Smrg unsigned int tmp_new_mods; 697818534a1Smrg 698818534a1Smrg if (_XkbUnavailable(dpy)) { 699818534a1Smrg tmp_ev.state = event->state ^ dpy->mode_switch; 7001ab64890Smrg if (XkbLookupKeySym(dpy, tmp_ev.keycode, tmp_ev.state, 7011ab64890Smrg &tmp_new_mods, &tmp_keysym) && 702818534a1Smrg tmp_keysym != NoSymbol && tmp_keysym < 0x80) { 7031ab64890Smrg *keysym = tmp_keysym; 7041ab64890Smrg } 705818534a1Smrg } 706818534a1Smrg else { 7071ab64890Smrg int n = XkbKeyNumGroups(dpy->xkb_info->desc, tmp_ev.keycode); 7081ab64890Smrg int i; 709818534a1Smrg 7101ab64890Smrg for (i = 0; i < n; i++) { 7111ab64890Smrg if (XkbGroupForCoreState(event->state) == i) 7121ab64890Smrg continue; 713818534a1Smrg tmp_ev.state = XkbBuildCoreState(tmp_ev.state, i); 7141ab64890Smrg if (XkbLookupKeySym(dpy, tmp_ev.keycode, tmp_ev.state, 715818534a1Smrg &tmp_new_mods, &tmp_keysym) && 716818534a1Smrg tmp_keysym != NoSymbol && tmp_keysym < 0x80) { 7171ab64890Smrg *keysym = tmp_keysym; 718818534a1Smrg new_mods = (event->state & (~tmp_new_mods)); 7191ab64890Smrg break; 7201ab64890Smrg } 7211ab64890Smrg } 7221ab64890Smrg } 72361b2299dSmrg } 7241ab64890Smrg 7251ab64890Smrg /* We *should* use the new_mods (which does not contain any modifiers */ 7261ab64890Smrg /* that were used to compute the symbol here, but pre-XKB XLookupString */ 7271ab64890Smrg /* did not and we have to remain compatible. Sigh. */ 7281ab64890Smrg if (_XkbUnavailable(dpy) || 729818534a1Smrg (dpy->xkb_info->xlib_ctrls & XkbLC_ConsumeLookupMods) == 0) 730818534a1Smrg new_mods = event->state; 7311ab64890Smrg 732818534a1Smrg rtrnLen = XkbLookupKeyBinding(dpy, *keysym, new_mods, buffer, nbytes, NULL); 733818534a1Smrg if (rtrnLen > 0) 734818534a1Smrg return rtrnLen; 7351ab64890Smrg 736818534a1Smrg return XkbTranslateKeySym(dpy, keysym, new_mods, buffer, nbytes, NULL); 7371ab64890Smrg} 7381ab64890Smrg 7391ab64890Smrg 7401ab64890Smrgint 741818534a1SmrgXkbLookupKeyBinding(Display *dpy, 742818534a1Smrg register KeySym sym, 743818534a1Smrg unsigned int mods, 744818534a1Smrg char *buffer, 745818534a1Smrg int nbytes, 746818534a1Smrg int *extra_rtrn) 7471ab64890Smrg{ 74861b2299dSmrg register struct _XKeytrans *p; 7491ab64890Smrg 7501ab64890Smrg if (extra_rtrn) 751818534a1Smrg *extra_rtrn = 0; 7521ab64890Smrg for (p = dpy->key_bindings; p; p = p->next) { 753818534a1Smrg if (((mods & AllMods) == p->state) && (sym == p->key)) { 754818534a1Smrg int tmp = p->len; 755818534a1Smrg 756818534a1Smrg if (tmp > nbytes) { 757818534a1Smrg if (extra_rtrn) 758818534a1Smrg *extra_rtrn = (tmp - nbytes); 759818534a1Smrg tmp = nbytes; 760818534a1Smrg } 7619c019ec5Smaya memcpy(buffer, p->string, (size_t) tmp); 762818534a1Smrg if (tmp < nbytes) 763818534a1Smrg buffer[tmp] = '\0'; 764818534a1Smrg return tmp; 765818534a1Smrg } 7661ab64890Smrg } 7671ab64890Smrg return 0; 7681ab64890Smrg} 7691ab64890Smrg 7701ab64890Smrgchar 771818534a1SmrgXkbToControl(char ch) 7721ab64890Smrg{ 7731ab64890Smrg register char c = ch; 77461b2299dSmrg 775818534a1Smrg if ((c >= '@' && c < '\177') || c == ' ') 776818534a1Smrg c &= 0x1F; 777818534a1Smrg else if (c == '2') 778818534a1Smrg c = '\000'; 779818534a1Smrg else if (c >= '3' && c <= '7') 780818534a1Smrg c -= ('3' - '\033'); 781818534a1Smrg else if (c == '8') 782818534a1Smrg c = '\177'; 783818534a1Smrg else if (c == '/') 784818534a1Smrg c = '_' & 0x1F; 7851ab64890Smrg return c; 7861ab64890Smrg} 787