XKBBind.c revision 1ab64890
11ab64890Smrg/* $Xorg: XKBBind.c,v 1.4 2001/02/09 02:03:37 xorgcvs Exp $ */ 21ab64890Smrg/* 31ab64890Smrg 41ab64890SmrgCopyright 1985, 1987, 1994, 1998 The Open Group 51ab64890Smrg 61ab64890SmrgPermission to use, copy, modify, distribute, and sell this software and its 71ab64890Smrgdocumentation for any purpose is hereby granted without fee, provided that 81ab64890Smrgthe above copyright notice appear in all copies and that both that 91ab64890Smrgcopyright notice and this permission notice appear in supporting 101ab64890Smrgdocumentation. 111ab64890Smrg 121ab64890SmrgThe above copyright notice and this permission notice shall be included 131ab64890Smrgin all copies or substantial portions of the Software. 141ab64890Smrg 151ab64890SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 161ab64890SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 171ab64890SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 181ab64890SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 191ab64890SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 201ab64890SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 211ab64890SmrgOTHER DEALINGS IN THE SOFTWARE. 221ab64890Smrg 231ab64890SmrgExcept as contained in this notice, the name of The Open Group shall 241ab64890Smrgnot be used in advertising or otherwise to promote the sale, use or 251ab64890Smrgother dealings in this Software without prior written authorization 261ab64890Smrgfrom The Open Group. 271ab64890Smrg 281ab64890Smrg*/ 291ab64890Smrg/* $XFree86: xc/lib/X11/XKBBind.c,v 3.19 2003/05/27 22:26:25 tsi Exp $ */ 301ab64890Smrg 311ab64890Smrg /* the new monsters ate the old ones */ 321ab64890Smrg 331ab64890Smrg#define NEED_EVENTS 341ab64890Smrg#ifdef HAVE_CONFIG_H 351ab64890Smrg#include <config.h> 361ab64890Smrg#endif 371ab64890Smrg#include "XKBlib.h" 381ab64890Smrg#include <X11/Xlibint.h> 391ab64890Smrg#include <X11/Xutil.h> 401ab64890Smrg#include <X11/keysym.h> 411ab64890Smrg#include <stdio.h> 421ab64890Smrg#include <ctype.h> 431ab64890Smrg 441ab64890Smrg#include <X11/extensions/XKBproto.h> 451ab64890Smrg#include "XKBlibint.h" 461ab64890Smrg 471ab64890Smrg#ifdef USE_OWN_COMPOSE 481ab64890Smrg#define COMPOSE_NO_CONST_MEMBERS 491ab64890Smrg#include "imComp.h" 501ab64890Smrg#endif 511ab64890Smrg 521ab64890Smrg#define AllMods (ShiftMask|LockMask|ControlMask| \ 531ab64890Smrg Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask) 541ab64890Smrg 551ab64890Smrgstatic int _XkbLoadDpy( 561ab64890Smrg Display *dpy 571ab64890Smrg); 581ab64890Smrg 591ab64890Smrgstruct _XKeytrans { 601ab64890Smrg struct _XKeytrans *next;/* next on list */ 611ab64890Smrg char *string; /* string to return when the time comes */ 621ab64890Smrg int len; /* length of string (since NULL is legit)*/ 631ab64890Smrg KeySym key; /* keysym rebound */ 641ab64890Smrg unsigned int state; /* modifier state */ 651ab64890Smrg KeySym *modifiers; /* modifier keysyms you want */ 661ab64890Smrg int mlen; /* length of modifier list */ 671ab64890Smrg}; 681ab64890Smrg 691ab64890SmrgKeySym 701ab64890SmrgXkbKeycodeToKeysym(Display *dpy, 711ab64890Smrg#if NeedWidePrototypes 721ab64890Smrg unsigned int kc, 731ab64890Smrg#else 741ab64890Smrg KeyCode kc, 751ab64890Smrg#endif 761ab64890Smrg int group, 771ab64890Smrg int level) 781ab64890Smrg{ 791ab64890Smrg XkbDescRec *xkb; 801ab64890Smrg 811ab64890Smrg if (_XkbUnavailable(dpy)) 821ab64890Smrg return NoSymbol; 831ab64890Smrg 841ab64890Smrg _XkbCheckPendingRefresh(dpy,dpy->xkb_info); 851ab64890Smrg 861ab64890Smrg xkb = dpy->xkb_info->desc; 871ab64890Smrg if ((kc<xkb->min_key_code)||(kc>xkb->max_key_code)) 881ab64890Smrg return NoSymbol; 891ab64890Smrg 901ab64890Smrg if ((group<0)||(level<0)||(group>=XkbKeyNumGroups(xkb,kc))) 911ab64890Smrg return NoSymbol; 921ab64890Smrg if (level>=XkbKeyGroupWidth(xkb,kc,group)) { 931ab64890Smrg /* for compatibility with the core protocol, _always_ allow */ 941ab64890Smrg /* two symbols in the first two groups. If either of the */ 951ab64890Smrg /* two is of type ONE_LEVEL, just replicate the first symbol */ 961ab64890Smrg if ((group>XkbGroup2Index)||(XkbKeyGroupWidth(xkb,kc,group)!=1)|| 971ab64890Smrg (level!=1)) { 981ab64890Smrg return NoSymbol; 991ab64890Smrg } 1001ab64890Smrg level= 0; 1011ab64890Smrg } 1021ab64890Smrg return XkbKeySymEntry(xkb,kc,level,group); 1031ab64890Smrg} 1041ab64890Smrg 1051ab64890SmrgKeySym 1061ab64890SmrgXKeycodeToKeysym(Display *dpy, 1071ab64890Smrg#if NeedWidePrototypes 1081ab64890Smrg unsigned int kc, 1091ab64890Smrg#else 1101ab64890Smrg KeyCode kc, 1111ab64890Smrg#endif 1121ab64890Smrg int col) 1131ab64890Smrg{ 1141ab64890Smrg XkbDescRec *xkb; 1151ab64890Smrg 1161ab64890Smrg if (_XkbUnavailable(dpy)) 1171ab64890Smrg return _XKeycodeToKeysym(dpy, kc, col); 1181ab64890Smrg 1191ab64890Smrg _XkbCheckPendingRefresh(dpy,dpy->xkb_info); 1201ab64890Smrg 1211ab64890Smrg xkb = dpy->xkb_info->desc; 1221ab64890Smrg if ((kc<xkb->min_key_code)||(kc>xkb->max_key_code)) 1231ab64890Smrg return NoSymbol; 1241ab64890Smrg 1251ab64890Smrg if (col>3) { 1261ab64890Smrg int lastSym,tmp,nGrp; 1271ab64890Smrg 1281ab64890Smrg lastSym= 3; 1291ab64890Smrg nGrp= XkbKeyNumGroups(xkb,kc); 1301ab64890Smrg if ((nGrp>0)&&((tmp=XkbKeyGroupWidth(xkb,kc,XkbGroup1Index))>2)) { 1311ab64890Smrg if (col<=(lastSym+tmp-2)) 1321ab64890Smrg return XkbKeycodeToKeysym(dpy,kc,XkbGroup1Index,col-lastSym+2); 1331ab64890Smrg lastSym+= tmp-2; 1341ab64890Smrg } 1351ab64890Smrg if ((nGrp>1)&&((tmp=XkbKeyGroupWidth(xkb,kc,XkbGroup2Index))>2)) { 1361ab64890Smrg if (col<=(lastSym+tmp-2)) 1371ab64890Smrg return XkbKeycodeToKeysym(dpy,kc,XkbGroup2Index,col-lastSym+2); 1381ab64890Smrg lastSym+= tmp-2; 1391ab64890Smrg } 1401ab64890Smrg if (nGrp>2) { 1411ab64890Smrg tmp= XkbKeyGroupWidth(xkb,kc,XkbGroup3Index); 1421ab64890Smrg if (col<=lastSym+tmp) 1431ab64890Smrg return XkbKeycodeToKeysym(dpy,kc,XkbGroup3Index,col-lastSym); 1441ab64890Smrg lastSym+= tmp; 1451ab64890Smrg } 1461ab64890Smrg if (nGrp>3) { 1471ab64890Smrg tmp= XkbKeyGroupWidth(xkb,kc,XkbGroup4Index); 1481ab64890Smrg if (col<=lastSym+tmp) 1491ab64890Smrg return XkbKeycodeToKeysym(dpy,kc,XkbGroup4Index,col-lastSym); 1501ab64890Smrg } 1511ab64890Smrg return NoSymbol; 1521ab64890Smrg } 1531ab64890Smrg return XkbKeycodeToKeysym(dpy,kc,(col>>1),(col&1)); 1541ab64890Smrg} 1551ab64890Smrg 1561ab64890SmrgKeyCode 1571ab64890SmrgXKeysymToKeycode(Display *dpy, KeySym ks) 1581ab64890Smrg{ 1591ab64890Smrg register int i, j, gotOne; 1601ab64890Smrg 1611ab64890Smrg if (_XkbUnavailable(dpy)) 1621ab64890Smrg return _XKeysymToKeycode(dpy,ks); 1631ab64890Smrg _XkbCheckPendingRefresh(dpy,dpy->xkb_info); 1641ab64890Smrg 1651ab64890Smrg j= 0; 1661ab64890Smrg do { 1671ab64890Smrg register XkbDescRec *xkb = dpy->xkb_info->desc; 1681ab64890Smrg gotOne= 0; 1691ab64890Smrg for (i = dpy->min_keycode; i <= dpy->max_keycode; i++) { 1701ab64890Smrg if ( j<(int)XkbKeyNumSyms(xkb,i) ) { 1711ab64890Smrg gotOne = 1; 1721ab64890Smrg if ((XkbKeySym(xkb,i,j)==ks)) 1731ab64890Smrg return i; 1741ab64890Smrg } 1751ab64890Smrg } 1761ab64890Smrg j++; 1771ab64890Smrg } while (gotOne); 1781ab64890Smrg return 0; 1791ab64890Smrg} 1801ab64890Smrg 1811ab64890Smrgstatic int 1821ab64890Smrg_XkbComputeModmap(Display *dpy) 1831ab64890Smrg{ 1841ab64890Smrgregister XkbDescPtr xkb; 1851ab64890Smrg 1861ab64890Smrg xkb= dpy->xkb_info->desc; 1871ab64890Smrg if (XkbGetUpdatedMap(dpy,XkbModifierMapMask,xkb)==Success) 1881ab64890Smrg return 1; 1891ab64890Smrg return 0; 1901ab64890Smrg} 1911ab64890Smrg 1921ab64890Smrgunsigned 1931ab64890SmrgXkbKeysymToModifiers(Display *dpy,KeySym ks) 1941ab64890Smrg{ 1951ab64890Smrg XkbDescRec *xkb; 1961ab64890Smrg register int i,j; 1971ab64890Smrg register KeySym *pSyms; 1981ab64890Smrg CARD8 mods; 1991ab64890Smrg 2001ab64890Smrg if (_XkbUnavailable(dpy)) 2011ab64890Smrg return _XKeysymToModifiers(dpy,ks); 2021ab64890Smrg _XkbCheckPendingRefresh(dpy,dpy->xkb_info); 2031ab64890Smrg 2041ab64890Smrg if (_XkbNeedModmap(dpy->xkb_info)&&(!_XkbComputeModmap(dpy))) 2051ab64890Smrg return _XKeysymToModifiers(dpy,ks); 2061ab64890Smrg 2071ab64890Smrg xkb= dpy->xkb_info->desc; 2081ab64890Smrg mods= 0; 2091ab64890Smrg for (i = xkb->min_key_code; i <= (int)xkb->max_key_code; i++) { 2101ab64890Smrg pSyms= XkbKeySymsPtr(xkb,i); 2111ab64890Smrg for (j=XkbKeyNumSyms(xkb,i)-1;j>=0;j--) { 2121ab64890Smrg if (pSyms[j]==ks) { 2131ab64890Smrg mods|= xkb->map->modmap[i]; 2141ab64890Smrg break; 2151ab64890Smrg } 2161ab64890Smrg } 2171ab64890Smrg } 2181ab64890Smrg return mods; 2191ab64890Smrg} 2201ab64890Smrg 2211ab64890SmrgKeySym 2221ab64890SmrgXLookupKeysym(register XKeyEvent *event, int col) 2231ab64890Smrg{ 2241ab64890Smrg Display *dpy = event->display; 2251ab64890Smrg if (_XkbUnavailable(dpy)) 2261ab64890Smrg return _XLookupKeysym(event, col); 2271ab64890Smrg _XkbCheckPendingRefresh(dpy,dpy->xkb_info); 2281ab64890Smrg return XKeycodeToKeysym(dpy, event->keycode, col); 2291ab64890Smrg} 2301ab64890Smrg 2311ab64890Smrg /* 2321ab64890Smrg * Not a public entry point -- XkbTranslateKey is an obsolete name 2331ab64890Smrg * that is preserved here so that functions linked against the old 2341ab64890Smrg * version will continue to work in a shared library environment. 2351ab64890Smrg */ 2361ab64890Smrgint 2371ab64890SmrgXkbTranslateKey( register Display * dpy, 2381ab64890Smrg KeyCode key, 2391ab64890Smrg register unsigned int mods, 2401ab64890Smrg unsigned int * mods_rtrn, 2411ab64890Smrg KeySym * keysym_rtrn); 2421ab64890Smrgint 2431ab64890SmrgXkbTranslateKey( register Display * dpy, 2441ab64890Smrg KeyCode key, 2451ab64890Smrg register unsigned int mods, 2461ab64890Smrg unsigned int * mods_rtrn, 2471ab64890Smrg KeySym * keysym_rtrn) 2481ab64890Smrg{ 2491ab64890Smrg return XkbLookupKeySym(dpy,key,mods,mods_rtrn,keysym_rtrn); 2501ab64890Smrg} 2511ab64890Smrg 2521ab64890SmrgBool 2531ab64890SmrgXkbLookupKeySym( register Display * dpy, 2541ab64890Smrg KeyCode key, 2551ab64890Smrg register unsigned int mods, 2561ab64890Smrg unsigned int * mods_rtrn, 2571ab64890Smrg KeySym * keysym_rtrn) 2581ab64890Smrg{ 2591ab64890Smrg if (_XkbUnavailable(dpy)) 2601ab64890Smrg return _XTranslateKey(dpy, key, mods, mods_rtrn, keysym_rtrn); 2611ab64890Smrg _XkbCheckPendingRefresh(dpy,dpy->xkb_info); 2621ab64890Smrg return XkbTranslateKeyCode(dpy->xkb_info->desc,key,mods,mods_rtrn, 2631ab64890Smrg keysym_rtrn); 2641ab64890Smrg} 2651ab64890Smrg 2661ab64890SmrgBool 2671ab64890SmrgXkbTranslateKeyCode( register XkbDescPtr xkb, 2681ab64890Smrg KeyCode key, 2691ab64890Smrg register unsigned int mods, 2701ab64890Smrg unsigned int * mods_rtrn, 2711ab64890Smrg KeySym * keysym_rtrn) 2721ab64890Smrg{ 2731ab64890Smrg XkbKeyTypeRec *type; 2741ab64890Smrg int col,nKeyGroups; 2751ab64890Smrg unsigned preserve,effectiveGroup; 2761ab64890Smrg KeySym *syms; 2771ab64890Smrg 2781ab64890Smrg if (mods_rtrn!=NULL) 2791ab64890Smrg *mods_rtrn = 0; 2801ab64890Smrg 2811ab64890Smrg nKeyGroups= XkbKeyNumGroups(xkb,key); 2821ab64890Smrg if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) { 2831ab64890Smrg if (keysym_rtrn!=NULL) 2841ab64890Smrg *keysym_rtrn = NoSymbol; 2851ab64890Smrg return False; 2861ab64890Smrg } 2871ab64890Smrg 2881ab64890Smrg syms = XkbKeySymsPtr(xkb,key); 2891ab64890Smrg 2901ab64890Smrg /* find the offset of the effective group */ 2911ab64890Smrg col = 0; 2921ab64890Smrg effectiveGroup= XkbGroupForCoreState(mods); 2931ab64890Smrg if ( effectiveGroup>=nKeyGroups ) { 2941ab64890Smrg unsigned groupInfo= XkbKeyGroupInfo(xkb,key); 2951ab64890Smrg switch (XkbOutOfRangeGroupAction(groupInfo)) { 2961ab64890Smrg default: 2971ab64890Smrg effectiveGroup %= nKeyGroups; 2981ab64890Smrg break; 2991ab64890Smrg case XkbClampIntoRange: 3001ab64890Smrg effectiveGroup = nKeyGroups-1; 3011ab64890Smrg break; 3021ab64890Smrg case XkbRedirectIntoRange: 3031ab64890Smrg effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo); 3041ab64890Smrg if (effectiveGroup>=nKeyGroups) 3051ab64890Smrg effectiveGroup= 0; 3061ab64890Smrg break; 3071ab64890Smrg } 3081ab64890Smrg } 3091ab64890Smrg col= effectiveGroup*XkbKeyGroupsWidth(xkb,key); 3101ab64890Smrg type = XkbKeyKeyType(xkb,key,effectiveGroup); 3111ab64890Smrg 3121ab64890Smrg preserve= 0; 3131ab64890Smrg if (type->map) { /* find the column (shift level) within the group */ 3141ab64890Smrg register int i; 3151ab64890Smrg register XkbKTMapEntryPtr entry; 3161ab64890Smrg for (i=0,entry=type->map;i<type->map_count;i++,entry++) { 3171ab64890Smrg if ((entry->active)&&((mods&type->mods.mask)==entry->mods.mask)) { 3181ab64890Smrg col+= entry->level; 3191ab64890Smrg if (type->preserve) 3201ab64890Smrg preserve= type->preserve[i].mask; 3211ab64890Smrg break; 3221ab64890Smrg } 3231ab64890Smrg } 3241ab64890Smrg } 3251ab64890Smrg 3261ab64890Smrg if (keysym_rtrn!=NULL) 3271ab64890Smrg *keysym_rtrn= syms[col]; 3281ab64890Smrg if (mods_rtrn) { 3291ab64890Smrg *mods_rtrn= type->mods.mask&(~preserve); 3301ab64890Smrg /* The Motif VTS doesn't get the help callback called if help 3311ab64890Smrg * is bound to Shift+<whatever>, and it appears as though it 3321ab64890Smrg * is XkbTranslateKeyCode that is causing the problem. The 3331ab64890Smrg * core X version of XTranslateKey always OR's in ShiftMask 3341ab64890Smrg * and LockMask for mods_rtrn, so this "fix" keeps this behavior 3351ab64890Smrg * and solves the VTS problem. 3361ab64890Smrg */ 3371ab64890Smrg if ((xkb->dpy)&&(xkb->dpy->xkb_info)&& 3381ab64890Smrg (xkb->dpy->xkb_info->xlib_ctrls&XkbLC_AlwaysConsumeShiftAndLock)) { 3391ab64890Smrg *mods_rtrn|= (ShiftMask|LockMask); 3401ab64890Smrg } 3411ab64890Smrg } 3421ab64890Smrg return (syms[col]!=NoSymbol); 3431ab64890Smrg} 3441ab64890Smrg 3451ab64890SmrgStatus 3461ab64890SmrgXkbRefreshKeyboardMapping(register XkbMapNotifyEvent *event) 3471ab64890Smrg{ 3481ab64890Smrg Display *dpy = event->display; 3491ab64890Smrg XkbInfoPtr xkbi; 3501ab64890Smrg 3511ab64890Smrg if (_XkbUnavailable(dpy)) { 3521ab64890Smrg _XRefreshKeyboardMapping((XMappingEvent *)event); 3531ab64890Smrg return Success; 3541ab64890Smrg } 3551ab64890Smrg xkbi= dpy->xkb_info; 3561ab64890Smrg 3571ab64890Smrg if (((event->type&0x7f)-xkbi->codes->first_event)!=XkbEventCode) 3581ab64890Smrg return BadMatch; 3591ab64890Smrg if (event->xkb_type==XkbNewKeyboardNotify) { 3601ab64890Smrg _XkbReloadDpy(dpy); 3611ab64890Smrg return Success; 3621ab64890Smrg } 3631ab64890Smrg if (event->xkb_type==XkbMapNotify) { 3641ab64890Smrg XkbMapChangesRec changes; 3651ab64890Smrg Status rtrn; 3661ab64890Smrg 3671ab64890Smrg if (xkbi->flags&XkbMapPending) 3681ab64890Smrg changes= xkbi->changes; 3691ab64890Smrg else bzero(&changes,sizeof(changes)); 3701ab64890Smrg XkbNoteMapChanges(&changes,event,XKB_XLIB_MAP_MASK); 3711ab64890Smrg if ((rtrn=XkbGetMapChanges(dpy,xkbi->desc,&changes))!=Success) { 3721ab64890Smrg#ifdef DEBUG 3731ab64890Smrg fprintf(stderr,"Internal Error! XkbGetMapChanges failed:\n"); 3741ab64890Smrg#endif 3751ab64890Smrg xkbi->changes= changes; 3761ab64890Smrg } 3771ab64890Smrg else if (xkbi->flags&XkbMapPending) { 3781ab64890Smrg xkbi->flags&= ~XkbMapPending; 3791ab64890Smrg bzero(&xkbi->changes,sizeof(XkbMapChangesRec)); 3801ab64890Smrg } 3811ab64890Smrg return rtrn; 3821ab64890Smrg } 3831ab64890Smrg return BadMatch; 3841ab64890Smrg} 3851ab64890Smrg 3861ab64890Smrgint 3871ab64890SmrgXRefreshKeyboardMapping(register XMappingEvent *event) 3881ab64890Smrg{ 3891ab64890Smrg XkbEvent *xkbevent = (XkbEvent *)event; 3901ab64890Smrg Display *dpy = event->display; 3911ab64890Smrg XkbMapChangesRec changes; 3921ab64890Smrg XkbInfoPtr xkbi; 3931ab64890Smrg 3941ab64890Smrg /* always do this for input methods, which still use the old keymap */ 3951ab64890Smrg (void) _XRefreshKeyboardMapping(event); 3961ab64890Smrg 3971ab64890Smrg if (_XkbUnavailable(dpy)) 3981ab64890Smrg return 1; 3991ab64890Smrg 4001ab64890Smrg xkbi = dpy->xkb_info; 4011ab64890Smrg 4021ab64890Smrg if (((event->type&0x7f)-xkbi->codes->first_event)==XkbEventCode) 4031ab64890Smrg return XkbRefreshKeyboardMapping(&xkbevent->map); 4041ab64890Smrg 4051ab64890Smrg if (xkbi->flags&XkbXlibNewKeyboard) { 4061ab64890Smrg _XkbReloadDpy(dpy); 4071ab64890Smrg return 1; 4081ab64890Smrg } 4091ab64890Smrg 4101ab64890Smrg if ((xkbi->flags&XkbMapPending)||(event->request==MappingKeyboard)) { 4111ab64890Smrg if (xkbi->flags&XkbMapPending) { 4121ab64890Smrg changes= xkbi->changes; 4131ab64890Smrg _XkbNoteCoreMapChanges(&changes,event,XKB_XLIB_MAP_MASK); 4141ab64890Smrg } 4151ab64890Smrg else { 4161ab64890Smrg bzero(&changes,sizeof(changes)); 4171ab64890Smrg changes.changed= XkbKeySymsMask; 4181ab64890Smrg if (xkbi->desc->min_key_code<xkbi->desc->max_key_code) { 4191ab64890Smrg changes.first_key_sym= xkbi->desc->min_key_code; 4201ab64890Smrg changes.num_key_syms= xkbi->desc->max_key_code- 4211ab64890Smrg xkbi->desc->min_key_code+1; 4221ab64890Smrg } 4231ab64890Smrg else { 4241ab64890Smrg changes.first_key_sym= event->first_keycode; 4251ab64890Smrg changes.num_key_syms= event->count; 4261ab64890Smrg } 4271ab64890Smrg } 4281ab64890Smrg 4291ab64890Smrg if (XkbGetMapChanges(dpy,xkbi->desc, &changes)!=Success) { 4301ab64890Smrg#ifdef DEBUG 4311ab64890Smrg fprintf(stderr,"Internal Error! XkbGetMapChanges failed:\n"); 4321ab64890Smrg if (changes.changed&XkbKeyTypesMask) { 4331ab64890Smrg int first= changes.first_type; 4341ab64890Smrg int last= changes.first_type+changes.num_types-1; 4351ab64890Smrg fprintf(stderr," types: %d..%d\n",first,last); 4361ab64890Smrg } 4371ab64890Smrg if (changes.changed&XkbKeySymsMask) { 4381ab64890Smrg int first= changes.first_key_sym; 4391ab64890Smrg int last= changes.first_key_sym+changes.num_key_syms-1; 4401ab64890Smrg fprintf(stderr," symbols: %d..%d\n",first,last); 4411ab64890Smrg } 4421ab64890Smrg if (changes.changed&XkbKeyActionsMask) { 4431ab64890Smrg int last,first= changes.first_key_act; 4441ab64890Smrg last= changes.first_key_act+changes.num_key_acts-1; 4451ab64890Smrg fprintf(stderr," acts: %d..%d\n",first,last); 4461ab64890Smrg } 4471ab64890Smrg if (changes.changed&XkbKeyBehaviorsMask) { 4481ab64890Smrg int last,first= changes.first_key_behavior; 4491ab64890Smrg last= first+changes.num_key_behaviors-1; 4501ab64890Smrg fprintf(stderr," behaviors: %d..%d\n",first,last); 4511ab64890Smrg } 4521ab64890Smrg if (changes.changed&XkbVirtualModsMask) { 4531ab64890Smrg fprintf(stderr,"virtual mods: 0x%04x\n", 4541ab64890Smrg changes.vmods); 4551ab64890Smrg } 4561ab64890Smrg if (changes.changed&XkbExplicitComponentsMask) { 4571ab64890Smrg int last,first= changes.first_key_explicit; 4581ab64890Smrg last= first+changes.num_key_explicit-1; 4591ab64890Smrg fprintf(stderr," explicit: %d..%d\n",first,last); 4601ab64890Smrg } 4611ab64890Smrg#endif 4621ab64890Smrg } 4631ab64890Smrg LockDisplay(dpy); 4641ab64890Smrg if (xkbi->flags&XkbMapPending) { 4651ab64890Smrg xkbi->flags&= ~XkbMapPending; 4661ab64890Smrg bzero(&xkbi->changes,sizeof(XkbMapChangesRec)); 4671ab64890Smrg } 4681ab64890Smrg UnlockDisplay(dpy); 4691ab64890Smrg } 4701ab64890Smrg if (event->request==MappingModifier) { 4711ab64890Smrg LockDisplay(dpy); 4721ab64890Smrg if (xkbi->desc->map->modmap) { 4731ab64890Smrg _XkbFree(xkbi->desc->map->modmap); 4741ab64890Smrg xkbi->desc->map->modmap= NULL; 4751ab64890Smrg } 4761ab64890Smrg if (dpy->key_bindings) { 4771ab64890Smrg register struct _XKeytrans *p; 4781ab64890Smrg for (p = dpy->key_bindings; p; p = p->next) { 4791ab64890Smrg register int i; 4801ab64890Smrg p->state= 0; 4811ab64890Smrg if (p->mlen>0) { 4821ab64890Smrg for (i = 0; i < p->mlen; i++) { 4831ab64890Smrg p->state|= XkbKeysymToModifiers(dpy,p->modifiers[i]); 4841ab64890Smrg } 4851ab64890Smrg if (p->state) p->state &= AllMods; 4861ab64890Smrg else p->state = AnyModifier; 4871ab64890Smrg } 4881ab64890Smrg } 4891ab64890Smrg } 4901ab64890Smrg UnlockDisplay(dpy); 4911ab64890Smrg } 4921ab64890Smrg return 1; 4931ab64890Smrg} 4941ab64890Smrg 4951ab64890Smrgstatic int 4961ab64890Smrg_XkbLoadDpy(Display *dpy) 4971ab64890Smrg{ 4981ab64890Smrg XkbInfoPtr xkbi; 4991ab64890Smrg unsigned query,oldEvents; 5001ab64890Smrg XkbDescRec *desc; 5011ab64890Smrg 5021ab64890Smrg if (!XkbUseExtension(dpy,NULL,NULL)) 5031ab64890Smrg return 0; 5041ab64890Smrg 5051ab64890Smrg xkbi = dpy->xkb_info; 5061ab64890Smrg query = XkbAllClientInfoMask; 5071ab64890Smrg desc = XkbGetMap(dpy,query,XkbUseCoreKbd); 5081ab64890Smrg if (!desc) { 5091ab64890Smrg#ifdef DEBUG 5101ab64890Smrg fprintf(stderr,"Warning! XkbGetMap failed!\n"); 5111ab64890Smrg#endif 5121ab64890Smrg return 0; 5131ab64890Smrg } 5141ab64890Smrg LockDisplay(dpy); 5151ab64890Smrg xkbi->desc = desc; 5161ab64890Smrg 5171ab64890Smrg UnlockDisplay(dpy); 5181ab64890Smrg oldEvents= xkbi->selected_events; 5191ab64890Smrg if (!(xkbi->xlib_ctrls&XkbLC_IgnoreNewKeyboards)) { 5201ab64890Smrg XkbSelectEventDetails(dpy,xkbi->desc->device_spec,XkbNewKeyboardNotify, 5211ab64890Smrg XkbNKN_KeycodesMask|XkbNKN_DeviceIDMask, 5221ab64890Smrg XkbNKN_KeycodesMask|XkbNKN_DeviceIDMask); 5231ab64890Smrg } 5241ab64890Smrg XkbSelectEventDetails(dpy,xkbi->desc->device_spec,XkbMapNotify, 5251ab64890Smrg XkbAllClientInfoMask,XkbAllClientInfoMask); 5261ab64890Smrg LockDisplay(dpy); 5271ab64890Smrg xkbi->selected_events= oldEvents; 5281ab64890Smrg UnlockDisplay(dpy); 5291ab64890Smrg return 1; 5301ab64890Smrg} 5311ab64890Smrg 5321ab64890Smrgvoid 5331ab64890Smrg_XkbReloadDpy(Display *dpy) 5341ab64890Smrg{ 5351ab64890Smrg XkbInfoPtr xkbi; 5361ab64890Smrg XkbDescRec *desc; 5371ab64890Smrg unsigned oldDeviceID; 5381ab64890Smrg 5391ab64890Smrg if (_XkbUnavailable(dpy)) 5401ab64890Smrg return; 5411ab64890Smrg 5421ab64890Smrg xkbi = dpy->xkb_info; 5431ab64890Smrg LockDisplay(dpy); 5441ab64890Smrg if (xkbi->desc) { 5451ab64890Smrg oldDeviceID= xkbi->desc->device_spec; 5461ab64890Smrg XkbFreeKeyboard(xkbi->desc,XkbAllComponentsMask,True); 5471ab64890Smrg xkbi->desc= NULL; 5481ab64890Smrg xkbi->flags&= ~(XkbMapPending|XkbXlibNewKeyboard); 5491ab64890Smrg xkbi->changes.changed= 0; 5501ab64890Smrg } 5511ab64890Smrg else oldDeviceID= XkbUseCoreKbd; 5521ab64890Smrg UnlockDisplay(dpy); 5531ab64890Smrg desc = XkbGetMap(dpy,XkbAllClientInfoMask,XkbUseCoreKbd); 5541ab64890Smrg if (!desc) 5551ab64890Smrg return; 5561ab64890Smrg LockDisplay(dpy); 5571ab64890Smrg xkbi->desc = desc; 5581ab64890Smrg UnlockDisplay(dpy); 5591ab64890Smrg 5601ab64890Smrg if (desc->device_spec!=oldDeviceID) { 5611ab64890Smrg /* transfer(?) event masks here */ 5621ab64890Smrg#ifdef NOTYET 5631ab64890Smrg unsigned oldEvents; 5641ab64890Smrg oldEvents= xkbi->selected_events; 5651ab64890Smrg XkbSelectEventDetails(dpy,xkbi->desc->device_spec,XkbMapNotify, 5661ab64890Smrg XkbAllMapComponentsMask,XkbAllClientInfoMask); 5671ab64890Smrg LockDisplay(dpy); 5681ab64890Smrg xkbi->selected_events= oldEvents; 5691ab64890Smrg UnlockDisplay(dpy); 5701ab64890Smrg#endif 5711ab64890Smrg } 5721ab64890Smrg return; 5731ab64890Smrg} 5741ab64890Smrg 5751ab64890Smrgint 5761ab64890SmrgXkbTranslateKeySym( register Display * dpy, 5771ab64890Smrg register KeySym * sym_rtrn, 5781ab64890Smrg unsigned int mods, 5791ab64890Smrg char * buffer, 5801ab64890Smrg int nbytes, 5811ab64890Smrg int * extra_rtrn) 5821ab64890Smrg{ 5831ab64890Smrg register XkbInfoPtr xkb; 5841ab64890Smrg XkbKSToMBFunc cvtr; 5851ab64890Smrg XPointer priv; 5861ab64890Smrg char tmp[4]; 5871ab64890Smrg int n; 5881ab64890Smrg 5891ab64890Smrg xkb= dpy->xkb_info; 5901ab64890Smrg if (!xkb->cvt.KSToMB) { 5911ab64890Smrg _XkbGetConverters(_XkbGetCharset(),&xkb->cvt); 5921ab64890Smrg _XkbGetConverters("ISO8859-1",&xkb->latin1cvt); 5931ab64890Smrg } 5941ab64890Smrg 5951ab64890Smrg if (extra_rtrn) 5961ab64890Smrg *extra_rtrn= 0; 5971ab64890Smrg 5981ab64890Smrg if ((buffer==NULL)||(nbytes==0)) { 5991ab64890Smrg buffer= tmp; 6001ab64890Smrg nbytes= 4; 6011ab64890Smrg } 6021ab64890Smrg 6031ab64890Smrg /* see if symbol rebound, if so, return that string. */ 6041ab64890Smrg n = XkbLookupKeyBinding(dpy,*sym_rtrn,mods,buffer,nbytes,extra_rtrn); 6051ab64890Smrg if (n) 6061ab64890Smrg return n; 6071ab64890Smrg 6081ab64890Smrg if ( nbytes>0 ) 6091ab64890Smrg buffer[0]= '\0'; 6101ab64890Smrg 6111ab64890Smrg if ( xkb->cvt.KSToUpper && (mods&LockMask) ) { 6121ab64890Smrg *sym_rtrn = (*xkb->cvt.KSToUpper)(*sym_rtrn); 6131ab64890Smrg } 6141ab64890Smrg if (xkb->xlib_ctrls & XkbLC_ForceLatin1Lookup) { 6151ab64890Smrg cvtr = xkb->latin1cvt.KSToMB; 6161ab64890Smrg priv = xkb->latin1cvt.KSToMBPriv; 6171ab64890Smrg } else { 6181ab64890Smrg cvtr = xkb->cvt.KSToMB; 6191ab64890Smrg priv = xkb->cvt.KSToMBPriv; 6201ab64890Smrg } 6211ab64890Smrg 6221ab64890Smrg n = (*cvtr)(priv,*sym_rtrn,buffer,nbytes,extra_rtrn); 6231ab64890Smrg 6241ab64890Smrg if ((!xkb->cvt.KSToUpper)&&( mods&LockMask )) { 6251ab64890Smrg register int i; 6261ab64890Smrg int change; 6271ab64890Smrg char ch; 6281ab64890Smrg for (i=change=0;i<n;i++) { 6291ab64890Smrg ch= toupper(buffer[i]); 6301ab64890Smrg change= (change||(buffer[i]!=ch)); 6311ab64890Smrg buffer[i] = ch; 6321ab64890Smrg } 6331ab64890Smrg if (change) { 6341ab64890Smrg if (n==1) 6351ab64890Smrg *sym_rtrn=(*xkb->cvt.MBToKS)(xkb->cvt.MBToKSPriv,buffer,n,0); 6361ab64890Smrg else *sym_rtrn= NoSymbol; 6371ab64890Smrg } 6381ab64890Smrg } 6391ab64890Smrg 6401ab64890Smrg if ( mods&ControlMask ) { 6411ab64890Smrg if ( n==1 ) { 6421ab64890Smrg buffer[0]= XkbToControl(buffer[0]); 6431ab64890Smrg if ( nbytes>1 ) 6441ab64890Smrg buffer[1]= '\0'; 6451ab64890Smrg return 1; 6461ab64890Smrg } 6471ab64890Smrg if ( nbytes > 0 ) 6481ab64890Smrg buffer[0]= '\0'; 6491ab64890Smrg return 0; 6501ab64890Smrg } 6511ab64890Smrg return n; 6521ab64890Smrg} 6531ab64890Smrg 6541ab64890Smrgint 6551ab64890SmrgXLookupString ( register XKeyEvent * event, 6561ab64890Smrg char * buffer, 6571ab64890Smrg int nbytes, 6581ab64890Smrg KeySym * keysym, 6591ab64890Smrg XComposeStatus * status) 6601ab64890Smrg{ 6611ab64890Smrg KeySym dummy; 6621ab64890Smrg int rtrnLen; 6631ab64890Smrg unsigned int new_mods; 6641ab64890Smrg Display *dpy = event->display; 6651ab64890Smrg 6661ab64890Smrg if (keysym==NULL) 6671ab64890Smrg keysym= &dummy; 6681ab64890Smrg if (!XkbLookupKeySym(dpy,event->keycode,event->state, &new_mods,keysym)) 6691ab64890Smrg return 0; 6701ab64890Smrg new_mods= (event->state&(~new_mods)); 6711ab64890Smrg 6721ab64890Smrg /* find the group where a symbol can be converted to control one */ 6731ab64890Smrg if (new_mods&ControlMask && *keysym > 0x7F && 6741ab64890Smrg (dpy->xkb_info->xlib_ctrls & XkbLC_ControlFallback)) { 6751ab64890Smrg XKeyEvent tmp_ev = *event; 6761ab64890Smrg KeySym tmp_keysym; 6771ab64890Smrg unsigned int tmp_new_mods; 6781ab64890Smrg if (_XkbUnavailable(dpy)) { 6791ab64890Smrg tmp_ev.state= event->state ^ dpy->mode_switch; 6801ab64890Smrg if (XkbLookupKeySym(dpy, tmp_ev.keycode, tmp_ev.state, 6811ab64890Smrg &tmp_new_mods, &tmp_keysym) && 6821ab64890Smrg tmp_keysym != NoSymbol && tmp_keysym < 0x80 ) { 6831ab64890Smrg *keysym = tmp_keysym; 6841ab64890Smrg } 6851ab64890Smrg } else { 6861ab64890Smrg int n = XkbKeyNumGroups(dpy->xkb_info->desc, tmp_ev.keycode); 6871ab64890Smrg int i; 6881ab64890Smrg for (i = 0; i < n; i++) { 6891ab64890Smrg if (XkbGroupForCoreState(event->state) == i) 6901ab64890Smrg continue; 6911ab64890Smrg tmp_ev.state= XkbBuildCoreState(tmp_ev.state, i); 6921ab64890Smrg if (XkbLookupKeySym(dpy, tmp_ev.keycode, tmp_ev.state, 6931ab64890Smrg &tmp_new_mods, &tmp_keysym) && 6941ab64890Smrg tmp_keysym != NoSymbol && tmp_keysym < 0x80 ) { 6951ab64890Smrg *keysym = tmp_keysym; 6961ab64890Smrg new_mods= (event->state&(~tmp_new_mods)); 6971ab64890Smrg break; 6981ab64890Smrg } 6991ab64890Smrg } 7001ab64890Smrg } 7011ab64890Smrg } 7021ab64890Smrg 7031ab64890Smrg#ifdef USE_OWN_COMPOSE 7041ab64890Smrg if ( status ) { 7051ab64890Smrg static int been_here= 0; 7061ab64890Smrg if ( !been_here ) { 7071ab64890Smrg XimCompInitTables(); 7081ab64890Smrg been_here = 1; 7091ab64890Smrg } 7101ab64890Smrg if ( !XimCompLegalStatus(status) ) { 7111ab64890Smrg status->compose_ptr = NULL; 7121ab64890Smrg status->chars_matched = 0; 7131ab64890Smrg } 7141ab64890Smrg if ( ((status->chars_matched>0)&&(status->compose_ptr!=NULL)) || 7151ab64890Smrg XimCompIsComposeKey(*keysym,event->keycode,status) ) { 7161ab64890Smrg XimCompRtrn rtrn; 7171ab64890Smrg 7181ab64890Smrg switch (XimCompProcessSym(status,*keysym,&rtrn)) { 7191ab64890Smrg case XIM_COMP_IGNORE: 7201ab64890Smrg break; 7211ab64890Smrg case XIM_COMP_IN_PROGRESS: 7221ab64890Smrg if ( keysym!=NULL ) 7231ab64890Smrg *keysym = NoSymbol; 7241ab64890Smrg#ifndef NO_COMPOSE_LED 7251ab64890Smrg if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) { 7261ab64890Smrg XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED, 7271ab64890Smrg True,True,False,NULL); 7281ab64890Smrg } 7291ab64890Smrg#endif 7301ab64890Smrg return 0; 7311ab64890Smrg case XIM_COMP_FAIL: 7321ab64890Smrg { 7331ab64890Smrg static Atom _ComposeFail= None; 7341ab64890Smrg int n = 0, len= 0; 7351ab64890Smrg#ifndef NO_COMPOSE_LED 7361ab64890Smrg if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) { 7371ab64890Smrg XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED, 7381ab64890Smrg True,False,False,NULL); 7391ab64890Smrg } 7401ab64890Smrg#endif 7411ab64890Smrg#ifndef NO_BELL_ON_COMPOSE_FAIL 7421ab64890Smrg if (dpy->xkb_info->xlib_ctrls&XkbLC_BeepOnComposeFail) { 7431ab64890Smrg if (_ComposeFail==None) 7441ab64890Smrg _ComposeFail= XInternAtom(dpy,"ComposeFail",0); 7451ab64890Smrg XkbBell(dpy,event->window,0,_ComposeFail); 7461ab64890Smrg } 7471ab64890Smrg#endif 7481ab64890Smrg for (n=len=0;rtrn.sym[n]!=XK_VoidSymbol;n++) { 7491ab64890Smrg if ( nbytes-len > 0 ) { 7501ab64890Smrg len+= XkbTranslateKeySym(dpy,&rtrn.sym[n],new_mods, 7511ab64890Smrg buffer+len,nbytes-len, 7521ab64890Smrg NULL); 7531ab64890Smrg } 7541ab64890Smrg } 7551ab64890Smrg if ( keysym!=NULL ) { 7561ab64890Smrg if ( n==1 ) *keysym = rtrn.sym[0]; 7571ab64890Smrg else *keysym = NoSymbol; 7581ab64890Smrg } 7591ab64890Smrg return len; 7601ab64890Smrg } 7611ab64890Smrg case XIM_COMP_SUCCEED: 7621ab64890Smrg { 7631ab64890Smrg int len,n = 0; 7641ab64890Smrg 7651ab64890Smrg#ifndef NO_COMPOSE_LED 7661ab64890Smrg if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) { 7671ab64890Smrg XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED, 7681ab64890Smrg True,False,False,NULL); 7691ab64890Smrg } 7701ab64890Smrg#endif 7711ab64890Smrg *keysym = rtrn.matchSym; 7721ab64890Smrg if ( rtrn.str[0]!='\0' ) { 7731ab64890Smrg strncpy(buffer,rtrn.str,nbytes-1); 7741ab64890Smrg buffer[nbytes-1]= '\0'; 7751ab64890Smrg len = (int)strlen(buffer); 7761ab64890Smrg } 7771ab64890Smrg else { 7781ab64890Smrg len = XkbTranslateKeySym(dpy,keysym,new_mods, 7791ab64890Smrg buffer,nbytes, 7801ab64890Smrg NULL); 7811ab64890Smrg } 7821ab64890Smrg for (n=0;rtrn.sym[n]!=XK_VoidSymbol;n++) { 7831ab64890Smrg if ( nbytes-len > 0 ) { 7841ab64890Smrg len+= XkbTranslateKeySym(dpy,&rtrn.sym[n], 7851ab64890Smrg event->state, 7861ab64890Smrg buffer+len,nbytes-len, 7871ab64890Smrg NULL); 7881ab64890Smrg } 7891ab64890Smrg } 7901ab64890Smrg return len; 7911ab64890Smrg } 7921ab64890Smrg } 7931ab64890Smrg } 7941ab64890Smrg } 7951ab64890Smrg#endif 7961ab64890Smrg 7971ab64890Smrg /* We *should* use the new_mods (which does not contain any modifiers */ 7981ab64890Smrg /* that were used to compute the symbol here, but pre-XKB XLookupString */ 7991ab64890Smrg /* did not and we have to remain compatible. Sigh. */ 8001ab64890Smrg if (_XkbUnavailable(dpy) || 8011ab64890Smrg (dpy->xkb_info->xlib_ctrls&XkbLC_ConsumeLookupMods)==0) 8021ab64890Smrg new_mods= event->state; 8031ab64890Smrg 8041ab64890Smrg rtrnLen= XkbLookupKeyBinding(dpy,*keysym,new_mods,buffer,nbytes,NULL); 8051ab64890Smrg if (rtrnLen>0) 8061ab64890Smrg return rtrnLen; 8071ab64890Smrg 8081ab64890Smrg return XkbTranslateKeySym(dpy,keysym,new_mods,buffer,nbytes,NULL); 8091ab64890Smrg} 8101ab64890Smrg 8111ab64890Smrg 8121ab64890Smrgint 8131ab64890SmrgXkbLookupKeyBinding( Display * dpy, 8141ab64890Smrg register KeySym sym, 8151ab64890Smrg unsigned int mods, 8161ab64890Smrg char * buffer, 8171ab64890Smrg int nbytes, 8181ab64890Smrg int * extra_rtrn) 8191ab64890Smrg{ 8201ab64890Smrg register struct _XKeytrans *p; 8211ab64890Smrg 8221ab64890Smrg if (extra_rtrn) 8231ab64890Smrg *extra_rtrn= 0; 8241ab64890Smrg for (p = dpy->key_bindings; p; p = p->next) { 8251ab64890Smrg if (((mods & AllMods) == p->state) && (sym == p->key)) { 8261ab64890Smrg int tmp = p->len; 8271ab64890Smrg if (tmp > nbytes) { 8281ab64890Smrg if (extra_rtrn) 8291ab64890Smrg *extra_rtrn= (tmp-nbytes); 8301ab64890Smrg tmp = nbytes; 8311ab64890Smrg } 8321ab64890Smrg memcpy (buffer, p->string, tmp); 8331ab64890Smrg if (tmp < nbytes) buffer[tmp]= '\0'; 8341ab64890Smrg return tmp; 8351ab64890Smrg } 8361ab64890Smrg } 8371ab64890Smrg return 0; 8381ab64890Smrg} 8391ab64890Smrg 8401ab64890Smrgchar 8411ab64890SmrgXkbToControl( char ch ) 8421ab64890Smrg{ 8431ab64890Smrg register char c = ch; 8441ab64890Smrg 8451ab64890Smrg if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F; 8461ab64890Smrg else if (c == '2') c = '\000'; 8471ab64890Smrg else if (c >= '3' && c <= '7') c -= ('3' - '\033'); 8481ab64890Smrg else if (c == '8') c = '\177'; 8491ab64890Smrg else if (c == '/') c = '_' & 0x1F; 8501ab64890Smrg return c; 8511ab64890Smrg} 852