XKBBind.c revision 9c019ec5
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) { 116818534a1Smrg int lastSym, tmp, nGrp; 117818534a1Smrg 118818534a1Smrg lastSym = 3; 119818534a1Smrg nGrp = XkbKeyNumGroups(xkb, kc); 120818534a1Smrg if ((nGrp > 0) && 121818534a1Smrg ((tmp = XkbKeyGroupWidth(xkb, kc, XkbGroup1Index)) > 2)) { 122818534a1Smrg if (col <= (lastSym + tmp - 2)) 123818534a1Smrg return XkbKeycodeToKeysym(dpy, kc, XkbGroup1Index, 124818534a1Smrg col - lastSym + 2); 125818534a1Smrg lastSym += tmp - 2; 126818534a1Smrg } 127818534a1Smrg if ((nGrp > 1) && 128818534a1Smrg ((tmp = XkbKeyGroupWidth(xkb, kc, XkbGroup2Index)) > 2)) { 129818534a1Smrg if (col <= (lastSym + tmp - 2)) 130818534a1Smrg return XkbKeycodeToKeysym(dpy, kc, XkbGroup2Index, 131818534a1Smrg col - lastSym + 2); 132818534a1Smrg lastSym += tmp - 2; 133818534a1Smrg } 134818534a1Smrg if (nGrp > 2) { 135818534a1Smrg tmp = XkbKeyGroupWidth(xkb, kc, XkbGroup3Index); 136818534a1Smrg if (col <= lastSym + tmp) 137818534a1Smrg return XkbKeycodeToKeysym(dpy, kc, XkbGroup3Index, 138818534a1Smrg col - lastSym); 139818534a1Smrg lastSym += tmp; 140818534a1Smrg } 141818534a1Smrg if (nGrp > 3) { 142818534a1Smrg tmp = XkbKeyGroupWidth(xkb, kc, XkbGroup4Index); 143818534a1Smrg if (col <= lastSym + tmp) 144818534a1Smrg return XkbKeycodeToKeysym(dpy, kc, XkbGroup4Index, 145818534a1Smrg col - lastSym); 146818534a1Smrg } 147818534a1Smrg return NoSymbol; 1481ab64890Smrg } 149818534a1Smrg return XkbKeycodeToKeysym(dpy, kc, (col >> 1), (col & 1)); 1501ab64890Smrg} 1511ab64890Smrg 1521ab64890SmrgKeyCode 1531ab64890SmrgXKeysymToKeycode(Display *dpy, KeySym ks) 1541ab64890Smrg{ 1551ab64890Smrg register int i, j, gotOne; 1561ab64890Smrg 1571ab64890Smrg if (_XkbUnavailable(dpy)) 158818534a1Smrg return _XKeysymToKeycode(dpy, ks); 159818534a1Smrg _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 1601ab64890Smrg 161818534a1Smrg j = 0; 1621ab64890Smrg do { 163818534a1Smrg register XkbDescRec *xkb = dpy->xkb_info->desc; 164818534a1Smrg gotOne = 0; 165818534a1Smrg for (i = dpy->min_keycode; i <= dpy->max_keycode; i++) { 166818534a1Smrg if (j < (int) XkbKeyNumSyms(xkb, i)) { 167818534a1Smrg gotOne = 1; 168818534a1Smrg if ((XkbKeySym(xkb, i, j) == ks)) 169818534a1Smrg return i; 170818534a1Smrg } 171818534a1Smrg } 172818534a1Smrg j++; 1731ab64890Smrg } while (gotOne); 1741ab64890Smrg return 0; 1751ab64890Smrg} 1761ab64890Smrg 1771ab64890Smrgstatic int 1781ab64890Smrg_XkbComputeModmap(Display *dpy) 1791ab64890Smrg{ 180818534a1Smrg register XkbDescPtr xkb; 1811ab64890Smrg 182818534a1Smrg xkb = dpy->xkb_info->desc; 183818534a1Smrg if (XkbGetUpdatedMap(dpy, XkbModifierMapMask, xkb) == Success) 184818534a1Smrg return 1; 1851ab64890Smrg return 0; 1861ab64890Smrg} 1871ab64890Smrg 1881ab64890Smrgunsigned 189818534a1SmrgXkbKeysymToModifiers(Display *dpy, KeySym ks) 1901ab64890Smrg{ 1911ab64890Smrg XkbDescRec *xkb; 192818534a1Smrg register int i, j; 1931ab64890Smrg register KeySym *pSyms; 1941ab64890Smrg CARD8 mods; 1951ab64890Smrg 1961ab64890Smrg if (_XkbUnavailable(dpy)) 197818534a1Smrg return _XKeysymToModifiers(dpy, ks); 198818534a1Smrg _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 199818534a1Smrg 200818534a1Smrg if (_XkbNeedModmap(dpy->xkb_info) && (!_XkbComputeModmap(dpy))) 201818534a1Smrg return _XKeysymToModifiers(dpy, ks); 202818534a1Smrg 203818534a1Smrg xkb = dpy->xkb_info->desc; 204818534a1Smrg mods = 0; 205818534a1Smrg for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) { 206818534a1Smrg pSyms = XkbKeySymsPtr(xkb, i); 207818534a1Smrg for (j = XkbKeyNumSyms(xkb, i) - 1; j >= 0; j--) { 208818534a1Smrg if (pSyms[j] == ks) { 209818534a1Smrg mods |= xkb->map->modmap[i]; 210818534a1Smrg break; 211818534a1Smrg } 212818534a1Smrg } 2131ab64890Smrg } 2141ab64890Smrg return mods; 2151ab64890Smrg} 2161ab64890Smrg 2171ab64890SmrgKeySym 218818534a1SmrgXLookupKeysym(register XKeyEvent * event, int col) 2191ab64890Smrg{ 2201ab64890Smrg Display *dpy = event->display; 221818534a1Smrg 2221ab64890Smrg if (_XkbUnavailable(dpy)) 223818534a1Smrg return _XLookupKeysym(event, col); 224818534a1Smrg _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 2251ab64890Smrg return XKeycodeToKeysym(dpy, event->keycode, col); 2261ab64890Smrg} 2271ab64890Smrg 2281ab64890Smrg /* 22961b2299dSmrg * Not a public entry point -- XkbTranslateKey is an obsolete name 23061b2299dSmrg * that is preserved here so that functions linked against the old 2311ab64890Smrg * version will continue to work in a shared library environment. 2321ab64890Smrg */ 2331ab64890Smrgint 234818534a1SmrgXkbTranslateKey(register Display *dpy, 235818534a1Smrg KeyCode key, 236818534a1Smrg register unsigned int mods, 237818534a1Smrg unsigned int *mods_rtrn, 238818534a1Smrg KeySym *keysym_rtrn); 239818534a1Smrg 2401ab64890Smrgint 241818534a1SmrgXkbTranslateKey(register Display *dpy, 242818534a1Smrg KeyCode key, 243818534a1Smrg register unsigned int mods, 244818534a1Smrg unsigned int *mods_rtrn, 245818534a1Smrg KeySym *keysym_rtrn) 2461ab64890Smrg{ 247818534a1Smrg return XkbLookupKeySym(dpy, key, mods, mods_rtrn, keysym_rtrn); 2481ab64890Smrg} 2491ab64890Smrg 2501ab64890SmrgBool 251818534a1SmrgXkbLookupKeySym(register Display *dpy, 252818534a1Smrg KeyCode key, 253818534a1Smrg register unsigned int mods, 254818534a1Smrg unsigned int *mods_rtrn, 255818534a1Smrg KeySym *keysym_rtrn) 2561ab64890Smrg{ 2571ab64890Smrg if (_XkbUnavailable(dpy)) 258818534a1Smrg return _XTranslateKey(dpy, key, mods, mods_rtrn, keysym_rtrn); 259818534a1Smrg _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 260818534a1Smrg return XkbTranslateKeyCode(dpy->xkb_info->desc, key, mods, mods_rtrn, 261818534a1Smrg keysym_rtrn); 2621ab64890Smrg} 2631ab64890Smrg 2641ab64890SmrgBool 265818534a1SmrgXkbTranslateKeyCode(register XkbDescPtr xkb, 266818534a1Smrg KeyCode key, 267818534a1Smrg register unsigned int mods, 268818534a1Smrg unsigned int *mods_rtrn, 269818534a1Smrg KeySym *keysym_rtrn) 2701ab64890Smrg{ 2711ab64890Smrg XkbKeyTypeRec *type; 272818534a1Smrg int col, nKeyGroups; 273818534a1Smrg unsigned preserve, effectiveGroup; 2741ab64890Smrg KeySym *syms; 2751ab64890Smrg 276818534a1Smrg if (mods_rtrn != NULL) 277818534a1Smrg *mods_rtrn = 0; 2781ab64890Smrg 279818534a1Smrg nKeyGroups = XkbKeyNumGroups(xkb, key); 280818534a1Smrg if ((!XkbKeycodeInRange(xkb, key)) || (nKeyGroups == 0)) { 281818534a1Smrg if (keysym_rtrn != NULL) 282818534a1Smrg *keysym_rtrn = NoSymbol; 283818534a1Smrg return False; 2841ab64890Smrg } 2851ab64890Smrg 286818534a1Smrg syms = XkbKeySymsPtr(xkb, key); 2871ab64890Smrg 2881ab64890Smrg /* find the offset of the effective group */ 2891ab64890Smrg col = 0; 290818534a1Smrg effectiveGroup = XkbGroupForCoreState(mods); 291818534a1Smrg if (effectiveGroup >= nKeyGroups) { 292818534a1Smrg unsigned groupInfo = XkbKeyGroupInfo(xkb, key); 293818534a1Smrg 294818534a1Smrg switch (XkbOutOfRangeGroupAction(groupInfo)) { 295818534a1Smrg default: 296818534a1Smrg effectiveGroup %= nKeyGroups; 297818534a1Smrg break; 298818534a1Smrg case XkbClampIntoRange: 299818534a1Smrg effectiveGroup = nKeyGroups - 1; 300818534a1Smrg break; 301818534a1Smrg case XkbRedirectIntoRange: 302818534a1Smrg effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo); 303818534a1Smrg if (effectiveGroup >= nKeyGroups) 304818534a1Smrg effectiveGroup = 0; 305818534a1Smrg break; 306818534a1Smrg } 3071ab64890Smrg } 308818534a1Smrg col = effectiveGroup * XkbKeyGroupsWidth(xkb, key); 309818534a1Smrg type = XkbKeyKeyType(xkb, key, effectiveGroup); 310818534a1Smrg 311818534a1Smrg preserve = 0; 312818534a1Smrg if (type->map) { /* find the column (shift level) within the group */ 313818534a1Smrg register int i; 314818534a1Smrg register XkbKTMapEntryPtr entry; 315818534a1Smrg 316818534a1Smrg for (i = 0, entry = type->map; i < type->map_count; i++, entry++) { 317818534a1Smrg if ((entry->active) && 318818534a1Smrg ((mods & type->mods.mask) == entry->mods.mask)) { 319818534a1Smrg col += entry->level; 320818534a1Smrg if (type->preserve) 321818534a1Smrg preserve = type->preserve[i].mask; 322818534a1Smrg break; 323818534a1Smrg } 324818534a1Smrg } 3251ab64890Smrg } 3261ab64890Smrg 327818534a1Smrg if (keysym_rtrn != NULL) 328818534a1Smrg *keysym_rtrn = syms[col]; 3291ab64890Smrg if (mods_rtrn) { 330818534a1Smrg *mods_rtrn = type->mods.mask & (~preserve); 331818534a1Smrg /* The Motif VTS doesn't get the help callback called if help 332818534a1Smrg * is bound to Shift+<whatever>, and it appears as though it 333818534a1Smrg * is XkbTranslateKeyCode that is causing the problem. The 334818534a1Smrg * core X version of XTranslateKey always OR's in ShiftMask 335818534a1Smrg * and LockMask for mods_rtrn, so this "fix" keeps this behavior 336818534a1Smrg * and solves the VTS problem. 337818534a1Smrg */ 338818534a1Smrg if ((xkb->dpy) && (xkb->dpy->xkb_info) && 339818534a1Smrg (xkb->dpy->xkb_info-> 340818534a1Smrg xlib_ctrls & XkbLC_AlwaysConsumeShiftAndLock)) { 341818534a1Smrg *mods_rtrn |= (ShiftMask | LockMask); 342818534a1Smrg } 3431ab64890Smrg } 344818534a1Smrg return (syms[col] != NoSymbol); 3451ab64890Smrg} 3461ab64890Smrg 3471ab64890SmrgStatus 348818534a1SmrgXkbRefreshKeyboardMapping(register XkbMapNotifyEvent * event) 3491ab64890Smrg{ 3501ab64890Smrg Display *dpy = event->display; 3511ab64890Smrg XkbInfoPtr xkbi; 3521ab64890Smrg 3531ab64890Smrg if (_XkbUnavailable(dpy)) { 354818534a1Smrg _XRefreshKeyboardMapping((XMappingEvent *) event); 355818534a1Smrg return Success; 3561ab64890Smrg } 357818534a1Smrg xkbi = dpy->xkb_info; 3581ab64890Smrg 359818534a1Smrg if (((event->type & 0x7f) - xkbi->codes->first_event) != XkbEventCode) 360818534a1Smrg return BadMatch; 361818534a1Smrg if (event->xkb_type == XkbNewKeyboardNotify) { 362818534a1Smrg _XkbReloadDpy(dpy); 363818534a1Smrg return Success; 3641ab64890Smrg } 365818534a1Smrg if (event->xkb_type == XkbMapNotify) { 366818534a1Smrg XkbMapChangesRec changes; 367818534a1Smrg Status rtrn; 368818534a1Smrg 369818534a1Smrg if (xkbi->flags & XkbMapPending) 370818534a1Smrg changes = xkbi->changes; 371818534a1Smrg else 372818534a1Smrg bzero(&changes, sizeof(changes)); 373818534a1Smrg XkbNoteMapChanges(&changes, event, XKB_XLIB_MAP_MASK); 374818534a1Smrg if ((rtrn = XkbGetMapChanges(dpy, xkbi->desc, &changes)) != Success) { 3751ab64890Smrg#ifdef DEBUG 376818534a1Smrg fprintf(stderr, "Internal Error! XkbGetMapChanges failed:\n"); 3771ab64890Smrg#endif 378818534a1Smrg xkbi->changes = changes; 379818534a1Smrg } 380818534a1Smrg else if (xkbi->flags & XkbMapPending) { 381818534a1Smrg xkbi->flags &= ~XkbMapPending; 382818534a1Smrg bzero(&xkbi->changes, sizeof(XkbMapChangesRec)); 383818534a1Smrg } 384818534a1Smrg return rtrn; 3851ab64890Smrg } 3861ab64890Smrg return BadMatch; 3871ab64890Smrg} 3881ab64890Smrg 3891ab64890Smrgint 390818534a1SmrgXRefreshKeyboardMapping(register XMappingEvent * event) 3911ab64890Smrg{ 392818534a1Smrg XkbEvent *xkbevent = (XkbEvent *) event; 3931ab64890Smrg Display *dpy = event->display; 3941ab64890Smrg XkbMapChangesRec changes; 3951ab64890Smrg XkbInfoPtr xkbi; 3961ab64890Smrg 3971ab64890Smrg /* always do this for input methods, which still use the old keymap */ 3981ab64890Smrg (void) _XRefreshKeyboardMapping(event); 3991ab64890Smrg 4001ab64890Smrg if (_XkbUnavailable(dpy)) 401818534a1Smrg return 1; 4021ab64890Smrg 4031ab64890Smrg xkbi = dpy->xkb_info; 4041ab64890Smrg 405818534a1Smrg if (((event->type & 0x7f) - xkbi->codes->first_event) == XkbEventCode) 406818534a1Smrg return XkbRefreshKeyboardMapping(&xkbevent->map); 4071ab64890Smrg 408818534a1Smrg if (xkbi->flags & XkbXlibNewKeyboard) { 409818534a1Smrg _XkbReloadDpy(dpy); 410818534a1Smrg return 1; 4111ab64890Smrg } 4121ab64890Smrg 413818534a1Smrg if ((xkbi->flags & XkbMapPending) || (event->request == MappingKeyboard)) { 414818534a1Smrg if (xkbi->flags & XkbMapPending) { 415818534a1Smrg changes = xkbi->changes; 416818534a1Smrg _XkbNoteCoreMapChanges(&changes, event, XKB_XLIB_MAP_MASK); 417818534a1Smrg } 418818534a1Smrg else { 419818534a1Smrg bzero(&changes, sizeof(changes)); 420818534a1Smrg changes.changed = XkbKeySymsMask; 421818534a1Smrg if (xkbi->desc->min_key_code < xkbi->desc->max_key_code) { 422818534a1Smrg changes.first_key_sym = xkbi->desc->min_key_code; 423818534a1Smrg changes.num_key_syms = xkbi->desc->max_key_code - 424818534a1Smrg xkbi->desc->min_key_code + 1; 425818534a1Smrg } 426818534a1Smrg else { 427818534a1Smrg changes.first_key_sym = event->first_keycode; 428818534a1Smrg changes.num_key_syms = event->count; 429818534a1Smrg } 430818534a1Smrg } 431818534a1Smrg 432818534a1Smrg if (XkbGetMapChanges(dpy, xkbi->desc, &changes) != Success) { 4331ab64890Smrg#ifdef DEBUG 434818534a1Smrg fprintf(stderr, "Internal Error! XkbGetMapChanges failed:\n"); 435818534a1Smrg if (changes.changed & XkbKeyTypesMask) { 436818534a1Smrg int first = changes.first_type; 437818534a1Smrg int last = changes.first_type + changes.num_types - 1; 438818534a1Smrg 439818534a1Smrg fprintf(stderr, " types: %d..%d\n", first, last); 440818534a1Smrg } 441818534a1Smrg if (changes.changed & XkbKeySymsMask) { 442818534a1Smrg int first = changes.first_key_sym; 443818534a1Smrg int last = changes.first_key_sym + changes.num_key_syms - 1; 444818534a1Smrg 445818534a1Smrg fprintf(stderr, " symbols: %d..%d\n", first, last); 446818534a1Smrg } 447818534a1Smrg if (changes.changed & XkbKeyActionsMask) { 448818534a1Smrg int first = changes.first_key_act; 449818534a1Smrg int last = changes.first_key_act + changes.num_key_acts - 1; 450818534a1Smrg 451818534a1Smrg fprintf(stderr, " acts: %d..%d\n", first, last); 452818534a1Smrg } 453818534a1Smrg if (changes.changed & XkbKeyBehaviorsMask) { 454818534a1Smrg int first = changes.first_key_behavior; 455818534a1Smrg int last = first + changes.num_key_behaviors - 1; 456818534a1Smrg 457818534a1Smrg fprintf(stderr, " behaviors: %d..%d\n", first, last); 458818534a1Smrg } 459818534a1Smrg if (changes.changed & XkbVirtualModsMask) { 460818534a1Smrg fprintf(stderr, "virtual mods: 0x%04x\n", changes.vmods); 461818534a1Smrg } 462818534a1Smrg if (changes.changed & XkbExplicitComponentsMask) { 463818534a1Smrg int first = changes.first_key_explicit; 464818534a1Smrg int last = first + changes.num_key_explicit - 1; 465818534a1Smrg 466818534a1Smrg fprintf(stderr, " explicit: %d..%d\n", first, last); 467818534a1Smrg } 4681ab64890Smrg#endif 469818534a1Smrg } 470818534a1Smrg LockDisplay(dpy); 471818534a1Smrg if (xkbi->flags & XkbMapPending) { 472818534a1Smrg xkbi->flags &= ~XkbMapPending; 473818534a1Smrg bzero(&xkbi->changes, sizeof(XkbMapChangesRec)); 474818534a1Smrg } 475818534a1Smrg UnlockDisplay(dpy); 4761ab64890Smrg } 477818534a1Smrg if (event->request == MappingModifier) { 478818534a1Smrg LockDisplay(dpy); 479818534a1Smrg if (xkbi->desc->map->modmap) { 480818534a1Smrg _XkbFree(xkbi->desc->map->modmap); 481818534a1Smrg xkbi->desc->map->modmap = NULL; 482818534a1Smrg } 483818534a1Smrg if (dpy->key_bindings) { 484818534a1Smrg register struct _XKeytrans *p; 485818534a1Smrg 486818534a1Smrg for (p = dpy->key_bindings; p; p = p->next) { 487818534a1Smrg register int i; 488818534a1Smrg 489818534a1Smrg p->state = 0; 490818534a1Smrg if (p->mlen > 0) { 491818534a1Smrg for (i = 0; i < p->mlen; i++) { 492818534a1Smrg p->state |= XkbKeysymToModifiers(dpy, p->modifiers[i]); 493818534a1Smrg } 494818534a1Smrg if (p->state) 495818534a1Smrg p->state &= AllMods; 496818534a1Smrg else 497818534a1Smrg p->state = AnyModifier; 498818534a1Smrg } 499818534a1Smrg } 500818534a1Smrg } 501818534a1Smrg UnlockDisplay(dpy); 5021ab64890Smrg } 5031ab64890Smrg return 1; 5041ab64890Smrg} 5051ab64890Smrg 5061ab64890Smrgstatic int 5071ab64890Smrg_XkbLoadDpy(Display *dpy) 5081ab64890Smrg{ 5091ab64890Smrg XkbInfoPtr xkbi; 510818534a1Smrg unsigned query, oldEvents; 5111ab64890Smrg XkbDescRec *desc; 5121ab64890Smrg 513818534a1Smrg if (!XkbUseExtension(dpy, NULL, NULL)) 514818534a1Smrg return 0; 5151ab64890Smrg 5161ab64890Smrg xkbi = dpy->xkb_info; 5171ab64890Smrg query = XkbAllClientInfoMask; 518818534a1Smrg desc = XkbGetMap(dpy, query, XkbUseCoreKbd); 5191ab64890Smrg if (!desc) { 5201ab64890Smrg#ifdef DEBUG 521818534a1Smrg fprintf(stderr, "Warning! XkbGetMap failed!\n"); 5221ab64890Smrg#endif 523818534a1Smrg return 0; 5241ab64890Smrg } 5251ab64890Smrg LockDisplay(dpy); 5261ab64890Smrg xkbi->desc = desc; 5271ab64890Smrg 5281ab64890Smrg UnlockDisplay(dpy); 529818534a1Smrg oldEvents = xkbi->selected_events; 530818534a1Smrg if (!(xkbi->xlib_ctrls & XkbLC_IgnoreNewKeyboards)) { 531818534a1Smrg XkbSelectEventDetails(dpy, xkbi->desc->device_spec, 532818534a1Smrg XkbNewKeyboardNotify, 533818534a1Smrg XkbNKN_KeycodesMask | XkbNKN_DeviceIDMask, 534818534a1Smrg XkbNKN_KeycodesMask | XkbNKN_DeviceIDMask); 5351ab64890Smrg } 536818534a1Smrg XkbSelectEventDetails(dpy, xkbi->desc->device_spec, XkbMapNotify, 537818534a1Smrg XkbAllClientInfoMask, XkbAllClientInfoMask); 5381ab64890Smrg LockDisplay(dpy); 539818534a1Smrg xkbi->selected_events = oldEvents; 5401ab64890Smrg UnlockDisplay(dpy); 5411ab64890Smrg return 1; 5421ab64890Smrg} 5431ab64890Smrg 5441ab64890Smrgvoid 5451ab64890Smrg_XkbReloadDpy(Display *dpy) 5461ab64890Smrg{ 5471ab64890Smrg XkbInfoPtr xkbi; 5481ab64890Smrg XkbDescRec *desc; 549818534a1Smrg unsigned oldDeviceID; 5501ab64890Smrg 5511ab64890Smrg if (_XkbUnavailable(dpy)) 552818534a1Smrg return; 5531ab64890Smrg 5541ab64890Smrg xkbi = dpy->xkb_info; 5551ab64890Smrg LockDisplay(dpy); 5561ab64890Smrg if (xkbi->desc) { 557818534a1Smrg oldDeviceID = xkbi->desc->device_spec; 558818534a1Smrg XkbFreeKeyboard(xkbi->desc, XkbAllComponentsMask, True); 559818534a1Smrg xkbi->desc = NULL; 560818534a1Smrg xkbi->flags &= ~(XkbMapPending | XkbXlibNewKeyboard); 561818534a1Smrg xkbi->changes.changed = 0; 5621ab64890Smrg } 563818534a1Smrg else 564818534a1Smrg oldDeviceID = XkbUseCoreKbd; 5651ab64890Smrg UnlockDisplay(dpy); 566818534a1Smrg desc = XkbGetMap(dpy, XkbAllClientInfoMask, XkbUseCoreKbd); 5671ab64890Smrg if (!desc) 568818534a1Smrg return; 5691ab64890Smrg LockDisplay(dpy); 5701ab64890Smrg xkbi->desc = desc; 5711ab64890Smrg UnlockDisplay(dpy); 5721ab64890Smrg 573818534a1Smrg if (desc->device_spec != oldDeviceID) { 574818534a1Smrg /* transfer(?) event masks here */ 5751ab64890Smrg#ifdef NOTYET 576818534a1Smrg unsigned oldEvents; 577818534a1Smrg 578818534a1Smrg oldEvents = xkbi->selected_events; 579818534a1Smrg XkbSelectEventDetails(dpy, xkbi->desc->device_spec, XkbMapNotify, 580818534a1Smrg XkbAllMapComponentsMask, XkbAllClientInfoMask); 581818534a1Smrg LockDisplay(dpy); 582818534a1Smrg xkbi->selected_events = oldEvents; 583818534a1Smrg UnlockDisplay(dpy); 5841ab64890Smrg#endif 5851ab64890Smrg } 5861ab64890Smrg return; 5871ab64890Smrg} 5881ab64890Smrg 5891ab64890Smrgint 590818534a1SmrgXkbTranslateKeySym(register Display *dpy, 591818534a1Smrg register KeySym *sym_rtrn, 592818534a1Smrg unsigned int mods, 593818534a1Smrg char *buffer, 594818534a1Smrg int nbytes, 595818534a1Smrg int *extra_rtrn) 5961ab64890Smrg{ 597818534a1Smrg register XkbInfoPtr xkb; 5981ab64890Smrg XkbKSToMBFunc cvtr; 5991ab64890Smrg XPointer priv; 6001ab64890Smrg char tmp[4]; 6011ab64890Smrg int n; 6021ab64890Smrg 603818534a1Smrg xkb = dpy->xkb_info; 6041ab64890Smrg if (!xkb->cvt.KSToMB) { 605818534a1Smrg _XkbGetConverters(_XkbGetCharset(), &xkb->cvt); 606818534a1Smrg _XkbGetConverters("ISO8859-1", &xkb->latin1cvt); 6071ab64890Smrg } 6081ab64890Smrg 6091ab64890Smrg if (extra_rtrn) 610818534a1Smrg *extra_rtrn = 0; 6111ab64890Smrg 612818534a1Smrg if ((buffer == NULL) || (nbytes == 0)) { 613818534a1Smrg buffer = tmp; 614818534a1Smrg nbytes = 4; 6151ab64890Smrg } 6161ab64890Smrg 6171ab64890Smrg /* see if symbol rebound, if so, return that string. */ 618818534a1Smrg n = XkbLookupKeyBinding(dpy, *sym_rtrn, mods, buffer, nbytes, extra_rtrn); 6191ab64890Smrg if (n) 6201ab64890Smrg return n; 6211ab64890Smrg 622818534a1Smrg if (nbytes > 0) 623818534a1Smrg buffer[0] = '\0'; 6241ab64890Smrg 625818534a1Smrg if (xkb->cvt.KSToUpper && (mods & LockMask)) { 626818534a1Smrg *sym_rtrn = (*xkb->cvt.KSToUpper) (*sym_rtrn); 6271ab64890Smrg } 6281ab64890Smrg if (xkb->xlib_ctrls & XkbLC_ForceLatin1Lookup) { 629818534a1Smrg cvtr = xkb->latin1cvt.KSToMB; 630818534a1Smrg priv = xkb->latin1cvt.KSToMBPriv; 631818534a1Smrg } 632818534a1Smrg else { 633818534a1Smrg cvtr = xkb->cvt.KSToMB; 634818534a1Smrg priv = xkb->cvt.KSToMBPriv; 6351ab64890Smrg } 6361ab64890Smrg 637818534a1Smrg n = (*cvtr) (priv, *sym_rtrn, buffer, nbytes, extra_rtrn); 638818534a1Smrg 639818534a1Smrg if ((!xkb->cvt.KSToUpper) && (mods & LockMask)) { 640818534a1Smrg register int i; 641818534a1Smrg int change; 642818534a1Smrg 643818534a1Smrg for (i = change = 0; i < n; i++) { 644818534a1Smrg char ch = toupper(buffer[i]); 645818534a1Smrg change = (change || (buffer[i] != ch)); 646818534a1Smrg buffer[i] = ch; 647818534a1Smrg } 648818534a1Smrg if (change) { 649818534a1Smrg if (n == 1) 650818534a1Smrg *sym_rtrn = 651818534a1Smrg (*xkb->cvt.MBToKS) (xkb->cvt.MBToKSPriv, buffer, n, NULL); 652818534a1Smrg else 653818534a1Smrg *sym_rtrn = NoSymbol; 654818534a1Smrg } 6551ab64890Smrg } 6561ab64890Smrg 657818534a1Smrg if (mods & ControlMask) { 658818534a1Smrg if (n == 1) { 659818534a1Smrg buffer[0] = XkbToControl(buffer[0]); 660818534a1Smrg if (nbytes > 1) 661818534a1Smrg buffer[1] = '\0'; 662818534a1Smrg return 1; 663818534a1Smrg } 664818534a1Smrg if (nbytes > 0) 665818534a1Smrg buffer[0] = '\0'; 666818534a1Smrg return 0; 6671ab64890Smrg } 6681ab64890Smrg return n; 6691ab64890Smrg} 6701ab64890Smrg 6711ab64890Smrgint 672818534a1SmrgXLookupString(register XKeyEvent *event, 673818534a1Smrg char *buffer, 674818534a1Smrg int nbytes, 675818534a1Smrg KeySym *keysym, 676818534a1Smrg XComposeStatus *status) 6771ab64890Smrg{ 678818534a1Smrg KeySym dummy; 6791ab64890Smrg int rtrnLen; 6801ab64890Smrg unsigned int new_mods; 6811ab64890Smrg Display *dpy = event->display; 6821ab64890Smrg 683818534a1Smrg if (keysym == NULL) 684818534a1Smrg keysym = &dummy; 685818534a1Smrg if (!XkbLookupKeySym(dpy, event->keycode, event->state, &new_mods, keysym)) 686818534a1Smrg return 0; 687818534a1Smrg new_mods = (event->state & (~new_mods)); 6881ab64890Smrg 6891ab64890Smrg /* find the group where a symbol can be converted to control one */ 690818534a1Smrg if (new_mods & ControlMask && *keysym > 0x7F && 691818534a1Smrg (dpy->xkb_info->xlib_ctrls & XkbLC_ControlFallback)) { 692818534a1Smrg XKeyEvent tmp_ev = *event; 693818534a1Smrg KeySym tmp_keysym; 694818534a1Smrg unsigned int tmp_new_mods; 695818534a1Smrg 696818534a1Smrg if (_XkbUnavailable(dpy)) { 697818534a1Smrg tmp_ev.state = event->state ^ dpy->mode_switch; 6981ab64890Smrg if (XkbLookupKeySym(dpy, tmp_ev.keycode, tmp_ev.state, 6991ab64890Smrg &tmp_new_mods, &tmp_keysym) && 700818534a1Smrg tmp_keysym != NoSymbol && tmp_keysym < 0x80) { 7011ab64890Smrg *keysym = tmp_keysym; 7021ab64890Smrg } 703818534a1Smrg } 704818534a1Smrg else { 7051ab64890Smrg int n = XkbKeyNumGroups(dpy->xkb_info->desc, tmp_ev.keycode); 7061ab64890Smrg int i; 707818534a1Smrg 7081ab64890Smrg for (i = 0; i < n; i++) { 7091ab64890Smrg if (XkbGroupForCoreState(event->state) == i) 7101ab64890Smrg continue; 711818534a1Smrg tmp_ev.state = XkbBuildCoreState(tmp_ev.state, i); 7121ab64890Smrg if (XkbLookupKeySym(dpy, tmp_ev.keycode, tmp_ev.state, 713818534a1Smrg &tmp_new_mods, &tmp_keysym) && 714818534a1Smrg tmp_keysym != NoSymbol && tmp_keysym < 0x80) { 7151ab64890Smrg *keysym = tmp_keysym; 716818534a1Smrg new_mods = (event->state & (~tmp_new_mods)); 7171ab64890Smrg break; 7181ab64890Smrg } 7191ab64890Smrg } 7201ab64890Smrg } 72161b2299dSmrg } 7221ab64890Smrg 7231ab64890Smrg /* We *should* use the new_mods (which does not contain any modifiers */ 7241ab64890Smrg /* that were used to compute the symbol here, but pre-XKB XLookupString */ 7251ab64890Smrg /* did not and we have to remain compatible. Sigh. */ 7261ab64890Smrg if (_XkbUnavailable(dpy) || 727818534a1Smrg (dpy->xkb_info->xlib_ctrls & XkbLC_ConsumeLookupMods) == 0) 728818534a1Smrg new_mods = event->state; 7291ab64890Smrg 730818534a1Smrg rtrnLen = XkbLookupKeyBinding(dpy, *keysym, new_mods, buffer, nbytes, NULL); 731818534a1Smrg if (rtrnLen > 0) 732818534a1Smrg return rtrnLen; 7331ab64890Smrg 734818534a1Smrg return XkbTranslateKeySym(dpy, keysym, new_mods, buffer, nbytes, NULL); 7351ab64890Smrg} 7361ab64890Smrg 7371ab64890Smrg 7381ab64890Smrgint 739818534a1SmrgXkbLookupKeyBinding(Display *dpy, 740818534a1Smrg register KeySym sym, 741818534a1Smrg unsigned int mods, 742818534a1Smrg char *buffer, 743818534a1Smrg int nbytes, 744818534a1Smrg int *extra_rtrn) 7451ab64890Smrg{ 74661b2299dSmrg register struct _XKeytrans *p; 7471ab64890Smrg 7481ab64890Smrg if (extra_rtrn) 749818534a1Smrg *extra_rtrn = 0; 7501ab64890Smrg for (p = dpy->key_bindings; p; p = p->next) { 751818534a1Smrg if (((mods & AllMods) == p->state) && (sym == p->key)) { 752818534a1Smrg int tmp = p->len; 753818534a1Smrg 754818534a1Smrg if (tmp > nbytes) { 755818534a1Smrg if (extra_rtrn) 756818534a1Smrg *extra_rtrn = (tmp - nbytes); 757818534a1Smrg tmp = nbytes; 758818534a1Smrg } 7599c019ec5Smaya memcpy(buffer, p->string, (size_t) tmp); 760818534a1Smrg if (tmp < nbytes) 761818534a1Smrg buffer[tmp] = '\0'; 762818534a1Smrg return tmp; 763818534a1Smrg } 7641ab64890Smrg } 7651ab64890Smrg return 0; 7661ab64890Smrg} 7671ab64890Smrg 7681ab64890Smrgchar 769818534a1SmrgXkbToControl(char ch) 7701ab64890Smrg{ 7711ab64890Smrg register char c = ch; 77261b2299dSmrg 773818534a1Smrg if ((c >= '@' && c < '\177') || c == ' ') 774818534a1Smrg c &= 0x1F; 775818534a1Smrg else if (c == '2') 776818534a1Smrg c = '\000'; 777818534a1Smrg else if (c >= '3' && c <= '7') 778818534a1Smrg c -= ('3' - '\033'); 779818534a1Smrg else if (c == '8') 780818534a1Smrg c = '\177'; 781818534a1Smrg else if (c == '/') 782818534a1Smrg c = '_' & 0x1F; 7831ab64890Smrg return c; 7841ab64890Smrg} 785