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#endif 3005b261ecSmrg 3105b261ecSmrg#include <stdio.h> 3205b261ecSmrg#include <X11/X.h> 3305b261ecSmrg#include <X11/Xproto.h> 3405b261ecSmrg#include "misc.h" 3505b261ecSmrg#include "inputstr.h" 3605b261ecSmrg#include <X11/keysym.h> 3705b261ecSmrg#define XKBSRV_NEED_FILE_FUNCS 3805b261ecSmrg#include <xkbsrv.h> 3905b261ecSmrg 4005b261ecSmrg/***====================================================================***/ 4105b261ecSmrg 4205b261ecSmrg#define CORE_SYM(i) (i<map_width?core_syms[i]:NoSymbol) 4305b261ecSmrg#define XKB_OFFSET(g,l) (((g)*groupsWidth)+(l)) 4405b261ecSmrg 4505b261ecSmrgint 4635c4bbdfSmrgXkbKeyTypesForCoreSymbols(XkbDescPtr xkb, 4735c4bbdfSmrg int map_width, 4835c4bbdfSmrg KeySym * core_syms, 4935c4bbdfSmrg unsigned int protected, 5035c4bbdfSmrg int *types_inout, KeySym * xkb_syms_rtrn) 5105b261ecSmrg{ 5235c4bbdfSmrg register int i; 5335c4bbdfSmrg unsigned int empty; 5435c4bbdfSmrg int nSyms[XkbNumKbdGroups]; 5535c4bbdfSmrg int nGroups, tmp, groupsWidth; 5635c4bbdfSmrg BOOL replicated = FALSE; 5705b261ecSmrg 5805b261ecSmrg /* Section 12.2 of the protocol describes this process in more detail */ 5905b261ecSmrg /* Step 1: find the # of symbols in the core mapping per group */ 6035c4bbdfSmrg groupsWidth = 2; 6135c4bbdfSmrg for (i = 0; i < XkbNumKbdGroups; i++) { 6235c4bbdfSmrg if ((protected & (1 << i)) && (types_inout[i] < xkb->map->num_types)) { 6335c4bbdfSmrg nSyms[i] = xkb->map->types[types_inout[i]].num_levels; 6435c4bbdfSmrg if (nSyms[i] > groupsWidth) 6535c4bbdfSmrg groupsWidth = nSyms[i]; 6635c4bbdfSmrg } 6735c4bbdfSmrg else { 6835c4bbdfSmrg types_inout[i] = XkbTwoLevelIndex; /* don't really know, yet */ 6935c4bbdfSmrg nSyms[i] = 2; 7035c4bbdfSmrg } 7135c4bbdfSmrg } 7235c4bbdfSmrg if (nSyms[XkbGroup1Index] < 2) 7335c4bbdfSmrg nSyms[XkbGroup1Index] = 2; 7435c4bbdfSmrg if (nSyms[XkbGroup2Index] < 2) 7535c4bbdfSmrg nSyms[XkbGroup2Index] = 2; 7635c4bbdfSmrg /* Step 2: Copy the symbols from the core ordering to XKB ordering */ 7735c4bbdfSmrg /* symbols in the core are in the order: */ 7835c4bbdfSmrg /* G1L1 G1L2 G2L1 G2L2 [G1L[3-n]] [G2L[3-n]] [G3L*] [G3L*] */ 7935c4bbdfSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index, 0)] = CORE_SYM(0); 8035c4bbdfSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index, 1)] = CORE_SYM(1); 8135c4bbdfSmrg for (i = 2; i < nSyms[XkbGroup1Index]; i++) { 8235c4bbdfSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index, i)] = CORE_SYM(2 + i); 8335c4bbdfSmrg } 8435c4bbdfSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index, 0)] = CORE_SYM(2); 8535c4bbdfSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index, 1)] = CORE_SYM(3); 8635c4bbdfSmrg tmp = 2 + (nSyms[XkbGroup1Index] - 2); /* offset to extra group2 syms */ 8735c4bbdfSmrg for (i = 2; i < nSyms[XkbGroup2Index]; i++) { 8835c4bbdfSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index, i)] = CORE_SYM(tmp + i); 8905b261ecSmrg } 906747b715Smrg 916747b715Smrg /* Special case: if only the first group is explicit, and the symbols 926747b715Smrg * replicate across all groups, then we have a Section 12.4 replication */ 9335c4bbdfSmrg if ((protected & ~XkbExplicitKeyType1Mask) == 0) { 946747b715Smrg int j, width = nSyms[XkbGroup1Index]; 956747b715Smrg 966747b715Smrg replicated = TRUE; 976747b715Smrg 986747b715Smrg /* Check ABAB in ABABCDECDEABCDE */ 996747b715Smrg if ((width > 0 && CORE_SYM(0) != CORE_SYM(2)) || 1006747b715Smrg (width > 1 && CORE_SYM(1) != CORE_SYM(3))) 1016747b715Smrg replicated = FALSE; 1026747b715Smrg 1036747b715Smrg /* Check CDECDE in ABABCDECDEABCDE */ 10435c4bbdfSmrg for (i = 2; i < width && replicated; i++) { 1056747b715Smrg if (CORE_SYM(2 + i) != CORE_SYM(i + width)) 1066747b715Smrg replicated = FALSE; 1076747b715Smrg } 1086747b715Smrg 1096747b715Smrg /* Check ABCDE in ABABCDECDEABCDE */ 1106747b715Smrg for (j = 2; replicated && 11135c4bbdfSmrg j < XkbNumKbdGroups && map_width >= width * (j + 1); j++) { 11235c4bbdfSmrg for (i = 0; i < width && replicated; i++) { 1136747b715Smrg if (CORE_SYM(((i < 2) ? i : 2 + i)) != CORE_SYM(i + width * j)) 1146747b715Smrg replicated = FALSE; 1156747b715Smrg } 1166747b715Smrg } 1176747b715Smrg } 1186747b715Smrg 11935c4bbdfSmrg if (replicated) { 12035c4bbdfSmrg nSyms[XkbGroup2Index] = 0; 12135c4bbdfSmrg nSyms[XkbGroup3Index] = 0; 12235c4bbdfSmrg nSyms[XkbGroup4Index] = 0; 12335c4bbdfSmrg nGroups = 1; 12435c4bbdfSmrg } 12535c4bbdfSmrg else { 12635c4bbdfSmrg tmp = nSyms[XkbGroup1Index] + nSyms[XkbGroup2Index]; 12735c4bbdfSmrg if ((tmp >= map_width) && 12835c4bbdfSmrg ((protected & (XkbExplicitKeyType3Mask | XkbExplicitKeyType4Mask)) 12935c4bbdfSmrg == 0)) { 13035c4bbdfSmrg nSyms[XkbGroup3Index] = 0; 13135c4bbdfSmrg nSyms[XkbGroup4Index] = 0; 13235c4bbdfSmrg nGroups = 2; 13335c4bbdfSmrg } 13435c4bbdfSmrg else { 13535c4bbdfSmrg nGroups = 3; 13635c4bbdfSmrg for (i = 0; i < nSyms[XkbGroup3Index]; i++, tmp++) { 13735c4bbdfSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup3Index, i)] = CORE_SYM(tmp); 1386747b715Smrg } 13935c4bbdfSmrg if ((tmp < map_width) || (protected & XkbExplicitKeyType4Mask)) { 14035c4bbdfSmrg nGroups = 4; 14135c4bbdfSmrg for (i = 0; i < nSyms[XkbGroup4Index]; i++, tmp++) { 14235c4bbdfSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup4Index, i)] = 14335c4bbdfSmrg CORE_SYM(tmp); 1446747b715Smrg } 1456747b715Smrg } 1466747b715Smrg else { 14735c4bbdfSmrg nSyms[XkbGroup4Index] = 0; 1486747b715Smrg } 1496747b715Smrg } 15005b261ecSmrg } 15105b261ecSmrg /* steps 3&4: alphanumeric expansion, assign canonical types */ 15235c4bbdfSmrg empty = 0; 15335c4bbdfSmrg for (i = 0; i < nGroups; i++) { 15435c4bbdfSmrg KeySym *syms; 15535c4bbdfSmrg 15635c4bbdfSmrg syms = &xkb_syms_rtrn[XKB_OFFSET(i, 0)]; 15735c4bbdfSmrg if ((nSyms[i] > 1) && (syms[1] == NoSymbol) && (syms[0] != NoSymbol)) { 15835c4bbdfSmrg KeySym upper, lower; 15935c4bbdfSmrg 16035c4bbdfSmrg XkbConvertCase(syms[0], &lower, &upper); 16135c4bbdfSmrg if (upper != lower) { 16235c4bbdfSmrg xkb_syms_rtrn[XKB_OFFSET(i, 0)] = lower; 16335c4bbdfSmrg xkb_syms_rtrn[XKB_OFFSET(i, 1)] = upper; 16435c4bbdfSmrg if ((protected & (1 << i)) == 0) 16535c4bbdfSmrg types_inout[i] = XkbAlphabeticIndex; 16635c4bbdfSmrg } 16735c4bbdfSmrg else if ((protected & (1 << i)) == 0) { 16835c4bbdfSmrg types_inout[i] = XkbOneLevelIndex; 16935c4bbdfSmrg /* nSyms[i]= 1; */ 17035c4bbdfSmrg } 17135c4bbdfSmrg } 17235c4bbdfSmrg if (((protected & (1 << i)) == 0) && 17335c4bbdfSmrg (types_inout[i] == XkbTwoLevelIndex)) { 17435c4bbdfSmrg if (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1])) 17535c4bbdfSmrg types_inout[i] = XkbKeypadIndex; 17635c4bbdfSmrg else { 17735c4bbdfSmrg KeySym upper, lower; 17835c4bbdfSmrg 17935c4bbdfSmrg XkbConvertCase(syms[0], &lower, &upper); 18035c4bbdfSmrg if ((syms[0] == lower) && (syms[1] == upper)) 18135c4bbdfSmrg types_inout[i] = XkbAlphabeticIndex; 18235c4bbdfSmrg } 18335c4bbdfSmrg } 18435c4bbdfSmrg if (syms[0] == NoSymbol) { 18535c4bbdfSmrg register int n; 18635c4bbdfSmrg Bool found; 18735c4bbdfSmrg 18835c4bbdfSmrg for (n = 1, found = FALSE; (!found) && (n < nSyms[i]); n++) { 18935c4bbdfSmrg found = (syms[n] != NoSymbol); 19035c4bbdfSmrg } 19135c4bbdfSmrg if (!found) 19235c4bbdfSmrg empty |= (1 << i); 19335c4bbdfSmrg } 19405b261ecSmrg } 19505b261ecSmrg /* step 5: squoosh out empty groups */ 19605b261ecSmrg if (empty) { 19735c4bbdfSmrg for (i = nGroups - 1; i >= 0; i--) { 19835c4bbdfSmrg if (((empty & (1 << i)) == 0) || (protected & (1 << i))) 19935c4bbdfSmrg break; 20035c4bbdfSmrg nGroups--; 20135c4bbdfSmrg } 20205b261ecSmrg } 20335c4bbdfSmrg if (nGroups < 1) 20435c4bbdfSmrg return 0; 20505b261ecSmrg 20605b261ecSmrg /* step 6: replicate group 1 into group two, if necessary */ 20735c4bbdfSmrg if ((nGroups > 1) && 20835c4bbdfSmrg ((empty & (XkbGroup1Mask | XkbGroup2Mask)) == XkbGroup2Mask)) { 20935c4bbdfSmrg if ((protected & (XkbExplicitKeyType1Mask | XkbExplicitKeyType2Mask)) == 21035c4bbdfSmrg 0) { 21135c4bbdfSmrg nSyms[XkbGroup2Index] = nSyms[XkbGroup1Index]; 21235c4bbdfSmrg types_inout[XkbGroup2Index] = types_inout[XkbGroup1Index]; 21335c4bbdfSmrg memcpy((char *) &xkb_syms_rtrn[2], (char *) xkb_syms_rtrn, 21435c4bbdfSmrg 2 * sizeof(KeySym)); 21535c4bbdfSmrg } 21635c4bbdfSmrg else if (types_inout[XkbGroup1Index] == types_inout[XkbGroup2Index]) { 21735c4bbdfSmrg memcpy((char *) &xkb_syms_rtrn[nSyms[XkbGroup1Index]], 21835c4bbdfSmrg (char *) xkb_syms_rtrn, 21935c4bbdfSmrg nSyms[XkbGroup1Index] * sizeof(KeySym)); 22035c4bbdfSmrg } 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 */ 22935c4bbdfSmrg if (nGroups > 1) { 23035c4bbdfSmrg Bool sameType, allOneLevel, canonical = TRUE; 23135c4bbdfSmrg 23235c4bbdfSmrg allOneLevel = (xkb->map->types[types_inout[0]].num_levels == 1); 23335c4bbdfSmrg for (i = 1, sameType = TRUE; (allOneLevel || sameType) && (i < nGroups); 23435c4bbdfSmrg i++) { 23535c4bbdfSmrg sameType = (sameType && 23635c4bbdfSmrg (types_inout[i] == types_inout[XkbGroup1Index])); 23735c4bbdfSmrg if (allOneLevel) 23835c4bbdfSmrg allOneLevel = (xkb->map->types[types_inout[i]].num_levels == 1); 23935c4bbdfSmrg if (types_inout[i] > XkbLastRequiredType) 24035c4bbdfSmrg canonical = FALSE; 24135c4bbdfSmrg } 24235c4bbdfSmrg if (((sameType) || canonical) && 24335c4bbdfSmrg (!(protected & 24435c4bbdfSmrg (XkbExplicitKeyTypesMask & ~XkbExplicitKeyType1Mask)))) { 24535c4bbdfSmrg register int s; 24635c4bbdfSmrg Bool identical; 24735c4bbdfSmrg 24835c4bbdfSmrg for (i = 1, identical = TRUE; identical && (i < nGroups); i++) { 24935c4bbdfSmrg KeySym *syms; 25035c4bbdfSmrg 2516747b715Smrg if (nSyms[i] != nSyms[XkbGroup1Index]) 2526747b715Smrg identical = FALSE; 25335c4bbdfSmrg syms = &xkb_syms_rtrn[XKB_OFFSET(i, 0)]; 25435c4bbdfSmrg for (s = 0; identical && (s < nSyms[i]); s++) { 25535c4bbdfSmrg if (syms[s] != xkb_syms_rtrn[s]) 25635c4bbdfSmrg identical = FALSE; 25735c4bbdfSmrg } 25835c4bbdfSmrg } 25935c4bbdfSmrg if (identical) 26035c4bbdfSmrg nGroups = 1; 26135c4bbdfSmrg } 26235c4bbdfSmrg if (allOneLevel && (nGroups > 1)) { 26335c4bbdfSmrg KeySym *syms; 26435c4bbdfSmrg 26535c4bbdfSmrg syms = &xkb_syms_rtrn[nSyms[XkbGroup1Index]]; 26635c4bbdfSmrg nSyms[XkbGroup1Index] = 1; 26735c4bbdfSmrg for (i = 1; i < nGroups; i++) { 26835c4bbdfSmrg xkb_syms_rtrn[i] = syms[0]; 26935c4bbdfSmrg syms += nSyms[i]; 27035c4bbdfSmrg nSyms[i] = 1; 27135c4bbdfSmrg } 27235c4bbdfSmrg } 27305b261ecSmrg } 27405b261ecSmrg return nGroups; 27505b261ecSmrg} 27605b261ecSmrg 27705b261ecSmrgstatic XkbSymInterpretPtr 27835c4bbdfSmrg_XkbFindMatchingInterp(XkbDescPtr xkb, 27935c4bbdfSmrg KeySym sym, unsigned int real_mods, unsigned int level) 28005b261ecSmrg{ 28135c4bbdfSmrg register unsigned i; 28235c4bbdfSmrg XkbSymInterpretPtr interp, rtrn; 28335c4bbdfSmrg CARD8 mods; 28435c4bbdfSmrg 28535c4bbdfSmrg rtrn = NULL; 28635c4bbdfSmrg interp = xkb->compat->sym_interpret; 28735c4bbdfSmrg for (i = 0; i < xkb->compat->num_si; i++, interp++) { 28835c4bbdfSmrg if ((interp->sym == NoSymbol) || (sym == interp->sym)) { 28935c4bbdfSmrg int match; 29035c4bbdfSmrg 29135c4bbdfSmrg if ((level == 0) || ((interp->match & XkbSI_LevelOneOnly) == 0)) 29235c4bbdfSmrg mods = real_mods; 29335c4bbdfSmrg else 29435c4bbdfSmrg mods = 0; 29535c4bbdfSmrg switch (interp->match & XkbSI_OpMask) { 29635c4bbdfSmrg case XkbSI_NoneOf: 29735c4bbdfSmrg match = ((interp->mods & mods) == 0); 29835c4bbdfSmrg break; 29935c4bbdfSmrg case XkbSI_AnyOfOrNone: 30035c4bbdfSmrg match = ((mods == 0) || ((interp->mods & mods) != 0)); 30135c4bbdfSmrg break; 30235c4bbdfSmrg case XkbSI_AnyOf: 30335c4bbdfSmrg match = ((interp->mods & mods) != 0); 30435c4bbdfSmrg break; 30535c4bbdfSmrg case XkbSI_AllOf: 30635c4bbdfSmrg match = ((interp->mods & mods) == interp->mods); 30735c4bbdfSmrg break; 30835c4bbdfSmrg case XkbSI_Exactly: 30935c4bbdfSmrg match = (interp->mods == mods); 31035c4bbdfSmrg break; 31135c4bbdfSmrg default: 31235c4bbdfSmrg match = 0; 31335c4bbdfSmrg break; 31435c4bbdfSmrg } 31535c4bbdfSmrg if (match) { 31635c4bbdfSmrg if (interp->sym != NoSymbol) { 31735c4bbdfSmrg return interp; 31835c4bbdfSmrg } 31935c4bbdfSmrg else if (rtrn == NULL) { 32035c4bbdfSmrg rtrn = interp; 32135c4bbdfSmrg } 32235c4bbdfSmrg } 32335c4bbdfSmrg } 32405b261ecSmrg } 32505b261ecSmrg return rtrn; 32605b261ecSmrg} 32705b261ecSmrg 32805b261ecSmrgstatic void 32935c4bbdfSmrg_XkbAddKeyChange(KeyCode *pFirst, unsigned char *pNum, KeyCode newKey) 33005b261ecSmrg{ 33135c4bbdfSmrg KeyCode last; 33205b261ecSmrg 33335c4bbdfSmrg last = (*pFirst) + (*pNum); 33435c4bbdfSmrg if (newKey < *pFirst) { 33535c4bbdfSmrg *pFirst = newKey; 33635c4bbdfSmrg *pNum = (last - newKey) + 1; 33705b261ecSmrg } 33835c4bbdfSmrg else if (newKey > last) { 33935c4bbdfSmrg *pNum = (last - *pFirst) + 1; 34005b261ecSmrg } 34105b261ecSmrg return; 34205b261ecSmrg} 34305b261ecSmrg 34405b261ecSmrgstatic void 34535c4bbdfSmrg_XkbSetActionKeyMods(XkbDescPtr xkb, XkbAction *act, unsigned mods) 34605b261ecSmrg{ 34735c4bbdfSmrg unsigned tmp; 34805b261ecSmrg 34905b261ecSmrg switch (act->type) { 35035c4bbdfSmrg case XkbSA_SetMods: 35135c4bbdfSmrg case XkbSA_LatchMods: 35235c4bbdfSmrg case XkbSA_LockMods: 35335c4bbdfSmrg if (act->mods.flags & XkbSA_UseModMapMods) 35435c4bbdfSmrg act->mods.real_mods = act->mods.mask = mods; 35535c4bbdfSmrg if ((tmp = XkbModActionVMods(&act->mods)) != 0) { 35635c4bbdfSmrg XkbVirtualModsToReal(xkb, tmp, &tmp); 35735c4bbdfSmrg act->mods.mask |= tmp; 35835c4bbdfSmrg } 35935c4bbdfSmrg break; 36035c4bbdfSmrg case XkbSA_ISOLock: 36135c4bbdfSmrg if (act->iso.flags & XkbSA_UseModMapMods) 36235c4bbdfSmrg act->iso.real_mods = act->iso.mask = mods; 36335c4bbdfSmrg if ((tmp = XkbModActionVMods(&act->iso)) != 0) { 36435c4bbdfSmrg XkbVirtualModsToReal(xkb, tmp, &tmp); 36535c4bbdfSmrg act->iso.mask |= tmp; 36635c4bbdfSmrg } 36735c4bbdfSmrg break; 36805b261ecSmrg } 36905b261ecSmrg return; 37005b261ecSmrg} 37105b261ecSmrg 37205b261ecSmrg#define IBUF_SIZE 8 37305b261ecSmrg 37405b261ecSmrgBool 37535c4bbdfSmrgXkbApplyCompatMapToKey(XkbDescPtr xkb, KeyCode key, XkbChangesPtr changes) 37605b261ecSmrg{ 37735c4bbdfSmrg KeySym *syms; 37835c4bbdfSmrg unsigned char explicit, mods; 37935c4bbdfSmrg XkbSymInterpretPtr *interps, ibuf[IBUF_SIZE]; 38035c4bbdfSmrg int n, nSyms, found; 38135c4bbdfSmrg unsigned changed, tmp; 38235c4bbdfSmrg 38335c4bbdfSmrg if ((!xkb) || (!xkb->map) || (!xkb->map->key_sym_map) || 38435c4bbdfSmrg (!xkb->compat) || (!xkb->compat->sym_interpret) || 38535c4bbdfSmrg (key < xkb->min_key_code) || (key > xkb->max_key_code)) { 38635c4bbdfSmrg return FALSE; 38735c4bbdfSmrg } 38835c4bbdfSmrg if (((!xkb->server) || (!xkb->server->key_acts)) && 38935c4bbdfSmrg (XkbAllocServerMap(xkb, XkbAllServerInfoMask, 0) != Success)) { 39035c4bbdfSmrg return FALSE; 39135c4bbdfSmrg } 39235c4bbdfSmrg changed = 0; /* keeps track of what has changed in _this_ call */ 39335c4bbdfSmrg explicit = xkb->server->explicit[key]; 39435c4bbdfSmrg if (explicit & XkbExplicitInterpretMask) /* nothing to do */ 39535c4bbdfSmrg return TRUE; 39635c4bbdfSmrg mods = (xkb->map->modmap ? xkb->map->modmap[key] : 0); 39735c4bbdfSmrg nSyms = XkbKeyNumSyms(xkb, key); 39835c4bbdfSmrg syms = XkbKeySymsPtr(xkb, key); 39935c4bbdfSmrg if (nSyms > IBUF_SIZE) { 40035c4bbdfSmrg interps = calloc(nSyms, sizeof(XkbSymInterpretPtr)); 40135c4bbdfSmrg if (interps == NULL) { 40235c4bbdfSmrg interps = ibuf; 40335c4bbdfSmrg nSyms = IBUF_SIZE; 40435c4bbdfSmrg } 40505b261ecSmrg } 40605b261ecSmrg else { 40735c4bbdfSmrg interps = ibuf; 40835c4bbdfSmrg } 40935c4bbdfSmrg found = 0; 41035c4bbdfSmrg for (n = 0; n < nSyms; n++) { 41135c4bbdfSmrg unsigned level = (n % XkbKeyGroupsWidth(xkb, key)); 41235c4bbdfSmrg 41335c4bbdfSmrg interps[n] = NULL; 41435c4bbdfSmrg if (syms[n] != NoSymbol) { 41535c4bbdfSmrg interps[n] = _XkbFindMatchingInterp(xkb, syms[n], mods, level); 41635c4bbdfSmrg if (interps[n] && interps[n]->act.type != XkbSA_NoAction) 41735c4bbdfSmrg found++; 41835c4bbdfSmrg else 41935c4bbdfSmrg interps[n] = NULL; 42035c4bbdfSmrg } 42105b261ecSmrg } 42205b261ecSmrg /* 1/28/96 (ef) -- XXX! WORKING HERE */ 42305b261ecSmrg if (!found) { 42435c4bbdfSmrg if (xkb->server->key_acts[key] != 0) { 42535c4bbdfSmrg xkb->server->key_acts[key] = 0; 42635c4bbdfSmrg changed |= XkbKeyActionsMask; 42735c4bbdfSmrg } 42805b261ecSmrg } 42905b261ecSmrg else { 43035c4bbdfSmrg XkbAction *pActs; 43135c4bbdfSmrg unsigned int new_vmodmask; 43235c4bbdfSmrg 43335c4bbdfSmrg changed |= XkbKeyActionsMask; 43435c4bbdfSmrg pActs = XkbResizeKeyActions(xkb, key, nSyms); 43535c4bbdfSmrg if (!pActs) { 43605b261ecSmrg if (nSyms > IBUF_SIZE) 4376747b715Smrg free(interps); 43835c4bbdfSmrg return FALSE; 43935c4bbdfSmrg } 44035c4bbdfSmrg new_vmodmask = 0; 44135c4bbdfSmrg for (n = 0; n < nSyms; n++) { 44235c4bbdfSmrg if (interps[n]) { 44335c4bbdfSmrg unsigned effMods; 44435c4bbdfSmrg 44535c4bbdfSmrg pActs[n] = *((XkbAction *) &interps[n]->act); 44635c4bbdfSmrg if ((n == 0) || ((interps[n]->match & XkbSI_LevelOneOnly) == 0)) { 44735c4bbdfSmrg effMods = mods; 44835c4bbdfSmrg if (interps[n]->virtual_mod != XkbNoModifier) 44935c4bbdfSmrg new_vmodmask |= (1 << interps[n]->virtual_mod); 45035c4bbdfSmrg } 45135c4bbdfSmrg else 45235c4bbdfSmrg effMods = 0; 45335c4bbdfSmrg _XkbSetActionKeyMods(xkb, &pActs[n], effMods); 45435c4bbdfSmrg } 45535c4bbdfSmrg else 45635c4bbdfSmrg pActs[n].type = XkbSA_NoAction; 45735c4bbdfSmrg } 45835c4bbdfSmrg if (((explicit & XkbExplicitVModMapMask) == 0) && 45935c4bbdfSmrg (xkb->server->vmodmap[key] != new_vmodmask)) { 46035c4bbdfSmrg changed |= XkbVirtualModMapMask; 46135c4bbdfSmrg xkb->server->vmodmap[key] = new_vmodmask; 46235c4bbdfSmrg } 46335c4bbdfSmrg if (interps[0]) { 46435c4bbdfSmrg if ((interps[0]->flags & XkbSI_LockingKey) && 46535c4bbdfSmrg ((explicit & XkbExplicitBehaviorMask) == 0)) { 46635c4bbdfSmrg xkb->server->behaviors[key].type = XkbKB_Lock; 46735c4bbdfSmrg changed |= XkbKeyBehaviorsMask; 46835c4bbdfSmrg } 46935c4bbdfSmrg if (((explicit & XkbExplicitAutoRepeatMask) == 0) && (xkb->ctrls)) { 47035c4bbdfSmrg CARD8 old; 47135c4bbdfSmrg 47235c4bbdfSmrg old = BitIsOn(xkb->ctrls->per_key_repeat, key); 47335c4bbdfSmrg if (interps[0]->flags & XkbSI_AutoRepeat) 47435c4bbdfSmrg SetBit(xkb->ctrls->per_key_repeat, key); 47535c4bbdfSmrg else 47635c4bbdfSmrg ClearBit(xkb->ctrls->per_key_repeat, key); 47735c4bbdfSmrg if (changes && old != BitIsOn(xkb->ctrls->per_key_repeat, key)) 47835c4bbdfSmrg changes->ctrls.changed_ctrls |= XkbPerKeyRepeatMask; 47935c4bbdfSmrg } 48035c4bbdfSmrg } 48135c4bbdfSmrg } 48235c4bbdfSmrg if ((!found) || (interps[0] == NULL)) { 48335c4bbdfSmrg if (((explicit & XkbExplicitAutoRepeatMask) == 0) && (xkb->ctrls)) { 48435c4bbdfSmrg CARD8 old; 48535c4bbdfSmrg 48635c4bbdfSmrg old = BitIsOn(xkb->ctrls->per_key_repeat, key); 48735c4bbdfSmrg SetBit(xkb->ctrls->per_key_repeat, key); 48835c4bbdfSmrg if (changes && (old != BitIsOn(xkb->ctrls->per_key_repeat, key))) 48935c4bbdfSmrg changes->ctrls.changed_ctrls |= XkbPerKeyRepeatMask; 49035c4bbdfSmrg } 49135c4bbdfSmrg if (((explicit & XkbExplicitBehaviorMask) == 0) && 49235c4bbdfSmrg (xkb->server->behaviors[key].type == XkbKB_Lock)) { 49335c4bbdfSmrg xkb->server->behaviors[key].type = XkbKB_Default; 49435c4bbdfSmrg changed |= XkbKeyBehaviorsMask; 49535c4bbdfSmrg } 49605b261ecSmrg } 49705b261ecSmrg if (changes) { 49835c4bbdfSmrg XkbMapChangesPtr mc; 49935c4bbdfSmrg 50035c4bbdfSmrg mc = &changes->map; 50135c4bbdfSmrg tmp = (changed & mc->changed); 50235c4bbdfSmrg if (tmp & XkbKeyActionsMask) 50335c4bbdfSmrg _XkbAddKeyChange(&mc->first_key_act, &mc->num_key_acts, key); 50435c4bbdfSmrg else if (changed & XkbKeyActionsMask) { 50535c4bbdfSmrg mc->changed |= XkbKeyActionsMask; 50635c4bbdfSmrg mc->first_key_act = key; 50735c4bbdfSmrg mc->num_key_acts = 1; 50835c4bbdfSmrg } 50935c4bbdfSmrg if (tmp & XkbKeyBehaviorsMask) { 51035c4bbdfSmrg _XkbAddKeyChange(&mc->first_key_behavior, &mc->num_key_behaviors, 51135c4bbdfSmrg key); 51235c4bbdfSmrg } 51335c4bbdfSmrg else if (changed & XkbKeyBehaviorsMask) { 51435c4bbdfSmrg mc->changed |= XkbKeyBehaviorsMask; 51535c4bbdfSmrg mc->first_key_behavior = key; 51635c4bbdfSmrg mc->num_key_behaviors = 1; 51735c4bbdfSmrg } 51835c4bbdfSmrg if (tmp & XkbVirtualModMapMask) 51935c4bbdfSmrg _XkbAddKeyChange(&mc->first_vmodmap_key, &mc->num_vmodmap_keys, 52035c4bbdfSmrg key); 52135c4bbdfSmrg else if (changed & XkbVirtualModMapMask) { 52235c4bbdfSmrg mc->changed |= XkbVirtualModMapMask; 52335c4bbdfSmrg mc->first_vmodmap_key = key; 52435c4bbdfSmrg mc->num_vmodmap_keys = 1; 52535c4bbdfSmrg } 52635c4bbdfSmrg mc->changed |= changed; 52735c4bbdfSmrg } 52835c4bbdfSmrg if (interps != ibuf) 52935c4bbdfSmrg free(interps); 5306747b715Smrg return TRUE; 53105b261ecSmrg} 53205b261ecSmrg 53305b261ecSmrgStatus 53435c4bbdfSmrgXkbChangeTypesOfKey(XkbDescPtr xkb, 53535c4bbdfSmrg int key, 53635c4bbdfSmrg int nGroups, 53735c4bbdfSmrg unsigned groups, int *newTypesIn, XkbMapChangesPtr changes) 53805b261ecSmrg{ 53935c4bbdfSmrg XkbKeyTypePtr pOldType, pNewType; 54035c4bbdfSmrg register int i; 54135c4bbdfSmrg int width, nOldGroups, oldWidth, newTypes[XkbNumKbdGroups]; 54235c4bbdfSmrg 54335c4bbdfSmrg if ((!xkb) || (!XkbKeycodeInRange(xkb, key)) || (!xkb->map) || 54435c4bbdfSmrg (!xkb->map->types) || (!newTypesIn) || 54535c4bbdfSmrg ((groups & XkbAllGroupsMask) == 0) || (nGroups > XkbNumKbdGroups)) { 54635c4bbdfSmrg return BadMatch; 54735c4bbdfSmrg } 54835c4bbdfSmrg if (nGroups == 0) { 54935c4bbdfSmrg for (i = 0; i < XkbNumKbdGroups; i++) { 55035c4bbdfSmrg xkb->map->key_sym_map[key].kt_index[i] = XkbOneLevelIndex; 55135c4bbdfSmrg } 55235c4bbdfSmrg i = xkb->map->key_sym_map[key].group_info; 55335c4bbdfSmrg i = XkbSetNumGroups(i, 0); 55435c4bbdfSmrg xkb->map->key_sym_map[key].group_info = i; 55535c4bbdfSmrg XkbResizeKeySyms(xkb, key, 0); 556f2346221Smrg XkbResizeKeyActions(xkb, key, 0); 55735c4bbdfSmrg return Success; 55835c4bbdfSmrg } 55935c4bbdfSmrg 56035c4bbdfSmrg nOldGroups = XkbKeyNumGroups(xkb, key); 56135c4bbdfSmrg oldWidth = XkbKeyGroupsWidth(xkb, key); 56235c4bbdfSmrg for (width = i = 0; i < nGroups; i++) { 56335c4bbdfSmrg if (groups & (1 << i)) 56435c4bbdfSmrg newTypes[i] = newTypesIn[i]; 56535c4bbdfSmrg else if (i < nOldGroups) 56635c4bbdfSmrg newTypes[i] = XkbKeyKeyTypeIndex(xkb, key, i); 56735c4bbdfSmrg else if (nOldGroups > 0) 56835c4bbdfSmrg newTypes[i] = XkbKeyKeyTypeIndex(xkb, key, XkbGroup1Index); 56935c4bbdfSmrg else 57035c4bbdfSmrg newTypes[i] = XkbTwoLevelIndex; 57135c4bbdfSmrg if (newTypes[i] > xkb->map->num_types) 57235c4bbdfSmrg return BadMatch; 57335c4bbdfSmrg pNewType = &xkb->map->types[newTypes[i]]; 57435c4bbdfSmrg if (pNewType->num_levels > width) 57535c4bbdfSmrg width = pNewType->num_levels; 57635c4bbdfSmrg } 57735c4bbdfSmrg if ((xkb->ctrls) && (nGroups > xkb->ctrls->num_groups)) 57835c4bbdfSmrg xkb->ctrls->num_groups = nGroups; 57935c4bbdfSmrg if ((width != oldWidth) || (nGroups != nOldGroups)) { 58035c4bbdfSmrg KeySym oldSyms[XkbMaxSymsPerKey], *pSyms; 58135c4bbdfSmrg int nCopy; 58235c4bbdfSmrg 58335c4bbdfSmrg if (nOldGroups == 0) { 58435c4bbdfSmrg pSyms = XkbResizeKeySyms(xkb, key, width * nGroups); 58535c4bbdfSmrg if (pSyms != NULL) { 58635c4bbdfSmrg i = xkb->map->key_sym_map[key].group_info; 58735c4bbdfSmrg i = XkbSetNumGroups(i, nGroups); 58835c4bbdfSmrg xkb->map->key_sym_map[key].group_info = i; 58935c4bbdfSmrg xkb->map->key_sym_map[key].width = width; 59035c4bbdfSmrg for (i = 0; i < nGroups; i++) { 59135c4bbdfSmrg xkb->map->key_sym_map[key].kt_index[i] = newTypes[i]; 59235c4bbdfSmrg } 59335c4bbdfSmrg return Success; 59435c4bbdfSmrg } 59535c4bbdfSmrg return BadAlloc; 59635c4bbdfSmrg } 59735c4bbdfSmrg pSyms = XkbKeySymsPtr(xkb, key); 59835c4bbdfSmrg memcpy(oldSyms, pSyms, XkbKeyNumSyms(xkb, key) * sizeof(KeySym)); 59935c4bbdfSmrg pSyms = XkbResizeKeySyms(xkb, key, width * nGroups); 60035c4bbdfSmrg if (pSyms == NULL) 60135c4bbdfSmrg return BadAlloc; 60235c4bbdfSmrg memset(pSyms, 0, width * nGroups * sizeof(KeySym)); 60335c4bbdfSmrg for (i = 0; (i < nGroups) && (i < nOldGroups); i++) { 60435c4bbdfSmrg pOldType = XkbKeyKeyType(xkb, key, i); 60535c4bbdfSmrg pNewType = &xkb->map->types[newTypes[i]]; 60635c4bbdfSmrg if (pNewType->num_levels > pOldType->num_levels) 60735c4bbdfSmrg nCopy = pOldType->num_levels; 60835c4bbdfSmrg else 60935c4bbdfSmrg nCopy = pNewType->num_levels; 61035c4bbdfSmrg memcpy(&pSyms[i * width], &oldSyms[i * oldWidth], 61135c4bbdfSmrg nCopy * sizeof(KeySym)); 61235c4bbdfSmrg } 61335c4bbdfSmrg if (XkbKeyHasActions(xkb, key)) { 61435c4bbdfSmrg XkbAction oldActs[XkbMaxSymsPerKey], *pActs; 61535c4bbdfSmrg 61635c4bbdfSmrg pActs = XkbKeyActionsPtr(xkb, key); 61735c4bbdfSmrg memcpy(oldActs, pActs, XkbKeyNumSyms(xkb, key) * sizeof(XkbAction)); 61835c4bbdfSmrg pActs = XkbResizeKeyActions(xkb, key, width * nGroups); 61935c4bbdfSmrg if (pActs == NULL) 62035c4bbdfSmrg return BadAlloc; 62135c4bbdfSmrg memset(pActs, 0, width * nGroups * sizeof(XkbAction)); 62235c4bbdfSmrg for (i = 0; (i < nGroups) && (i < nOldGroups); i++) { 62335c4bbdfSmrg pOldType = XkbKeyKeyType(xkb, key, i); 62435c4bbdfSmrg pNewType = &xkb->map->types[newTypes[i]]; 62535c4bbdfSmrg if (pNewType->num_levels > pOldType->num_levels) 62635c4bbdfSmrg nCopy = pOldType->num_levels; 62735c4bbdfSmrg else 62835c4bbdfSmrg nCopy = pNewType->num_levels; 62935c4bbdfSmrg memcpy(&pActs[i * width], &oldActs[i * oldWidth], 63035c4bbdfSmrg nCopy * sizeof(XkbAction)); 63135c4bbdfSmrg } 63235c4bbdfSmrg } 63335c4bbdfSmrg i = xkb->map->key_sym_map[key].group_info; 63435c4bbdfSmrg i = XkbSetNumGroups(i, nGroups); 63535c4bbdfSmrg xkb->map->key_sym_map[key].group_info = i; 63635c4bbdfSmrg xkb->map->key_sym_map[key].width = width; 63735c4bbdfSmrg } 63835c4bbdfSmrg width = 0; 63935c4bbdfSmrg for (i = 0; i < nGroups; i++) { 64035c4bbdfSmrg xkb->map->key_sym_map[key].kt_index[i] = newTypes[i]; 64135c4bbdfSmrg if (xkb->map->types[newTypes[i]].num_levels > width) 64235c4bbdfSmrg width = xkb->map->types[newTypes[i]].num_levels; 64335c4bbdfSmrg } 64435c4bbdfSmrg xkb->map->key_sym_map[key].width = width; 64535c4bbdfSmrg if (changes != NULL) { 64635c4bbdfSmrg if (changes->changed & XkbKeySymsMask) { 64735c4bbdfSmrg _XkbAddKeyChange(&changes->first_key_sym, &changes->num_key_syms, 64835c4bbdfSmrg key); 64935c4bbdfSmrg } 65035c4bbdfSmrg else { 65135c4bbdfSmrg changes->changed |= XkbKeySymsMask; 65235c4bbdfSmrg changes->first_key_sym = key; 65335c4bbdfSmrg changes->num_key_syms = 1; 65435c4bbdfSmrg } 65505b261ecSmrg } 65605b261ecSmrg return Success; 65705b261ecSmrg} 65805b261ecSmrg 65905b261ecSmrg/***====================================================================***/ 66005b261ecSmrg 66105b261ecSmrgBool 66235c4bbdfSmrgXkbVirtualModsToReal(XkbDescPtr xkb, unsigned virtual_mask, unsigned *mask_rtrn) 66305b261ecSmrg{ 66435c4bbdfSmrg register int i, bit; 66535c4bbdfSmrg register unsigned mask; 66635c4bbdfSmrg 667ed6184dfSmrg if ((xkb == NULL) || (xkb->server == NULL)) { 668ed6184dfSmrg *mask_rtrn = 0; 66935c4bbdfSmrg return FALSE; 670ed6184dfSmrg } 67135c4bbdfSmrg if (virtual_mask == 0) { 67235c4bbdfSmrg *mask_rtrn = 0; 67335c4bbdfSmrg return TRUE; 67435c4bbdfSmrg } 67535c4bbdfSmrg for (i = mask = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) { 67635c4bbdfSmrg if (virtual_mask & bit) 67735c4bbdfSmrg mask |= xkb->server->vmods[i]; 67835c4bbdfSmrg } 67935c4bbdfSmrg *mask_rtrn = mask; 6806747b715Smrg return TRUE; 68105b261ecSmrg} 68205b261ecSmrg 68305b261ecSmrg/***====================================================================***/ 68405b261ecSmrg 68505b261ecSmrgstatic Bool 68635c4bbdfSmrgXkbUpdateActionVirtualMods(XkbDescPtr xkb, XkbAction *act, unsigned changed) 68705b261ecSmrg{ 68835c4bbdfSmrg unsigned int tmp; 68905b261ecSmrg 69005b261ecSmrg switch (act->type) { 69135c4bbdfSmrg case XkbSA_SetMods: 69235c4bbdfSmrg case XkbSA_LatchMods: 69335c4bbdfSmrg case XkbSA_LockMods: 69435c4bbdfSmrg if (((tmp = XkbModActionVMods(&act->mods)) & changed) != 0) { 69535c4bbdfSmrg XkbVirtualModsToReal(xkb, tmp, &tmp); 69635c4bbdfSmrg act->mods.mask = act->mods.real_mods; 69735c4bbdfSmrg act->mods.mask |= tmp; 69835c4bbdfSmrg return TRUE; 69935c4bbdfSmrg } 70035c4bbdfSmrg break; 70135c4bbdfSmrg case XkbSA_ISOLock: 70235c4bbdfSmrg if ((((tmp = XkbModActionVMods(&act->iso)) != 0) & changed) != 0) { 70335c4bbdfSmrg XkbVirtualModsToReal(xkb, tmp, &tmp); 70435c4bbdfSmrg act->iso.mask = act->iso.real_mods; 70535c4bbdfSmrg act->iso.mask |= tmp; 70635c4bbdfSmrg return TRUE; 70735c4bbdfSmrg } 70835c4bbdfSmrg break; 70905b261ecSmrg } 7106747b715Smrg return FALSE; 71105b261ecSmrg} 71205b261ecSmrg 71305b261ecSmrgstatic void 71435c4bbdfSmrgXkbUpdateKeyTypeVirtualMods(XkbDescPtr xkb, 71535c4bbdfSmrg XkbKeyTypePtr type, 71635c4bbdfSmrg unsigned int changed, XkbChangesPtr changes) 71705b261ecSmrg{ 71835c4bbdfSmrg register unsigned int i; 71935c4bbdfSmrg unsigned int mask; 72035c4bbdfSmrg 72135c4bbdfSmrg XkbVirtualModsToReal(xkb, type->mods.vmods, &mask); 72235c4bbdfSmrg type->mods.mask = type->mods.real_mods | mask; 72335c4bbdfSmrg if ((type->map_count > 0) && (type->mods.vmods != 0)) { 72435c4bbdfSmrg XkbKTMapEntryPtr entry; 72535c4bbdfSmrg 72635c4bbdfSmrg for (i = 0, entry = type->map; i < type->map_count; i++, entry++) { 72735c4bbdfSmrg if (entry->mods.vmods != 0) { 72835c4bbdfSmrg XkbVirtualModsToReal(xkb, entry->mods.vmods, &mask); 72935c4bbdfSmrg entry->mods.mask = entry->mods.real_mods | mask; 73035c4bbdfSmrg /* entry is active if vmods are bound */ 73135c4bbdfSmrg entry->active = (mask != 0); 73235c4bbdfSmrg } 73335c4bbdfSmrg else 73435c4bbdfSmrg entry->active = 1; 73535c4bbdfSmrg } 73605b261ecSmrg } 73705b261ecSmrg if (changes) { 73835c4bbdfSmrg int type_ndx; 73935c4bbdfSmrg 74035c4bbdfSmrg type_ndx = type - xkb->map->types; 74135c4bbdfSmrg if ((type_ndx < 0) || (type_ndx > xkb->map->num_types)) 74235c4bbdfSmrg return; 74335c4bbdfSmrg if (changes->map.changed & XkbKeyTypesMask) { 74435c4bbdfSmrg int last; 74535c4bbdfSmrg 74635c4bbdfSmrg last = changes->map.first_type + changes->map.num_types - 1; 74735c4bbdfSmrg if (type_ndx < changes->map.first_type) { 74835c4bbdfSmrg changes->map.first_type = type_ndx; 74935c4bbdfSmrg changes->map.num_types = (last - type_ndx) + 1; 75035c4bbdfSmrg } 75135c4bbdfSmrg else if (type_ndx > last) { 75235c4bbdfSmrg changes->map.num_types = 75335c4bbdfSmrg (type_ndx - changes->map.first_type) + 1; 75435c4bbdfSmrg } 75535c4bbdfSmrg } 75635c4bbdfSmrg else { 75735c4bbdfSmrg changes->map.changed |= XkbKeyTypesMask; 75835c4bbdfSmrg changes->map.first_type = type_ndx; 75935c4bbdfSmrg changes->map.num_types = 1; 76035c4bbdfSmrg } 76105b261ecSmrg } 76205b261ecSmrg return; 76305b261ecSmrg} 76405b261ecSmrg 76505b261ecSmrgBool 76635c4bbdfSmrgXkbApplyVirtualModChanges(XkbDescPtr xkb, unsigned changed, 76735c4bbdfSmrg XkbChangesPtr changes) 76805b261ecSmrg{ 76935c4bbdfSmrg register int i; 77035c4bbdfSmrg unsigned int checkState = 0; 77135c4bbdfSmrg 77235c4bbdfSmrg if ((!xkb) || (!xkb->map) || (changed == 0)) 77335c4bbdfSmrg return FALSE; 77435c4bbdfSmrg for (i = 0; i < xkb->map->num_types; i++) { 77535c4bbdfSmrg if (xkb->map->types[i].mods.vmods & changed) 77635c4bbdfSmrg XkbUpdateKeyTypeVirtualMods(xkb, &xkb->map->types[i], changed, 77735c4bbdfSmrg changes); 77835c4bbdfSmrg } 77935c4bbdfSmrg if (changed & xkb->ctrls->internal.vmods) { 78035c4bbdfSmrg unsigned int newMask; 78135c4bbdfSmrg 78235c4bbdfSmrg XkbVirtualModsToReal(xkb, xkb->ctrls->internal.vmods, &newMask); 78335c4bbdfSmrg newMask |= xkb->ctrls->internal.real_mods; 78435c4bbdfSmrg if (xkb->ctrls->internal.mask != newMask) { 78535c4bbdfSmrg xkb->ctrls->internal.mask = newMask; 78635c4bbdfSmrg if (changes) { 78735c4bbdfSmrg changes->ctrls.changed_ctrls |= XkbInternalModsMask; 78835c4bbdfSmrg checkState = TRUE; 78935c4bbdfSmrg } 79035c4bbdfSmrg } 79135c4bbdfSmrg } 79235c4bbdfSmrg if (changed & xkb->ctrls->ignore_lock.vmods) { 79335c4bbdfSmrg unsigned int newMask; 79435c4bbdfSmrg 79535c4bbdfSmrg XkbVirtualModsToReal(xkb, xkb->ctrls->ignore_lock.vmods, &newMask); 79635c4bbdfSmrg newMask |= xkb->ctrls->ignore_lock.real_mods; 79735c4bbdfSmrg if (xkb->ctrls->ignore_lock.mask != newMask) { 79835c4bbdfSmrg xkb->ctrls->ignore_lock.mask = newMask; 79935c4bbdfSmrg if (changes) { 80035c4bbdfSmrg changes->ctrls.changed_ctrls |= XkbIgnoreLockModsMask; 80135c4bbdfSmrg checkState = TRUE; 80235c4bbdfSmrg } 80335c4bbdfSmrg } 80435c4bbdfSmrg } 80535c4bbdfSmrg if (xkb->indicators != NULL) { 80635c4bbdfSmrg XkbIndicatorMapPtr map; 80735c4bbdfSmrg 80835c4bbdfSmrg map = &xkb->indicators->maps[0]; 80935c4bbdfSmrg for (i = 0; i < XkbNumIndicators; i++, map++) { 81035c4bbdfSmrg if (map->mods.vmods & changed) { 81135c4bbdfSmrg unsigned int newMask; 81235c4bbdfSmrg 81335c4bbdfSmrg XkbVirtualModsToReal(xkb, map->mods.vmods, &newMask); 81435c4bbdfSmrg newMask |= map->mods.real_mods; 81535c4bbdfSmrg if (newMask != map->mods.mask) { 81635c4bbdfSmrg map->mods.mask = newMask; 81735c4bbdfSmrg if (changes) { 81835c4bbdfSmrg changes->indicators.map_changes |= (1 << i); 81935c4bbdfSmrg checkState = TRUE; 82035c4bbdfSmrg } 82135c4bbdfSmrg } 82235c4bbdfSmrg } 82335c4bbdfSmrg } 82435c4bbdfSmrg } 82535c4bbdfSmrg if (xkb->compat != NULL) { 82635c4bbdfSmrg XkbCompatMapPtr compat; 82735c4bbdfSmrg 82835c4bbdfSmrg compat = xkb->compat; 82935c4bbdfSmrg for (i = 0; i < XkbNumKbdGroups; i++) { 83035c4bbdfSmrg unsigned int newMask; 83135c4bbdfSmrg 83235c4bbdfSmrg XkbVirtualModsToReal(xkb, compat->groups[i].vmods, &newMask); 83335c4bbdfSmrg newMask |= compat->groups[i].real_mods; 83435c4bbdfSmrg if (compat->groups[i].mask != newMask) { 83535c4bbdfSmrg compat->groups[i].mask = newMask; 83635c4bbdfSmrg if (changes) { 83735c4bbdfSmrg changes->compat.changed_groups |= (1 << i); 83835c4bbdfSmrg checkState = TRUE; 83935c4bbdfSmrg } 84035c4bbdfSmrg } 84135c4bbdfSmrg } 84205b261ecSmrg } 84305b261ecSmrg if (xkb->map && xkb->server) { 84435c4bbdfSmrg int highChange = 0, lowChange = -1; 84535c4bbdfSmrg 84635c4bbdfSmrg for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) { 84735c4bbdfSmrg if (XkbKeyHasActions(xkb, i)) { 84835c4bbdfSmrg register XkbAction *pAct; 84935c4bbdfSmrg register int n; 85035c4bbdfSmrg 85135c4bbdfSmrg pAct = XkbKeyActionsPtr(xkb, i); 85235c4bbdfSmrg for (n = XkbKeyNumActions(xkb, i); n > 0; n--, pAct++) { 85335c4bbdfSmrg if ((pAct->type != XkbSA_NoAction) && 85435c4bbdfSmrg XkbUpdateActionVirtualMods(xkb, pAct, changed)) { 85535c4bbdfSmrg if (lowChange < 0) 85635c4bbdfSmrg lowChange = i; 85735c4bbdfSmrg highChange = i; 85835c4bbdfSmrg } 85935c4bbdfSmrg } 86035c4bbdfSmrg } 86135c4bbdfSmrg } 86235c4bbdfSmrg if (changes && (lowChange > 0)) { /* something changed */ 86335c4bbdfSmrg if (changes->map.changed & XkbKeyActionsMask) { 86435c4bbdfSmrg int last; 86535c4bbdfSmrg 86635c4bbdfSmrg if (changes->map.first_key_act < lowChange) 86735c4bbdfSmrg lowChange = changes->map.first_key_act; 86835c4bbdfSmrg last = 86935c4bbdfSmrg changes->map.first_key_act + changes->map.num_key_acts - 1; 87035c4bbdfSmrg if (last > highChange) 87135c4bbdfSmrg highChange = last; 87235c4bbdfSmrg } 87335c4bbdfSmrg changes->map.changed |= XkbKeyActionsMask; 87435c4bbdfSmrg changes->map.first_key_act = lowChange; 87535c4bbdfSmrg changes->map.num_key_acts = (highChange - lowChange) + 1; 87635c4bbdfSmrg } 87705b261ecSmrg } 87805b261ecSmrg return checkState; 87905b261ecSmrg} 880