XKBMisc.c revision 35c4bbdf
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 935c4bbdfSmrgdocumentation, and that the name of Silicon Graphics not be 1035c4bbdfSmrgused in advertising or publicity pertaining to distribution 1105b261ecSmrgof the software without specific prior written permission. 1235c4bbdfSmrgSilicon 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 1635c4bbdfSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 1735c4bbdfSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 1805b261ecSmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 1935c4bbdfSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 2035c4bbdfSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 2135c4bbdfSmrgDATA 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 4835c4bbdfSmrgXkbKeyTypesForCoreSymbols(XkbDescPtr xkb, 4935c4bbdfSmrg int map_width, 5035c4bbdfSmrg KeySym * core_syms, 5135c4bbdfSmrg unsigned int protected, 5235c4bbdfSmrg int *types_inout, KeySym * xkb_syms_rtrn) 5305b261ecSmrg{ 5435c4bbdfSmrg register int i; 5535c4bbdfSmrg unsigned int empty; 5635c4bbdfSmrg int nSyms[XkbNumKbdGroups]; 5735c4bbdfSmrg int nGroups, tmp, groupsWidth; 5835c4bbdfSmrg BOOL replicated = FALSE; 5905b261ecSmrg 6005b261ecSmrg /* Section 12.2 of the protocol describes this process in more detail */ 6105b261ecSmrg /* Step 1: find the # of symbols in the core mapping per group */ 6235c4bbdfSmrg groupsWidth = 2; 6335c4bbdfSmrg for (i = 0; i < XkbNumKbdGroups; i++) { 6435c4bbdfSmrg if ((protected & (1 << i)) && (types_inout[i] < xkb->map->num_types)) { 6535c4bbdfSmrg nSyms[i] = xkb->map->types[types_inout[i]].num_levels; 6635c4bbdfSmrg if (nSyms[i] > groupsWidth) 6735c4bbdfSmrg groupsWidth = nSyms[i]; 6835c4bbdfSmrg } 6935c4bbdfSmrg else { 7035c4bbdfSmrg types_inout[i] = XkbTwoLevelIndex; /* don't really know, yet */ 7135c4bbdfSmrg nSyms[i] = 2; 7235c4bbdfSmrg } 7335c4bbdfSmrg } 7435c4bbdfSmrg if (nSyms[XkbGroup1Index] < 2) 7535c4bbdfSmrg nSyms[XkbGroup1Index] = 2; 7635c4bbdfSmrg if (nSyms[XkbGroup2Index] < 2) 7735c4bbdfSmrg nSyms[XkbGroup2Index] = 2; 7835c4bbdfSmrg /* Step 2: Copy the symbols from the core ordering to XKB ordering */ 7935c4bbdfSmrg /* symbols in the core are in the order: */ 8035c4bbdfSmrg /* G1L1 G1L2 G2L1 G2L2 [G1L[3-n]] [G2L[3-n]] [G3L*] [G3L*] */ 8135c4bbdfSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index, 0)] = CORE_SYM(0); 8235c4bbdfSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index, 1)] = CORE_SYM(1); 8335c4bbdfSmrg for (i = 2; i < nSyms[XkbGroup1Index]; i++) { 8435c4bbdfSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index, i)] = CORE_SYM(2 + i); 8535c4bbdfSmrg } 8635c4bbdfSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index, 0)] = CORE_SYM(2); 8735c4bbdfSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index, 1)] = CORE_SYM(3); 8835c4bbdfSmrg tmp = 2 + (nSyms[XkbGroup1Index] - 2); /* offset to extra group2 syms */ 8935c4bbdfSmrg for (i = 2; i < nSyms[XkbGroup2Index]; i++) { 9035c4bbdfSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index, i)] = CORE_SYM(tmp + i); 9105b261ecSmrg } 926747b715Smrg 936747b715Smrg /* Special case: if only the first group is explicit, and the symbols 946747b715Smrg * replicate across all groups, then we have a Section 12.4 replication */ 9535c4bbdfSmrg if ((protected & ~XkbExplicitKeyType1Mask) == 0) { 966747b715Smrg int j, width = nSyms[XkbGroup1Index]; 976747b715Smrg 986747b715Smrg replicated = TRUE; 996747b715Smrg 1006747b715Smrg /* Check ABAB in ABABCDECDEABCDE */ 1016747b715Smrg if ((width > 0 && CORE_SYM(0) != CORE_SYM(2)) || 1026747b715Smrg (width > 1 && CORE_SYM(1) != CORE_SYM(3))) 1036747b715Smrg replicated = FALSE; 1046747b715Smrg 1056747b715Smrg /* Check CDECDE in ABABCDECDEABCDE */ 10635c4bbdfSmrg for (i = 2; i < width && replicated; i++) { 1076747b715Smrg if (CORE_SYM(2 + i) != CORE_SYM(i + width)) 1086747b715Smrg replicated = FALSE; 1096747b715Smrg } 1106747b715Smrg 1116747b715Smrg /* Check ABCDE in ABABCDECDEABCDE */ 1126747b715Smrg for (j = 2; replicated && 11335c4bbdfSmrg j < XkbNumKbdGroups && map_width >= width * (j + 1); j++) { 11435c4bbdfSmrg for (i = 0; i < width && replicated; i++) { 1156747b715Smrg if (CORE_SYM(((i < 2) ? i : 2 + i)) != CORE_SYM(i + width * j)) 1166747b715Smrg replicated = FALSE; 1176747b715Smrg } 1186747b715Smrg } 1196747b715Smrg } 1206747b715Smrg 12135c4bbdfSmrg if (replicated) { 12235c4bbdfSmrg nSyms[XkbGroup2Index] = 0; 12335c4bbdfSmrg nSyms[XkbGroup3Index] = 0; 12435c4bbdfSmrg nSyms[XkbGroup4Index] = 0; 12535c4bbdfSmrg nGroups = 1; 12635c4bbdfSmrg } 12735c4bbdfSmrg else { 12835c4bbdfSmrg tmp = nSyms[XkbGroup1Index] + nSyms[XkbGroup2Index]; 12935c4bbdfSmrg if ((tmp >= map_width) && 13035c4bbdfSmrg ((protected & (XkbExplicitKeyType3Mask | XkbExplicitKeyType4Mask)) 13135c4bbdfSmrg == 0)) { 13235c4bbdfSmrg nSyms[XkbGroup3Index] = 0; 13335c4bbdfSmrg nSyms[XkbGroup4Index] = 0; 13435c4bbdfSmrg nGroups = 2; 13535c4bbdfSmrg } 13635c4bbdfSmrg else { 13735c4bbdfSmrg nGroups = 3; 13835c4bbdfSmrg for (i = 0; i < nSyms[XkbGroup3Index]; i++, tmp++) { 13935c4bbdfSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup3Index, i)] = CORE_SYM(tmp); 1406747b715Smrg } 14135c4bbdfSmrg if ((tmp < map_width) || (protected & XkbExplicitKeyType4Mask)) { 14235c4bbdfSmrg nGroups = 4; 14335c4bbdfSmrg for (i = 0; i < nSyms[XkbGroup4Index]; i++, tmp++) { 14435c4bbdfSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup4Index, i)] = 14535c4bbdfSmrg CORE_SYM(tmp); 1466747b715Smrg } 1476747b715Smrg } 1486747b715Smrg else { 14935c4bbdfSmrg nSyms[XkbGroup4Index] = 0; 1506747b715Smrg } 1516747b715Smrg } 15205b261ecSmrg } 15305b261ecSmrg /* steps 3&4: alphanumeric expansion, assign canonical types */ 15435c4bbdfSmrg empty = 0; 15535c4bbdfSmrg for (i = 0; i < nGroups; i++) { 15635c4bbdfSmrg KeySym *syms; 15735c4bbdfSmrg 15835c4bbdfSmrg syms = &xkb_syms_rtrn[XKB_OFFSET(i, 0)]; 15935c4bbdfSmrg if ((nSyms[i] > 1) && (syms[1] == NoSymbol) && (syms[0] != NoSymbol)) { 16035c4bbdfSmrg KeySym upper, lower; 16135c4bbdfSmrg 16235c4bbdfSmrg XkbConvertCase(syms[0], &lower, &upper); 16335c4bbdfSmrg if (upper != lower) { 16435c4bbdfSmrg xkb_syms_rtrn[XKB_OFFSET(i, 0)] = lower; 16535c4bbdfSmrg xkb_syms_rtrn[XKB_OFFSET(i, 1)] = upper; 16635c4bbdfSmrg if ((protected & (1 << i)) == 0) 16735c4bbdfSmrg types_inout[i] = XkbAlphabeticIndex; 16835c4bbdfSmrg } 16935c4bbdfSmrg else if ((protected & (1 << i)) == 0) { 17035c4bbdfSmrg types_inout[i] = XkbOneLevelIndex; 17135c4bbdfSmrg /* nSyms[i]= 1; */ 17235c4bbdfSmrg } 17335c4bbdfSmrg } 17435c4bbdfSmrg if (((protected & (1 << i)) == 0) && 17535c4bbdfSmrg (types_inout[i] == XkbTwoLevelIndex)) { 17635c4bbdfSmrg if (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1])) 17735c4bbdfSmrg types_inout[i] = XkbKeypadIndex; 17835c4bbdfSmrg else { 17935c4bbdfSmrg KeySym upper, lower; 18035c4bbdfSmrg 18135c4bbdfSmrg XkbConvertCase(syms[0], &lower, &upper); 18235c4bbdfSmrg if ((syms[0] == lower) && (syms[1] == upper)) 18335c4bbdfSmrg types_inout[i] = XkbAlphabeticIndex; 18435c4bbdfSmrg } 18535c4bbdfSmrg } 18635c4bbdfSmrg if (syms[0] == NoSymbol) { 18735c4bbdfSmrg register int n; 18835c4bbdfSmrg Bool found; 18935c4bbdfSmrg 19035c4bbdfSmrg for (n = 1, found = FALSE; (!found) && (n < nSyms[i]); n++) { 19135c4bbdfSmrg found = (syms[n] != NoSymbol); 19235c4bbdfSmrg } 19335c4bbdfSmrg if (!found) 19435c4bbdfSmrg empty |= (1 << i); 19535c4bbdfSmrg } 19605b261ecSmrg } 19705b261ecSmrg /* step 5: squoosh out empty groups */ 19805b261ecSmrg if (empty) { 19935c4bbdfSmrg for (i = nGroups - 1; i >= 0; i--) { 20035c4bbdfSmrg if (((empty & (1 << i)) == 0) || (protected & (1 << i))) 20135c4bbdfSmrg break; 20235c4bbdfSmrg nGroups--; 20335c4bbdfSmrg } 20405b261ecSmrg } 20535c4bbdfSmrg if (nGroups < 1) 20635c4bbdfSmrg return 0; 20705b261ecSmrg 20805b261ecSmrg /* step 6: replicate group 1 into group two, if necessary */ 20935c4bbdfSmrg if ((nGroups > 1) && 21035c4bbdfSmrg ((empty & (XkbGroup1Mask | XkbGroup2Mask)) == XkbGroup2Mask)) { 21135c4bbdfSmrg if ((protected & (XkbExplicitKeyType1Mask | XkbExplicitKeyType2Mask)) == 21235c4bbdfSmrg 0) { 21335c4bbdfSmrg nSyms[XkbGroup2Index] = nSyms[XkbGroup1Index]; 21435c4bbdfSmrg types_inout[XkbGroup2Index] = types_inout[XkbGroup1Index]; 21535c4bbdfSmrg memcpy((char *) &xkb_syms_rtrn[2], (char *) xkb_syms_rtrn, 21635c4bbdfSmrg 2 * sizeof(KeySym)); 21735c4bbdfSmrg } 21835c4bbdfSmrg else if (types_inout[XkbGroup1Index] == types_inout[XkbGroup2Index]) { 21935c4bbdfSmrg memcpy((char *) &xkb_syms_rtrn[nSyms[XkbGroup1Index]], 22035c4bbdfSmrg (char *) xkb_syms_rtrn, 22135c4bbdfSmrg nSyms[XkbGroup1Index] * sizeof(KeySym)); 22235c4bbdfSmrg } 22305b261ecSmrg } 22405b261ecSmrg 2254642e01fSmrg /* step 7: check for all groups identical or all width 1 2264642e01fSmrg * 2274642e01fSmrg * Special feature: if group 1 has an explicit type and all other groups 2284642e01fSmrg * have canonical types with same symbols, we assume it's info lost from 2294642e01fSmrg * the core replication. 2304642e01fSmrg */ 23135c4bbdfSmrg if (nGroups > 1) { 23235c4bbdfSmrg Bool sameType, allOneLevel, canonical = TRUE; 23335c4bbdfSmrg 23435c4bbdfSmrg allOneLevel = (xkb->map->types[types_inout[0]].num_levels == 1); 23535c4bbdfSmrg for (i = 1, sameType = TRUE; (allOneLevel || sameType) && (i < nGroups); 23635c4bbdfSmrg i++) { 23735c4bbdfSmrg sameType = (sameType && 23835c4bbdfSmrg (types_inout[i] == types_inout[XkbGroup1Index])); 23935c4bbdfSmrg if (allOneLevel) 24035c4bbdfSmrg allOneLevel = (xkb->map->types[types_inout[i]].num_levels == 1); 24135c4bbdfSmrg if (types_inout[i] > XkbLastRequiredType) 24235c4bbdfSmrg canonical = FALSE; 24335c4bbdfSmrg } 24435c4bbdfSmrg if (((sameType) || canonical) && 24535c4bbdfSmrg (!(protected & 24635c4bbdfSmrg (XkbExplicitKeyTypesMask & ~XkbExplicitKeyType1Mask)))) { 24735c4bbdfSmrg register int s; 24835c4bbdfSmrg Bool identical; 24935c4bbdfSmrg 25035c4bbdfSmrg for (i = 1, identical = TRUE; identical && (i < nGroups); i++) { 25135c4bbdfSmrg KeySym *syms; 25235c4bbdfSmrg 2536747b715Smrg if (nSyms[i] != nSyms[XkbGroup1Index]) 2546747b715Smrg identical = FALSE; 25535c4bbdfSmrg syms = &xkb_syms_rtrn[XKB_OFFSET(i, 0)]; 25635c4bbdfSmrg for (s = 0; identical && (s < nSyms[i]); s++) { 25735c4bbdfSmrg if (syms[s] != xkb_syms_rtrn[s]) 25835c4bbdfSmrg identical = FALSE; 25935c4bbdfSmrg } 26035c4bbdfSmrg } 26135c4bbdfSmrg if (identical) 26235c4bbdfSmrg nGroups = 1; 26335c4bbdfSmrg } 26435c4bbdfSmrg if (allOneLevel && (nGroups > 1)) { 26535c4bbdfSmrg KeySym *syms; 26635c4bbdfSmrg 26735c4bbdfSmrg syms = &xkb_syms_rtrn[nSyms[XkbGroup1Index]]; 26835c4bbdfSmrg nSyms[XkbGroup1Index] = 1; 26935c4bbdfSmrg for (i = 1; i < nGroups; i++) { 27035c4bbdfSmrg xkb_syms_rtrn[i] = syms[0]; 27135c4bbdfSmrg syms += nSyms[i]; 27235c4bbdfSmrg nSyms[i] = 1; 27335c4bbdfSmrg } 27435c4bbdfSmrg } 27505b261ecSmrg } 27605b261ecSmrg return nGroups; 27705b261ecSmrg} 27805b261ecSmrg 27905b261ecSmrgstatic XkbSymInterpretPtr 28035c4bbdfSmrg_XkbFindMatchingInterp(XkbDescPtr xkb, 28135c4bbdfSmrg KeySym sym, unsigned int real_mods, unsigned int level) 28205b261ecSmrg{ 28335c4bbdfSmrg register unsigned i; 28435c4bbdfSmrg XkbSymInterpretPtr interp, rtrn; 28535c4bbdfSmrg CARD8 mods; 28635c4bbdfSmrg 28735c4bbdfSmrg rtrn = NULL; 28835c4bbdfSmrg interp = xkb->compat->sym_interpret; 28935c4bbdfSmrg for (i = 0; i < xkb->compat->num_si; i++, interp++) { 29035c4bbdfSmrg if ((interp->sym == NoSymbol) || (sym == interp->sym)) { 29135c4bbdfSmrg int match; 29235c4bbdfSmrg 29335c4bbdfSmrg if ((level == 0) || ((interp->match & XkbSI_LevelOneOnly) == 0)) 29435c4bbdfSmrg mods = real_mods; 29535c4bbdfSmrg else 29635c4bbdfSmrg mods = 0; 29735c4bbdfSmrg switch (interp->match & XkbSI_OpMask) { 29835c4bbdfSmrg case XkbSI_NoneOf: 29935c4bbdfSmrg match = ((interp->mods & mods) == 0); 30035c4bbdfSmrg break; 30135c4bbdfSmrg case XkbSI_AnyOfOrNone: 30235c4bbdfSmrg match = ((mods == 0) || ((interp->mods & mods) != 0)); 30335c4bbdfSmrg break; 30435c4bbdfSmrg case XkbSI_AnyOf: 30535c4bbdfSmrg match = ((interp->mods & mods) != 0); 30635c4bbdfSmrg break; 30735c4bbdfSmrg case XkbSI_AllOf: 30835c4bbdfSmrg match = ((interp->mods & mods) == interp->mods); 30935c4bbdfSmrg break; 31035c4bbdfSmrg case XkbSI_Exactly: 31135c4bbdfSmrg match = (interp->mods == mods); 31235c4bbdfSmrg break; 31335c4bbdfSmrg default: 31435c4bbdfSmrg match = 0; 31535c4bbdfSmrg break; 31635c4bbdfSmrg } 31735c4bbdfSmrg if (match) { 31835c4bbdfSmrg if (interp->sym != NoSymbol) { 31935c4bbdfSmrg return interp; 32035c4bbdfSmrg } 32135c4bbdfSmrg else if (rtrn == NULL) { 32235c4bbdfSmrg rtrn = interp; 32335c4bbdfSmrg } 32435c4bbdfSmrg } 32535c4bbdfSmrg } 32605b261ecSmrg } 32705b261ecSmrg return rtrn; 32805b261ecSmrg} 32905b261ecSmrg 33005b261ecSmrgstatic void 33135c4bbdfSmrg_XkbAddKeyChange(KeyCode *pFirst, unsigned char *pNum, KeyCode newKey) 33205b261ecSmrg{ 33335c4bbdfSmrg KeyCode last; 33405b261ecSmrg 33535c4bbdfSmrg last = (*pFirst) + (*pNum); 33635c4bbdfSmrg if (newKey < *pFirst) { 33735c4bbdfSmrg *pFirst = newKey; 33835c4bbdfSmrg *pNum = (last - newKey) + 1; 33905b261ecSmrg } 34035c4bbdfSmrg else if (newKey > last) { 34135c4bbdfSmrg *pNum = (last - *pFirst) + 1; 34205b261ecSmrg } 34305b261ecSmrg return; 34405b261ecSmrg} 34505b261ecSmrg 34605b261ecSmrgstatic void 34735c4bbdfSmrg_XkbSetActionKeyMods(XkbDescPtr xkb, XkbAction *act, unsigned mods) 34805b261ecSmrg{ 34935c4bbdfSmrg unsigned tmp; 35005b261ecSmrg 35105b261ecSmrg switch (act->type) { 35235c4bbdfSmrg case XkbSA_SetMods: 35335c4bbdfSmrg case XkbSA_LatchMods: 35435c4bbdfSmrg case XkbSA_LockMods: 35535c4bbdfSmrg if (act->mods.flags & XkbSA_UseModMapMods) 35635c4bbdfSmrg act->mods.real_mods = act->mods.mask = mods; 35735c4bbdfSmrg if ((tmp = XkbModActionVMods(&act->mods)) != 0) { 35835c4bbdfSmrg XkbVirtualModsToReal(xkb, tmp, &tmp); 35935c4bbdfSmrg act->mods.mask |= tmp; 36035c4bbdfSmrg } 36135c4bbdfSmrg break; 36235c4bbdfSmrg case XkbSA_ISOLock: 36335c4bbdfSmrg if (act->iso.flags & XkbSA_UseModMapMods) 36435c4bbdfSmrg act->iso.real_mods = act->iso.mask = mods; 36535c4bbdfSmrg if ((tmp = XkbModActionVMods(&act->iso)) != 0) { 36635c4bbdfSmrg XkbVirtualModsToReal(xkb, tmp, &tmp); 36735c4bbdfSmrg act->iso.mask |= tmp; 36835c4bbdfSmrg } 36935c4bbdfSmrg break; 37005b261ecSmrg } 37105b261ecSmrg return; 37205b261ecSmrg} 37305b261ecSmrg 37405b261ecSmrg#define IBUF_SIZE 8 37505b261ecSmrg 37605b261ecSmrgBool 37735c4bbdfSmrgXkbApplyCompatMapToKey(XkbDescPtr xkb, KeyCode key, XkbChangesPtr changes) 37805b261ecSmrg{ 37935c4bbdfSmrg KeySym *syms; 38035c4bbdfSmrg unsigned char explicit, mods; 38135c4bbdfSmrg XkbSymInterpretPtr *interps, ibuf[IBUF_SIZE]; 38235c4bbdfSmrg int n, nSyms, found; 38335c4bbdfSmrg unsigned changed, tmp; 38435c4bbdfSmrg 38535c4bbdfSmrg if ((!xkb) || (!xkb->map) || (!xkb->map->key_sym_map) || 38635c4bbdfSmrg (!xkb->compat) || (!xkb->compat->sym_interpret) || 38735c4bbdfSmrg (key < xkb->min_key_code) || (key > xkb->max_key_code)) { 38835c4bbdfSmrg return FALSE; 38935c4bbdfSmrg } 39035c4bbdfSmrg if (((!xkb->server) || (!xkb->server->key_acts)) && 39135c4bbdfSmrg (XkbAllocServerMap(xkb, XkbAllServerInfoMask, 0) != Success)) { 39235c4bbdfSmrg return FALSE; 39335c4bbdfSmrg } 39435c4bbdfSmrg changed = 0; /* keeps track of what has changed in _this_ call */ 39535c4bbdfSmrg explicit = xkb->server->explicit[key]; 39635c4bbdfSmrg if (explicit & XkbExplicitInterpretMask) /* nothing to do */ 39735c4bbdfSmrg return TRUE; 39835c4bbdfSmrg mods = (xkb->map->modmap ? xkb->map->modmap[key] : 0); 39935c4bbdfSmrg nSyms = XkbKeyNumSyms(xkb, key); 40035c4bbdfSmrg syms = XkbKeySymsPtr(xkb, key); 40135c4bbdfSmrg if (nSyms > IBUF_SIZE) { 40235c4bbdfSmrg interps = calloc(nSyms, sizeof(XkbSymInterpretPtr)); 40335c4bbdfSmrg if (interps == NULL) { 40435c4bbdfSmrg interps = ibuf; 40535c4bbdfSmrg nSyms = IBUF_SIZE; 40635c4bbdfSmrg } 40705b261ecSmrg } 40805b261ecSmrg else { 40935c4bbdfSmrg interps = ibuf; 41035c4bbdfSmrg } 41135c4bbdfSmrg found = 0; 41235c4bbdfSmrg for (n = 0; n < nSyms; n++) { 41335c4bbdfSmrg unsigned level = (n % XkbKeyGroupsWidth(xkb, key)); 41435c4bbdfSmrg 41535c4bbdfSmrg interps[n] = NULL; 41635c4bbdfSmrg if (syms[n] != NoSymbol) { 41735c4bbdfSmrg interps[n] = _XkbFindMatchingInterp(xkb, syms[n], mods, level); 41835c4bbdfSmrg if (interps[n] && interps[n]->act.type != XkbSA_NoAction) 41935c4bbdfSmrg found++; 42035c4bbdfSmrg else 42135c4bbdfSmrg interps[n] = NULL; 42235c4bbdfSmrg } 42305b261ecSmrg } 42405b261ecSmrg /* 1/28/96 (ef) -- XXX! WORKING HERE */ 42505b261ecSmrg if (!found) { 42635c4bbdfSmrg if (xkb->server->key_acts[key] != 0) { 42735c4bbdfSmrg xkb->server->key_acts[key] = 0; 42835c4bbdfSmrg changed |= XkbKeyActionsMask; 42935c4bbdfSmrg } 43005b261ecSmrg } 43105b261ecSmrg else { 43235c4bbdfSmrg XkbAction *pActs; 43335c4bbdfSmrg unsigned int new_vmodmask; 43435c4bbdfSmrg 43535c4bbdfSmrg changed |= XkbKeyActionsMask; 43635c4bbdfSmrg pActs = XkbResizeKeyActions(xkb, key, nSyms); 43735c4bbdfSmrg if (!pActs) { 43805b261ecSmrg if (nSyms > IBUF_SIZE) 4396747b715Smrg free(interps); 44035c4bbdfSmrg return FALSE; 44135c4bbdfSmrg } 44235c4bbdfSmrg new_vmodmask = 0; 44335c4bbdfSmrg for (n = 0; n < nSyms; n++) { 44435c4bbdfSmrg if (interps[n]) { 44535c4bbdfSmrg unsigned effMods; 44635c4bbdfSmrg 44735c4bbdfSmrg pActs[n] = *((XkbAction *) &interps[n]->act); 44835c4bbdfSmrg if ((n == 0) || ((interps[n]->match & XkbSI_LevelOneOnly) == 0)) { 44935c4bbdfSmrg effMods = mods; 45035c4bbdfSmrg if (interps[n]->virtual_mod != XkbNoModifier) 45135c4bbdfSmrg new_vmodmask |= (1 << interps[n]->virtual_mod); 45235c4bbdfSmrg } 45335c4bbdfSmrg else 45435c4bbdfSmrg effMods = 0; 45535c4bbdfSmrg _XkbSetActionKeyMods(xkb, &pActs[n], effMods); 45635c4bbdfSmrg } 45735c4bbdfSmrg else 45835c4bbdfSmrg pActs[n].type = XkbSA_NoAction; 45935c4bbdfSmrg } 46035c4bbdfSmrg if (((explicit & XkbExplicitVModMapMask) == 0) && 46135c4bbdfSmrg (xkb->server->vmodmap[key] != new_vmodmask)) { 46235c4bbdfSmrg changed |= XkbVirtualModMapMask; 46335c4bbdfSmrg xkb->server->vmodmap[key] = new_vmodmask; 46435c4bbdfSmrg } 46535c4bbdfSmrg if (interps[0]) { 46635c4bbdfSmrg if ((interps[0]->flags & XkbSI_LockingKey) && 46735c4bbdfSmrg ((explicit & XkbExplicitBehaviorMask) == 0)) { 46835c4bbdfSmrg xkb->server->behaviors[key].type = XkbKB_Lock; 46935c4bbdfSmrg changed |= XkbKeyBehaviorsMask; 47035c4bbdfSmrg } 47135c4bbdfSmrg if (((explicit & XkbExplicitAutoRepeatMask) == 0) && (xkb->ctrls)) { 47235c4bbdfSmrg CARD8 old; 47335c4bbdfSmrg 47435c4bbdfSmrg old = BitIsOn(xkb->ctrls->per_key_repeat, key); 47535c4bbdfSmrg if (interps[0]->flags & XkbSI_AutoRepeat) 47635c4bbdfSmrg SetBit(xkb->ctrls->per_key_repeat, key); 47735c4bbdfSmrg else 47835c4bbdfSmrg ClearBit(xkb->ctrls->per_key_repeat, key); 47935c4bbdfSmrg if (changes && old != BitIsOn(xkb->ctrls->per_key_repeat, key)) 48035c4bbdfSmrg changes->ctrls.changed_ctrls |= XkbPerKeyRepeatMask; 48135c4bbdfSmrg } 48235c4bbdfSmrg } 48335c4bbdfSmrg } 48435c4bbdfSmrg if ((!found) || (interps[0] == NULL)) { 48535c4bbdfSmrg if (((explicit & XkbExplicitAutoRepeatMask) == 0) && (xkb->ctrls)) { 48635c4bbdfSmrg CARD8 old; 48735c4bbdfSmrg 48835c4bbdfSmrg old = BitIsOn(xkb->ctrls->per_key_repeat, key); 48935c4bbdfSmrg SetBit(xkb->ctrls->per_key_repeat, key); 49035c4bbdfSmrg if (changes && (old != BitIsOn(xkb->ctrls->per_key_repeat, key))) 49135c4bbdfSmrg changes->ctrls.changed_ctrls |= XkbPerKeyRepeatMask; 49235c4bbdfSmrg } 49335c4bbdfSmrg if (((explicit & XkbExplicitBehaviorMask) == 0) && 49435c4bbdfSmrg (xkb->server->behaviors[key].type == XkbKB_Lock)) { 49535c4bbdfSmrg xkb->server->behaviors[key].type = XkbKB_Default; 49635c4bbdfSmrg changed |= XkbKeyBehaviorsMask; 49735c4bbdfSmrg } 49805b261ecSmrg } 49905b261ecSmrg if (changes) { 50035c4bbdfSmrg XkbMapChangesPtr mc; 50135c4bbdfSmrg 50235c4bbdfSmrg mc = &changes->map; 50335c4bbdfSmrg tmp = (changed & mc->changed); 50435c4bbdfSmrg if (tmp & XkbKeyActionsMask) 50535c4bbdfSmrg _XkbAddKeyChange(&mc->first_key_act, &mc->num_key_acts, key); 50635c4bbdfSmrg else if (changed & XkbKeyActionsMask) { 50735c4bbdfSmrg mc->changed |= XkbKeyActionsMask; 50835c4bbdfSmrg mc->first_key_act = key; 50935c4bbdfSmrg mc->num_key_acts = 1; 51035c4bbdfSmrg } 51135c4bbdfSmrg if (tmp & XkbKeyBehaviorsMask) { 51235c4bbdfSmrg _XkbAddKeyChange(&mc->first_key_behavior, &mc->num_key_behaviors, 51335c4bbdfSmrg key); 51435c4bbdfSmrg } 51535c4bbdfSmrg else if (changed & XkbKeyBehaviorsMask) { 51635c4bbdfSmrg mc->changed |= XkbKeyBehaviorsMask; 51735c4bbdfSmrg mc->first_key_behavior = key; 51835c4bbdfSmrg mc->num_key_behaviors = 1; 51935c4bbdfSmrg } 52035c4bbdfSmrg if (tmp & XkbVirtualModMapMask) 52135c4bbdfSmrg _XkbAddKeyChange(&mc->first_vmodmap_key, &mc->num_vmodmap_keys, 52235c4bbdfSmrg key); 52335c4bbdfSmrg else if (changed & XkbVirtualModMapMask) { 52435c4bbdfSmrg mc->changed |= XkbVirtualModMapMask; 52535c4bbdfSmrg mc->first_vmodmap_key = key; 52635c4bbdfSmrg mc->num_vmodmap_keys = 1; 52735c4bbdfSmrg } 52835c4bbdfSmrg mc->changed |= changed; 52935c4bbdfSmrg } 53035c4bbdfSmrg if (interps != ibuf) 53135c4bbdfSmrg free(interps); 5326747b715Smrg return TRUE; 53305b261ecSmrg} 53405b261ecSmrg 53505b261ecSmrgStatus 53635c4bbdfSmrgXkbChangeTypesOfKey(XkbDescPtr xkb, 53735c4bbdfSmrg int key, 53835c4bbdfSmrg int nGroups, 53935c4bbdfSmrg unsigned groups, int *newTypesIn, XkbMapChangesPtr changes) 54005b261ecSmrg{ 54135c4bbdfSmrg XkbKeyTypePtr pOldType, pNewType; 54235c4bbdfSmrg register int i; 54335c4bbdfSmrg int width, nOldGroups, oldWidth, newTypes[XkbNumKbdGroups]; 54435c4bbdfSmrg 54535c4bbdfSmrg if ((!xkb) || (!XkbKeycodeInRange(xkb, key)) || (!xkb->map) || 54635c4bbdfSmrg (!xkb->map->types) || (!newTypesIn) || 54735c4bbdfSmrg ((groups & XkbAllGroupsMask) == 0) || (nGroups > XkbNumKbdGroups)) { 54835c4bbdfSmrg return BadMatch; 54935c4bbdfSmrg } 55035c4bbdfSmrg if (nGroups == 0) { 55135c4bbdfSmrg for (i = 0; i < XkbNumKbdGroups; i++) { 55235c4bbdfSmrg xkb->map->key_sym_map[key].kt_index[i] = XkbOneLevelIndex; 55335c4bbdfSmrg } 55435c4bbdfSmrg i = xkb->map->key_sym_map[key].group_info; 55535c4bbdfSmrg i = XkbSetNumGroups(i, 0); 55635c4bbdfSmrg xkb->map->key_sym_map[key].group_info = i; 55735c4bbdfSmrg XkbResizeKeySyms(xkb, key, 0); 55835c4bbdfSmrg return Success; 55935c4bbdfSmrg } 56035c4bbdfSmrg 56135c4bbdfSmrg nOldGroups = XkbKeyNumGroups(xkb, key); 56235c4bbdfSmrg oldWidth = XkbKeyGroupsWidth(xkb, key); 56335c4bbdfSmrg for (width = i = 0; i < nGroups; i++) { 56435c4bbdfSmrg if (groups & (1 << i)) 56535c4bbdfSmrg newTypes[i] = newTypesIn[i]; 56635c4bbdfSmrg else if (i < nOldGroups) 56735c4bbdfSmrg newTypes[i] = XkbKeyKeyTypeIndex(xkb, key, i); 56835c4bbdfSmrg else if (nOldGroups > 0) 56935c4bbdfSmrg newTypes[i] = XkbKeyKeyTypeIndex(xkb, key, XkbGroup1Index); 57035c4bbdfSmrg else 57135c4bbdfSmrg newTypes[i] = XkbTwoLevelIndex; 57235c4bbdfSmrg if (newTypes[i] > xkb->map->num_types) 57335c4bbdfSmrg return BadMatch; 57435c4bbdfSmrg pNewType = &xkb->map->types[newTypes[i]]; 57535c4bbdfSmrg if (pNewType->num_levels > width) 57635c4bbdfSmrg width = pNewType->num_levels; 57735c4bbdfSmrg } 57835c4bbdfSmrg if ((xkb->ctrls) && (nGroups > xkb->ctrls->num_groups)) 57935c4bbdfSmrg xkb->ctrls->num_groups = nGroups; 58035c4bbdfSmrg if ((width != oldWidth) || (nGroups != nOldGroups)) { 58135c4bbdfSmrg KeySym oldSyms[XkbMaxSymsPerKey], *pSyms; 58235c4bbdfSmrg int nCopy; 58335c4bbdfSmrg 58435c4bbdfSmrg if (nOldGroups == 0) { 58535c4bbdfSmrg pSyms = XkbResizeKeySyms(xkb, key, width * nGroups); 58635c4bbdfSmrg if (pSyms != NULL) { 58735c4bbdfSmrg i = xkb->map->key_sym_map[key].group_info; 58835c4bbdfSmrg i = XkbSetNumGroups(i, nGroups); 58935c4bbdfSmrg xkb->map->key_sym_map[key].group_info = i; 59035c4bbdfSmrg xkb->map->key_sym_map[key].width = width; 59135c4bbdfSmrg for (i = 0; i < nGroups; i++) { 59235c4bbdfSmrg xkb->map->key_sym_map[key].kt_index[i] = newTypes[i]; 59335c4bbdfSmrg } 59435c4bbdfSmrg return Success; 59535c4bbdfSmrg } 59635c4bbdfSmrg return BadAlloc; 59735c4bbdfSmrg } 59835c4bbdfSmrg pSyms = XkbKeySymsPtr(xkb, key); 59935c4bbdfSmrg memcpy(oldSyms, pSyms, XkbKeyNumSyms(xkb, key) * sizeof(KeySym)); 60035c4bbdfSmrg pSyms = XkbResizeKeySyms(xkb, key, width * nGroups); 60135c4bbdfSmrg if (pSyms == NULL) 60235c4bbdfSmrg return BadAlloc; 60335c4bbdfSmrg memset(pSyms, 0, width * nGroups * sizeof(KeySym)); 60435c4bbdfSmrg for (i = 0; (i < nGroups) && (i < nOldGroups); i++) { 60535c4bbdfSmrg pOldType = XkbKeyKeyType(xkb, key, i); 60635c4bbdfSmrg pNewType = &xkb->map->types[newTypes[i]]; 60735c4bbdfSmrg if (pNewType->num_levels > pOldType->num_levels) 60835c4bbdfSmrg nCopy = pOldType->num_levels; 60935c4bbdfSmrg else 61035c4bbdfSmrg nCopy = pNewType->num_levels; 61135c4bbdfSmrg memcpy(&pSyms[i * width], &oldSyms[i * oldWidth], 61235c4bbdfSmrg nCopy * sizeof(KeySym)); 61335c4bbdfSmrg } 61435c4bbdfSmrg if (XkbKeyHasActions(xkb, key)) { 61535c4bbdfSmrg XkbAction oldActs[XkbMaxSymsPerKey], *pActs; 61635c4bbdfSmrg 61735c4bbdfSmrg pActs = XkbKeyActionsPtr(xkb, key); 61835c4bbdfSmrg memcpy(oldActs, pActs, XkbKeyNumSyms(xkb, key) * sizeof(XkbAction)); 61935c4bbdfSmrg pActs = XkbResizeKeyActions(xkb, key, width * nGroups); 62035c4bbdfSmrg if (pActs == NULL) 62135c4bbdfSmrg return BadAlloc; 62235c4bbdfSmrg memset(pActs, 0, width * nGroups * sizeof(XkbAction)); 62335c4bbdfSmrg for (i = 0; (i < nGroups) && (i < nOldGroups); i++) { 62435c4bbdfSmrg pOldType = XkbKeyKeyType(xkb, key, i); 62535c4bbdfSmrg pNewType = &xkb->map->types[newTypes[i]]; 62635c4bbdfSmrg if (pNewType->num_levels > pOldType->num_levels) 62735c4bbdfSmrg nCopy = pOldType->num_levels; 62835c4bbdfSmrg else 62935c4bbdfSmrg nCopy = pNewType->num_levels; 63035c4bbdfSmrg memcpy(&pActs[i * width], &oldActs[i * oldWidth], 63135c4bbdfSmrg nCopy * sizeof(XkbAction)); 63235c4bbdfSmrg } 63335c4bbdfSmrg } 63435c4bbdfSmrg i = xkb->map->key_sym_map[key].group_info; 63535c4bbdfSmrg i = XkbSetNumGroups(i, nGroups); 63635c4bbdfSmrg xkb->map->key_sym_map[key].group_info = i; 63735c4bbdfSmrg xkb->map->key_sym_map[key].width = width; 63835c4bbdfSmrg } 63935c4bbdfSmrg width = 0; 64035c4bbdfSmrg for (i = 0; i < nGroups; i++) { 64135c4bbdfSmrg xkb->map->key_sym_map[key].kt_index[i] = newTypes[i]; 64235c4bbdfSmrg if (xkb->map->types[newTypes[i]].num_levels > width) 64335c4bbdfSmrg width = xkb->map->types[newTypes[i]].num_levels; 64435c4bbdfSmrg } 64535c4bbdfSmrg xkb->map->key_sym_map[key].width = width; 64635c4bbdfSmrg if (changes != NULL) { 64735c4bbdfSmrg if (changes->changed & XkbKeySymsMask) { 64835c4bbdfSmrg _XkbAddKeyChange(&changes->first_key_sym, &changes->num_key_syms, 64935c4bbdfSmrg key); 65035c4bbdfSmrg } 65135c4bbdfSmrg else { 65235c4bbdfSmrg changes->changed |= XkbKeySymsMask; 65335c4bbdfSmrg changes->first_key_sym = key; 65435c4bbdfSmrg changes->num_key_syms = 1; 65535c4bbdfSmrg } 65605b261ecSmrg } 65705b261ecSmrg return Success; 65805b261ecSmrg} 65905b261ecSmrg 66005b261ecSmrg/***====================================================================***/ 66105b261ecSmrg 66205b261ecSmrgBool 66335c4bbdfSmrgXkbVirtualModsToReal(XkbDescPtr xkb, unsigned virtual_mask, unsigned *mask_rtrn) 66405b261ecSmrg{ 66535c4bbdfSmrg register int i, bit; 66635c4bbdfSmrg register unsigned mask; 66735c4bbdfSmrg 66835c4bbdfSmrg if (xkb == NULL) 66935c4bbdfSmrg return FALSE; 67035c4bbdfSmrg if (virtual_mask == 0) { 67135c4bbdfSmrg *mask_rtrn = 0; 67235c4bbdfSmrg return TRUE; 67335c4bbdfSmrg } 67435c4bbdfSmrg if (xkb->server == NULL) 67535c4bbdfSmrg return FALSE; 67635c4bbdfSmrg for (i = mask = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) { 67735c4bbdfSmrg if (virtual_mask & bit) 67835c4bbdfSmrg mask |= xkb->server->vmods[i]; 67935c4bbdfSmrg } 68035c4bbdfSmrg *mask_rtrn = mask; 6816747b715Smrg return TRUE; 68205b261ecSmrg} 68305b261ecSmrg 68405b261ecSmrg/***====================================================================***/ 68505b261ecSmrg 68605b261ecSmrgstatic Bool 68735c4bbdfSmrgXkbUpdateActionVirtualMods(XkbDescPtr xkb, XkbAction *act, unsigned changed) 68805b261ecSmrg{ 68935c4bbdfSmrg unsigned int tmp; 69005b261ecSmrg 69105b261ecSmrg switch (act->type) { 69235c4bbdfSmrg case XkbSA_SetMods: 69335c4bbdfSmrg case XkbSA_LatchMods: 69435c4bbdfSmrg case XkbSA_LockMods: 69535c4bbdfSmrg if (((tmp = XkbModActionVMods(&act->mods)) & changed) != 0) { 69635c4bbdfSmrg XkbVirtualModsToReal(xkb, tmp, &tmp); 69735c4bbdfSmrg act->mods.mask = act->mods.real_mods; 69835c4bbdfSmrg act->mods.mask |= tmp; 69935c4bbdfSmrg return TRUE; 70035c4bbdfSmrg } 70135c4bbdfSmrg break; 70235c4bbdfSmrg case XkbSA_ISOLock: 70335c4bbdfSmrg if ((((tmp = XkbModActionVMods(&act->iso)) != 0) & changed) != 0) { 70435c4bbdfSmrg XkbVirtualModsToReal(xkb, tmp, &tmp); 70535c4bbdfSmrg act->iso.mask = act->iso.real_mods; 70635c4bbdfSmrg act->iso.mask |= tmp; 70735c4bbdfSmrg return TRUE; 70835c4bbdfSmrg } 70935c4bbdfSmrg break; 71005b261ecSmrg } 7116747b715Smrg return FALSE; 71205b261ecSmrg} 71305b261ecSmrg 71405b261ecSmrgstatic void 71535c4bbdfSmrgXkbUpdateKeyTypeVirtualMods(XkbDescPtr xkb, 71635c4bbdfSmrg XkbKeyTypePtr type, 71735c4bbdfSmrg unsigned int changed, XkbChangesPtr changes) 71805b261ecSmrg{ 71935c4bbdfSmrg register unsigned int i; 72035c4bbdfSmrg unsigned int mask; 72135c4bbdfSmrg 72235c4bbdfSmrg XkbVirtualModsToReal(xkb, type->mods.vmods, &mask); 72335c4bbdfSmrg type->mods.mask = type->mods.real_mods | mask; 72435c4bbdfSmrg if ((type->map_count > 0) && (type->mods.vmods != 0)) { 72535c4bbdfSmrg XkbKTMapEntryPtr entry; 72635c4bbdfSmrg 72735c4bbdfSmrg for (i = 0, entry = type->map; i < type->map_count; i++, entry++) { 72835c4bbdfSmrg if (entry->mods.vmods != 0) { 72935c4bbdfSmrg XkbVirtualModsToReal(xkb, entry->mods.vmods, &mask); 73035c4bbdfSmrg entry->mods.mask = entry->mods.real_mods | mask; 73135c4bbdfSmrg /* entry is active if vmods are bound */ 73235c4bbdfSmrg entry->active = (mask != 0); 73335c4bbdfSmrg } 73435c4bbdfSmrg else 73535c4bbdfSmrg entry->active = 1; 73635c4bbdfSmrg } 73705b261ecSmrg } 73805b261ecSmrg if (changes) { 73935c4bbdfSmrg int type_ndx; 74035c4bbdfSmrg 74135c4bbdfSmrg type_ndx = type - xkb->map->types; 74235c4bbdfSmrg if ((type_ndx < 0) || (type_ndx > xkb->map->num_types)) 74335c4bbdfSmrg return; 74435c4bbdfSmrg if (changes->map.changed & XkbKeyTypesMask) { 74535c4bbdfSmrg int last; 74635c4bbdfSmrg 74735c4bbdfSmrg last = changes->map.first_type + changes->map.num_types - 1; 74835c4bbdfSmrg if (type_ndx < changes->map.first_type) { 74935c4bbdfSmrg changes->map.first_type = type_ndx; 75035c4bbdfSmrg changes->map.num_types = (last - type_ndx) + 1; 75135c4bbdfSmrg } 75235c4bbdfSmrg else if (type_ndx > last) { 75335c4bbdfSmrg changes->map.num_types = 75435c4bbdfSmrg (type_ndx - changes->map.first_type) + 1; 75535c4bbdfSmrg } 75635c4bbdfSmrg } 75735c4bbdfSmrg else { 75835c4bbdfSmrg changes->map.changed |= XkbKeyTypesMask; 75935c4bbdfSmrg changes->map.first_type = type_ndx; 76035c4bbdfSmrg changes->map.num_types = 1; 76135c4bbdfSmrg } 76205b261ecSmrg } 76305b261ecSmrg return; 76405b261ecSmrg} 76505b261ecSmrg 76605b261ecSmrgBool 76735c4bbdfSmrgXkbApplyVirtualModChanges(XkbDescPtr xkb, unsigned changed, 76835c4bbdfSmrg XkbChangesPtr changes) 76905b261ecSmrg{ 77035c4bbdfSmrg register int i; 77135c4bbdfSmrg unsigned int checkState = 0; 77235c4bbdfSmrg 77335c4bbdfSmrg if ((!xkb) || (!xkb->map) || (changed == 0)) 77435c4bbdfSmrg return FALSE; 77535c4bbdfSmrg for (i = 0; i < xkb->map->num_types; i++) { 77635c4bbdfSmrg if (xkb->map->types[i].mods.vmods & changed) 77735c4bbdfSmrg XkbUpdateKeyTypeVirtualMods(xkb, &xkb->map->types[i], changed, 77835c4bbdfSmrg changes); 77935c4bbdfSmrg } 78035c4bbdfSmrg if (changed & xkb->ctrls->internal.vmods) { 78135c4bbdfSmrg unsigned int newMask; 78235c4bbdfSmrg 78335c4bbdfSmrg XkbVirtualModsToReal(xkb, xkb->ctrls->internal.vmods, &newMask); 78435c4bbdfSmrg newMask |= xkb->ctrls->internal.real_mods; 78535c4bbdfSmrg if (xkb->ctrls->internal.mask != newMask) { 78635c4bbdfSmrg xkb->ctrls->internal.mask = newMask; 78735c4bbdfSmrg if (changes) { 78835c4bbdfSmrg changes->ctrls.changed_ctrls |= XkbInternalModsMask; 78935c4bbdfSmrg checkState = TRUE; 79035c4bbdfSmrg } 79135c4bbdfSmrg } 79235c4bbdfSmrg } 79335c4bbdfSmrg if (changed & xkb->ctrls->ignore_lock.vmods) { 79435c4bbdfSmrg unsigned int newMask; 79535c4bbdfSmrg 79635c4bbdfSmrg XkbVirtualModsToReal(xkb, xkb->ctrls->ignore_lock.vmods, &newMask); 79735c4bbdfSmrg newMask |= xkb->ctrls->ignore_lock.real_mods; 79835c4bbdfSmrg if (xkb->ctrls->ignore_lock.mask != newMask) { 79935c4bbdfSmrg xkb->ctrls->ignore_lock.mask = newMask; 80035c4bbdfSmrg if (changes) { 80135c4bbdfSmrg changes->ctrls.changed_ctrls |= XkbIgnoreLockModsMask; 80235c4bbdfSmrg checkState = TRUE; 80335c4bbdfSmrg } 80435c4bbdfSmrg } 80535c4bbdfSmrg } 80635c4bbdfSmrg if (xkb->indicators != NULL) { 80735c4bbdfSmrg XkbIndicatorMapPtr map; 80835c4bbdfSmrg 80935c4bbdfSmrg map = &xkb->indicators->maps[0]; 81035c4bbdfSmrg for (i = 0; i < XkbNumIndicators; i++, map++) { 81135c4bbdfSmrg if (map->mods.vmods & changed) { 81235c4bbdfSmrg unsigned int newMask; 81335c4bbdfSmrg 81435c4bbdfSmrg XkbVirtualModsToReal(xkb, map->mods.vmods, &newMask); 81535c4bbdfSmrg newMask |= map->mods.real_mods; 81635c4bbdfSmrg if (newMask != map->mods.mask) { 81735c4bbdfSmrg map->mods.mask = newMask; 81835c4bbdfSmrg if (changes) { 81935c4bbdfSmrg changes->indicators.map_changes |= (1 << i); 82035c4bbdfSmrg checkState = TRUE; 82135c4bbdfSmrg } 82235c4bbdfSmrg } 82335c4bbdfSmrg } 82435c4bbdfSmrg } 82535c4bbdfSmrg } 82635c4bbdfSmrg if (xkb->compat != NULL) { 82735c4bbdfSmrg XkbCompatMapPtr compat; 82835c4bbdfSmrg 82935c4bbdfSmrg compat = xkb->compat; 83035c4bbdfSmrg for (i = 0; i < XkbNumKbdGroups; i++) { 83135c4bbdfSmrg unsigned int newMask; 83235c4bbdfSmrg 83335c4bbdfSmrg XkbVirtualModsToReal(xkb, compat->groups[i].vmods, &newMask); 83435c4bbdfSmrg newMask |= compat->groups[i].real_mods; 83535c4bbdfSmrg if (compat->groups[i].mask != newMask) { 83635c4bbdfSmrg compat->groups[i].mask = newMask; 83735c4bbdfSmrg if (changes) { 83835c4bbdfSmrg changes->compat.changed_groups |= (1 << i); 83935c4bbdfSmrg checkState = TRUE; 84035c4bbdfSmrg } 84135c4bbdfSmrg } 84235c4bbdfSmrg } 84305b261ecSmrg } 84405b261ecSmrg if (xkb->map && xkb->server) { 84535c4bbdfSmrg int highChange = 0, lowChange = -1; 84635c4bbdfSmrg 84735c4bbdfSmrg for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) { 84835c4bbdfSmrg if (XkbKeyHasActions(xkb, i)) { 84935c4bbdfSmrg register XkbAction *pAct; 85035c4bbdfSmrg register int n; 85135c4bbdfSmrg 85235c4bbdfSmrg pAct = XkbKeyActionsPtr(xkb, i); 85335c4bbdfSmrg for (n = XkbKeyNumActions(xkb, i); n > 0; n--, pAct++) { 85435c4bbdfSmrg if ((pAct->type != XkbSA_NoAction) && 85535c4bbdfSmrg XkbUpdateActionVirtualMods(xkb, pAct, changed)) { 85635c4bbdfSmrg if (lowChange < 0) 85735c4bbdfSmrg lowChange = i; 85835c4bbdfSmrg highChange = i; 85935c4bbdfSmrg } 86035c4bbdfSmrg } 86135c4bbdfSmrg } 86235c4bbdfSmrg } 86335c4bbdfSmrg if (changes && (lowChange > 0)) { /* something changed */ 86435c4bbdfSmrg if (changes->map.changed & XkbKeyActionsMask) { 86535c4bbdfSmrg int last; 86635c4bbdfSmrg 86735c4bbdfSmrg if (changes->map.first_key_act < lowChange) 86835c4bbdfSmrg lowChange = changes->map.first_key_act; 86935c4bbdfSmrg last = 87035c4bbdfSmrg changes->map.first_key_act + changes->map.num_key_acts - 1; 87135c4bbdfSmrg if (last > highChange) 87235c4bbdfSmrg highChange = last; 87335c4bbdfSmrg } 87435c4bbdfSmrg changes->map.changed |= XkbKeyActionsMask; 87535c4bbdfSmrg changes->map.first_key_act = lowChange; 87635c4bbdfSmrg changes->map.num_key_acts = (highChange - lowChange) + 1; 87735c4bbdfSmrg } 87805b261ecSmrg } 87905b261ecSmrg return checkState; 88005b261ecSmrg} 881