11ab64890Smrg/************************************************************ 21ab64890SmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc. 31ab64890Smrg 41ab64890SmrgPermission to use, copy, modify, and distribute this 51ab64890Smrgsoftware and its documentation for any purpose and without 61ab64890Smrgfee is hereby granted, provided that the above copyright 71ab64890Smrgnotice appear in all copies and that both that copyright 81ab64890Smrgnotice and this permission notice appear in supporting 961b2299dSmrgdocumentation, and that the name of Silicon Graphics not be 1061b2299dSmrgused in advertising or publicity pertaining to distribution 111ab64890Smrgof the software without specific prior written permission. 1261b2299dSmrgSilicon Graphics makes no representation about the suitability 131ab64890Smrgof this software for any purpose. It is provided "as is" 141ab64890Smrgwithout any express or implied warranty. 151ab64890Smrg 1661b2299dSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 1761b2299dSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 181ab64890SmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 1961b2299dSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 2061b2299dSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 2161b2299dSmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 221ab64890SmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 231ab64890SmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE. 241ab64890Smrg 251ab64890Smrg********************************************************/ 261ab64890Smrg 27818534a1Smrg#ifdef HAVE_CONFIG_H 281ab64890Smrg#include <config.h> 291ab64890Smrg#endif 301ab64890Smrg 311ab64890Smrg 321ab64890Smrg#include <stdio.h> 331ab64890Smrg#include "Xlibint.h" 341ab64890Smrg#include <X11/extensions/XKBproto.h> 351ab64890Smrg#include <X11/keysym.h> 361ab64890Smrg#include "XKBlibint.h" 371ab64890Smrg 381ab64890Smrg 391ab64890Smrg/***====================================================================***/ 401ab64890Smrg 411ab64890Smrg#define mapSize(m) (sizeof(m)/sizeof(XkbKTMapEntryRec)) 42818534a1Smrgstatic XkbKTMapEntryRec map2Level[] = { 43818534a1Smrg { True, ShiftMask, {1, ShiftMask, 0} } 441ab64890Smrg}; 451ab64890Smrg 46818534a1Smrgstatic XkbKTMapEntryRec mapAlpha[] = { 47818534a1Smrg { True, ShiftMask, {1, ShiftMask, 0} }, 48818534a1Smrg { True, LockMask, {0, LockMask, 0} } 491ab64890Smrg}; 501ab64890Smrg 51818534a1Smrgstatic XkbModsRec preAlpha[] = { 52818534a1Smrg { 0, 0, 0 }, 53818534a1Smrg { LockMask, LockMask, 0 } 541ab64890Smrg}; 551ab64890Smrg 561ab64890Smrg#define NL_VMOD_MASK 0 57818534a1Smrgstatic XkbKTMapEntryRec mapKeypad[] = { 58818534a1Smrg { True, ShiftMask, { 1, ShiftMask, 0 } }, 59818534a1Smrg { False, 0, { 1, 0, NL_VMOD_MASK } } 601ab64890Smrg}; 611ab64890Smrg 62818534a1Smrgstatic XkbKeyTypeRec canonicalTypes[XkbNumRequiredTypes] = { 63818534a1Smrg { { 0, 0, 0 }, 64818534a1Smrg 1, /* num_levels */ 65818534a1Smrg 0, /* map_count */ 66818534a1Smrg NULL, NULL, 67818534a1Smrg None, NULL 68818534a1Smrg }, 69818534a1Smrg { { ShiftMask, ShiftMask, 0 }, 70818534a1Smrg 2, /* num_levels */ 71818534a1Smrg mapSize(map2Level), /* map_count */ 72818534a1Smrg map2Level, NULL, 73818534a1Smrg None, NULL 74818534a1Smrg }, 75818534a1Smrg { { ShiftMask|LockMask, ShiftMask|LockMask, 0 }, 76818534a1Smrg 2, /* num_levels */ 77818534a1Smrg mapSize(mapAlpha), /* map_count */ 78818534a1Smrg mapAlpha, preAlpha, 79818534a1Smrg None, NULL 80818534a1Smrg }, 81818534a1Smrg { { ShiftMask, ShiftMask, NL_VMOD_MASK }, 82818534a1Smrg 2, /* num_levels */ 83818534a1Smrg mapSize(mapKeypad), /* map_count */ 84818534a1Smrg mapKeypad, NULL, 85818534a1Smrg None, NULL 86818534a1Smrg } 871ab64890Smrg}; 881ab64890Smrg 891ab64890SmrgStatus 90818534a1SmrgXkbInitCanonicalKeyTypes(XkbDescPtr xkb, unsigned which, int keypadVMod) 911ab64890Smrg{ 92818534a1Smrg XkbClientMapPtr map; 93818534a1Smrg XkbKeyTypePtr from, to; 94818534a1Smrg Status rtrn; 951ab64890Smrg 961ab64890Smrg if (!xkb) 97818534a1Smrg return BadMatch; 98818534a1Smrg rtrn = XkbAllocClientMap(xkb, XkbKeyTypesMask, XkbNumRequiredTypes); 99818534a1Smrg if (rtrn != Success) 100818534a1Smrg return rtrn; 101818534a1Smrg map = xkb->map; 102818534a1Smrg if ((which & XkbAllRequiredTypes) == 0) 103818534a1Smrg return Success; 104818534a1Smrg rtrn = Success; 105818534a1Smrg from = canonicalTypes; 106818534a1Smrg to = map->types; 107818534a1Smrg if (which & XkbOneLevelMask) 108818534a1Smrg rtrn = XkbCopyKeyType(&from[XkbOneLevelIndex], &to[XkbOneLevelIndex]); 109818534a1Smrg if ((which & XkbTwoLevelMask) && (rtrn == Success)) 110818534a1Smrg rtrn = XkbCopyKeyType(&from[XkbTwoLevelIndex], &to[XkbTwoLevelIndex]); 111818534a1Smrg if ((which & XkbAlphabeticMask) && (rtrn == Success)) 112818534a1Smrg rtrn = 113818534a1Smrg XkbCopyKeyType(&from[XkbAlphabeticIndex], &to[XkbAlphabeticIndex]); 114818534a1Smrg if ((which & XkbKeypadMask) && (rtrn == Success)) { 115818534a1Smrg XkbKeyTypePtr type; 116818534a1Smrg 117818534a1Smrg rtrn = XkbCopyKeyType(&from[XkbKeypadIndex], &to[XkbKeypadIndex]); 118818534a1Smrg type = &to[XkbKeypadIndex]; 119818534a1Smrg if ((keypadVMod >= 0) && (keypadVMod < XkbNumVirtualMods) && 120818534a1Smrg (rtrn == Success)) { 121818534a1Smrg type->mods.vmods = (1 << keypadVMod); 122818534a1Smrg type->map[0].active = True; 123818534a1Smrg type->map[0].mods.mask = ShiftMask; 124818534a1Smrg type->map[0].mods.real_mods = ShiftMask; 125818534a1Smrg type->map[0].mods.vmods = 0; 126818534a1Smrg type->map[0].level = 1; 127818534a1Smrg type->map[1].active = False; 128818534a1Smrg type->map[1].mods.mask = 0; 129818534a1Smrg type->map[1].mods.real_mods = 0; 130818534a1Smrg type->map[1].mods.vmods = (1 << keypadVMod); 131818534a1Smrg type->map[1].level = 1; 132818534a1Smrg } 1331ab64890Smrg } 1341ab64890Smrg return Success; 1351ab64890Smrg} 1361ab64890Smrg 1371ab64890Smrg/***====================================================================***/ 1381ab64890Smrg 1391ab64890Smrg#define CORE_SYM(i) (i<map_width?core_syms[i]:NoSymbol) 1401ab64890Smrg#define XKB_OFFSET(g,l) (((g)*groupsWidth)+(l)) 1411ab64890Smrg 1421ab64890Smrgint 143818534a1SmrgXkbKeyTypesForCoreSymbols(XkbDescPtr xkb, 144818534a1Smrg int map_width, 145818534a1Smrg KeySym *core_syms, 146818534a1Smrg unsigned int protected, 147818534a1Smrg int *types_inout, 148818534a1Smrg KeySym *xkb_syms_rtrn) 1491ab64890Smrg{ 150818534a1Smrg register int i; 151818534a1Smrg unsigned int empty; 152818534a1Smrg int nSyms[XkbNumKbdGroups]; 153818534a1Smrg int nGroups, tmp, groupsWidth; 1541ab64890Smrg 1551ab64890Smrg /* Section 12.2 of the protocol describes this process in more detail */ 1561ab64890Smrg /* Step 1: find the # of symbols in the core mapping per group */ 157818534a1Smrg groupsWidth = 2; 158818534a1Smrg for (i = 0; i < XkbNumKbdGroups; i++) { 159818534a1Smrg if ((protected & (1 << i)) && (types_inout[i] < xkb->map->num_types)) { 160818534a1Smrg nSyms[i] = xkb->map->types[types_inout[i]].num_levels; 161818534a1Smrg if (nSyms[i] > groupsWidth) 162818534a1Smrg groupsWidth = nSyms[i]; 163818534a1Smrg } 164818534a1Smrg else { 165818534a1Smrg types_inout[i] = XkbTwoLevelIndex; /* don't really know, yet */ 166818534a1Smrg nSyms[i] = 2; 167818534a1Smrg } 168818534a1Smrg } 169818534a1Smrg if (nSyms[XkbGroup1Index] < 2) 170818534a1Smrg nSyms[XkbGroup1Index] = 2; 171818534a1Smrg if (nSyms[XkbGroup2Index] < 2) 172818534a1Smrg nSyms[XkbGroup2Index] = 2; 173818534a1Smrg /* Step 2: Copy the symbols from the core ordering to XKB ordering */ 174818534a1Smrg /* symbols in the core are in the order: */ 175818534a1Smrg /* G1L1 G1L2 G2L1 G2L2 [G1L[3-n]] [G2L[3-n]] [G3L*] [G3L*] */ 176818534a1Smrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index, 0)] = CORE_SYM(0); 177818534a1Smrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index, 1)] = CORE_SYM(1); 178818534a1Smrg for (i = 2; i < nSyms[XkbGroup1Index]; i++) { 179818534a1Smrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index, i)] = CORE_SYM(2 + i); 180818534a1Smrg } 181818534a1Smrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index, 0)] = CORE_SYM(2); 182818534a1Smrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index, 1)] = CORE_SYM(3); 183818534a1Smrg tmp = 2 + (nSyms[XkbGroup1Index] - 2); /* offset to extra group2 syms */ 184818534a1Smrg for (i = 2; i < nSyms[XkbGroup2Index]; i++) { 185818534a1Smrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index, i)] = CORE_SYM(tmp + i); 186818534a1Smrg } 187818534a1Smrg tmp = nSyms[XkbGroup1Index] + nSyms[XkbGroup2Index]; 188818534a1Smrg if ((tmp >= map_width) && 189818534a1Smrg ((protected & (XkbExplicitKeyType3Mask | XkbExplicitKeyType4Mask)) == 190818534a1Smrg 0)) { 191818534a1Smrg nSyms[XkbGroup3Index] = 0; 192818534a1Smrg nSyms[XkbGroup4Index] = 0; 193818534a1Smrg nGroups = 2; 1941ab64890Smrg } 1951ab64890Smrg else { 196818534a1Smrg nGroups = 3; 197818534a1Smrg for (i = 0; i < nSyms[XkbGroup3Index]; i++, tmp++) { 198818534a1Smrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup3Index, i)] = CORE_SYM(tmp); 199818534a1Smrg } 200818534a1Smrg if ((tmp < map_width) || (protected & XkbExplicitKeyType4Mask)) { 201818534a1Smrg nGroups = 4; 202818534a1Smrg for (i = 0; i < nSyms[XkbGroup4Index]; i++, tmp++) { 203818534a1Smrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup4Index, i)] = CORE_SYM(tmp); 204818534a1Smrg } 205818534a1Smrg } 206818534a1Smrg else { 207818534a1Smrg nSyms[XkbGroup4Index] = 0; 208818534a1Smrg } 2091ab64890Smrg } 2101ab64890Smrg /* steps 3&4: alphanumeric expansion, assign canonical types */ 211818534a1Smrg empty = 0; 212818534a1Smrg for (i = 0; i < nGroups; i++) { 213818534a1Smrg KeySym *syms; 214818534a1Smrg 215818534a1Smrg syms = &xkb_syms_rtrn[XKB_OFFSET(i, 0)]; 216818534a1Smrg if ((nSyms[i] > 1) && (syms[1] == NoSymbol) && (syms[0] != NoSymbol)) { 217818534a1Smrg KeySym upper, lower; 218818534a1Smrg 219818534a1Smrg XConvertCase(syms[0], &lower, &upper); 220818534a1Smrg if (upper != lower) { 221818534a1Smrg xkb_syms_rtrn[XKB_OFFSET(i, 0)] = lower; 222818534a1Smrg xkb_syms_rtrn[XKB_OFFSET(i, 1)] = upper; 223818534a1Smrg if ((protected & (1 << i)) == 0) 224818534a1Smrg types_inout[i] = XkbAlphabeticIndex; 225818534a1Smrg } 226818534a1Smrg else if ((protected & (1 << i)) == 0) { 227818534a1Smrg types_inout[i] = XkbOneLevelIndex; 228818534a1Smrg /* nSyms[i]= 1; */ 229818534a1Smrg } 230818534a1Smrg } 231818534a1Smrg if (((protected & (1 << i)) == 0) && 232818534a1Smrg (types_inout[i] == XkbTwoLevelIndex)) { 233818534a1Smrg if (IsKeypadKey(syms[0]) || IsKeypadKey(syms[1])) 234818534a1Smrg types_inout[i] = XkbKeypadIndex; 235818534a1Smrg else { 236818534a1Smrg KeySym upper, lower; 237818534a1Smrg 238818534a1Smrg XConvertCase(syms[0], &lower, &upper); 239818534a1Smrg if ((syms[0] == lower) && (syms[1] == upper)) 240818534a1Smrg types_inout[i] = XkbAlphabeticIndex; 241818534a1Smrg } 242818534a1Smrg } 243818534a1Smrg if (syms[0] == NoSymbol) { 244818534a1Smrg register int n; 245818534a1Smrg Bool found; 246818534a1Smrg 247818534a1Smrg for (n = 1, found = False; (!found) && (n < nSyms[i]); n++) { 248818534a1Smrg found = (syms[n] != NoSymbol); 249818534a1Smrg } 250818534a1Smrg if (!found) 251818534a1Smrg empty |= (1 << i); 252818534a1Smrg } 2531ab64890Smrg } 2541ab64890Smrg /* step 5: squoosh out empty groups */ 2551ab64890Smrg if (empty) { 256818534a1Smrg for (i = nGroups - 1; i >= 0; i--) { 257818534a1Smrg if (((empty & (1 << i)) == 0) || (protected & (1 << i))) 258818534a1Smrg break; 259818534a1Smrg nGroups--; 260818534a1Smrg } 2611ab64890Smrg } 262818534a1Smrg if (nGroups < 1) 263818534a1Smrg return 0; 2641ab64890Smrg 2651ab64890Smrg /* step 6: replicate group 1 into group two, if necessary */ 266818534a1Smrg if ((nGroups > 1) && 267818534a1Smrg ((empty & (XkbGroup1Mask | XkbGroup2Mask)) == XkbGroup2Mask)) { 268818534a1Smrg if ((protected & (XkbExplicitKeyType1Mask | XkbExplicitKeyType2Mask)) == 269818534a1Smrg 0) { 270818534a1Smrg nSyms[XkbGroup2Index] = nSyms[XkbGroup1Index]; 271818534a1Smrg types_inout[XkbGroup2Index] = types_inout[XkbGroup1Index]; 272818534a1Smrg memcpy((char *) &xkb_syms_rtrn[2], (char *) xkb_syms_rtrn, 273818534a1Smrg 2 * sizeof(KeySym)); 274818534a1Smrg } 275818534a1Smrg else if (types_inout[XkbGroup1Index] == types_inout[XkbGroup2Index]) { 276818534a1Smrg memcpy((char *) &xkb_syms_rtrn[nSyms[XkbGroup1Index]], 277818534a1Smrg (char *) xkb_syms_rtrn, 278818534a1Smrg nSyms[XkbGroup1Index] * sizeof(KeySym)); 279818534a1Smrg } 2801ab64890Smrg } 2811ab64890Smrg 2821ab64890Smrg /* step 7: check for all groups identical or all width 1 */ 283818534a1Smrg if (nGroups > 1) { 284818534a1Smrg Bool sameType, allOneLevel; 285818534a1Smrg 286818534a1Smrg allOneLevel = (xkb->map->types[types_inout[0]].num_levels == 1); 287818534a1Smrg for (i = 1, sameType = True; (allOneLevel || sameType) && (i < nGroups); 288818534a1Smrg i++) { 289818534a1Smrg sameType = (sameType && 290818534a1Smrg (types_inout[i] == types_inout[XkbGroup1Index])); 291818534a1Smrg if (allOneLevel) 292818534a1Smrg allOneLevel = (xkb->map->types[types_inout[i]].num_levels == 1); 293818534a1Smrg } 294818534a1Smrg if ((sameType) && 295818534a1Smrg (!(protected & 296818534a1Smrg (XkbExplicitKeyTypesMask & ~XkbExplicitKeyType1Mask)))) { 297818534a1Smrg register int s; 298818534a1Smrg Bool identical; 299818534a1Smrg 300818534a1Smrg for (i = 1, identical = True; identical && (i < nGroups); i++) { 301818534a1Smrg KeySym *syms; 302818534a1Smrg 303818534a1Smrg syms = &xkb_syms_rtrn[XKB_OFFSET(i, 0)]; 304818534a1Smrg for (s = 0; identical && (s < nSyms[i]); s++) { 305818534a1Smrg if (syms[s] != xkb_syms_rtrn[s]) 306818534a1Smrg identical = False; 307818534a1Smrg } 308818534a1Smrg } 309818534a1Smrg if (identical) 310818534a1Smrg nGroups = 1; 311818534a1Smrg } 312818534a1Smrg if (allOneLevel && (nGroups > 1)) { 313818534a1Smrg KeySym *syms; 314818534a1Smrg 315818534a1Smrg syms = &xkb_syms_rtrn[nSyms[XkbGroup1Index]]; 316818534a1Smrg nSyms[XkbGroup1Index] = 1; 317818534a1Smrg for (i = 1; i < nGroups; i++) { 318818534a1Smrg xkb_syms_rtrn[i] = syms[0]; 319818534a1Smrg syms += nSyms[i]; 320818534a1Smrg nSyms[i] = 1; 321818534a1Smrg } 322818534a1Smrg } 3231ab64890Smrg } 3241ab64890Smrg return nGroups; 3251ab64890Smrg} 3261ab64890Smrg 3271ab64890Smrgstatic XkbSymInterpretPtr 328818534a1Smrg_XkbFindMatchingInterp(XkbDescPtr xkb, 329818534a1Smrg KeySym sym, 330818534a1Smrg unsigned int real_mods, 331818534a1Smrg unsigned int level) 3321ab64890Smrg{ 333818534a1Smrg register unsigned i; 334818534a1Smrg XkbSymInterpretPtr interp, rtrn; 335818534a1Smrg CARD8 mods; 336818534a1Smrg 337818534a1Smrg rtrn = NULL; 338818534a1Smrg interp = xkb->compat->sym_interpret; 339818534a1Smrg for (i = 0; i < xkb->compat->num_si; i++, interp++) { 340818534a1Smrg if ((interp->sym == NoSymbol) || (sym == interp->sym)) { 341818534a1Smrg int match; 342818534a1Smrg 343818534a1Smrg if ((level == 0) || ((interp->match & XkbSI_LevelOneOnly) == 0)) 344818534a1Smrg mods = real_mods; 345818534a1Smrg else 346818534a1Smrg mods = 0; 347818534a1Smrg switch (interp->match & XkbSI_OpMask) { 348818534a1Smrg case XkbSI_NoneOf: 349818534a1Smrg match = ((interp->mods & mods) == 0); 350818534a1Smrg break; 351818534a1Smrg case XkbSI_AnyOfOrNone: 352818534a1Smrg match = ((mods == 0) || ((interp->mods & mods) != 0)); 353818534a1Smrg break; 354818534a1Smrg case XkbSI_AnyOf: 355818534a1Smrg match = ((interp->mods & mods) != 0); 356818534a1Smrg break; 357818534a1Smrg case XkbSI_AllOf: 358818534a1Smrg match = ((interp->mods & mods) == interp->mods); 359818534a1Smrg break; 360818534a1Smrg case XkbSI_Exactly: 361818534a1Smrg match = (interp->mods == mods); 362818534a1Smrg break; 363818534a1Smrg default: 364818534a1Smrg match = 0; 365818534a1Smrg break; 366818534a1Smrg } 367818534a1Smrg if (match) { 368818534a1Smrg if (interp->sym != NoSymbol) { 369818534a1Smrg return interp; 370818534a1Smrg } 371818534a1Smrg else if (rtrn == NULL) { 372818534a1Smrg rtrn = interp; 373818534a1Smrg } 374818534a1Smrg } 375818534a1Smrg } 3761ab64890Smrg } 3771ab64890Smrg return rtrn; 3781ab64890Smrg} 3791ab64890Smrg 3801ab64890Smrgstatic void 381818534a1Smrg_XkbAddKeyChange(KeyCode *pFirst, unsigned char *pNum, KeyCode newKey) 3821ab64890Smrg{ 383818534a1Smrg KeyCode last; 3841ab64890Smrg 385818534a1Smrg last = (*pFirst) + (*pNum); 386818534a1Smrg if (newKey < *pFirst) { 387818534a1Smrg *pFirst = newKey; 388818534a1Smrg *pNum = (last - newKey) + 1; 3891ab64890Smrg } 390818534a1Smrg else if (newKey > last) { 391818534a1Smrg *pNum = (last - *pFirst) + 1; 3921ab64890Smrg } 3931ab64890Smrg return; 3941ab64890Smrg} 3951ab64890Smrg 3961ab64890Smrgstatic void 397818534a1Smrg_XkbSetActionKeyMods(XkbDescPtr xkb, XkbAction *act, unsigned mods) 3981ab64890Smrg{ 399818534a1Smrg unsigned tmp; 4001ab64890Smrg 4011ab64890Smrg switch (act->type) { 402818534a1Smrg case XkbSA_SetMods: 403818534a1Smrg case XkbSA_LatchMods: 404818534a1Smrg case XkbSA_LockMods: 405818534a1Smrg if (act->mods.flags & XkbSA_UseModMapMods) 406818534a1Smrg act->mods.real_mods = act->mods.mask = mods; 407818534a1Smrg if ((tmp = XkbModActionVMods(&act->mods)) != 0) { 408818534a1Smrg XkbVirtualModsToReal(xkb, tmp, &tmp); 409818534a1Smrg act->mods.mask |= tmp; 410818534a1Smrg } 411818534a1Smrg break; 412818534a1Smrg case XkbSA_ISOLock: 413818534a1Smrg if (act->iso.flags & XkbSA_UseModMapMods) 414818534a1Smrg act->iso.real_mods = act->iso.mask = mods; 415818534a1Smrg if ((tmp = XkbModActionVMods(&act->iso)) != 0) { 416818534a1Smrg XkbVirtualModsToReal(xkb, tmp, &tmp); 417818534a1Smrg act->iso.mask |= tmp; 418818534a1Smrg } 419818534a1Smrg break; 4201ab64890Smrg } 4211ab64890Smrg return; 4221ab64890Smrg} 4231ab64890Smrg 4241ab64890Smrg#define IBUF_SIZE 8 4251ab64890Smrg 4261ab64890SmrgBool 427818534a1SmrgXkbApplyCompatMapToKey(XkbDescPtr xkb, KeyCode key, XkbChangesPtr changes) 4281ab64890Smrg{ 429818534a1Smrg KeySym *syms; 430818534a1Smrg unsigned char explicit, mods; 431818534a1Smrg XkbSymInterpretPtr *interps, ibuf[IBUF_SIZE]; 432818534a1Smrg int n, nSyms, found; 433818534a1Smrg unsigned changed, tmp; 434818534a1Smrg 435818534a1Smrg if ((!xkb) || (!xkb->map) || (!xkb->map->key_sym_map) || 436818534a1Smrg (!xkb->compat) || (!xkb->compat->sym_interpret) || 437818534a1Smrg (key < xkb->min_key_code) || (key > xkb->max_key_code)) { 438818534a1Smrg return False; 439818534a1Smrg } 440818534a1Smrg if (((!xkb->server) || (!xkb->server->key_acts)) && 441818534a1Smrg (XkbAllocServerMap(xkb, XkbAllServerInfoMask, 0) != Success)) { 442818534a1Smrg return False; 443818534a1Smrg } 444818534a1Smrg changed = 0; /* keeps track of what has changed in _this_ call */ 445818534a1Smrg explicit = xkb->server->explicit[key]; 446818534a1Smrg if (explicit & XkbExplicitInterpretMask) /* nothing to do */ 447818534a1Smrg return True; 448818534a1Smrg mods = (xkb->map->modmap ? xkb->map->modmap[key] : 0); 449818534a1Smrg nSyms = XkbKeyNumSyms(xkb, key); 450818534a1Smrg syms = XkbKeySymsPtr(xkb, key); 451818534a1Smrg if (nSyms > IBUF_SIZE) { 452818534a1Smrg interps = _XkbTypedCalloc(nSyms, XkbSymInterpretPtr); 453818534a1Smrg if (interps == NULL) { 454818534a1Smrg interps = ibuf; 455818534a1Smrg nSyms = IBUF_SIZE; 456818534a1Smrg } 4571ab64890Smrg } 4581ab64890Smrg else { 459818534a1Smrg interps = ibuf; 460818534a1Smrg } 461818534a1Smrg found = 0; 462818534a1Smrg for (n = 0; n < nSyms; n++) { 463818534a1Smrg unsigned level = (n % XkbKeyGroupsWidth(xkb, key)); 464818534a1Smrg 465818534a1Smrg interps[n] = NULL; 466818534a1Smrg if (syms[n] != NoSymbol) { 467818534a1Smrg interps[n] = _XkbFindMatchingInterp(xkb, syms[n], mods, level); 468818534a1Smrg if (interps[n] && interps[n]->act.type != XkbSA_NoAction) 469818534a1Smrg found++; 470818534a1Smrg else 471818534a1Smrg interps[n] = NULL; 472818534a1Smrg } 4731ab64890Smrg } 4741ab64890Smrg /* 1/28/96 (ef) -- XXX! WORKING HERE */ 4751ab64890Smrg if (!found) { 476818534a1Smrg if (xkb->server->key_acts[key] != 0) { 477818534a1Smrg xkb->server->key_acts[key] = 0; 478818534a1Smrg changed |= XkbKeyActionsMask; 479818534a1Smrg } 4801ab64890Smrg } 4811ab64890Smrg else { 482818534a1Smrg XkbAction *pActs; 483818534a1Smrg unsigned int new_vmodmask; 484818534a1Smrg 485818534a1Smrg changed |= XkbKeyActionsMask; 486818534a1Smrg pActs = XkbResizeKeyActions(xkb, key, nSyms); 487818534a1Smrg if (!pActs) { 4881ab64890Smrg if (nSyms > IBUF_SIZE) 4891ab64890Smrg Xfree(interps); 490818534a1Smrg return False; 491818534a1Smrg } 492818534a1Smrg new_vmodmask = 0; 493818534a1Smrg for (n = 0; n < nSyms; n++) { 494818534a1Smrg if (interps[n]) { 495818534a1Smrg unsigned effMods; 496818534a1Smrg 497818534a1Smrg pActs[n] = *((XkbAction *) &interps[n]->act); 498818534a1Smrg if ((n == 0) || ((interps[n]->match & XkbSI_LevelOneOnly) == 0)) { 499818534a1Smrg effMods = mods; 500818534a1Smrg if (interps[n]->virtual_mod != XkbNoModifier) 501818534a1Smrg new_vmodmask |= (1 << interps[n]->virtual_mod); 502818534a1Smrg } 503818534a1Smrg else 504818534a1Smrg effMods = 0; 505818534a1Smrg _XkbSetActionKeyMods(xkb, &pActs[n], effMods); 506818534a1Smrg } 507818534a1Smrg else 508818534a1Smrg pActs[n].type = XkbSA_NoAction; 509818534a1Smrg } 510818534a1Smrg if (((explicit & XkbExplicitVModMapMask) == 0) && 511818534a1Smrg (xkb->server->vmodmap[key] != new_vmodmask)) { 512818534a1Smrg changed |= XkbVirtualModMapMask; 513818534a1Smrg xkb->server->vmodmap[key] = new_vmodmask; 514818534a1Smrg } 515818534a1Smrg if (interps[0]) { 516818534a1Smrg if ((interps[0]->flags & XkbSI_LockingKey) && 517818534a1Smrg ((explicit & XkbExplicitBehaviorMask) == 0)) { 518818534a1Smrg xkb->server->behaviors[key].type = XkbKB_Lock; 519818534a1Smrg changed |= XkbKeyBehaviorsMask; 520818534a1Smrg } 521818534a1Smrg if (((explicit & XkbExplicitAutoRepeatMask) == 0) && (xkb->ctrls)) { 522818534a1Smrg CARD8 old; 523818534a1Smrg 524818534a1Smrg old = xkb->ctrls->per_key_repeat[key / 8]; 525818534a1Smrg if (interps[0]->flags & XkbSI_AutoRepeat) 526818534a1Smrg xkb->ctrls->per_key_repeat[key / 8] |= (1 << (key % 8)); 527818534a1Smrg else 528818534a1Smrg xkb->ctrls->per_key_repeat[key / 8] &= ~(1 << (key % 8)); 529818534a1Smrg if (changes && (old != xkb->ctrls->per_key_repeat[key / 8])) 530818534a1Smrg changes->ctrls.changed_ctrls |= XkbPerKeyRepeatMask; 531818534a1Smrg } 532818534a1Smrg } 533818534a1Smrg } 534818534a1Smrg if ((!found) || (interps[0] == NULL)) { 535818534a1Smrg if (((explicit & XkbExplicitAutoRepeatMask) == 0) && (xkb->ctrls)) { 536818534a1Smrg CARD8 old; 537818534a1Smrg 538818534a1Smrg old = xkb->ctrls->per_key_repeat[key / 8]; 5391ab64890Smrg#ifdef RETURN_SHOULD_REPEAT 540818534a1Smrg if (*XkbKeySymsPtr(xkb, key) != XK_Return) 5411ab64890Smrg#endif 542818534a1Smrg xkb->ctrls->per_key_repeat[key / 8] |= (1 << (key % 8)); 543818534a1Smrg if (changes && (old != xkb->ctrls->per_key_repeat[key / 8])) 544818534a1Smrg changes->ctrls.changed_ctrls |= XkbPerKeyRepeatMask; 545818534a1Smrg } 546818534a1Smrg if (((explicit & XkbExplicitBehaviorMask) == 0) && 547818534a1Smrg (xkb->server->behaviors[key].type == XkbKB_Lock)) { 548818534a1Smrg xkb->server->behaviors[key].type = XkbKB_Default; 549818534a1Smrg changed |= XkbKeyBehaviorsMask; 550818534a1Smrg } 5511ab64890Smrg } 5521ab64890Smrg if (changes) { 553818534a1Smrg XkbMapChangesPtr mc; 554818534a1Smrg 555818534a1Smrg mc = &changes->map; 556818534a1Smrg tmp = (changed & mc->changed); 557818534a1Smrg if (tmp & XkbKeyActionsMask) 558818534a1Smrg _XkbAddKeyChange(&mc->first_key_act, &mc->num_key_acts, key); 559818534a1Smrg else if (changed & XkbKeyActionsMask) { 560818534a1Smrg mc->changed |= XkbKeyActionsMask; 561818534a1Smrg mc->first_key_act = key; 562818534a1Smrg mc->num_key_acts = 1; 563818534a1Smrg } 564818534a1Smrg if (tmp & XkbKeyBehaviorsMask) { 565818534a1Smrg _XkbAddKeyChange(&mc->first_key_behavior, &mc->num_key_behaviors, 566818534a1Smrg key); 567818534a1Smrg } 568818534a1Smrg else if (changed & XkbKeyBehaviorsMask) { 569818534a1Smrg mc->changed |= XkbKeyBehaviorsMask; 570818534a1Smrg mc->first_key_behavior = key; 571818534a1Smrg mc->num_key_behaviors = 1; 572818534a1Smrg } 573818534a1Smrg if (tmp & XkbVirtualModMapMask) 574818534a1Smrg _XkbAddKeyChange(&mc->first_vmodmap_key, &mc->num_vmodmap_keys, 575818534a1Smrg key); 576818534a1Smrg else if (changed & XkbVirtualModMapMask) { 577818534a1Smrg mc->changed |= XkbVirtualModMapMask; 578818534a1Smrg mc->first_vmodmap_key = key; 579818534a1Smrg mc->num_vmodmap_keys = 1; 580818534a1Smrg } 581818534a1Smrg mc->changed |= changed; 582818534a1Smrg } 583818534a1Smrg if (interps != ibuf) 584818534a1Smrg _XkbFree(interps); 5851ab64890Smrg return True; 5861ab64890Smrg} 5871ab64890Smrg 5881ab64890SmrgBool 589818534a1SmrgXkbUpdateMapFromCore(XkbDescPtr xkb, 590818534a1Smrg KeyCode first_key, 591818534a1Smrg int num_keys, 592818534a1Smrg int map_width, 593818534a1Smrg KeySym *core_keysyms, 594818534a1Smrg XkbChangesPtr changes) 5951ab64890Smrg{ 596818534a1Smrg register int key, last_key; 597818534a1Smrg KeySym *syms; 5981ab64890Smrg 599818534a1Smrg syms = &core_keysyms[(first_key - xkb->min_key_code) * map_width]; 6001ab64890Smrg if (changes) { 601818534a1Smrg if (changes->map.changed & XkbKeySymsMask) { 602818534a1Smrg _XkbAddKeyChange(&changes->map.first_key_sym, 603818534a1Smrg &changes->map.num_key_syms, first_key); 604818534a1Smrg if (num_keys > 1) { 605818534a1Smrg _XkbAddKeyChange(&changes->map.first_key_sym, 606818534a1Smrg &changes->map.num_key_syms, 607818534a1Smrg first_key + num_keys - 1); 608818534a1Smrg } 609818534a1Smrg } 610818534a1Smrg else { 611818534a1Smrg changes->map.changed |= XkbKeySymsMask; 612818534a1Smrg changes->map.first_key_sym = first_key; 613818534a1Smrg changes->map.num_key_syms = num_keys; 614818534a1Smrg } 615818534a1Smrg } 616818534a1Smrg last_key = first_key + num_keys - 1; 617818534a1Smrg for (key = first_key; key <= last_key; key++, syms += map_width) { 618818534a1Smrg XkbMapChangesPtr mc; 619818534a1Smrg unsigned explicit; 620818534a1Smrg KeySym tsyms[XkbMaxSymsPerKey]; 621818534a1Smrg int types[XkbNumKbdGroups]; 622818534a1Smrg int nG; 623818534a1Smrg 624818534a1Smrg explicit = xkb->server->explicit[key] & XkbExplicitKeyTypesMask; 625818534a1Smrg types[XkbGroup1Index] = XkbKeyKeyTypeIndex(xkb, key, XkbGroup1Index); 626818534a1Smrg types[XkbGroup2Index] = XkbKeyKeyTypeIndex(xkb, key, XkbGroup2Index); 627818534a1Smrg types[XkbGroup3Index] = XkbKeyKeyTypeIndex(xkb, key, XkbGroup3Index); 628818534a1Smrg types[XkbGroup4Index] = XkbKeyKeyTypeIndex(xkb, key, XkbGroup4Index); 629818534a1Smrg nG = XkbKeyTypesForCoreSymbols(xkb, map_width, syms, explicit, types, 630818534a1Smrg tsyms); 631818534a1Smrg if (changes) 632818534a1Smrg mc = &changes->map; 633818534a1Smrg else 634818534a1Smrg mc = NULL; 635818534a1Smrg XkbChangeTypesOfKey(xkb, key, nG, XkbAllGroupsMask, types, mc); 636818534a1Smrg memcpy((char *) XkbKeySymsPtr(xkb, key), (char *) tsyms, 637818534a1Smrg XkbKeyNumSyms(xkb, key) * sizeof(KeySym)); 638818534a1Smrg XkbApplyCompatMapToKey(xkb, key, changes); 639818534a1Smrg } 640818534a1Smrg 641818534a1Smrg if ((xkb->map->modmap != NULL) && (changes) && 642818534a1Smrg (changes->map.changed & (XkbVirtualModMapMask | XkbModifierMapMask))) { 643818534a1Smrg unsigned char newVMods[XkbNumVirtualMods]; 644818534a1Smrg register unsigned bit, i; 645818534a1Smrg unsigned present; 646818534a1Smrg 647818534a1Smrg bzero(newVMods, XkbNumVirtualMods); 648818534a1Smrg present = 0; 649818534a1Smrg for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) { 650818534a1Smrg if (xkb->server->vmodmap[key] == 0) 651818534a1Smrg continue; 652818534a1Smrg for (i = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) { 653818534a1Smrg if (bit & xkb->server->vmodmap[key]) { 654818534a1Smrg present |= bit; 655818534a1Smrg newVMods[i] |= xkb->map->modmap[key]; 656818534a1Smrg } 657818534a1Smrg } 658818534a1Smrg } 659818534a1Smrg for (i = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) { 660818534a1Smrg if ((bit & present) && (newVMods[i] != xkb->server->vmods[i])) { 661818534a1Smrg changes->map.changed |= XkbVirtualModsMask; 662818534a1Smrg changes->map.vmods |= bit; 663818534a1Smrg xkb->server->vmods[i] = newVMods[i]; 664818534a1Smrg } 665818534a1Smrg } 666818534a1Smrg } 667818534a1Smrg if (changes && (changes->map.changed & XkbVirtualModsMask)) 668818534a1Smrg XkbApplyVirtualModChanges(xkb, changes->map.vmods, changes); 6691ab64890Smrg return True; 6701ab64890Smrg} 6711ab64890Smrg 6721ab64890SmrgStatus 673818534a1SmrgXkbChangeTypesOfKey(XkbDescPtr xkb, 674818534a1Smrg int key, 675818534a1Smrg int nGroups, 676818534a1Smrg unsigned groups, 677818534a1Smrg int *newTypesIn, 678818534a1Smrg XkbMapChangesPtr changes) 6791ab64890Smrg{ 680818534a1Smrg XkbKeyTypePtr pOldType, pNewType; 681818534a1Smrg register int i; 682818534a1Smrg int width, nOldGroups, oldWidth, newTypes[XkbNumKbdGroups]; 683818534a1Smrg 684818534a1Smrg if ((!xkb) || (!XkbKeycodeInRange(xkb, key)) || (!xkb->map) || 68507fb9b8fSmrg (!xkb->map->types) || (!newTypesIn) || 68607fb9b8fSmrg ((groups & XkbAllGroupsMask) == 0) || (nGroups > XkbNumKbdGroups)) { 687818534a1Smrg return BadMatch; 688818534a1Smrg } 689818534a1Smrg if (nGroups == 0) { 690818534a1Smrg for (i = 0; i < XkbNumKbdGroups; i++) { 691818534a1Smrg xkb->map->key_sym_map[key].kt_index[i] = XkbOneLevelIndex; 692818534a1Smrg } 693818534a1Smrg i = xkb->map->key_sym_map[key].group_info; 694818534a1Smrg i = XkbSetNumGroups(i, 0); 695818534a1Smrg xkb->map->key_sym_map[key].group_info = i; 696818534a1Smrg XkbResizeKeySyms(xkb, key, 0); 69707fb9b8fSmrg XkbResizeKeyActions(xkb, key, 0); 698818534a1Smrg return Success; 699818534a1Smrg } 700818534a1Smrg 701818534a1Smrg nOldGroups = XkbKeyNumGroups(xkb, key); 702818534a1Smrg oldWidth = XkbKeyGroupsWidth(xkb, key); 703818534a1Smrg for (width = i = 0; i < nGroups; i++) { 704818534a1Smrg if (groups & (1 << i)) 705818534a1Smrg newTypes[i] = newTypesIn[i]; 706818534a1Smrg else if (i < nOldGroups) 707818534a1Smrg newTypes[i] = XkbKeyKeyTypeIndex(xkb, key, i); 708818534a1Smrg else if (nOldGroups > 0) 709818534a1Smrg newTypes[i] = XkbKeyKeyTypeIndex(xkb, key, XkbGroup1Index); 710818534a1Smrg else 711818534a1Smrg newTypes[i] = XkbTwoLevelIndex; 712818534a1Smrg if (newTypes[i] > xkb->map->num_types) 713818534a1Smrg return BadMatch; 714818534a1Smrg pNewType = &xkb->map->types[newTypes[i]]; 715818534a1Smrg if (pNewType->num_levels > width) 716818534a1Smrg width = pNewType->num_levels; 717818534a1Smrg } 718818534a1Smrg if ((xkb->ctrls) && (nGroups > xkb->ctrls->num_groups)) 719818534a1Smrg xkb->ctrls->num_groups = nGroups; 720818534a1Smrg if ((width != oldWidth) || (nGroups != nOldGroups)) { 721818534a1Smrg KeySym oldSyms[XkbMaxSymsPerKey], *pSyms; 722818534a1Smrg int nCopy; 723818534a1Smrg 724818534a1Smrg if (nOldGroups == 0) { 725818534a1Smrg pSyms = XkbResizeKeySyms(xkb, key, width * nGroups); 726818534a1Smrg if (pSyms != NULL) { 727818534a1Smrg i = xkb->map->key_sym_map[key].group_info; 728818534a1Smrg i = XkbSetNumGroups(i, nGroups); 729818534a1Smrg xkb->map->key_sym_map[key].group_info = i; 730818534a1Smrg xkb->map->key_sym_map[key].width = width; 731818534a1Smrg for (i = 0; i < nGroups; i++) { 732818534a1Smrg xkb->map->key_sym_map[key].kt_index[i] = newTypes[i]; 733818534a1Smrg } 734818534a1Smrg return Success; 735818534a1Smrg } 736818534a1Smrg return BadAlloc; 737818534a1Smrg } 738818534a1Smrg pSyms = XkbKeySymsPtr(xkb, key); 7399c019ec5Smaya memcpy(oldSyms, pSyms, (size_t) XkbKeyNumSyms(xkb, key) * sizeof(KeySym)); 740818534a1Smrg pSyms = XkbResizeKeySyms(xkb, key, width * nGroups); 741818534a1Smrg if (pSyms == NULL) 742818534a1Smrg return BadAlloc; 743818534a1Smrg bzero(pSyms, width * nGroups * sizeof(KeySym)); 744818534a1Smrg for (i = 0; (i < nGroups) && (i < nOldGroups); i++) { 745818534a1Smrg pOldType = XkbKeyKeyType(xkb, key, i); 746818534a1Smrg pNewType = &xkb->map->types[newTypes[i]]; 747818534a1Smrg if (pNewType->num_levels > pOldType->num_levels) 748818534a1Smrg nCopy = pOldType->num_levels; 749818534a1Smrg else 750818534a1Smrg nCopy = pNewType->num_levels; 751818534a1Smrg memcpy(&pSyms[i * width], &oldSyms[i * oldWidth], 752818534a1Smrg nCopy * sizeof(KeySym)); 753818534a1Smrg } 754818534a1Smrg if (XkbKeyHasActions(xkb, key)) { 755818534a1Smrg XkbAction oldActs[XkbMaxSymsPerKey], *pActs; 756818534a1Smrg 757818534a1Smrg pActs = XkbKeyActionsPtr(xkb, key); 7589c019ec5Smaya memcpy(oldActs, pActs, (size_t) XkbKeyNumSyms(xkb, key) * sizeof(XkbAction)); 759818534a1Smrg pActs = XkbResizeKeyActions(xkb, key, width * nGroups); 760818534a1Smrg if (pActs == NULL) 761818534a1Smrg return BadAlloc; 762818534a1Smrg bzero(pActs, width * nGroups * sizeof(XkbAction)); 763818534a1Smrg for (i = 0; (i < nGroups) && (i < nOldGroups); i++) { 764818534a1Smrg pOldType = XkbKeyKeyType(xkb, key, i); 765818534a1Smrg pNewType = &xkb->map->types[newTypes[i]]; 766818534a1Smrg if (pNewType->num_levels > pOldType->num_levels) 767818534a1Smrg nCopy = pOldType->num_levels; 768818534a1Smrg else 769818534a1Smrg nCopy = pNewType->num_levels; 770818534a1Smrg memcpy(&pActs[i * width], &oldActs[i * oldWidth], 771818534a1Smrg nCopy * sizeof(XkbAction)); 772818534a1Smrg } 773818534a1Smrg } 774818534a1Smrg i = xkb->map->key_sym_map[key].group_info; 775818534a1Smrg i = XkbSetNumGroups(i, nGroups); 776818534a1Smrg xkb->map->key_sym_map[key].group_info = i; 777818534a1Smrg xkb->map->key_sym_map[key].width = width; 778818534a1Smrg } 779818534a1Smrg width = 0; 780818534a1Smrg for (i = 0; i < nGroups; i++) { 781818534a1Smrg xkb->map->key_sym_map[key].kt_index[i] = newTypes[i]; 782818534a1Smrg if (xkb->map->types[newTypes[i]].num_levels > width) 783818534a1Smrg width = xkb->map->types[newTypes[i]].num_levels; 784818534a1Smrg } 785818534a1Smrg xkb->map->key_sym_map[key].width = width; 786818534a1Smrg if (changes != NULL) { 787818534a1Smrg if (changes->changed & XkbKeySymsMask) { 788818534a1Smrg _XkbAddKeyChange(&changes->first_key_sym, &changes->num_key_syms, 789818534a1Smrg key); 790818534a1Smrg } 791818534a1Smrg else { 792818534a1Smrg changes->changed |= XkbKeySymsMask; 793818534a1Smrg changes->first_key_sym = key; 794818534a1Smrg changes->num_key_syms = 1; 795818534a1Smrg } 7961ab64890Smrg } 7971ab64890Smrg return Success; 7981ab64890Smrg} 7991ab64890Smrg 8001ab64890Smrg/***====================================================================***/ 8011ab64890Smrg 8021ab64890SmrgBool 803818534a1SmrgXkbVirtualModsToReal(XkbDescPtr xkb, unsigned virtual_mask, unsigned *mask_rtrn) 8041ab64890Smrg{ 805818534a1Smrg register int i, bit; 806818534a1Smrg register unsigned mask; 807818534a1Smrg 80807fb9b8fSmrg if ((xkb == NULL) || (xkb->server == NULL)) { 80907fb9b8fSmrg *mask_rtrn = 0; 810818534a1Smrg return False; 81107fb9b8fSmrg } 812818534a1Smrg if (virtual_mask == 0) { 813818534a1Smrg *mask_rtrn = 0; 814818534a1Smrg return True; 815818534a1Smrg } 816818534a1Smrg for (i = mask = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) { 817818534a1Smrg if (virtual_mask & bit) 818818534a1Smrg mask |= xkb->server->vmods[i]; 819818534a1Smrg } 820818534a1Smrg *mask_rtrn = mask; 8211ab64890Smrg return True; 8221ab64890Smrg} 8231ab64890Smrg 8241ab64890Smrg/***====================================================================***/ 8251ab64890Smrg 8261ab64890SmrgBool 827818534a1SmrgXkbUpdateActionVirtualMods(XkbDescPtr xkb, XkbAction *act, unsigned changed) 8281ab64890Smrg{ 829818534a1Smrg unsigned int tmp; 8301ab64890Smrg 8311ab64890Smrg switch (act->type) { 832818534a1Smrg case XkbSA_SetMods: 833818534a1Smrg case XkbSA_LatchMods: 834818534a1Smrg case XkbSA_LockMods: 835818534a1Smrg if (((tmp = XkbModActionVMods(&act->mods)) & changed) != 0) { 836818534a1Smrg XkbVirtualModsToReal(xkb, tmp, &tmp); 837818534a1Smrg act->mods.mask = act->mods.real_mods; 838818534a1Smrg act->mods.mask |= tmp; 839818534a1Smrg return True; 840818534a1Smrg } 841818534a1Smrg break; 842818534a1Smrg case XkbSA_ISOLock: 843818534a1Smrg if ((((tmp = XkbModActionVMods(&act->iso)) != 0) & changed) != 0) { 844818534a1Smrg XkbVirtualModsToReal(xkb, tmp, &tmp); 845818534a1Smrg act->iso.mask = act->iso.real_mods; 846818534a1Smrg act->iso.mask |= tmp; 847818534a1Smrg return True; 848818534a1Smrg } 849818534a1Smrg break; 8501ab64890Smrg } 8511ab64890Smrg return False; 8521ab64890Smrg} 8531ab64890Smrg 8541ab64890Smrgvoid 855818534a1SmrgXkbUpdateKeyTypeVirtualMods(XkbDescPtr xkb, 856818534a1Smrg XkbKeyTypePtr type, 857818534a1Smrg unsigned int changed, 858818534a1Smrg XkbChangesPtr changes) 8591ab64890Smrg{ 860818534a1Smrg register unsigned int i; 861e9628295Smrg unsigned int mask = 0; 862818534a1Smrg 863818534a1Smrg XkbVirtualModsToReal(xkb, type->mods.vmods, &mask); 864818534a1Smrg type->mods.mask = type->mods.real_mods | mask; 865818534a1Smrg if ((type->map_count > 0) && (type->mods.vmods != 0)) { 866818534a1Smrg XkbKTMapEntryPtr entry; 867818534a1Smrg 868818534a1Smrg for (i = 0, entry = type->map; i < type->map_count; i++, entry++) { 869818534a1Smrg if (entry->mods.vmods != 0) { 870818534a1Smrg XkbVirtualModsToReal(xkb, entry->mods.vmods, &mask); 871818534a1Smrg entry->mods.mask = entry->mods.real_mods | mask; 872818534a1Smrg /* entry is active if vmods are bound */ 873818534a1Smrg entry->active = (mask != 0); 874818534a1Smrg } 875818534a1Smrg else 876818534a1Smrg entry->active = 1; 877818534a1Smrg } 8781ab64890Smrg } 8791ab64890Smrg if (changes) { 880818534a1Smrg int type_ndx; 881818534a1Smrg 882818534a1Smrg type_ndx = type - xkb->map->types; 883818534a1Smrg if ((type_ndx < 0) || (type_ndx > xkb->map->num_types)) 884818534a1Smrg return; 885818534a1Smrg if (changes->map.changed & XkbKeyTypesMask) { 886818534a1Smrg int last; 887818534a1Smrg 888818534a1Smrg last = changes->map.first_type + changes->map.num_types - 1; 889818534a1Smrg if (type_ndx < changes->map.first_type) { 890818534a1Smrg changes->map.first_type = type_ndx; 891818534a1Smrg changes->map.num_types = (last - type_ndx) + 1; 892818534a1Smrg } 893818534a1Smrg else if (type_ndx > last) { 894818534a1Smrg changes->map.num_types = 895818534a1Smrg (type_ndx - changes->map.first_type) + 1; 896818534a1Smrg } 897818534a1Smrg } 898818534a1Smrg else { 899818534a1Smrg changes->map.changed |= XkbKeyTypesMask; 900818534a1Smrg changes->map.first_type = type_ndx; 901818534a1Smrg changes->map.num_types = 1; 902818534a1Smrg } 9031ab64890Smrg } 9041ab64890Smrg return; 9051ab64890Smrg} 9061ab64890Smrg 9071ab64890SmrgBool 908818534a1SmrgXkbApplyVirtualModChanges(XkbDescPtr xkb, 909818534a1Smrg unsigned changed, 910818534a1Smrg XkbChangesPtr changes) 9111ab64890Smrg{ 912818534a1Smrg register int i; 913818534a1Smrg unsigned int checkState = 0; 914818534a1Smrg 915818534a1Smrg if ((!xkb) || (!xkb->map) || (changed == 0)) 916818534a1Smrg return False; 917818534a1Smrg for (i = 0; i < xkb->map->num_types; i++) { 918818534a1Smrg if (xkb->map->types[i].mods.vmods & changed) 919818534a1Smrg XkbUpdateKeyTypeVirtualMods(xkb, &xkb->map->types[i], changed, 920818534a1Smrg changes); 921818534a1Smrg } 922818534a1Smrg if (changed & xkb->ctrls->internal.vmods) { 923818534a1Smrg unsigned int newMask; 924818534a1Smrg 925818534a1Smrg XkbVirtualModsToReal(xkb, xkb->ctrls->internal.vmods, &newMask); 926818534a1Smrg newMask |= xkb->ctrls->internal.real_mods; 927818534a1Smrg if (xkb->ctrls->internal.mask != newMask) { 928818534a1Smrg xkb->ctrls->internal.mask = newMask; 929818534a1Smrg if (changes) { 930818534a1Smrg changes->ctrls.changed_ctrls |= XkbInternalModsMask; 931818534a1Smrg checkState = True; 932818534a1Smrg } 933818534a1Smrg } 934818534a1Smrg } 935818534a1Smrg if (changed & xkb->ctrls->ignore_lock.vmods) { 936818534a1Smrg unsigned int newMask; 937818534a1Smrg 938818534a1Smrg XkbVirtualModsToReal(xkb, xkb->ctrls->ignore_lock.vmods, &newMask); 939818534a1Smrg newMask |= xkb->ctrls->ignore_lock.real_mods; 940818534a1Smrg if (xkb->ctrls->ignore_lock.mask != newMask) { 941818534a1Smrg xkb->ctrls->ignore_lock.mask = newMask; 942818534a1Smrg if (changes) { 943818534a1Smrg changes->ctrls.changed_ctrls |= XkbIgnoreLockModsMask; 944818534a1Smrg checkState = True; 945818534a1Smrg } 946818534a1Smrg } 947818534a1Smrg } 948818534a1Smrg if (xkb->indicators != NULL) { 949818534a1Smrg XkbIndicatorMapPtr map; 950818534a1Smrg 951818534a1Smrg map = &xkb->indicators->maps[0]; 952818534a1Smrg for (i = 0; i < XkbNumIndicators; i++, map++) { 953818534a1Smrg if (map->mods.vmods & changed) { 954818534a1Smrg unsigned int newMask; 955818534a1Smrg 956818534a1Smrg XkbVirtualModsToReal(xkb, map->mods.vmods, &newMask); 957818534a1Smrg newMask |= map->mods.real_mods; 958818534a1Smrg if (newMask != map->mods.mask) { 959818534a1Smrg map->mods.mask = newMask; 960818534a1Smrg if (changes) { 961818534a1Smrg changes->indicators.map_changes |= (1 << i); 962818534a1Smrg checkState = True; 963818534a1Smrg } 964818534a1Smrg } 965818534a1Smrg } 966818534a1Smrg } 967818534a1Smrg } 968818534a1Smrg if (xkb->compat != NULL) { 969818534a1Smrg XkbCompatMapPtr compat; 970818534a1Smrg 971818534a1Smrg compat = xkb->compat; 972818534a1Smrg for (i = 0; i < XkbNumKbdGroups; i++) { 973818534a1Smrg unsigned int newMask; 974818534a1Smrg 975818534a1Smrg XkbVirtualModsToReal(xkb, compat->groups[i].vmods, &newMask); 976818534a1Smrg newMask |= compat->groups[i].real_mods; 977818534a1Smrg if (compat->groups[i].mask != newMask) { 978818534a1Smrg compat->groups[i].mask = newMask; 979818534a1Smrg if (changes) { 980818534a1Smrg changes->compat.changed_groups |= (1 << i); 981818534a1Smrg checkState = True; 982818534a1Smrg } 983818534a1Smrg } 984818534a1Smrg } 9851ab64890Smrg } 9861ab64890Smrg if (xkb->map && xkb->server) { 987818534a1Smrg int highChange = 0, lowChange = -1; 988818534a1Smrg 989818534a1Smrg for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) { 990818534a1Smrg if (XkbKeyHasActions(xkb, i)) { 991818534a1Smrg register XkbAction *pAct; 992818534a1Smrg register int n; 993818534a1Smrg 994818534a1Smrg pAct = XkbKeyActionsPtr(xkb, i); 995818534a1Smrg for (n = XkbKeyNumActions(xkb, i); n > 0; n--, pAct++) { 996818534a1Smrg if ((pAct->type != XkbSA_NoAction) && 997818534a1Smrg XkbUpdateActionVirtualMods(xkb, pAct, changed)) { 998818534a1Smrg if (lowChange < 0) 999818534a1Smrg lowChange = i; 1000818534a1Smrg highChange = i; 1001818534a1Smrg } 1002818534a1Smrg } 1003818534a1Smrg } 1004818534a1Smrg } 1005818534a1Smrg if (changes && (lowChange > 0)) { /* something changed */ 1006818534a1Smrg if (changes->map.changed & XkbKeyActionsMask) { 1007818534a1Smrg int last; 1008818534a1Smrg 1009818534a1Smrg if (changes->map.first_key_act < lowChange) 1010818534a1Smrg lowChange = changes->map.first_key_act; 1011818534a1Smrg last = 1012818534a1Smrg changes->map.first_key_act + changes->map.num_key_acts - 1; 1013818534a1Smrg if (last > highChange) 1014818534a1Smrg highChange = last; 1015818534a1Smrg } 1016818534a1Smrg changes->map.changed |= XkbKeyActionsMask; 1017818534a1Smrg changes->map.first_key_act = lowChange; 1018818534a1Smrg changes->map.num_key_acts = (highChange - lowChange) + 1; 1019818534a1Smrg } 10201ab64890Smrg } 10211ab64890Smrg return checkState; 10221ab64890Smrg} 1023