XKBMisc.c revision 6747b715
105b261ecSmrg/************************************************************ 205b261ecSmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc. 305b261ecSmrg 405b261ecSmrgPermission to use, copy, modify, and distribute this 505b261ecSmrgsoftware and its documentation for any purpose and without 605b261ecSmrgfee is hereby granted, provided that the above copyright 705b261ecSmrgnotice appear in all copies and that both that copyright 805b261ecSmrgnotice and this permission notice appear in supporting 905b261ecSmrgdocumentation, and that the name of Silicon Graphics not be 1005b261ecSmrgused in advertising or publicity pertaining to distribution 1105b261ecSmrgof the software without specific prior written permission. 1205b261ecSmrgSilicon Graphics makes no representation about the suitability 1305b261ecSmrgof this software for any purpose. It is provided "as is" 1405b261ecSmrgwithout any express or implied warranty. 1505b261ecSmrg 1605b261ecSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 1705b261ecSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 1805b261ecSmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 1905b261ecSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 2005b261ecSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 2105b261ecSmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 2205b261ecSmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 2305b261ecSmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE. 2405b261ecSmrg 2505b261ecSmrg********************************************************/ 2605b261ecSmrg 2705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 2805b261ecSmrg#include <dix-config.h> 2905b261ecSmrg#elif defined(HAVE_CONFIG_H) 3005b261ecSmrg#include <config.h> 3105b261ecSmrg#endif 3205b261ecSmrg 3305b261ecSmrg#include <stdio.h> 3405b261ecSmrg#include <X11/X.h> 3505b261ecSmrg#include <X11/Xproto.h> 3605b261ecSmrg#include "misc.h" 3705b261ecSmrg#include "inputstr.h" 3805b261ecSmrg#include <X11/keysym.h> 3905b261ecSmrg#define XKBSRV_NEED_FILE_FUNCS 4005b261ecSmrg#include <xkbsrv.h> 4105b261ecSmrg 4205b261ecSmrg/***====================================================================***/ 4305b261ecSmrg 4405b261ecSmrg#define CORE_SYM(i) (i<map_width?core_syms[i]:NoSymbol) 4505b261ecSmrg#define XKB_OFFSET(g,l) (((g)*groupsWidth)+(l)) 4605b261ecSmrg 4705b261ecSmrgint 4805b261ecSmrgXkbKeyTypesForCoreSymbols( XkbDescPtr xkb, 4905b261ecSmrg int map_width, 5005b261ecSmrg KeySym * core_syms, 5105b261ecSmrg unsigned int protected, 5205b261ecSmrg int * types_inout, 5305b261ecSmrg KeySym * xkb_syms_rtrn) 5405b261ecSmrg{ 5505b261ecSmrgregister int i; 5605b261ecSmrgunsigned int empty; 5705b261ecSmrgint nSyms[XkbNumKbdGroups]; 5805b261ecSmrgint nGroups,tmp,groupsWidth; 596747b715SmrgBOOL replicated = FALSE; 6005b261ecSmrg 6105b261ecSmrg /* Section 12.2 of the protocol describes this process in more detail */ 6205b261ecSmrg /* Step 1: find the # of symbols in the core mapping per group */ 6305b261ecSmrg groupsWidth= 2; 6405b261ecSmrg for (i=0;i<XkbNumKbdGroups;i++) { 6505b261ecSmrg if ((protected&(1<<i))&&(types_inout[i]<xkb->map->num_types)) { 6605b261ecSmrg nSyms[i]= xkb->map->types[types_inout[i]].num_levels; 6705b261ecSmrg if (nSyms[i]>groupsWidth) 6805b261ecSmrg groupsWidth= nSyms[i]; 6905b261ecSmrg } 7005b261ecSmrg else { 7105b261ecSmrg types_inout[i]= XkbTwoLevelIndex; /* don't really know, yet */ 7205b261ecSmrg nSyms[i]= 2; 7305b261ecSmrg } 7405b261ecSmrg } 7505b261ecSmrg if (nSyms[XkbGroup1Index]<2) 7605b261ecSmrg nSyms[XkbGroup1Index]= 2; 7705b261ecSmrg if (nSyms[XkbGroup2Index]<2) 7805b261ecSmrg nSyms[XkbGroup2Index]= 2; 7905b261ecSmrg /* Step 2: Copy the symbols from the core ordering to XKB ordering */ 8005b261ecSmrg /* symbols in the core are in the order: */ 8105b261ecSmrg /* G1L1 G1L2 G2L1 G2L2 [G1L[3-n]] [G2L[3-n]] [G3L*] [G3L*] */ 8205b261ecSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,0)]= CORE_SYM(0); 8305b261ecSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,1)]= CORE_SYM(1); 8405b261ecSmrg for (i=2;i<nSyms[XkbGroup1Index];i++) { 8505b261ecSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,i)]= CORE_SYM(2+i); 8605b261ecSmrg } 8705b261ecSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,0)]= CORE_SYM(2); 8805b261ecSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,1)]= CORE_SYM(3); 8905b261ecSmrg tmp= 2+(nSyms[XkbGroup1Index]-2); /* offset to extra group2 syms */ 9005b261ecSmrg for (i=2;i<nSyms[XkbGroup2Index];i++) { 9105b261ecSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,i)]= CORE_SYM(tmp+i); 9205b261ecSmrg } 936747b715Smrg 946747b715Smrg /* Special case: if only the first group is explicit, and the symbols 956747b715Smrg * replicate across all groups, then we have a Section 12.4 replication */ 966747b715Smrg if ((protected & ~XkbExplicitKeyType1Mask) == 0) 976747b715Smrg { 986747b715Smrg int j, width = nSyms[XkbGroup1Index]; 996747b715Smrg 1006747b715Smrg replicated = TRUE; 1016747b715Smrg 1026747b715Smrg /* Check ABAB in ABABCDECDEABCDE */ 1036747b715Smrg if ((width > 0 && CORE_SYM(0) != CORE_SYM(2)) || 1046747b715Smrg (width > 1 && CORE_SYM(1) != CORE_SYM(3))) 1056747b715Smrg replicated = FALSE; 1066747b715Smrg 1076747b715Smrg /* Check CDECDE in ABABCDECDEABCDE */ 1086747b715Smrg for (i = 2; i < width && replicated; i++) 1096747b715Smrg { 1106747b715Smrg if (CORE_SYM(2 + i) != CORE_SYM(i + width)) 1116747b715Smrg replicated = FALSE; 1126747b715Smrg } 1136747b715Smrg 1146747b715Smrg /* Check ABCDE in ABABCDECDEABCDE */ 1156747b715Smrg for (j = 2; replicated && 1166747b715Smrg j < XkbNumKbdGroups && 1176747b715Smrg map_width >= width * (j + 1); j++) 1186747b715Smrg { 1196747b715Smrg for (i = 0; i < width && replicated; i++) 1206747b715Smrg { 1216747b715Smrg if (CORE_SYM(((i < 2) ? i : 2 + i)) != CORE_SYM(i + width * j)) 1226747b715Smrg replicated = FALSE; 1236747b715Smrg } 1246747b715Smrg } 1256747b715Smrg } 1266747b715Smrg 1276747b715Smrg if (replicated) 1286747b715Smrg { 1296747b715Smrg nSyms[XkbGroup2Index]= 0; 13005b261ecSmrg nSyms[XkbGroup3Index]= 0; 13105b261ecSmrg nSyms[XkbGroup4Index]= 0; 1326747b715Smrg nGroups= 1; 1336747b715Smrg } else 1346747b715Smrg { 1356747b715Smrg tmp= nSyms[XkbGroup1Index]+nSyms[XkbGroup2Index]; 1366747b715Smrg if ((tmp>=map_width)&& 1376747b715Smrg ((protected&(XkbExplicitKeyType3Mask|XkbExplicitKeyType4Mask))==0)) { 1386747b715Smrg nSyms[XkbGroup3Index]= 0; 1396747b715Smrg nSyms[XkbGroup4Index]= 0; 1406747b715Smrg nGroups= 2; 1416747b715Smrg } else 1426747b715Smrg { 1436747b715Smrg nGroups= 3; 1446747b715Smrg for (i=0;i<nSyms[XkbGroup3Index];i++,tmp++) { 1456747b715Smrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup3Index,i)]= CORE_SYM(tmp); 1466747b715Smrg } 1476747b715Smrg if ((tmp<map_width)||(protected&XkbExplicitKeyType4Mask)) { 1486747b715Smrg nGroups= 4; 1496747b715Smrg for (i=0;i<nSyms[XkbGroup4Index];i++,tmp++) { 1506747b715Smrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup4Index,i)]= CORE_SYM(tmp); 1516747b715Smrg } 1526747b715Smrg } 1536747b715Smrg else { 1546747b715Smrg nSyms[XkbGroup4Index]= 0; 1556747b715Smrg } 1566747b715Smrg } 15705b261ecSmrg } 15805b261ecSmrg /* steps 3&4: alphanumeric expansion, assign canonical types */ 15905b261ecSmrg empty= 0; 16005b261ecSmrg for (i=0;i<nGroups;i++) { 16105b261ecSmrg KeySym *syms; 16205b261ecSmrg syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)]; 16305b261ecSmrg if ((nSyms[i]>1)&&(syms[1]==NoSymbol)&&(syms[0]!=NoSymbol)) { 16405b261ecSmrg KeySym upper,lower; 1656747b715Smrg XkbConvertCase(syms[0],&lower,&upper); 16605b261ecSmrg if (upper!=lower) { 16705b261ecSmrg xkb_syms_rtrn[XKB_OFFSET(i,0)]= lower; 16805b261ecSmrg xkb_syms_rtrn[XKB_OFFSET(i,1)]= upper; 16905b261ecSmrg if ((protected&(1<<i))==0) 17005b261ecSmrg types_inout[i]= XkbAlphabeticIndex; 17105b261ecSmrg } 17205b261ecSmrg else if ((protected&(1<<i))==0) { 17305b261ecSmrg types_inout[i]= XkbOneLevelIndex; 17405b261ecSmrg /* nSyms[i]= 1;*/ 17505b261ecSmrg } 17605b261ecSmrg } 17705b261ecSmrg if (((protected&(1<<i))==0)&&(types_inout[i]==XkbTwoLevelIndex)) { 1786747b715Smrg if (XkbKSIsKeypad(syms[0])||XkbKSIsKeypad(syms[1])) 17905b261ecSmrg types_inout[i]= XkbKeypadIndex; 18005b261ecSmrg else { 18105b261ecSmrg KeySym upper,lower; 1826747b715Smrg XkbConvertCase(syms[0],&lower,&upper); 18305b261ecSmrg if ((syms[0]==lower)&&(syms[1]==upper)) 18405b261ecSmrg types_inout[i]= XkbAlphabeticIndex; 18505b261ecSmrg } 18605b261ecSmrg } 18705b261ecSmrg if (syms[0]==NoSymbol) { 18805b261ecSmrg register int n; 18905b261ecSmrg Bool found; 1906747b715Smrg for (n=1,found=FALSE;(!found)&&(n<nSyms[i]);n++) { 19105b261ecSmrg found= (syms[n]!=NoSymbol); 19205b261ecSmrg } 19305b261ecSmrg if (!found) 19405b261ecSmrg empty|= (1<<i); 19505b261ecSmrg } 19605b261ecSmrg } 19705b261ecSmrg /* step 5: squoosh out empty groups */ 19805b261ecSmrg if (empty) { 19905b261ecSmrg for (i=nGroups-1;i>=0;i--) { 20005b261ecSmrg if (((empty&(1<<i))==0)||(protected&(1<<i))) 20105b261ecSmrg break; 20205b261ecSmrg nGroups--; 20305b261ecSmrg } 20405b261ecSmrg } 20505b261ecSmrg if (nGroups<1) 20605b261ecSmrg return 0; 20705b261ecSmrg 20805b261ecSmrg /* step 6: replicate group 1 into group two, if necessary */ 20905b261ecSmrg if ((nGroups>1)&&((empty&(XkbGroup1Mask|XkbGroup2Mask))==XkbGroup2Mask)) { 21005b261ecSmrg if ((protected&(XkbExplicitKeyType1Mask|XkbExplicitKeyType2Mask))==0) { 21105b261ecSmrg nSyms[XkbGroup2Index]= nSyms[XkbGroup1Index]; 21205b261ecSmrg types_inout[XkbGroup2Index]= types_inout[XkbGroup1Index]; 21305b261ecSmrg memcpy((char *)&xkb_syms_rtrn[2],(char *)xkb_syms_rtrn, 21405b261ecSmrg 2*sizeof(KeySym)); 21505b261ecSmrg } 21605b261ecSmrg else if (types_inout[XkbGroup1Index]==types_inout[XkbGroup2Index]) { 21705b261ecSmrg memcpy((char *)&xkb_syms_rtrn[nSyms[XkbGroup1Index]], 21805b261ecSmrg (char *)xkb_syms_rtrn, 21905b261ecSmrg nSyms[XkbGroup1Index]*sizeof(KeySym)); 22005b261ecSmrg } 22105b261ecSmrg } 22205b261ecSmrg 2234642e01fSmrg /* step 7: check for all groups identical or all width 1 2244642e01fSmrg * 2254642e01fSmrg * Special feature: if group 1 has an explicit type and all other groups 2264642e01fSmrg * have canonical types with same symbols, we assume it's info lost from 2274642e01fSmrg * the core replication. 2284642e01fSmrg */ 22905b261ecSmrg if (nGroups>1) { 2306747b715Smrg Bool sameType,allOneLevel, canonical = TRUE; 23105b261ecSmrg allOneLevel= (xkb->map->types[types_inout[0]].num_levels==1); 2326747b715Smrg for (i=1,sameType=TRUE;(allOneLevel||sameType)&&(i<nGroups);i++) { 23305b261ecSmrg sameType=(sameType&&(types_inout[i]==types_inout[XkbGroup1Index])); 23405b261ecSmrg if (allOneLevel) 23505b261ecSmrg allOneLevel= (xkb->map->types[types_inout[i]].num_levels==1); 2364642e01fSmrg if (types_inout[i] > XkbLastRequiredType) 2376747b715Smrg canonical = FALSE; 23805b261ecSmrg } 2394642e01fSmrg if (((sameType) || canonical)&& 24005b261ecSmrg (!(protected&(XkbExplicitKeyTypesMask&~XkbExplicitKeyType1Mask)))){ 24105b261ecSmrg register int s; 24205b261ecSmrg Bool identical; 2436747b715Smrg for (i=1,identical=TRUE;identical&&(i<nGroups);i++) { 24405b261ecSmrg KeySym *syms; 2456747b715Smrg if (nSyms[i] != nSyms[XkbGroup1Index]) 2466747b715Smrg identical = FALSE; 24705b261ecSmrg syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)]; 24805b261ecSmrg for (s=0;identical&&(s<nSyms[i]);s++) { 24905b261ecSmrg if (syms[s]!=xkb_syms_rtrn[s]) 2506747b715Smrg identical= FALSE; 25105b261ecSmrg } 25205b261ecSmrg } 25305b261ecSmrg if (identical) 25405b261ecSmrg nGroups= 1; 25505b261ecSmrg } 25605b261ecSmrg if (allOneLevel && (nGroups>1)) { 25705b261ecSmrg KeySym *syms; 25805b261ecSmrg syms= &xkb_syms_rtrn[nSyms[XkbGroup1Index]]; 25905b261ecSmrg nSyms[XkbGroup1Index]= 1; 26005b261ecSmrg for (i=1;i<nGroups;i++) { 26105b261ecSmrg xkb_syms_rtrn[i]= syms[0]; 26205b261ecSmrg syms+= nSyms[i]; 26305b261ecSmrg nSyms[i]= 1; 26405b261ecSmrg } 26505b261ecSmrg } 26605b261ecSmrg } 26705b261ecSmrg return nGroups; 26805b261ecSmrg} 26905b261ecSmrg 27005b261ecSmrgstatic XkbSymInterpretPtr 27105b261ecSmrg_XkbFindMatchingInterp( XkbDescPtr xkb, 27205b261ecSmrg KeySym sym, 27305b261ecSmrg unsigned int real_mods, 27405b261ecSmrg unsigned int level) 27505b261ecSmrg{ 27605b261ecSmrgregister unsigned i; 27705b261ecSmrgXkbSymInterpretPtr interp,rtrn; 27805b261ecSmrgCARD8 mods; 27905b261ecSmrg 28005b261ecSmrg rtrn= NULL; 28105b261ecSmrg interp= xkb->compat->sym_interpret; 28205b261ecSmrg for (i=0;i<xkb->compat->num_si;i++,interp++) { 28305b261ecSmrg if ((interp->sym==NoSymbol)||(sym==interp->sym)) { 28405b261ecSmrg int match; 28505b261ecSmrg if ((level==0)||((interp->match&XkbSI_LevelOneOnly)==0)) 28605b261ecSmrg mods= real_mods; 28705b261ecSmrg else mods= 0; 28805b261ecSmrg switch (interp->match&XkbSI_OpMask) { 28905b261ecSmrg case XkbSI_NoneOf: 29005b261ecSmrg match= ((interp->mods&mods)==0); 29105b261ecSmrg break; 29205b261ecSmrg case XkbSI_AnyOfOrNone: 29305b261ecSmrg match= ((mods==0)||((interp->mods&mods)!=0)); 29405b261ecSmrg break; 29505b261ecSmrg case XkbSI_AnyOf: 29605b261ecSmrg match= ((interp->mods&mods)!=0); 29705b261ecSmrg break; 29805b261ecSmrg case XkbSI_AllOf: 29905b261ecSmrg match= ((interp->mods&mods)==interp->mods); 30005b261ecSmrg break; 30105b261ecSmrg case XkbSI_Exactly: 30205b261ecSmrg match= (interp->mods==mods); 30305b261ecSmrg break; 30405b261ecSmrg default: 30505b261ecSmrg match= 0; 30605b261ecSmrg break; 30705b261ecSmrg } 30805b261ecSmrg if (match) { 30905b261ecSmrg if (interp->sym!=NoSymbol) { 31005b261ecSmrg return interp; 31105b261ecSmrg } 31205b261ecSmrg else if (rtrn==NULL) { 31305b261ecSmrg rtrn= interp; 31405b261ecSmrg } 31505b261ecSmrg } 31605b261ecSmrg } 31705b261ecSmrg } 31805b261ecSmrg return rtrn; 31905b261ecSmrg} 32005b261ecSmrg 32105b261ecSmrgstatic void 32205b261ecSmrg_XkbAddKeyChange(KeyCode *pFirst,unsigned char *pNum,KeyCode newKey) 32305b261ecSmrg{ 32405b261ecSmrgKeyCode last; 32505b261ecSmrg 32605b261ecSmrg last= (*pFirst)+(*pNum); 32705b261ecSmrg if (newKey<*pFirst) { 32805b261ecSmrg *pFirst= newKey; 32905b261ecSmrg *pNum= (last-newKey)+1; 33005b261ecSmrg } 33105b261ecSmrg else if (newKey>last) { 33205b261ecSmrg *pNum= (last-*pFirst)+1; 33305b261ecSmrg } 33405b261ecSmrg return; 33505b261ecSmrg} 33605b261ecSmrg 33705b261ecSmrgstatic void 33805b261ecSmrg_XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction *act,unsigned mods) 33905b261ecSmrg{ 34005b261ecSmrgunsigned tmp; 34105b261ecSmrg 34205b261ecSmrg switch (act->type) { 34305b261ecSmrg case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: 34405b261ecSmrg if (act->mods.flags&XkbSA_UseModMapMods) 34505b261ecSmrg act->mods.real_mods= act->mods.mask= mods; 34605b261ecSmrg if ((tmp= XkbModActionVMods(&act->mods))!=0) { 34705b261ecSmrg XkbVirtualModsToReal(xkb,tmp,&tmp); 34805b261ecSmrg act->mods.mask|= tmp; 34905b261ecSmrg } 35005b261ecSmrg break; 35105b261ecSmrg case XkbSA_ISOLock: 35205b261ecSmrg if (act->iso.flags&XkbSA_UseModMapMods) 35305b261ecSmrg act->iso.real_mods= act->iso.mask= mods; 35405b261ecSmrg if ((tmp= XkbModActionVMods(&act->iso))!=0) { 35505b261ecSmrg XkbVirtualModsToReal(xkb,tmp,&tmp); 35605b261ecSmrg act->iso.mask|= tmp; 35705b261ecSmrg } 35805b261ecSmrg break; 35905b261ecSmrg } 36005b261ecSmrg return; 36105b261ecSmrg} 36205b261ecSmrg 36305b261ecSmrg#define IBUF_SIZE 8 36405b261ecSmrg 36505b261ecSmrgBool 36605b261ecSmrgXkbApplyCompatMapToKey(XkbDescPtr xkb,KeyCode key,XkbChangesPtr changes) 36705b261ecSmrg{ 36805b261ecSmrgKeySym * syms; 36905b261ecSmrgunsigned char explicit,mods; 37005b261ecSmrgXkbSymInterpretPtr *interps,ibuf[IBUF_SIZE]; 37105b261ecSmrgint n,nSyms,found; 37205b261ecSmrgunsigned changed,tmp; 37305b261ecSmrg 37405b261ecSmrg if ((!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)|| 37505b261ecSmrg (!xkb->compat)||(!xkb->compat->sym_interpret)|| 37605b261ecSmrg (key<xkb->min_key_code)||(key>xkb->max_key_code)) { 3776747b715Smrg return FALSE; 37805b261ecSmrg } 37905b261ecSmrg if (((!xkb->server)||(!xkb->server->key_acts))&& 38005b261ecSmrg (XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success)) { 3816747b715Smrg return FALSE; 38205b261ecSmrg } 38305b261ecSmrg changed= 0; /* keeps track of what has changed in _this_ call */ 38405b261ecSmrg explicit= xkb->server->explicit[key]; 38505b261ecSmrg if (explicit&XkbExplicitInterpretMask) /* nothing to do */ 3866747b715Smrg return TRUE; 38705b261ecSmrg mods= (xkb->map->modmap?xkb->map->modmap[key]:0); 38805b261ecSmrg nSyms= XkbKeyNumSyms(xkb,key); 38905b261ecSmrg syms= XkbKeySymsPtr(xkb,key); 39005b261ecSmrg if (nSyms>IBUF_SIZE) { 3916747b715Smrg interps= calloc(nSyms, sizeof(XkbSymInterpretPtr)); 39205b261ecSmrg if (interps==NULL) { 39305b261ecSmrg interps= ibuf; 39405b261ecSmrg nSyms= IBUF_SIZE; 39505b261ecSmrg } 39605b261ecSmrg } 39705b261ecSmrg else { 39805b261ecSmrg interps= ibuf; 39905b261ecSmrg } 40005b261ecSmrg found= 0; 40105b261ecSmrg for (n=0;n<nSyms;n++) { 40205b261ecSmrg unsigned level= (n%XkbKeyGroupsWidth(xkb,key)); 40305b261ecSmrg interps[n]= NULL; 40405b261ecSmrg if (syms[n]!=NoSymbol) { 40505b261ecSmrg interps[n]= _XkbFindMatchingInterp(xkb,syms[n],mods,level); 40605b261ecSmrg if (interps[n]&&interps[n]->act.type!=XkbSA_NoAction) 40705b261ecSmrg found++; 40805b261ecSmrg else interps[n]= NULL; 40905b261ecSmrg } 41005b261ecSmrg } 41105b261ecSmrg /* 1/28/96 (ef) -- XXX! WORKING HERE */ 41205b261ecSmrg if (!found) { 41305b261ecSmrg if (xkb->server->key_acts[key]!=0) { 41405b261ecSmrg xkb->server->key_acts[key]= 0; 41505b261ecSmrg changed|= XkbKeyActionsMask; 41605b261ecSmrg } 41705b261ecSmrg } 41805b261ecSmrg else { 41905b261ecSmrg XkbAction *pActs; 42005b261ecSmrg unsigned int new_vmodmask; 42105b261ecSmrg changed|= XkbKeyActionsMask; 42205b261ecSmrg pActs= XkbResizeKeyActions(xkb,key,nSyms); 42305b261ecSmrg if (!pActs) { 42405b261ecSmrg if (nSyms > IBUF_SIZE) 4256747b715Smrg free(interps); 4266747b715Smrg return FALSE; 42705b261ecSmrg } 42805b261ecSmrg new_vmodmask= 0; 42905b261ecSmrg for (n=0;n<nSyms;n++) { 43005b261ecSmrg if (interps[n]) { 43105b261ecSmrg unsigned effMods; 43205b261ecSmrg 43305b261ecSmrg pActs[n]= *((XkbAction *)&interps[n]->act); 43405b261ecSmrg if ((n==0)||((interps[n]->match&XkbSI_LevelOneOnly)==0)) { 43505b261ecSmrg effMods= mods; 43605b261ecSmrg if (interps[n]->virtual_mod!=XkbNoModifier) 43705b261ecSmrg new_vmodmask|= (1<<interps[n]->virtual_mod); 43805b261ecSmrg } 43905b261ecSmrg else effMods= 0; 44005b261ecSmrg _XkbSetActionKeyMods(xkb,&pActs[n],effMods); 44105b261ecSmrg } 44205b261ecSmrg else pActs[n].type= XkbSA_NoAction; 44305b261ecSmrg } 44405b261ecSmrg if (((explicit&XkbExplicitVModMapMask)==0)&& 44505b261ecSmrg (xkb->server->vmodmap[key]!=new_vmodmask)) { 44605b261ecSmrg changed|= XkbVirtualModMapMask; 44705b261ecSmrg xkb->server->vmodmap[key]= new_vmodmask; 44805b261ecSmrg } 44905b261ecSmrg if (interps[0]) { 45005b261ecSmrg if ((interps[0]->flags&XkbSI_LockingKey)&& 45105b261ecSmrg ((explicit&XkbExplicitBehaviorMask)==0)) { 45205b261ecSmrg xkb->server->behaviors[key].type= XkbKB_Lock; 45305b261ecSmrg changed|= XkbKeyBehaviorsMask; 45405b261ecSmrg } 45505b261ecSmrg if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) { 45605b261ecSmrg CARD8 old; 45705b261ecSmrg old= xkb->ctrls->per_key_repeat[key/8]; 45805b261ecSmrg if (interps[0]->flags&XkbSI_AutoRepeat) 45905b261ecSmrg xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8)); 46005b261ecSmrg else xkb->ctrls->per_key_repeat[key/8]&= ~(1<<(key%8)); 46105b261ecSmrg if (changes && (old!=xkb->ctrls->per_key_repeat[key/8])) 46205b261ecSmrg changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask; 46305b261ecSmrg } 46405b261ecSmrg } 46505b261ecSmrg } 46605b261ecSmrg if ((!found)||(interps[0]==NULL)) { 46705b261ecSmrg if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) { 46805b261ecSmrg CARD8 old; 46905b261ecSmrg old= xkb->ctrls->per_key_repeat[key/8]; 4704642e01fSmrg xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8)); 47105b261ecSmrg if (changes && (old!=xkb->ctrls->per_key_repeat[key/8])) 47205b261ecSmrg changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask; 47305b261ecSmrg } 47405b261ecSmrg if (((explicit&XkbExplicitBehaviorMask)==0)&& 47505b261ecSmrg (xkb->server->behaviors[key].type==XkbKB_Lock)) { 47605b261ecSmrg xkb->server->behaviors[key].type= XkbKB_Default; 47705b261ecSmrg changed|= XkbKeyBehaviorsMask; 47805b261ecSmrg } 47905b261ecSmrg } 48005b261ecSmrg if (changes) { 48105b261ecSmrg XkbMapChangesPtr mc; 48205b261ecSmrg mc= &changes->map; 48305b261ecSmrg tmp= (changed&mc->changed); 48405b261ecSmrg if (tmp&XkbKeyActionsMask) 48505b261ecSmrg _XkbAddKeyChange(&mc->first_key_act,&mc->num_key_acts,key); 48605b261ecSmrg else if (changed&XkbKeyActionsMask) { 48705b261ecSmrg mc->changed|= XkbKeyActionsMask; 48805b261ecSmrg mc->first_key_act= key; 48905b261ecSmrg mc->num_key_acts= 1; 49005b261ecSmrg } 49105b261ecSmrg if (tmp&XkbKeyBehaviorsMask) { 49205b261ecSmrg _XkbAddKeyChange(&mc->first_key_behavior,&mc->num_key_behaviors, 49305b261ecSmrg key); 49405b261ecSmrg } 49505b261ecSmrg else if (changed&XkbKeyBehaviorsMask) { 49605b261ecSmrg mc->changed|= XkbKeyBehaviorsMask; 49705b261ecSmrg mc->first_key_behavior= key; 49805b261ecSmrg mc->num_key_behaviors= 1; 49905b261ecSmrg } 50005b261ecSmrg if (tmp&XkbVirtualModMapMask) 50105b261ecSmrg _XkbAddKeyChange(&mc->first_vmodmap_key,&mc->num_vmodmap_keys,key); 50205b261ecSmrg else if (changed&XkbVirtualModMapMask) { 50305b261ecSmrg mc->changed|= XkbVirtualModMapMask; 50405b261ecSmrg mc->first_vmodmap_key= key; 50505b261ecSmrg mc->num_vmodmap_keys= 1; 50605b261ecSmrg } 50705b261ecSmrg mc->changed|= changed; 50805b261ecSmrg } 50905b261ecSmrg if (interps!=ibuf) 5106747b715Smrg free(interps); 5116747b715Smrg return TRUE; 51205b261ecSmrg} 51305b261ecSmrg 51405b261ecSmrgStatus 51505b261ecSmrgXkbChangeTypesOfKey( XkbDescPtr xkb, 51605b261ecSmrg int key, 51705b261ecSmrg int nGroups, 51805b261ecSmrg unsigned groups, 51905b261ecSmrg int * newTypesIn, 52005b261ecSmrg XkbMapChangesPtr changes) 52105b261ecSmrg{ 52205b261ecSmrgXkbKeyTypePtr pOldType,pNewType; 52305b261ecSmrgregister int i; 52405b261ecSmrgint width,nOldGroups,oldWidth,newTypes[XkbNumKbdGroups]; 52505b261ecSmrg 52605b261ecSmrg if ((!xkb) || (!XkbKeycodeInRange(xkb,key)) || (!xkb->map) || 5274642e01fSmrg (!xkb->map->types)||(!newTypesIn)||((groups&XkbAllGroupsMask)==0)|| 52805b261ecSmrg (nGroups>XkbNumKbdGroups)) { 52905b261ecSmrg return BadMatch; 53005b261ecSmrg } 53105b261ecSmrg if (nGroups==0) { 53205b261ecSmrg for (i=0;i<XkbNumKbdGroups;i++) { 53305b261ecSmrg xkb->map->key_sym_map[key].kt_index[i]= XkbOneLevelIndex; 53405b261ecSmrg } 53505b261ecSmrg i= xkb->map->key_sym_map[key].group_info; 53605b261ecSmrg i= XkbSetNumGroups(i,0); 53705b261ecSmrg xkb->map->key_sym_map[key].group_info= i; 53805b261ecSmrg XkbResizeKeySyms(xkb,key,0); 53905b261ecSmrg return Success; 54005b261ecSmrg } 54105b261ecSmrg 54205b261ecSmrg nOldGroups= XkbKeyNumGroups(xkb,key); 54305b261ecSmrg oldWidth= XkbKeyGroupsWidth(xkb,key); 54405b261ecSmrg for (width=i=0;i<nGroups;i++) { 54505b261ecSmrg if (groups&(1<<i)) 54605b261ecSmrg newTypes[i]= newTypesIn[i]; 54705b261ecSmrg else if (i<nOldGroups) 54805b261ecSmrg newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,i); 54905b261ecSmrg else if (nOldGroups>0) 55005b261ecSmrg newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index); 55105b261ecSmrg else newTypes[i]= XkbTwoLevelIndex; 55205b261ecSmrg if (newTypes[i]>xkb->map->num_types) 55305b261ecSmrg return BadMatch; 55405b261ecSmrg pNewType= &xkb->map->types[newTypes[i]]; 55505b261ecSmrg if (pNewType->num_levels>width) 55605b261ecSmrg width= pNewType->num_levels; 55705b261ecSmrg } 55805b261ecSmrg if ((xkb->ctrls)&&(nGroups>xkb->ctrls->num_groups)) 55905b261ecSmrg xkb->ctrls->num_groups= nGroups; 56005b261ecSmrg if ((width!=oldWidth)||(nGroups!=nOldGroups)) { 56105b261ecSmrg KeySym oldSyms[XkbMaxSymsPerKey],*pSyms; 56205b261ecSmrg int nCopy; 56305b261ecSmrg 56405b261ecSmrg if (nOldGroups==0) { 56505b261ecSmrg pSyms= XkbResizeKeySyms(xkb,key,width*nGroups); 56605b261ecSmrg if (pSyms!=NULL) { 56705b261ecSmrg i= xkb->map->key_sym_map[key].group_info; 56805b261ecSmrg i= XkbSetNumGroups(i,nGroups); 56905b261ecSmrg xkb->map->key_sym_map[key].group_info= i; 57005b261ecSmrg xkb->map->key_sym_map[key].width= width; 57105b261ecSmrg for (i=0;i<nGroups;i++) { 57205b261ecSmrg xkb->map->key_sym_map[key].kt_index[i]= newTypes[i]; 57305b261ecSmrg } 57405b261ecSmrg return Success; 57505b261ecSmrg } 57605b261ecSmrg return BadAlloc; 57705b261ecSmrg } 57805b261ecSmrg pSyms= XkbKeySymsPtr(xkb,key); 57905b261ecSmrg memcpy(oldSyms,pSyms,XkbKeyNumSyms(xkb,key)*sizeof(KeySym)); 58005b261ecSmrg pSyms= XkbResizeKeySyms(xkb,key,width*nGroups); 58105b261ecSmrg if (pSyms==NULL) 58205b261ecSmrg return BadAlloc; 5836747b715Smrg memset(pSyms, 0, width*nGroups*sizeof(KeySym)); 58405b261ecSmrg for (i=0;(i<nGroups)&&(i<nOldGroups);i++) { 58505b261ecSmrg pOldType= XkbKeyKeyType(xkb,key,i); 58605b261ecSmrg pNewType= &xkb->map->types[newTypes[i]]; 58705b261ecSmrg if (pNewType->num_levels>pOldType->num_levels) 58805b261ecSmrg nCopy= pOldType->num_levels; 58905b261ecSmrg else nCopy= pNewType->num_levels; 59005b261ecSmrg memcpy(&pSyms[i*width],&oldSyms[i*oldWidth],nCopy*sizeof(KeySym)); 59105b261ecSmrg } 59205b261ecSmrg if (XkbKeyHasActions(xkb,key)) { 59305b261ecSmrg XkbAction oldActs[XkbMaxSymsPerKey],*pActs; 59405b261ecSmrg pActs= XkbKeyActionsPtr(xkb,key); 59505b261ecSmrg memcpy(oldActs,pActs,XkbKeyNumSyms(xkb,key)*sizeof(XkbAction)); 59605b261ecSmrg pActs= XkbResizeKeyActions(xkb,key,width*nGroups); 59705b261ecSmrg if (pActs==NULL) 59805b261ecSmrg return BadAlloc; 5996747b715Smrg memset(pActs, 0, width*nGroups*sizeof(XkbAction)); 60005b261ecSmrg for (i=0;(i<nGroups)&&(i<nOldGroups);i++) { 60105b261ecSmrg pOldType= XkbKeyKeyType(xkb,key,i); 60205b261ecSmrg pNewType= &xkb->map->types[newTypes[i]]; 60305b261ecSmrg if (pNewType->num_levels>pOldType->num_levels) 60405b261ecSmrg nCopy= pOldType->num_levels; 60505b261ecSmrg else nCopy= pNewType->num_levels; 60605b261ecSmrg memcpy(&pActs[i*width],&oldActs[i*oldWidth], 60705b261ecSmrg nCopy*sizeof(XkbAction)); 60805b261ecSmrg } 60905b261ecSmrg } 61005b261ecSmrg i= xkb->map->key_sym_map[key].group_info; 61105b261ecSmrg i= XkbSetNumGroups(i,nGroups); 61205b261ecSmrg xkb->map->key_sym_map[key].group_info= i; 61305b261ecSmrg xkb->map->key_sym_map[key].width= width; 61405b261ecSmrg } 61505b261ecSmrg width= 0; 61605b261ecSmrg for (i=0;i<nGroups;i++) { 61705b261ecSmrg xkb->map->key_sym_map[key].kt_index[i]= newTypes[i]; 61805b261ecSmrg if (xkb->map->types[newTypes[i]].num_levels>width) 61905b261ecSmrg width= xkb->map->types[newTypes[i]].num_levels; 62005b261ecSmrg } 62105b261ecSmrg xkb->map->key_sym_map[key].width= width; 62205b261ecSmrg if (changes!=NULL) { 62305b261ecSmrg if (changes->changed&XkbKeySymsMask) { 62405b261ecSmrg _XkbAddKeyChange(&changes->first_key_sym,&changes->num_key_syms, 62505b261ecSmrg key); 62605b261ecSmrg } 62705b261ecSmrg else { 62805b261ecSmrg changes->changed|= XkbKeySymsMask; 62905b261ecSmrg changes->first_key_sym= key; 63005b261ecSmrg changes->num_key_syms= 1; 63105b261ecSmrg } 63205b261ecSmrg } 63305b261ecSmrg return Success; 63405b261ecSmrg} 63505b261ecSmrg 63605b261ecSmrg/***====================================================================***/ 63705b261ecSmrg 63805b261ecSmrgBool 63905b261ecSmrgXkbVirtualModsToReal(XkbDescPtr xkb,unsigned virtual_mask,unsigned *mask_rtrn) 64005b261ecSmrg{ 64105b261ecSmrgregister int i,bit; 64205b261ecSmrgregister unsigned mask; 64305b261ecSmrg 64405b261ecSmrg if (xkb==NULL) 6456747b715Smrg return FALSE; 64605b261ecSmrg if (virtual_mask==0) { 64705b261ecSmrg *mask_rtrn= 0; 6486747b715Smrg return TRUE; 64905b261ecSmrg } 65005b261ecSmrg if (xkb->server==NULL) 6516747b715Smrg return FALSE; 65205b261ecSmrg for (i=mask=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { 65305b261ecSmrg if (virtual_mask&bit) 65405b261ecSmrg mask|= xkb->server->vmods[i]; 65505b261ecSmrg } 65605b261ecSmrg *mask_rtrn= mask; 6576747b715Smrg return TRUE; 65805b261ecSmrg} 65905b261ecSmrg 66005b261ecSmrg/***====================================================================***/ 66105b261ecSmrg 66205b261ecSmrgstatic Bool 66305b261ecSmrgXkbUpdateActionVirtualMods(XkbDescPtr xkb,XkbAction *act,unsigned changed) 66405b261ecSmrg{ 66505b261ecSmrgunsigned int tmp; 66605b261ecSmrg 66705b261ecSmrg switch (act->type) { 66805b261ecSmrg case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: 66905b261ecSmrg if (((tmp= XkbModActionVMods(&act->mods))&changed)!=0) { 67005b261ecSmrg XkbVirtualModsToReal(xkb,tmp,&tmp); 67105b261ecSmrg act->mods.mask= act->mods.real_mods; 67205b261ecSmrg act->mods.mask|= tmp; 6736747b715Smrg return TRUE; 67405b261ecSmrg } 67505b261ecSmrg break; 67605b261ecSmrg case XkbSA_ISOLock: 67705b261ecSmrg if ((((tmp= XkbModActionVMods(&act->iso))!=0)&changed)!=0) { 67805b261ecSmrg XkbVirtualModsToReal(xkb,tmp,&tmp); 67905b261ecSmrg act->iso.mask= act->iso.real_mods; 68005b261ecSmrg act->iso.mask|= tmp; 6816747b715Smrg return TRUE; 68205b261ecSmrg } 68305b261ecSmrg break; 68405b261ecSmrg } 6856747b715Smrg return FALSE; 68605b261ecSmrg} 68705b261ecSmrg 68805b261ecSmrgstatic void 68905b261ecSmrgXkbUpdateKeyTypeVirtualMods( XkbDescPtr xkb, 69005b261ecSmrg XkbKeyTypePtr type, 69105b261ecSmrg unsigned int changed, 69205b261ecSmrg XkbChangesPtr changes) 69305b261ecSmrg{ 69405b261ecSmrgregister unsigned int i; 69505b261ecSmrgunsigned int mask; 69605b261ecSmrg 69705b261ecSmrg XkbVirtualModsToReal(xkb,type->mods.vmods,&mask); 69805b261ecSmrg type->mods.mask= type->mods.real_mods|mask; 69905b261ecSmrg if ((type->map_count>0)&&(type->mods.vmods!=0)) { 70005b261ecSmrg XkbKTMapEntryPtr entry; 70105b261ecSmrg for (i=0,entry=type->map;i<type->map_count;i++,entry++) { 70205b261ecSmrg if (entry->mods.vmods!=0) { 70305b261ecSmrg XkbVirtualModsToReal(xkb,entry->mods.vmods,&mask); 70405b261ecSmrg entry->mods.mask=entry->mods.real_mods|mask; 70505b261ecSmrg /* entry is active if vmods are bound*/ 70605b261ecSmrg entry->active= (mask!=0); 70705b261ecSmrg } 70805b261ecSmrg else entry->active= 1; 70905b261ecSmrg } 71005b261ecSmrg } 71105b261ecSmrg if (changes) { 71205b261ecSmrg int type_ndx; 71305b261ecSmrg type_ndx= type-xkb->map->types; 71405b261ecSmrg if ((type_ndx<0)||(type_ndx>xkb->map->num_types)) 71505b261ecSmrg return; 71605b261ecSmrg if (changes->map.changed&XkbKeyTypesMask) { 71705b261ecSmrg int last; 71805b261ecSmrg last= changes->map.first_type+changes->map.num_types-1; 71905b261ecSmrg if (type_ndx<changes->map.first_type) { 72005b261ecSmrg changes->map.first_type= type_ndx; 72105b261ecSmrg changes->map.num_types= (last-type_ndx)+1; 72205b261ecSmrg } 72305b261ecSmrg else if (type_ndx>last) { 72405b261ecSmrg changes->map.num_types= (type_ndx-changes->map.first_type)+1; 72505b261ecSmrg } 72605b261ecSmrg } 72705b261ecSmrg else { 72805b261ecSmrg changes->map.changed|= XkbKeyTypesMask; 72905b261ecSmrg changes->map.first_type= type_ndx; 73005b261ecSmrg changes->map.num_types= 1; 73105b261ecSmrg } 73205b261ecSmrg } 73305b261ecSmrg return; 73405b261ecSmrg} 73505b261ecSmrg 73605b261ecSmrgBool 73705b261ecSmrgXkbApplyVirtualModChanges(XkbDescPtr xkb,unsigned changed,XkbChangesPtr changes) 73805b261ecSmrg{ 73905b261ecSmrgregister int i; 74005b261ecSmrgunsigned int checkState = 0; 74105b261ecSmrg 74205b261ecSmrg if ((!xkb) || (!xkb->map) || (changed==0)) 7436747b715Smrg return FALSE; 74405b261ecSmrg for (i=0;i<xkb->map->num_types;i++) { 74505b261ecSmrg if (xkb->map->types[i].mods.vmods & changed) 74605b261ecSmrg XkbUpdateKeyTypeVirtualMods(xkb,&xkb->map->types[i],changed,changes); 74705b261ecSmrg } 74805b261ecSmrg if (changed&xkb->ctrls->internal.vmods) { 74905b261ecSmrg unsigned int newMask; 75005b261ecSmrg XkbVirtualModsToReal(xkb,xkb->ctrls->internal.vmods,&newMask); 75105b261ecSmrg newMask|= xkb->ctrls->internal.real_mods; 75205b261ecSmrg if (xkb->ctrls->internal.mask!=newMask) { 75305b261ecSmrg xkb->ctrls->internal.mask= newMask; 75405b261ecSmrg if (changes) { 75505b261ecSmrg changes->ctrls.changed_ctrls|= XkbInternalModsMask; 7566747b715Smrg checkState= TRUE; 75705b261ecSmrg } 75805b261ecSmrg } 75905b261ecSmrg } 76005b261ecSmrg if (changed&xkb->ctrls->ignore_lock.vmods) { 76105b261ecSmrg unsigned int newMask; 76205b261ecSmrg XkbVirtualModsToReal(xkb,xkb->ctrls->ignore_lock.vmods,&newMask); 76305b261ecSmrg newMask|= xkb->ctrls->ignore_lock.real_mods; 76405b261ecSmrg if (xkb->ctrls->ignore_lock.mask!=newMask) { 76505b261ecSmrg xkb->ctrls->ignore_lock.mask= newMask; 76605b261ecSmrg if (changes) { 76705b261ecSmrg changes->ctrls.changed_ctrls|= XkbIgnoreLockModsMask; 7686747b715Smrg checkState= TRUE; 76905b261ecSmrg } 77005b261ecSmrg } 77105b261ecSmrg } 77205b261ecSmrg if (xkb->indicators!=NULL) { 77305b261ecSmrg XkbIndicatorMapPtr map; 77405b261ecSmrg map= &xkb->indicators->maps[0]; 77505b261ecSmrg for (i=0;i<XkbNumIndicators;i++,map++) { 77605b261ecSmrg if (map->mods.vmods&changed) { 77705b261ecSmrg unsigned int newMask; 77805b261ecSmrg XkbVirtualModsToReal(xkb,map->mods.vmods,&newMask); 77905b261ecSmrg newMask|= map->mods.real_mods; 78005b261ecSmrg if (newMask!=map->mods.mask) { 78105b261ecSmrg map->mods.mask= newMask; 78205b261ecSmrg if (changes) { 78305b261ecSmrg changes->indicators.map_changes|= (1<<i); 7846747b715Smrg checkState= TRUE; 78505b261ecSmrg } 78605b261ecSmrg } 78705b261ecSmrg } 78805b261ecSmrg } 78905b261ecSmrg } 79005b261ecSmrg if (xkb->compat!=NULL) { 79105b261ecSmrg XkbCompatMapPtr compat; 79205b261ecSmrg compat= xkb->compat; 79305b261ecSmrg for (i=0;i<XkbNumKbdGroups;i++) { 79405b261ecSmrg unsigned int newMask; 79505b261ecSmrg XkbVirtualModsToReal(xkb,compat->groups[i].vmods,&newMask); 79605b261ecSmrg newMask|= compat->groups[i].real_mods; 79705b261ecSmrg if (compat->groups[i].mask!=newMask) { 79805b261ecSmrg compat->groups[i].mask= newMask; 79905b261ecSmrg if (changes) { 80005b261ecSmrg changes->compat.changed_groups|= (1<<i); 8016747b715Smrg checkState= TRUE; 80205b261ecSmrg } 80305b261ecSmrg } 80405b261ecSmrg } 80505b261ecSmrg } 80605b261ecSmrg if (xkb->map && xkb->server) { 80705b261ecSmrg int highChange = 0, lowChange = -1; 80805b261ecSmrg for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { 80905b261ecSmrg if (XkbKeyHasActions(xkb,i)) { 81005b261ecSmrg register XkbAction *pAct; 81105b261ecSmrg register int n; 81205b261ecSmrg 81305b261ecSmrg pAct= XkbKeyActionsPtr(xkb,i); 81405b261ecSmrg for (n=XkbKeyNumActions(xkb,i);n>0;n--,pAct++) { 81505b261ecSmrg if ((pAct->type!=XkbSA_NoAction)&& 81605b261ecSmrg XkbUpdateActionVirtualMods(xkb,pAct,changed)) { 81705b261ecSmrg if (lowChange<0) 81805b261ecSmrg lowChange= i; 81905b261ecSmrg highChange= i; 82005b261ecSmrg } 82105b261ecSmrg } 82205b261ecSmrg } 82305b261ecSmrg } 82405b261ecSmrg if (changes && (lowChange>0)) { /* something changed */ 82505b261ecSmrg if (changes->map.changed&XkbKeyActionsMask) { 82605b261ecSmrg int last; 82705b261ecSmrg if (changes->map.first_key_act<lowChange) 82805b261ecSmrg lowChange= changes->map.first_key_act; 82905b261ecSmrg last= changes->map.first_key_act+changes->map.num_key_acts-1; 83005b261ecSmrg if (last>highChange) 83105b261ecSmrg highChange= last; 83205b261ecSmrg } 83305b261ecSmrg changes->map.changed|= XkbKeyActionsMask; 83405b261ecSmrg changes->map.first_key_act= lowChange; 83505b261ecSmrg changes->map.num_key_acts= (highChange-lowChange)+1; 83605b261ecSmrg } 83705b261ecSmrg } 83805b261ecSmrg return checkState; 83905b261ecSmrg} 840