XKBBind.c revision 818534a1
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#ifdef USE_OWN_COMPOSE 45818534a1Smrg#define COMPOSE_NO_CONST_MEMBERS 461ab64890Smrg#include "imComp.h" 471ab64890Smrg#endif 481ab64890Smrg 491ab64890Smrg#define AllMods (ShiftMask|LockMask|ControlMask| \ 50818534a1Smrg Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask) 511ab64890Smrg 52818534a1Smrgstatic int _XkbLoadDpy(Display *dpy); 531ab64890Smrg 541ab64890Smrgstruct _XKeytrans { 55818534a1Smrg struct _XKeytrans *next; /* next on list */ 56818534a1Smrg char *string; /* string to return when the time comes */ 57818534a1Smrg int len; /* length of string (since NULL is legit) */ 58818534a1Smrg KeySym key; /* keysym rebound */ 59818534a1Smrg unsigned int state; /* modifier state */ 60818534a1Smrg KeySym *modifiers; /* modifier keysyms you want */ 61818534a1Smrg int mlen; /* length of modifier list */ 621ab64890Smrg}; 631ab64890Smrg 641ab64890SmrgKeySym 651ab64890SmrgXkbKeycodeToKeysym(Display *dpy, 661ab64890Smrg#if NeedWidePrototypes 67818534a1Smrg unsigned int kc, 681ab64890Smrg#else 69818534a1Smrg KeyCode kc, 701ab64890Smrg#endif 71818534a1Smrg int group, 72818534a1Smrg int level) 731ab64890Smrg{ 74818534a1Smrg XkbDescRec *xkb; 7561b2299dSmrg 761ab64890Smrg if (_XkbUnavailable(dpy)) 77818534a1Smrg return NoSymbol; 781ab64890Smrg 79818534a1Smrg _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 801ab64890Smrg 811ab64890Smrg xkb = dpy->xkb_info->desc; 82818534a1Smrg if ((kc < xkb->min_key_code) || (kc > xkb->max_key_code)) 83818534a1Smrg return NoSymbol; 84818534a1Smrg 85818534a1Smrg if ((group < 0) || (level < 0) || (group >= XkbKeyNumGroups(xkb, kc))) 86818534a1Smrg return NoSymbol; 87818534a1Smrg if (level >= XkbKeyGroupWidth(xkb, kc, group)) { 88818534a1Smrg /* for compatibility with the core protocol, _always_ allow */ 89818534a1Smrg /* two symbols in the first two groups. If either of the */ 90818534a1Smrg /* two is of type ONE_LEVEL, just replicate the first symbol */ 91818534a1Smrg if ((group > XkbGroup2Index) || (XkbKeyGroupWidth(xkb, kc, group) != 1) 92818534a1Smrg || (level != 1)) { 93818534a1Smrg return NoSymbol; 94818534a1Smrg } 95818534a1Smrg level = 0; 961ab64890Smrg } 97818534a1Smrg return XkbKeySymEntry(xkb, kc, level, group); 981ab64890Smrg} 991ab64890Smrg 1001ab64890SmrgKeySym 1011ab64890SmrgXKeycodeToKeysym(Display *dpy, 1021ab64890Smrg#if NeedWidePrototypes 103818534a1Smrg unsigned int kc, 1041ab64890Smrg#else 105818534a1Smrg KeyCode kc, 1061ab64890Smrg#endif 107818534a1Smrg int col) 1081ab64890Smrg{ 109818534a1Smrg XkbDescRec *xkb; 11061b2299dSmrg 1111ab64890Smrg if (_XkbUnavailable(dpy)) 112818534a1Smrg return _XKeycodeToKeysym(dpy, kc, col); 1131ab64890Smrg 114818534a1Smrg _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 1151ab64890Smrg 1161ab64890Smrg xkb = dpy->xkb_info->desc; 117818534a1Smrg if ((kc < xkb->min_key_code) || (kc > xkb->max_key_code)) 118818534a1Smrg return NoSymbol; 119818534a1Smrg 120818534a1Smrg if (col > 3) { 121818534a1Smrg int lastSym, tmp, nGrp; 122818534a1Smrg 123818534a1Smrg lastSym = 3; 124818534a1Smrg nGrp = XkbKeyNumGroups(xkb, kc); 125818534a1Smrg if ((nGrp > 0) && 126818534a1Smrg ((tmp = XkbKeyGroupWidth(xkb, kc, XkbGroup1Index)) > 2)) { 127818534a1Smrg if (col <= (lastSym + tmp - 2)) 128818534a1Smrg return XkbKeycodeToKeysym(dpy, kc, XkbGroup1Index, 129818534a1Smrg col - lastSym + 2); 130818534a1Smrg lastSym += tmp - 2; 131818534a1Smrg } 132818534a1Smrg if ((nGrp > 1) && 133818534a1Smrg ((tmp = XkbKeyGroupWidth(xkb, kc, XkbGroup2Index)) > 2)) { 134818534a1Smrg if (col <= (lastSym + tmp - 2)) 135818534a1Smrg return XkbKeycodeToKeysym(dpy, kc, XkbGroup2Index, 136818534a1Smrg col - lastSym + 2); 137818534a1Smrg lastSym += tmp - 2; 138818534a1Smrg } 139818534a1Smrg if (nGrp > 2) { 140818534a1Smrg tmp = XkbKeyGroupWidth(xkb, kc, XkbGroup3Index); 141818534a1Smrg if (col <= lastSym + tmp) 142818534a1Smrg return XkbKeycodeToKeysym(dpy, kc, XkbGroup3Index, 143818534a1Smrg col - lastSym); 144818534a1Smrg lastSym += tmp; 145818534a1Smrg } 146818534a1Smrg if (nGrp > 3) { 147818534a1Smrg tmp = XkbKeyGroupWidth(xkb, kc, XkbGroup4Index); 148818534a1Smrg if (col <= lastSym + tmp) 149818534a1Smrg return XkbKeycodeToKeysym(dpy, kc, XkbGroup4Index, 150818534a1Smrg col - lastSym); 151818534a1Smrg } 152818534a1Smrg return NoSymbol; 1531ab64890Smrg } 154818534a1Smrg return XkbKeycodeToKeysym(dpy, kc, (col >> 1), (col & 1)); 1551ab64890Smrg} 1561ab64890Smrg 1571ab64890SmrgKeyCode 1581ab64890SmrgXKeysymToKeycode(Display *dpy, KeySym ks) 1591ab64890Smrg{ 1601ab64890Smrg register int i, j, gotOne; 1611ab64890Smrg 1621ab64890Smrg if (_XkbUnavailable(dpy)) 163818534a1Smrg return _XKeysymToKeycode(dpy, ks); 164818534a1Smrg _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 1651ab64890Smrg 166818534a1Smrg j = 0; 1671ab64890Smrg do { 168818534a1Smrg register XkbDescRec *xkb = dpy->xkb_info->desc; 169818534a1Smrg gotOne = 0; 170818534a1Smrg for (i = dpy->min_keycode; i <= dpy->max_keycode; i++) { 171818534a1Smrg if (j < (int) XkbKeyNumSyms(xkb, i)) { 172818534a1Smrg gotOne = 1; 173818534a1Smrg if ((XkbKeySym(xkb, i, j) == ks)) 174818534a1Smrg return i; 175818534a1Smrg } 176818534a1Smrg } 177818534a1Smrg j++; 1781ab64890Smrg } while (gotOne); 1791ab64890Smrg return 0; 1801ab64890Smrg} 1811ab64890Smrg 1821ab64890Smrgstatic int 1831ab64890Smrg_XkbComputeModmap(Display *dpy) 1841ab64890Smrg{ 185818534a1Smrg register XkbDescPtr xkb; 1861ab64890Smrg 187818534a1Smrg xkb = dpy->xkb_info->desc; 188818534a1Smrg if (XkbGetUpdatedMap(dpy, XkbModifierMapMask, xkb) == Success) 189818534a1Smrg return 1; 1901ab64890Smrg return 0; 1911ab64890Smrg} 1921ab64890Smrg 1931ab64890Smrgunsigned 194818534a1SmrgXkbKeysymToModifiers(Display *dpy, KeySym ks) 1951ab64890Smrg{ 1961ab64890Smrg XkbDescRec *xkb; 197818534a1Smrg register int i, j; 1981ab64890Smrg register KeySym *pSyms; 1991ab64890Smrg CARD8 mods; 2001ab64890Smrg 2011ab64890Smrg if (_XkbUnavailable(dpy)) 202818534a1Smrg return _XKeysymToModifiers(dpy, ks); 203818534a1Smrg _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 204818534a1Smrg 205818534a1Smrg if (_XkbNeedModmap(dpy->xkb_info) && (!_XkbComputeModmap(dpy))) 206818534a1Smrg return _XKeysymToModifiers(dpy, ks); 207818534a1Smrg 208818534a1Smrg xkb = dpy->xkb_info->desc; 209818534a1Smrg mods = 0; 210818534a1Smrg for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) { 211818534a1Smrg pSyms = XkbKeySymsPtr(xkb, i); 212818534a1Smrg for (j = XkbKeyNumSyms(xkb, i) - 1; j >= 0; j--) { 213818534a1Smrg if (pSyms[j] == ks) { 214818534a1Smrg mods |= xkb->map->modmap[i]; 215818534a1Smrg break; 216818534a1Smrg } 217818534a1Smrg } 2181ab64890Smrg } 2191ab64890Smrg return mods; 2201ab64890Smrg} 2211ab64890Smrg 2221ab64890SmrgKeySym 223818534a1SmrgXLookupKeysym(register XKeyEvent * event, int col) 2241ab64890Smrg{ 2251ab64890Smrg Display *dpy = event->display; 226818534a1Smrg 2271ab64890Smrg if (_XkbUnavailable(dpy)) 228818534a1Smrg return _XLookupKeysym(event, col); 229818534a1Smrg _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 2301ab64890Smrg return XKeycodeToKeysym(dpy, event->keycode, col); 2311ab64890Smrg} 2321ab64890Smrg 2331ab64890Smrg /* 23461b2299dSmrg * Not a public entry point -- XkbTranslateKey is an obsolete name 23561b2299dSmrg * that is preserved here so that functions linked against the old 2361ab64890Smrg * version will continue to work in a shared library environment. 2371ab64890Smrg */ 2381ab64890Smrgint 239818534a1SmrgXkbTranslateKey(register Display *dpy, 240818534a1Smrg KeyCode key, 241818534a1Smrg register unsigned int mods, 242818534a1Smrg unsigned int *mods_rtrn, 243818534a1Smrg KeySym *keysym_rtrn); 244818534a1Smrg 2451ab64890Smrgint 246818534a1SmrgXkbTranslateKey(register Display *dpy, 247818534a1Smrg KeyCode key, 248818534a1Smrg register unsigned int mods, 249818534a1Smrg unsigned int *mods_rtrn, 250818534a1Smrg KeySym *keysym_rtrn) 2511ab64890Smrg{ 252818534a1Smrg return XkbLookupKeySym(dpy, key, mods, mods_rtrn, keysym_rtrn); 2531ab64890Smrg} 2541ab64890Smrg 2551ab64890SmrgBool 256818534a1SmrgXkbLookupKeySym(register Display *dpy, 257818534a1Smrg KeyCode key, 258818534a1Smrg register unsigned int mods, 259818534a1Smrg unsigned int *mods_rtrn, 260818534a1Smrg KeySym *keysym_rtrn) 2611ab64890Smrg{ 2621ab64890Smrg if (_XkbUnavailable(dpy)) 263818534a1Smrg return _XTranslateKey(dpy, key, mods, mods_rtrn, keysym_rtrn); 264818534a1Smrg _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 265818534a1Smrg return XkbTranslateKeyCode(dpy->xkb_info->desc, key, mods, mods_rtrn, 266818534a1Smrg keysym_rtrn); 2671ab64890Smrg} 2681ab64890Smrg 2691ab64890SmrgBool 270818534a1SmrgXkbTranslateKeyCode(register XkbDescPtr xkb, 271818534a1Smrg KeyCode key, 272818534a1Smrg register unsigned int mods, 273818534a1Smrg unsigned int *mods_rtrn, 274818534a1Smrg KeySym *keysym_rtrn) 2751ab64890Smrg{ 2761ab64890Smrg XkbKeyTypeRec *type; 277818534a1Smrg int col, nKeyGroups; 278818534a1Smrg unsigned preserve, effectiveGroup; 2791ab64890Smrg KeySym *syms; 2801ab64890Smrg 281818534a1Smrg if (mods_rtrn != NULL) 282818534a1Smrg *mods_rtrn = 0; 2831ab64890Smrg 284818534a1Smrg nKeyGroups = XkbKeyNumGroups(xkb, key); 285818534a1Smrg if ((!XkbKeycodeInRange(xkb, key)) || (nKeyGroups == 0)) { 286818534a1Smrg if (keysym_rtrn != NULL) 287818534a1Smrg *keysym_rtrn = NoSymbol; 288818534a1Smrg return False; 2891ab64890Smrg } 2901ab64890Smrg 291818534a1Smrg syms = XkbKeySymsPtr(xkb, key); 2921ab64890Smrg 2931ab64890Smrg /* find the offset of the effective group */ 2941ab64890Smrg col = 0; 295818534a1Smrg effectiveGroup = XkbGroupForCoreState(mods); 296818534a1Smrg if (effectiveGroup >= nKeyGroups) { 297818534a1Smrg unsigned groupInfo = XkbKeyGroupInfo(xkb, key); 298818534a1Smrg 299818534a1Smrg switch (XkbOutOfRangeGroupAction(groupInfo)) { 300818534a1Smrg default: 301818534a1Smrg effectiveGroup %= nKeyGroups; 302818534a1Smrg break; 303818534a1Smrg case XkbClampIntoRange: 304818534a1Smrg effectiveGroup = nKeyGroups - 1; 305818534a1Smrg break; 306818534a1Smrg case XkbRedirectIntoRange: 307818534a1Smrg effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo); 308818534a1Smrg if (effectiveGroup >= nKeyGroups) 309818534a1Smrg effectiveGroup = 0; 310818534a1Smrg break; 311818534a1Smrg } 3121ab64890Smrg } 313818534a1Smrg col = effectiveGroup * XkbKeyGroupsWidth(xkb, key); 314818534a1Smrg type = XkbKeyKeyType(xkb, key, effectiveGroup); 315818534a1Smrg 316818534a1Smrg preserve = 0; 317818534a1Smrg if (type->map) { /* find the column (shift level) within the group */ 318818534a1Smrg register int i; 319818534a1Smrg register XkbKTMapEntryPtr entry; 320818534a1Smrg 321818534a1Smrg for (i = 0, entry = type->map; i < type->map_count; i++, entry++) { 322818534a1Smrg if ((entry->active) && 323818534a1Smrg ((mods & type->mods.mask) == entry->mods.mask)) { 324818534a1Smrg col += entry->level; 325818534a1Smrg if (type->preserve) 326818534a1Smrg preserve = type->preserve[i].mask; 327818534a1Smrg break; 328818534a1Smrg } 329818534a1Smrg } 3301ab64890Smrg } 3311ab64890Smrg 332818534a1Smrg if (keysym_rtrn != NULL) 333818534a1Smrg *keysym_rtrn = syms[col]; 3341ab64890Smrg if (mods_rtrn) { 335818534a1Smrg *mods_rtrn = type->mods.mask & (~preserve); 336818534a1Smrg /* The Motif VTS doesn't get the help callback called if help 337818534a1Smrg * is bound to Shift+<whatever>, and it appears as though it 338818534a1Smrg * is XkbTranslateKeyCode that is causing the problem. The 339818534a1Smrg * core X version of XTranslateKey always OR's in ShiftMask 340818534a1Smrg * and LockMask for mods_rtrn, so this "fix" keeps this behavior 341818534a1Smrg * and solves the VTS problem. 342818534a1Smrg */ 343818534a1Smrg if ((xkb->dpy) && (xkb->dpy->xkb_info) && 344818534a1Smrg (xkb->dpy->xkb_info-> 345818534a1Smrg xlib_ctrls & XkbLC_AlwaysConsumeShiftAndLock)) { 346818534a1Smrg *mods_rtrn |= (ShiftMask | LockMask); 347818534a1Smrg } 3481ab64890Smrg } 349818534a1Smrg return (syms[col] != NoSymbol); 3501ab64890Smrg} 3511ab64890Smrg 3521ab64890SmrgStatus 353818534a1SmrgXkbRefreshKeyboardMapping(register XkbMapNotifyEvent * event) 3541ab64890Smrg{ 3551ab64890Smrg Display *dpy = event->display; 3561ab64890Smrg XkbInfoPtr xkbi; 3571ab64890Smrg 3581ab64890Smrg if (_XkbUnavailable(dpy)) { 359818534a1Smrg _XRefreshKeyboardMapping((XMappingEvent *) event); 360818534a1Smrg return Success; 3611ab64890Smrg } 362818534a1Smrg xkbi = dpy->xkb_info; 3631ab64890Smrg 364818534a1Smrg if (((event->type & 0x7f) - xkbi->codes->first_event) != XkbEventCode) 365818534a1Smrg return BadMatch; 366818534a1Smrg if (event->xkb_type == XkbNewKeyboardNotify) { 367818534a1Smrg _XkbReloadDpy(dpy); 368818534a1Smrg return Success; 3691ab64890Smrg } 370818534a1Smrg if (event->xkb_type == XkbMapNotify) { 371818534a1Smrg XkbMapChangesRec changes; 372818534a1Smrg Status rtrn; 373818534a1Smrg 374818534a1Smrg if (xkbi->flags & XkbMapPending) 375818534a1Smrg changes = xkbi->changes; 376818534a1Smrg else 377818534a1Smrg bzero(&changes, sizeof(changes)); 378818534a1Smrg XkbNoteMapChanges(&changes, event, XKB_XLIB_MAP_MASK); 379818534a1Smrg if ((rtrn = XkbGetMapChanges(dpy, xkbi->desc, &changes)) != Success) { 3801ab64890Smrg#ifdef DEBUG 381818534a1Smrg fprintf(stderr, "Internal Error! XkbGetMapChanges failed:\n"); 3821ab64890Smrg#endif 383818534a1Smrg xkbi->changes = changes; 384818534a1Smrg } 385818534a1Smrg else if (xkbi->flags & XkbMapPending) { 386818534a1Smrg xkbi->flags &= ~XkbMapPending; 387818534a1Smrg bzero(&xkbi->changes, sizeof(XkbMapChangesRec)); 388818534a1Smrg } 389818534a1Smrg return rtrn; 3901ab64890Smrg } 3911ab64890Smrg return BadMatch; 3921ab64890Smrg} 3931ab64890Smrg 3941ab64890Smrgint 395818534a1SmrgXRefreshKeyboardMapping(register XMappingEvent * event) 3961ab64890Smrg{ 397818534a1Smrg XkbEvent *xkbevent = (XkbEvent *) event; 3981ab64890Smrg Display *dpy = event->display; 3991ab64890Smrg XkbMapChangesRec changes; 4001ab64890Smrg XkbInfoPtr xkbi; 4011ab64890Smrg 4021ab64890Smrg /* always do this for input methods, which still use the old keymap */ 4031ab64890Smrg (void) _XRefreshKeyboardMapping(event); 4041ab64890Smrg 4051ab64890Smrg if (_XkbUnavailable(dpy)) 406818534a1Smrg return 1; 4071ab64890Smrg 4081ab64890Smrg xkbi = dpy->xkb_info; 4091ab64890Smrg 410818534a1Smrg if (((event->type & 0x7f) - xkbi->codes->first_event) == XkbEventCode) 411818534a1Smrg return XkbRefreshKeyboardMapping(&xkbevent->map); 4121ab64890Smrg 413818534a1Smrg if (xkbi->flags & XkbXlibNewKeyboard) { 414818534a1Smrg _XkbReloadDpy(dpy); 415818534a1Smrg return 1; 4161ab64890Smrg } 4171ab64890Smrg 418818534a1Smrg if ((xkbi->flags & XkbMapPending) || (event->request == MappingKeyboard)) { 419818534a1Smrg if (xkbi->flags & XkbMapPending) { 420818534a1Smrg changes = xkbi->changes; 421818534a1Smrg _XkbNoteCoreMapChanges(&changes, event, XKB_XLIB_MAP_MASK); 422818534a1Smrg } 423818534a1Smrg else { 424818534a1Smrg bzero(&changes, sizeof(changes)); 425818534a1Smrg changes.changed = XkbKeySymsMask; 426818534a1Smrg if (xkbi->desc->min_key_code < xkbi->desc->max_key_code) { 427818534a1Smrg changes.first_key_sym = xkbi->desc->min_key_code; 428818534a1Smrg changes.num_key_syms = xkbi->desc->max_key_code - 429818534a1Smrg xkbi->desc->min_key_code + 1; 430818534a1Smrg } 431818534a1Smrg else { 432818534a1Smrg changes.first_key_sym = event->first_keycode; 433818534a1Smrg changes.num_key_syms = event->count; 434818534a1Smrg } 435818534a1Smrg } 436818534a1Smrg 437818534a1Smrg if (XkbGetMapChanges(dpy, xkbi->desc, &changes) != Success) { 4381ab64890Smrg#ifdef DEBUG 439818534a1Smrg fprintf(stderr, "Internal Error! XkbGetMapChanges failed:\n"); 440818534a1Smrg if (changes.changed & XkbKeyTypesMask) { 441818534a1Smrg int first = changes.first_type; 442818534a1Smrg int last = changes.first_type + changes.num_types - 1; 443818534a1Smrg 444818534a1Smrg fprintf(stderr, " types: %d..%d\n", first, last); 445818534a1Smrg } 446818534a1Smrg if (changes.changed & XkbKeySymsMask) { 447818534a1Smrg int first = changes.first_key_sym; 448818534a1Smrg int last = changes.first_key_sym + changes.num_key_syms - 1; 449818534a1Smrg 450818534a1Smrg fprintf(stderr, " symbols: %d..%d\n", first, last); 451818534a1Smrg } 452818534a1Smrg if (changes.changed & XkbKeyActionsMask) { 453818534a1Smrg int first = changes.first_key_act; 454818534a1Smrg int last = changes.first_key_act + changes.num_key_acts - 1; 455818534a1Smrg 456818534a1Smrg fprintf(stderr, " acts: %d..%d\n", first, last); 457818534a1Smrg } 458818534a1Smrg if (changes.changed & XkbKeyBehaviorsMask) { 459818534a1Smrg int first = changes.first_key_behavior; 460818534a1Smrg int last = first + changes.num_key_behaviors - 1; 461818534a1Smrg 462818534a1Smrg fprintf(stderr, " behaviors: %d..%d\n", first, last); 463818534a1Smrg } 464818534a1Smrg if (changes.changed & XkbVirtualModsMask) { 465818534a1Smrg fprintf(stderr, "virtual mods: 0x%04x\n", changes.vmods); 466818534a1Smrg } 467818534a1Smrg if (changes.changed & XkbExplicitComponentsMask) { 468818534a1Smrg int first = changes.first_key_explicit; 469818534a1Smrg int last = first + changes.num_key_explicit - 1; 470818534a1Smrg 471818534a1Smrg fprintf(stderr, " explicit: %d..%d\n", first, last); 472818534a1Smrg } 4731ab64890Smrg#endif 474818534a1Smrg } 475818534a1Smrg LockDisplay(dpy); 476818534a1Smrg if (xkbi->flags & XkbMapPending) { 477818534a1Smrg xkbi->flags &= ~XkbMapPending; 478818534a1Smrg bzero(&xkbi->changes, sizeof(XkbMapChangesRec)); 479818534a1Smrg } 480818534a1Smrg UnlockDisplay(dpy); 4811ab64890Smrg } 482818534a1Smrg if (event->request == MappingModifier) { 483818534a1Smrg LockDisplay(dpy); 484818534a1Smrg if (xkbi->desc->map->modmap) { 485818534a1Smrg _XkbFree(xkbi->desc->map->modmap); 486818534a1Smrg xkbi->desc->map->modmap = NULL; 487818534a1Smrg } 488818534a1Smrg if (dpy->key_bindings) { 489818534a1Smrg register struct _XKeytrans *p; 490818534a1Smrg 491818534a1Smrg for (p = dpy->key_bindings; p; p = p->next) { 492818534a1Smrg register int i; 493818534a1Smrg 494818534a1Smrg p->state = 0; 495818534a1Smrg if (p->mlen > 0) { 496818534a1Smrg for (i = 0; i < p->mlen; i++) { 497818534a1Smrg p->state |= XkbKeysymToModifiers(dpy, p->modifiers[i]); 498818534a1Smrg } 499818534a1Smrg if (p->state) 500818534a1Smrg p->state &= AllMods; 501818534a1Smrg else 502818534a1Smrg p->state = AnyModifier; 503818534a1Smrg } 504818534a1Smrg } 505818534a1Smrg } 506818534a1Smrg UnlockDisplay(dpy); 5071ab64890Smrg } 5081ab64890Smrg return 1; 5091ab64890Smrg} 5101ab64890Smrg 5111ab64890Smrgstatic int 5121ab64890Smrg_XkbLoadDpy(Display *dpy) 5131ab64890Smrg{ 5141ab64890Smrg XkbInfoPtr xkbi; 515818534a1Smrg unsigned query, oldEvents; 5161ab64890Smrg XkbDescRec *desc; 5171ab64890Smrg 518818534a1Smrg if (!XkbUseExtension(dpy, NULL, NULL)) 519818534a1Smrg return 0; 5201ab64890Smrg 5211ab64890Smrg xkbi = dpy->xkb_info; 5221ab64890Smrg query = XkbAllClientInfoMask; 523818534a1Smrg desc = XkbGetMap(dpy, query, XkbUseCoreKbd); 5241ab64890Smrg if (!desc) { 5251ab64890Smrg#ifdef DEBUG 526818534a1Smrg fprintf(stderr, "Warning! XkbGetMap failed!\n"); 5271ab64890Smrg#endif 528818534a1Smrg return 0; 5291ab64890Smrg } 5301ab64890Smrg LockDisplay(dpy); 5311ab64890Smrg xkbi->desc = desc; 5321ab64890Smrg 5331ab64890Smrg UnlockDisplay(dpy); 534818534a1Smrg oldEvents = xkbi->selected_events; 535818534a1Smrg if (!(xkbi->xlib_ctrls & XkbLC_IgnoreNewKeyboards)) { 536818534a1Smrg XkbSelectEventDetails(dpy, xkbi->desc->device_spec, 537818534a1Smrg XkbNewKeyboardNotify, 538818534a1Smrg XkbNKN_KeycodesMask | XkbNKN_DeviceIDMask, 539818534a1Smrg XkbNKN_KeycodesMask | XkbNKN_DeviceIDMask); 5401ab64890Smrg } 541818534a1Smrg XkbSelectEventDetails(dpy, xkbi->desc->device_spec, XkbMapNotify, 542818534a1Smrg XkbAllClientInfoMask, XkbAllClientInfoMask); 5431ab64890Smrg LockDisplay(dpy); 544818534a1Smrg xkbi->selected_events = oldEvents; 5451ab64890Smrg UnlockDisplay(dpy); 5461ab64890Smrg return 1; 5471ab64890Smrg} 5481ab64890Smrg 5491ab64890Smrgvoid 5501ab64890Smrg_XkbReloadDpy(Display *dpy) 5511ab64890Smrg{ 5521ab64890Smrg XkbInfoPtr xkbi; 5531ab64890Smrg XkbDescRec *desc; 554818534a1Smrg unsigned oldDeviceID; 5551ab64890Smrg 5561ab64890Smrg if (_XkbUnavailable(dpy)) 557818534a1Smrg return; 5581ab64890Smrg 5591ab64890Smrg xkbi = dpy->xkb_info; 5601ab64890Smrg LockDisplay(dpy); 5611ab64890Smrg if (xkbi->desc) { 562818534a1Smrg oldDeviceID = xkbi->desc->device_spec; 563818534a1Smrg XkbFreeKeyboard(xkbi->desc, XkbAllComponentsMask, True); 564818534a1Smrg xkbi->desc = NULL; 565818534a1Smrg xkbi->flags &= ~(XkbMapPending | XkbXlibNewKeyboard); 566818534a1Smrg xkbi->changes.changed = 0; 5671ab64890Smrg } 568818534a1Smrg else 569818534a1Smrg oldDeviceID = XkbUseCoreKbd; 5701ab64890Smrg UnlockDisplay(dpy); 571818534a1Smrg desc = XkbGetMap(dpy, XkbAllClientInfoMask, XkbUseCoreKbd); 5721ab64890Smrg if (!desc) 573818534a1Smrg return; 5741ab64890Smrg LockDisplay(dpy); 5751ab64890Smrg xkbi->desc = desc; 5761ab64890Smrg UnlockDisplay(dpy); 5771ab64890Smrg 578818534a1Smrg if (desc->device_spec != oldDeviceID) { 579818534a1Smrg /* transfer(?) event masks here */ 5801ab64890Smrg#ifdef NOTYET 581818534a1Smrg unsigned oldEvents; 582818534a1Smrg 583818534a1Smrg oldEvents = xkbi->selected_events; 584818534a1Smrg XkbSelectEventDetails(dpy, xkbi->desc->device_spec, XkbMapNotify, 585818534a1Smrg XkbAllMapComponentsMask, XkbAllClientInfoMask); 586818534a1Smrg LockDisplay(dpy); 587818534a1Smrg xkbi->selected_events = oldEvents; 588818534a1Smrg UnlockDisplay(dpy); 5891ab64890Smrg#endif 5901ab64890Smrg } 5911ab64890Smrg return; 5921ab64890Smrg} 5931ab64890Smrg 5941ab64890Smrgint 595818534a1SmrgXkbTranslateKeySym(register Display *dpy, 596818534a1Smrg register KeySym *sym_rtrn, 597818534a1Smrg unsigned int mods, 598818534a1Smrg char *buffer, 599818534a1Smrg int nbytes, 600818534a1Smrg int *extra_rtrn) 6011ab64890Smrg{ 602818534a1Smrg register XkbInfoPtr xkb; 6031ab64890Smrg XkbKSToMBFunc cvtr; 6041ab64890Smrg XPointer priv; 6051ab64890Smrg char tmp[4]; 6061ab64890Smrg int n; 6071ab64890Smrg 608818534a1Smrg xkb = dpy->xkb_info; 6091ab64890Smrg if (!xkb->cvt.KSToMB) { 610818534a1Smrg _XkbGetConverters(_XkbGetCharset(), &xkb->cvt); 611818534a1Smrg _XkbGetConverters("ISO8859-1", &xkb->latin1cvt); 6121ab64890Smrg } 6131ab64890Smrg 6141ab64890Smrg if (extra_rtrn) 615818534a1Smrg *extra_rtrn = 0; 6161ab64890Smrg 617818534a1Smrg if ((buffer == NULL) || (nbytes == 0)) { 618818534a1Smrg buffer = tmp; 619818534a1Smrg nbytes = 4; 6201ab64890Smrg } 6211ab64890Smrg 6221ab64890Smrg /* see if symbol rebound, if so, return that string. */ 623818534a1Smrg n = XkbLookupKeyBinding(dpy, *sym_rtrn, mods, buffer, nbytes, extra_rtrn); 6241ab64890Smrg if (n) 6251ab64890Smrg return n; 6261ab64890Smrg 627818534a1Smrg if (nbytes > 0) 628818534a1Smrg buffer[0] = '\0'; 6291ab64890Smrg 630818534a1Smrg if (xkb->cvt.KSToUpper && (mods & LockMask)) { 631818534a1Smrg *sym_rtrn = (*xkb->cvt.KSToUpper) (*sym_rtrn); 6321ab64890Smrg } 6331ab64890Smrg if (xkb->xlib_ctrls & XkbLC_ForceLatin1Lookup) { 634818534a1Smrg cvtr = xkb->latin1cvt.KSToMB; 635818534a1Smrg priv = xkb->latin1cvt.KSToMBPriv; 636818534a1Smrg } 637818534a1Smrg else { 638818534a1Smrg cvtr = xkb->cvt.KSToMB; 639818534a1Smrg priv = xkb->cvt.KSToMBPriv; 6401ab64890Smrg } 6411ab64890Smrg 642818534a1Smrg n = (*cvtr) (priv, *sym_rtrn, buffer, nbytes, extra_rtrn); 643818534a1Smrg 644818534a1Smrg if ((!xkb->cvt.KSToUpper) && (mods & LockMask)) { 645818534a1Smrg register int i; 646818534a1Smrg int change; 647818534a1Smrg 648818534a1Smrg for (i = change = 0; i < n; i++) { 649818534a1Smrg char ch = toupper(buffer[i]); 650818534a1Smrg change = (change || (buffer[i] != ch)); 651818534a1Smrg buffer[i] = ch; 652818534a1Smrg } 653818534a1Smrg if (change) { 654818534a1Smrg if (n == 1) 655818534a1Smrg *sym_rtrn = 656818534a1Smrg (*xkb->cvt.MBToKS) (xkb->cvt.MBToKSPriv, buffer, n, NULL); 657818534a1Smrg else 658818534a1Smrg *sym_rtrn = NoSymbol; 659818534a1Smrg } 6601ab64890Smrg } 6611ab64890Smrg 662818534a1Smrg if (mods & ControlMask) { 663818534a1Smrg if (n == 1) { 664818534a1Smrg buffer[0] = XkbToControl(buffer[0]); 665818534a1Smrg if (nbytes > 1) 666818534a1Smrg buffer[1] = '\0'; 667818534a1Smrg return 1; 668818534a1Smrg } 669818534a1Smrg if (nbytes > 0) 670818534a1Smrg buffer[0] = '\0'; 671818534a1Smrg return 0; 6721ab64890Smrg } 6731ab64890Smrg return n; 6741ab64890Smrg} 6751ab64890Smrg 6761ab64890Smrgint 677818534a1SmrgXLookupString(register XKeyEvent *event, 678818534a1Smrg char *buffer, 679818534a1Smrg int nbytes, 680818534a1Smrg KeySym *keysym, 681818534a1Smrg XComposeStatus *status) 6821ab64890Smrg{ 683818534a1Smrg KeySym dummy; 6841ab64890Smrg int rtrnLen; 6851ab64890Smrg unsigned int new_mods; 6861ab64890Smrg Display *dpy = event->display; 6871ab64890Smrg 688818534a1Smrg if (keysym == NULL) 689818534a1Smrg keysym = &dummy; 690818534a1Smrg if (!XkbLookupKeySym(dpy, event->keycode, event->state, &new_mods, keysym)) 691818534a1Smrg return 0; 692818534a1Smrg new_mods = (event->state & (~new_mods)); 6931ab64890Smrg 6941ab64890Smrg /* find the group where a symbol can be converted to control one */ 695818534a1Smrg if (new_mods & ControlMask && *keysym > 0x7F && 696818534a1Smrg (dpy->xkb_info->xlib_ctrls & XkbLC_ControlFallback)) { 697818534a1Smrg XKeyEvent tmp_ev = *event; 698818534a1Smrg KeySym tmp_keysym; 699818534a1Smrg unsigned int tmp_new_mods; 700818534a1Smrg 701818534a1Smrg if (_XkbUnavailable(dpy)) { 702818534a1Smrg tmp_ev.state = event->state ^ dpy->mode_switch; 7031ab64890Smrg if (XkbLookupKeySym(dpy, tmp_ev.keycode, tmp_ev.state, 7041ab64890Smrg &tmp_new_mods, &tmp_keysym) && 705818534a1Smrg tmp_keysym != NoSymbol && tmp_keysym < 0x80) { 7061ab64890Smrg *keysym = tmp_keysym; 7071ab64890Smrg } 708818534a1Smrg } 709818534a1Smrg else { 7101ab64890Smrg int n = XkbKeyNumGroups(dpy->xkb_info->desc, tmp_ev.keycode); 7111ab64890Smrg int i; 712818534a1Smrg 7131ab64890Smrg for (i = 0; i < n; i++) { 7141ab64890Smrg if (XkbGroupForCoreState(event->state) == i) 7151ab64890Smrg continue; 716818534a1Smrg tmp_ev.state = XkbBuildCoreState(tmp_ev.state, i); 7171ab64890Smrg if (XkbLookupKeySym(dpy, tmp_ev.keycode, tmp_ev.state, 718818534a1Smrg &tmp_new_mods, &tmp_keysym) && 719818534a1Smrg tmp_keysym != NoSymbol && tmp_keysym < 0x80) { 7201ab64890Smrg *keysym = tmp_keysym; 721818534a1Smrg new_mods = (event->state & (~tmp_new_mods)); 7221ab64890Smrg break; 7231ab64890Smrg } 7241ab64890Smrg } 7251ab64890Smrg } 72661b2299dSmrg } 7271ab64890Smrg 7281ab64890Smrg#ifdef USE_OWN_COMPOSE 729818534a1Smrg if (status) { 730818534a1Smrg static int been_here = 0; 731818534a1Smrg 732818534a1Smrg if (!been_here) { 733818534a1Smrg XimCompInitTables(); 734818534a1Smrg been_here = 1; 735818534a1Smrg } 736818534a1Smrg if (!XimCompLegalStatus(status)) { 737818534a1Smrg status->compose_ptr = NULL; 738818534a1Smrg status->chars_matched = 0; 739818534a1Smrg } 740818534a1Smrg if (((status->chars_matched > 0) && (status->compose_ptr != NULL)) || 741818534a1Smrg XimCompIsComposeKey(*keysym, event->keycode, status)) { 742818534a1Smrg XimCompRtrn rtrn; 743818534a1Smrg 744818534a1Smrg switch (XimCompProcessSym(status, *keysym, &rtrn)) { 745818534a1Smrg case XIM_COMP_IGNORE: 746818534a1Smrg break; 747818534a1Smrg case XIM_COMP_IN_PROGRESS: 748818534a1Smrg if (keysym != NULL) 749818534a1Smrg *keysym = NoSymbol; 7501ab64890Smrg#ifndef NO_COMPOSE_LED 751818534a1Smrg if (dpy->xkb_info->xlib_ctrls & XkbLC_ComposeLED) { 752818534a1Smrg XkbSetNamedIndicator(dpy, dpy->xkb_info->composeLED, 753818534a1Smrg True, True, False, NULL); 754818534a1Smrg } 7551ab64890Smrg#endif 756818534a1Smrg return 0; 757818534a1Smrg case XIM_COMP_FAIL: 758818534a1Smrg { 759818534a1Smrg static Atom _ComposeFail = None; 760818534a1Smrg int n = 0, len = 0; 761818534a1Smrg 7621ab64890Smrg#ifndef NO_COMPOSE_LED 763818534a1Smrg if (dpy->xkb_info->xlib_ctrls & XkbLC_ComposeLED) { 764818534a1Smrg XkbSetNamedIndicator(dpy, dpy->xkb_info->composeLED, 765818534a1Smrg True, False, False, NULL); 766818534a1Smrg } 7671ab64890Smrg#endif 7681ab64890Smrg#ifndef NO_BELL_ON_COMPOSE_FAIL 769818534a1Smrg if (dpy->xkb_info->xlib_ctrls & XkbLC_BeepOnComposeFail) { 770818534a1Smrg if (_ComposeFail == None) 771818534a1Smrg _ComposeFail = XInternAtom(dpy, "ComposeFail", 0); 772818534a1Smrg XkbBell(dpy, event->window, 0, _ComposeFail); 773818534a1Smrg } 7741ab64890Smrg#endif 775818534a1Smrg for (n = len = 0; rtrn.sym[n] != XK_VoidSymbol; n++) { 776818534a1Smrg if (nbytes - len > 0) { 777818534a1Smrg len += XkbTranslateKeySym(dpy, &rtrn.sym[n], new_mods, 778818534a1Smrg buffer + len, nbytes - len, 779818534a1Smrg NULL); 780818534a1Smrg } 781818534a1Smrg } 782818534a1Smrg if (keysym != NULL) { 783818534a1Smrg if (n == 1) 784818534a1Smrg *keysym = rtrn.sym[0]; 785818534a1Smrg else 786818534a1Smrg *keysym = NoSymbol; 787818534a1Smrg } 788818534a1Smrg return len; 789818534a1Smrg } 790818534a1Smrg case XIM_COMP_SUCCEED: 791818534a1Smrg { 792818534a1Smrg int len, n = 0; 7931ab64890Smrg 7941ab64890Smrg#ifndef NO_COMPOSE_LED 795818534a1Smrg if (dpy->xkb_info->xlib_ctrls & XkbLC_ComposeLED) { 796818534a1Smrg XkbSetNamedIndicator(dpy, dpy->xkb_info->composeLED, 797818534a1Smrg True, False, False, NULL); 798818534a1Smrg } 7991ab64890Smrg#endif 800818534a1Smrg *keysym = rtrn.matchSym; 801818534a1Smrg if (rtrn.str[0] != '\0') { 802818534a1Smrg strncpy(buffer, rtrn.str, nbytes - 1); 803818534a1Smrg buffer[nbytes - 1] = '\0'; 804818534a1Smrg len = (int) strlen(buffer); 805818534a1Smrg } 806818534a1Smrg else { 807818534a1Smrg len = XkbTranslateKeySym(dpy, keysym, new_mods, 808818534a1Smrg buffer, nbytes, NULL); 809818534a1Smrg } 810818534a1Smrg for (n = 0; rtrn.sym[n] != XK_VoidSymbol; n++) { 811818534a1Smrg if (nbytes - len > 0) { 812818534a1Smrg len += XkbTranslateKeySym(dpy, &rtrn.sym[n], 813818534a1Smrg event->state, 814818534a1Smrg buffer + len, nbytes - len, 815818534a1Smrg NULL); 816818534a1Smrg } 817818534a1Smrg } 818818534a1Smrg return len; 819818534a1Smrg } 820818534a1Smrg } 821818534a1Smrg } 8221ab64890Smrg } 8231ab64890Smrg#endif 8241ab64890Smrg 8251ab64890Smrg /* We *should* use the new_mods (which does not contain any modifiers */ 8261ab64890Smrg /* that were used to compute the symbol here, but pre-XKB XLookupString */ 8271ab64890Smrg /* did not and we have to remain compatible. Sigh. */ 8281ab64890Smrg if (_XkbUnavailable(dpy) || 829818534a1Smrg (dpy->xkb_info->xlib_ctrls & XkbLC_ConsumeLookupMods) == 0) 830818534a1Smrg new_mods = event->state; 8311ab64890Smrg 832818534a1Smrg rtrnLen = XkbLookupKeyBinding(dpy, *keysym, new_mods, buffer, nbytes, NULL); 833818534a1Smrg if (rtrnLen > 0) 834818534a1Smrg return rtrnLen; 8351ab64890Smrg 836818534a1Smrg return XkbTranslateKeySym(dpy, keysym, new_mods, buffer, nbytes, NULL); 8371ab64890Smrg} 8381ab64890Smrg 8391ab64890Smrg 8401ab64890Smrgint 841818534a1SmrgXkbLookupKeyBinding(Display *dpy, 842818534a1Smrg register KeySym sym, 843818534a1Smrg unsigned int mods, 844818534a1Smrg char *buffer, 845818534a1Smrg int nbytes, 846818534a1Smrg int *extra_rtrn) 8471ab64890Smrg{ 84861b2299dSmrg register struct _XKeytrans *p; 8491ab64890Smrg 8501ab64890Smrg if (extra_rtrn) 851818534a1Smrg *extra_rtrn = 0; 8521ab64890Smrg for (p = dpy->key_bindings; p; p = p->next) { 853818534a1Smrg if (((mods & AllMods) == p->state) && (sym == p->key)) { 854818534a1Smrg int tmp = p->len; 855818534a1Smrg 856818534a1Smrg if (tmp > nbytes) { 857818534a1Smrg if (extra_rtrn) 858818534a1Smrg *extra_rtrn = (tmp - nbytes); 859818534a1Smrg tmp = nbytes; 860818534a1Smrg } 861818534a1Smrg memcpy(buffer, p->string, tmp); 862818534a1Smrg if (tmp < nbytes) 863818534a1Smrg buffer[tmp] = '\0'; 864818534a1Smrg return tmp; 865818534a1Smrg } 8661ab64890Smrg } 8671ab64890Smrg return 0; 8681ab64890Smrg} 8691ab64890Smrg 8701ab64890Smrgchar 871818534a1SmrgXkbToControl(char ch) 8721ab64890Smrg{ 8731ab64890Smrg register char c = ch; 87461b2299dSmrg 875818534a1Smrg if ((c >= '@' && c < '\177') || c == ' ') 876818534a1Smrg c &= 0x1F; 877818534a1Smrg else if (c == '2') 878818534a1Smrg c = '\000'; 879818534a1Smrg else if (c >= '3' && c <= '7') 880818534a1Smrg c -= ('3' - '\033'); 881818534a1Smrg else if (c == '8') 882818534a1Smrg c = '\177'; 883818534a1Smrg else if (c == '/') 884818534a1Smrg c = '_' & 0x1F; 8851ab64890Smrg return c; 8861ab64890Smrg} 887