xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

XKBMisc.c (30868B)


      1 /************************************************************
      2 Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
      3 
      4 Permission to use, copy, modify, and distribute this
      5 software and its documentation for any purpose and without
      6 fee is hereby granted, provided that the above copyright
      7 notice appear in all copies and that both that copyright
      8 notice and this permission notice appear in supporting
      9 documentation, and that the name of Silicon Graphics not be
     10 used in advertising or publicity pertaining to distribution
     11 of the software without specific prior written permission.
     12 Silicon Graphics makes no representation about the suitability
     13 of this software for any purpose. It is provided "as is"
     14 without any express or implied warranty.
     15 
     16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
     17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
     18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
     19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
     20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
     22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
     23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
     24 
     25 ********************************************************/
     26 
     27 #ifdef HAVE_DIX_CONFIG_H
     28 #include <dix-config.h>
     29 #endif
     30 
     31 #include <stdio.h>
     32 #include <X11/X.h>
     33 #include <X11/Xproto.h>
     34 #include "misc.h"
     35 #include "inputstr.h"
     36 #include <X11/keysym.h>
     37 #define	XKBSRV_NEED_FILE_FUNCS
     38 #include <xkbsrv.h>
     39 
     40 /***====================================================================***/
     41 
     42 #define	CORE_SYM(i)	(i<map_width?core_syms[i]:NoSymbol)
     43 #define	XKB_OFFSET(g,l)	(((g)*groupsWidth)+(l))
     44 
     45 int
     46 XkbKeyTypesForCoreSymbols(XkbDescPtr xkb,
     47                           int map_width,
     48                           KeySym * core_syms,
     49                           unsigned int protected,
     50                           int *types_inout, KeySym * xkb_syms_rtrn)
     51 {
     52     register int i;
     53     unsigned int empty;
     54     int nSyms[XkbNumKbdGroups];
     55     int nGroups, tmp, groupsWidth;
     56     BOOL replicated = FALSE;
     57 
     58     /* Section 12.2 of the protocol describes this process in more detail */
     59     /* Step 1:  find the # of symbols in the core mapping per group */
     60     groupsWidth = 2;
     61     for (i = 0; i < XkbNumKbdGroups; i++) {
     62         if ((protected & (1 << i)) && (types_inout[i] < xkb->map->num_types)) {
     63             nSyms[i] = xkb->map->types[types_inout[i]].num_levels;
     64             if (nSyms[i] > groupsWidth)
     65                 groupsWidth = nSyms[i];
     66         }
     67         else {
     68             types_inout[i] = XkbTwoLevelIndex;  /* don't really know, yet */
     69             nSyms[i] = 2;
     70         }
     71     }
     72     if (nSyms[XkbGroup1Index] < 2)
     73         nSyms[XkbGroup1Index] = 2;
     74     if (nSyms[XkbGroup2Index] < 2)
     75         nSyms[XkbGroup2Index] = 2;
     76     /* Step 2:  Copy the symbols from the core ordering to XKB ordering */
     77     /*          symbols in the core are in the order:                   */
     78     /*          G1L1 G1L2 G2L1 G2L2 [G1L[3-n]] [G2L[3-n]] [G3L*] [G3L*] */
     79     xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index, 0)] = CORE_SYM(0);
     80     xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index, 1)] = CORE_SYM(1);
     81     for (i = 2; i < nSyms[XkbGroup1Index]; i++) {
     82         xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index, i)] = CORE_SYM(2 + i);
     83     }
     84     xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index, 0)] = CORE_SYM(2);
     85     xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index, 1)] = CORE_SYM(3);
     86     tmp = 2 + (nSyms[XkbGroup1Index] - 2);      /* offset to extra group2 syms */
     87     for (i = 2; i < nSyms[XkbGroup2Index]; i++) {
     88         xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index, i)] = CORE_SYM(tmp + i);
     89     }
     90 
     91     /* Special case: if only the first group is explicit, and the symbols
     92      * replicate across all groups, then we have a Section 12.4 replication */
     93     if ((protected & ~XkbExplicitKeyType1Mask) == 0) {
     94         int j, width = nSyms[XkbGroup1Index];
     95 
     96         replicated = TRUE;
     97 
     98         /* Check ABAB in ABABCDECDEABCDE */
     99         if ((width > 0 && CORE_SYM(0) != CORE_SYM(2)) ||
    100             (width > 1 && CORE_SYM(1) != CORE_SYM(3)))
    101             replicated = FALSE;
    102 
    103         /* Check CDECDE in ABABCDECDEABCDE */
    104         for (i = 2; i < width && replicated; i++) {
    105             if (CORE_SYM(2 + i) != CORE_SYM(i + width))
    106                 replicated = FALSE;
    107         }
    108 
    109         /* Check ABCDE in ABABCDECDEABCDE */
    110         for (j = 2; replicated &&
    111              j < XkbNumKbdGroups && map_width >= width * (j + 1); j++) {
    112             for (i = 0; i < width && replicated; i++) {
    113                 if (CORE_SYM(((i < 2) ? i : 2 + i)) != CORE_SYM(i + width * j))
    114                     replicated = FALSE;
    115             }
    116         }
    117     }
    118 
    119     if (replicated) {
    120         nSyms[XkbGroup2Index] = 0;
    121         nSyms[XkbGroup3Index] = 0;
    122         nSyms[XkbGroup4Index] = 0;
    123         nGroups = 1;
    124     }
    125     else {
    126         tmp = nSyms[XkbGroup1Index] + nSyms[XkbGroup2Index];
    127         if ((tmp >= map_width) &&
    128             ((protected & (XkbExplicitKeyType3Mask | XkbExplicitKeyType4Mask))
    129              == 0)) {
    130             nSyms[XkbGroup3Index] = 0;
    131             nSyms[XkbGroup4Index] = 0;
    132             nGroups = 2;
    133         }
    134         else {
    135             nGroups = 3;
    136             for (i = 0; i < nSyms[XkbGroup3Index]; i++, tmp++) {
    137                 xkb_syms_rtrn[XKB_OFFSET(XkbGroup3Index, i)] = CORE_SYM(tmp);
    138             }
    139             if ((tmp < map_width) || (protected & XkbExplicitKeyType4Mask)) {
    140                 nGroups = 4;
    141                 for (i = 0; i < nSyms[XkbGroup4Index]; i++, tmp++) {
    142                     xkb_syms_rtrn[XKB_OFFSET(XkbGroup4Index, i)] =
    143                         CORE_SYM(tmp);
    144                 }
    145             }
    146             else {
    147                 nSyms[XkbGroup4Index] = 0;
    148             }
    149         }
    150     }
    151     /* steps 3&4: alphanumeric expansion,  assign canonical types */
    152     empty = 0;
    153     for (i = 0; i < nGroups; i++) {
    154         KeySym *syms;
    155 
    156         syms = &xkb_syms_rtrn[XKB_OFFSET(i, 0)];
    157         if ((nSyms[i] > 1) && (syms[1] == NoSymbol) && (syms[0] != NoSymbol)) {
    158             KeySym upper, lower;
    159 
    160             XkbConvertCase(syms[0], &lower, &upper);
    161             if (upper != lower) {
    162                 xkb_syms_rtrn[XKB_OFFSET(i, 0)] = lower;
    163                 xkb_syms_rtrn[XKB_OFFSET(i, 1)] = upper;
    164                 if ((protected & (1 << i)) == 0)
    165                     types_inout[i] = XkbAlphabeticIndex;
    166             }
    167             else if ((protected & (1 << i)) == 0) {
    168                 types_inout[i] = XkbOneLevelIndex;
    169                 /*      nSyms[i]=       1; */
    170             }
    171         }
    172         if (((protected & (1 << i)) == 0) &&
    173             (types_inout[i] == XkbTwoLevelIndex)) {
    174             if (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1]))
    175                 types_inout[i] = XkbKeypadIndex;
    176             else {
    177                 KeySym upper, lower;
    178 
    179                 XkbConvertCase(syms[0], &lower, &upper);
    180                 if ((syms[0] == lower) && (syms[1] == upper))
    181                     types_inout[i] = XkbAlphabeticIndex;
    182             }
    183         }
    184         if (syms[0] == NoSymbol) {
    185             register int n;
    186             Bool found;
    187 
    188             for (n = 1, found = FALSE; (!found) && (n < nSyms[i]); n++) {
    189                 found = (syms[n] != NoSymbol);
    190             }
    191             if (!found)
    192                 empty |= (1 << i);
    193         }
    194     }
    195     /* step 5: squoosh out empty groups */
    196     if (empty) {
    197         for (i = nGroups - 1; i >= 0; i--) {
    198             if (((empty & (1 << i)) == 0) || (protected & (1 << i)))
    199                 break;
    200             nGroups--;
    201         }
    202     }
    203     if (nGroups < 1)
    204         return 0;
    205 
    206     /* step 6: replicate group 1 into group two, if necessary */
    207     if ((nGroups > 1) &&
    208         ((empty & (XkbGroup1Mask | XkbGroup2Mask)) == XkbGroup2Mask)) {
    209         if ((protected & (XkbExplicitKeyType1Mask | XkbExplicitKeyType2Mask)) ==
    210             0) {
    211             nSyms[XkbGroup2Index] = nSyms[XkbGroup1Index];
    212             types_inout[XkbGroup2Index] = types_inout[XkbGroup1Index];
    213             memcpy((char *) &xkb_syms_rtrn[2], (char *) xkb_syms_rtrn,
    214                    2 * sizeof(KeySym));
    215         }
    216         else if (types_inout[XkbGroup1Index] == types_inout[XkbGroup2Index]) {
    217             memcpy((char *) &xkb_syms_rtrn[nSyms[XkbGroup1Index]],
    218                    (char *) xkb_syms_rtrn,
    219                    nSyms[XkbGroup1Index] * sizeof(KeySym));
    220         }
    221     }
    222 
    223     /* step 7: check for all groups identical or all width 1
    224      *
    225      * Special feature: if group 1 has an explicit type and all other groups
    226      * have canonical types with same symbols, we assume it's info lost from
    227      * the core replication.
    228      */
    229     if (nGroups > 1) {
    230         Bool sameType, allOneLevel, canonical = TRUE;
    231 
    232         allOneLevel = (xkb->map->types[types_inout[0]].num_levels == 1);
    233         for (i = 1, sameType = TRUE; (allOneLevel || sameType) && (i < nGroups);
    234              i++) {
    235             sameType = (sameType &&
    236                         (types_inout[i] == types_inout[XkbGroup1Index]));
    237             if (allOneLevel)
    238                 allOneLevel = (xkb->map->types[types_inout[i]].num_levels == 1);
    239             if (types_inout[i] > XkbLastRequiredType)
    240                 canonical = FALSE;
    241         }
    242         if (((sameType) || canonical) &&
    243             (!(protected &
    244                (XkbExplicitKeyTypesMask & ~XkbExplicitKeyType1Mask)))) {
    245             register int s;
    246             Bool identical;
    247 
    248             for (i = 1, identical = TRUE; identical && (i < nGroups); i++) {
    249                 KeySym *syms;
    250 
    251                 if (nSyms[i] != nSyms[XkbGroup1Index])
    252                     identical = FALSE;
    253                 syms = &xkb_syms_rtrn[XKB_OFFSET(i, 0)];
    254                 for (s = 0; identical && (s < nSyms[i]); s++) {
    255                     if (syms[s] != xkb_syms_rtrn[s])
    256                         identical = FALSE;
    257                 }
    258             }
    259             if (identical)
    260                 nGroups = 1;
    261         }
    262         if (allOneLevel && (nGroups > 1)) {
    263             KeySym *syms;
    264 
    265             syms = &xkb_syms_rtrn[nSyms[XkbGroup1Index]];
    266             nSyms[XkbGroup1Index] = 1;
    267             for (i = 1; i < nGroups; i++) {
    268                 xkb_syms_rtrn[i] = syms[0];
    269                 syms += nSyms[i];
    270                 nSyms[i] = 1;
    271             }
    272         }
    273     }
    274     return nGroups;
    275 }
    276 
    277 static XkbSymInterpretPtr
    278 _XkbFindMatchingInterp(XkbDescPtr xkb,
    279                        KeySym sym, unsigned int real_mods, unsigned int level)
    280 {
    281     register unsigned i;
    282     XkbSymInterpretPtr interp, rtrn;
    283     CARD8 mods;
    284 
    285     rtrn = NULL;
    286     interp = xkb->compat->sym_interpret;
    287     for (i = 0; i < xkb->compat->num_si; i++, interp++) {
    288         if ((interp->sym == NoSymbol) || (sym == interp->sym)) {
    289             int match;
    290 
    291             if ((level == 0) || ((interp->match & XkbSI_LevelOneOnly) == 0))
    292                 mods = real_mods;
    293             else
    294                 mods = 0;
    295             switch (interp->match & XkbSI_OpMask) {
    296             case XkbSI_NoneOf:
    297                 match = ((interp->mods & mods) == 0);
    298                 break;
    299             case XkbSI_AnyOfOrNone:
    300                 match = ((mods == 0) || ((interp->mods & mods) != 0));
    301                 break;
    302             case XkbSI_AnyOf:
    303                 match = ((interp->mods & mods) != 0);
    304                 break;
    305             case XkbSI_AllOf:
    306                 match = ((interp->mods & mods) == interp->mods);
    307                 break;
    308             case XkbSI_Exactly:
    309                 match = (interp->mods == mods);
    310                 break;
    311             default:
    312                 match = 0;
    313                 break;
    314             }
    315             if (match) {
    316                 if (interp->sym != NoSymbol) {
    317                     return interp;
    318                 }
    319                 else if (rtrn == NULL) {
    320                     rtrn = interp;
    321                 }
    322             }
    323         }
    324     }
    325     return rtrn;
    326 }
    327 
    328 static void
    329 _XkbAddKeyChange(KeyCode *pFirst, unsigned char *pNum, KeyCode newKey)
    330 {
    331     KeyCode last;
    332 
    333     last = (*pFirst) + (*pNum);
    334     if (newKey < *pFirst) {
    335         *pFirst = newKey;
    336         *pNum = (last - newKey) + 1;
    337     }
    338     else if (newKey > last) {
    339         *pNum = (last - *pFirst) + 1;
    340     }
    341     return;
    342 }
    343 
    344 static void
    345 _XkbSetActionKeyMods(XkbDescPtr xkb, XkbAction *act, unsigned mods)
    346 {
    347     unsigned tmp;
    348 
    349     switch (act->type) {
    350     case XkbSA_SetMods:
    351     case XkbSA_LatchMods:
    352     case XkbSA_LockMods:
    353         if (act->mods.flags & XkbSA_UseModMapMods)
    354             act->mods.real_mods = act->mods.mask = mods;
    355         if ((tmp = XkbModActionVMods(&act->mods)) != 0) {
    356             XkbVirtualModsToReal(xkb, tmp, &tmp);
    357             act->mods.mask |= tmp;
    358         }
    359         break;
    360     case XkbSA_ISOLock:
    361         if (act->iso.flags & XkbSA_UseModMapMods)
    362             act->iso.real_mods = act->iso.mask = mods;
    363         if ((tmp = XkbModActionVMods(&act->iso)) != 0) {
    364             XkbVirtualModsToReal(xkb, tmp, &tmp);
    365             act->iso.mask |= tmp;
    366         }
    367         break;
    368     }
    369     return;
    370 }
    371 
    372 #define	IBUF_SIZE	8
    373 
    374 Bool
    375 XkbApplyCompatMapToKey(XkbDescPtr xkb, KeyCode key, XkbChangesPtr changes)
    376 {
    377     KeySym *syms;
    378     unsigned char explicit, mods;
    379     XkbSymInterpretPtr *interps, ibuf[IBUF_SIZE];
    380     int n, nSyms, found;
    381     unsigned changed, tmp;
    382 
    383     if ((!xkb) || (!xkb->map) || (!xkb->map->key_sym_map) ||
    384         (!xkb->compat) || (!xkb->compat->sym_interpret) ||
    385         (key < xkb->min_key_code) || (key > xkb->max_key_code)) {
    386         return FALSE;
    387     }
    388     if (((!xkb->server) || (!xkb->server->key_acts)) &&
    389         (XkbAllocServerMap(xkb, XkbAllServerInfoMask, 0) != Success)) {
    390         return FALSE;
    391     }
    392     changed = 0;                /* keeps track of what has changed in _this_ call */
    393     explicit = xkb->server->explicit[key];
    394     if (explicit & XkbExplicitInterpretMask)    /* nothing to do */
    395         return TRUE;
    396     mods = (xkb->map->modmap ? xkb->map->modmap[key] : 0);
    397     nSyms = XkbKeyNumSyms(xkb, key);
    398     syms = XkbKeySymsPtr(xkb, key);
    399     if (nSyms > IBUF_SIZE) {
    400         interps = calloc(nSyms, sizeof(XkbSymInterpretPtr));
    401         if (interps == NULL) {
    402             interps = ibuf;
    403             nSyms = IBUF_SIZE;
    404         }
    405     }
    406     else {
    407         interps = ibuf;
    408     }
    409     found = 0;
    410     for (n = 0; n < nSyms; n++) {
    411         unsigned level = (n % XkbKeyGroupsWidth(xkb, key));
    412 
    413         interps[n] = NULL;
    414         if (syms[n] != NoSymbol) {
    415             interps[n] = _XkbFindMatchingInterp(xkb, syms[n], mods, level);
    416             if (interps[n] && interps[n]->act.type != XkbSA_NoAction)
    417                 found++;
    418             else
    419                 interps[n] = NULL;
    420         }
    421     }
    422     /* 1/28/96 (ef) -- XXX! WORKING HERE */
    423     if (!found) {
    424         if (xkb->server->key_acts[key] != 0) {
    425             xkb->server->key_acts[key] = 0;
    426             changed |= XkbKeyActionsMask;
    427         }
    428     }
    429     else {
    430         XkbAction *pActs;
    431         unsigned int new_vmodmask;
    432 
    433         changed |= XkbKeyActionsMask;
    434         pActs = XkbResizeKeyActions(xkb, key, nSyms);
    435         if (!pActs) {
    436             if (nSyms > IBUF_SIZE)
    437                 free(interps);
    438             return FALSE;
    439         }
    440         new_vmodmask = 0;
    441         for (n = 0; n < nSyms; n++) {
    442             if (interps[n]) {
    443                 unsigned effMods;
    444 
    445                 pActs[n] = *((XkbAction *) &interps[n]->act);
    446                 if ((n == 0) || ((interps[n]->match & XkbSI_LevelOneOnly) == 0)) {
    447                     effMods = mods;
    448                     if (interps[n]->virtual_mod != XkbNoModifier)
    449                         new_vmodmask |= (1 << interps[n]->virtual_mod);
    450                 }
    451                 else
    452                     effMods = 0;
    453                 _XkbSetActionKeyMods(xkb, &pActs[n], effMods);
    454             }
    455             else
    456                 pActs[n].type = XkbSA_NoAction;
    457         }
    458         if (((explicit & XkbExplicitVModMapMask) == 0) &&
    459             (xkb->server->vmodmap[key] != new_vmodmask)) {
    460             changed |= XkbVirtualModMapMask;
    461             xkb->server->vmodmap[key] = new_vmodmask;
    462         }
    463         if (interps[0]) {
    464             if ((interps[0]->flags & XkbSI_LockingKey) &&
    465                 ((explicit & XkbExplicitBehaviorMask) == 0)) {
    466                 xkb->server->behaviors[key].type = XkbKB_Lock;
    467                 changed |= XkbKeyBehaviorsMask;
    468             }
    469             if (((explicit & XkbExplicitAutoRepeatMask) == 0) && (xkb->ctrls)) {
    470                 CARD8 old;
    471 
    472                 old = BitIsOn(xkb->ctrls->per_key_repeat, key);
    473                 if (interps[0]->flags & XkbSI_AutoRepeat)
    474                     SetBit(xkb->ctrls->per_key_repeat, key);
    475                 else
    476                     ClearBit(xkb->ctrls->per_key_repeat, key);
    477                 if (changes && old != BitIsOn(xkb->ctrls->per_key_repeat, key))
    478                     changes->ctrls.changed_ctrls |= XkbPerKeyRepeatMask;
    479             }
    480         }
    481     }
    482     if ((!found) || (interps[0] == NULL)) {
    483         if (((explicit & XkbExplicitAutoRepeatMask) == 0) && (xkb->ctrls)) {
    484             CARD8 old;
    485 
    486             old = BitIsOn(xkb->ctrls->per_key_repeat, key);
    487             SetBit(xkb->ctrls->per_key_repeat, key);
    488             if (changes && (old != BitIsOn(xkb->ctrls->per_key_repeat, key)))
    489                 changes->ctrls.changed_ctrls |= XkbPerKeyRepeatMask;
    490         }
    491         if (((explicit & XkbExplicitBehaviorMask) == 0) &&
    492             (xkb->server->behaviors[key].type == XkbKB_Lock)) {
    493             xkb->server->behaviors[key].type = XkbKB_Default;
    494             changed |= XkbKeyBehaviorsMask;
    495         }
    496     }
    497     if (changes) {
    498         XkbMapChangesPtr mc;
    499 
    500         mc = &changes->map;
    501         tmp = (changed & mc->changed);
    502         if (tmp & XkbKeyActionsMask)
    503             _XkbAddKeyChange(&mc->first_key_act, &mc->num_key_acts, key);
    504         else if (changed & XkbKeyActionsMask) {
    505             mc->changed |= XkbKeyActionsMask;
    506             mc->first_key_act = key;
    507             mc->num_key_acts = 1;
    508         }
    509         if (tmp & XkbKeyBehaviorsMask) {
    510             _XkbAddKeyChange(&mc->first_key_behavior, &mc->num_key_behaviors,
    511                              key);
    512         }
    513         else if (changed & XkbKeyBehaviorsMask) {
    514             mc->changed |= XkbKeyBehaviorsMask;
    515             mc->first_key_behavior = key;
    516             mc->num_key_behaviors = 1;
    517         }
    518         if (tmp & XkbVirtualModMapMask)
    519             _XkbAddKeyChange(&mc->first_vmodmap_key, &mc->num_vmodmap_keys,
    520                              key);
    521         else if (changed & XkbVirtualModMapMask) {
    522             mc->changed |= XkbVirtualModMapMask;
    523             mc->first_vmodmap_key = key;
    524             mc->num_vmodmap_keys = 1;
    525         }
    526         mc->changed |= changed;
    527     }
    528     if (interps != ibuf)
    529         free(interps);
    530     return TRUE;
    531 }
    532 
    533 Status
    534 XkbChangeTypesOfKey(XkbDescPtr xkb,
    535                     int key,
    536                     int nGroups,
    537                     unsigned groups, int *newTypesIn, XkbMapChangesPtr changes)
    538 {
    539     XkbKeyTypePtr pOldType, pNewType;
    540     register int i;
    541     int width, nOldGroups, oldWidth, newTypes[XkbNumKbdGroups];
    542 
    543     if ((!xkb) || (!XkbKeycodeInRange(xkb, key)) || (!xkb->map) ||
    544         (!xkb->map->types) || (!newTypesIn) ||
    545         ((groups & XkbAllGroupsMask) == 0) || (nGroups > XkbNumKbdGroups)) {
    546         return BadMatch;
    547     }
    548     if (nGroups == 0) {
    549         for (i = 0; i < XkbNumKbdGroups; i++) {
    550             xkb->map->key_sym_map[key].kt_index[i] = XkbOneLevelIndex;
    551         }
    552         i = xkb->map->key_sym_map[key].group_info;
    553         i = XkbSetNumGroups(i, 0);
    554         xkb->map->key_sym_map[key].group_info = i;
    555         XkbResizeKeySyms(xkb, key, 0);
    556         return Success;
    557     }
    558 
    559     nOldGroups = XkbKeyNumGroups(xkb, key);
    560     oldWidth = XkbKeyGroupsWidth(xkb, key);
    561     for (width = i = 0; i < nGroups; i++) {
    562         if (groups & (1 << i))
    563             newTypes[i] = newTypesIn[i];
    564         else if (i < nOldGroups)
    565             newTypes[i] = XkbKeyKeyTypeIndex(xkb, key, i);
    566         else if (nOldGroups > 0)
    567             newTypes[i] = XkbKeyKeyTypeIndex(xkb, key, XkbGroup1Index);
    568         else
    569             newTypes[i] = XkbTwoLevelIndex;
    570         if (newTypes[i] > xkb->map->num_types)
    571             return BadMatch;
    572         pNewType = &xkb->map->types[newTypes[i]];
    573         if (pNewType->num_levels > width)
    574             width = pNewType->num_levels;
    575     }
    576     if ((xkb->ctrls) && (nGroups > xkb->ctrls->num_groups))
    577         xkb->ctrls->num_groups = nGroups;
    578     if ((width != oldWidth) || (nGroups != nOldGroups)) {
    579         KeySym oldSyms[XkbMaxSymsPerKey], *pSyms;
    580         int nCopy;
    581 
    582         if (nOldGroups == 0) {
    583             pSyms = XkbResizeKeySyms(xkb, key, width * nGroups);
    584             if (pSyms != NULL) {
    585                 i = xkb->map->key_sym_map[key].group_info;
    586                 i = XkbSetNumGroups(i, nGroups);
    587                 xkb->map->key_sym_map[key].group_info = i;
    588                 xkb->map->key_sym_map[key].width = width;
    589                 for (i = 0; i < nGroups; i++) {
    590                     xkb->map->key_sym_map[key].kt_index[i] = newTypes[i];
    591                 }
    592                 return Success;
    593             }
    594             return BadAlloc;
    595         }
    596         pSyms = XkbKeySymsPtr(xkb, key);
    597         memcpy(oldSyms, pSyms, XkbKeyNumSyms(xkb, key) * sizeof(KeySym));
    598         pSyms = XkbResizeKeySyms(xkb, key, width * nGroups);
    599         if (pSyms == NULL)
    600             return BadAlloc;
    601         memset(pSyms, 0, width * nGroups * sizeof(KeySym));
    602         for (i = 0; (i < nGroups) && (i < nOldGroups); i++) {
    603             pOldType = XkbKeyKeyType(xkb, key, i);
    604             pNewType = &xkb->map->types[newTypes[i]];
    605             if (pNewType->num_levels > pOldType->num_levels)
    606                 nCopy = pOldType->num_levels;
    607             else
    608                 nCopy = pNewType->num_levels;
    609             memcpy(&pSyms[i * width], &oldSyms[i * oldWidth],
    610                    nCopy * sizeof(KeySym));
    611         }
    612         if (XkbKeyHasActions(xkb, key)) {
    613             XkbAction oldActs[XkbMaxSymsPerKey], *pActs;
    614 
    615             pActs = XkbKeyActionsPtr(xkb, key);
    616             memcpy(oldActs, pActs, XkbKeyNumSyms(xkb, key) * sizeof(XkbAction));
    617             pActs = XkbResizeKeyActions(xkb, key, width * nGroups);
    618             if (pActs == NULL)
    619                 return BadAlloc;
    620             memset(pActs, 0, width * nGroups * sizeof(XkbAction));
    621             for (i = 0; (i < nGroups) && (i < nOldGroups); i++) {
    622                 pOldType = XkbKeyKeyType(xkb, key, i);
    623                 pNewType = &xkb->map->types[newTypes[i]];
    624                 if (pNewType->num_levels > pOldType->num_levels)
    625                     nCopy = pOldType->num_levels;
    626                 else
    627                     nCopy = pNewType->num_levels;
    628                 memcpy(&pActs[i * width], &oldActs[i * oldWidth],
    629                        nCopy * sizeof(XkbAction));
    630             }
    631         }
    632         i = xkb->map->key_sym_map[key].group_info;
    633         i = XkbSetNumGroups(i, nGroups);
    634         xkb->map->key_sym_map[key].group_info = i;
    635         xkb->map->key_sym_map[key].width = width;
    636     }
    637     width = 0;
    638     for (i = 0; i < nGroups; i++) {
    639         xkb->map->key_sym_map[key].kt_index[i] = newTypes[i];
    640         if (xkb->map->types[newTypes[i]].num_levels > width)
    641             width = xkb->map->types[newTypes[i]].num_levels;
    642     }
    643     xkb->map->key_sym_map[key].width = width;
    644     if (changes != NULL) {
    645         if (changes->changed & XkbKeySymsMask) {
    646             _XkbAddKeyChange(&changes->first_key_sym, &changes->num_key_syms,
    647                              key);
    648         }
    649         else {
    650             changes->changed |= XkbKeySymsMask;
    651             changes->first_key_sym = key;
    652             changes->num_key_syms = 1;
    653         }
    654     }
    655     return Success;
    656 }
    657 
    658 /***====================================================================***/
    659 
    660 Bool
    661 XkbVirtualModsToReal(XkbDescPtr xkb, unsigned virtual_mask, unsigned *mask_rtrn)
    662 {
    663     register int i, bit;
    664     register unsigned mask;
    665 
    666     if ((xkb == NULL) || (xkb->server == NULL)) {
    667         *mask_rtrn = 0;
    668         return FALSE;
    669     }
    670     if (virtual_mask == 0) {
    671         *mask_rtrn = 0;
    672         return TRUE;
    673     }
    674     for (i = mask = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
    675         if (virtual_mask & bit)
    676             mask |= xkb->server->vmods[i];
    677     }
    678     *mask_rtrn = mask;
    679     return TRUE;
    680 }
    681 
    682 /***====================================================================***/
    683 
    684 static Bool
    685 XkbUpdateActionVirtualMods(XkbDescPtr xkb, XkbAction *act, unsigned changed)
    686 {
    687     unsigned int tmp;
    688 
    689     switch (act->type) {
    690     case XkbSA_SetMods:
    691     case XkbSA_LatchMods:
    692     case XkbSA_LockMods:
    693         if (((tmp = XkbModActionVMods(&act->mods)) & changed) != 0) {
    694             XkbVirtualModsToReal(xkb, tmp, &tmp);
    695             act->mods.mask = act->mods.real_mods;
    696             act->mods.mask |= tmp;
    697             return TRUE;
    698         }
    699         break;
    700     case XkbSA_ISOLock:
    701         if ((((tmp = XkbModActionVMods(&act->iso)) != 0) & changed) != 0) {
    702             XkbVirtualModsToReal(xkb, tmp, &tmp);
    703             act->iso.mask = act->iso.real_mods;
    704             act->iso.mask |= tmp;
    705             return TRUE;
    706         }
    707         break;
    708     }
    709     return FALSE;
    710 }
    711 
    712 static void
    713 XkbUpdateKeyTypeVirtualMods(XkbDescPtr xkb,
    714                             XkbKeyTypePtr type,
    715                             unsigned int changed, XkbChangesPtr changes)
    716 {
    717     register unsigned int i;
    718     unsigned int mask;
    719 
    720     XkbVirtualModsToReal(xkb, type->mods.vmods, &mask);
    721     type->mods.mask = type->mods.real_mods | mask;
    722     if ((type->map_count > 0) && (type->mods.vmods != 0)) {
    723         XkbKTMapEntryPtr entry;
    724 
    725         for (i = 0, entry = type->map; i < type->map_count; i++, entry++) {
    726             if (entry->mods.vmods != 0) {
    727                 XkbVirtualModsToReal(xkb, entry->mods.vmods, &mask);
    728                 entry->mods.mask = entry->mods.real_mods | mask;
    729                 /* entry is active if vmods are bound */
    730                 entry->active = (mask != 0);
    731             }
    732             else
    733                 entry->active = 1;
    734         }
    735     }
    736     if (changes) {
    737         int type_ndx;
    738 
    739         type_ndx = type - xkb->map->types;
    740         if ((type_ndx < 0) || (type_ndx > xkb->map->num_types))
    741             return;
    742         if (changes->map.changed & XkbKeyTypesMask) {
    743             int last;
    744 
    745             last = changes->map.first_type + changes->map.num_types - 1;
    746             if (type_ndx < changes->map.first_type) {
    747                 changes->map.first_type = type_ndx;
    748                 changes->map.num_types = (last - type_ndx) + 1;
    749             }
    750             else if (type_ndx > last) {
    751                 changes->map.num_types =
    752                     (type_ndx - changes->map.first_type) + 1;
    753             }
    754         }
    755         else {
    756             changes->map.changed |= XkbKeyTypesMask;
    757             changes->map.first_type = type_ndx;
    758             changes->map.num_types = 1;
    759         }
    760     }
    761     return;
    762 }
    763 
    764 Bool
    765 XkbApplyVirtualModChanges(XkbDescPtr xkb, unsigned changed,
    766                           XkbChangesPtr changes)
    767 {
    768     register int i;
    769     unsigned int checkState = 0;
    770 
    771     if ((!xkb) || (!xkb->map) || (changed == 0))
    772         return FALSE;
    773     for (i = 0; i < xkb->map->num_types; i++) {
    774         if (xkb->map->types[i].mods.vmods & changed)
    775             XkbUpdateKeyTypeVirtualMods(xkb, &xkb->map->types[i], changed,
    776                                         changes);
    777     }
    778     if (changed & xkb->ctrls->internal.vmods) {
    779         unsigned int newMask;
    780 
    781         XkbVirtualModsToReal(xkb, xkb->ctrls->internal.vmods, &newMask);
    782         newMask |= xkb->ctrls->internal.real_mods;
    783         if (xkb->ctrls->internal.mask != newMask) {
    784             xkb->ctrls->internal.mask = newMask;
    785             if (changes) {
    786                 changes->ctrls.changed_ctrls |= XkbInternalModsMask;
    787                 checkState = TRUE;
    788             }
    789         }
    790     }
    791     if (changed & xkb->ctrls->ignore_lock.vmods) {
    792         unsigned int newMask;
    793 
    794         XkbVirtualModsToReal(xkb, xkb->ctrls->ignore_lock.vmods, &newMask);
    795         newMask |= xkb->ctrls->ignore_lock.real_mods;
    796         if (xkb->ctrls->ignore_lock.mask != newMask) {
    797             xkb->ctrls->ignore_lock.mask = newMask;
    798             if (changes) {
    799                 changes->ctrls.changed_ctrls |= XkbIgnoreLockModsMask;
    800                 checkState = TRUE;
    801             }
    802         }
    803     }
    804     if (xkb->indicators != NULL) {
    805         XkbIndicatorMapPtr map;
    806 
    807         map = &xkb->indicators->maps[0];
    808         for (i = 0; i < XkbNumIndicators; i++, map++) {
    809             if (map->mods.vmods & changed) {
    810                 unsigned int newMask;
    811 
    812                 XkbVirtualModsToReal(xkb, map->mods.vmods, &newMask);
    813                 newMask |= map->mods.real_mods;
    814                 if (newMask != map->mods.mask) {
    815                     map->mods.mask = newMask;
    816                     if (changes) {
    817                         changes->indicators.map_changes |= (1 << i);
    818                         checkState = TRUE;
    819                     }
    820                 }
    821             }
    822         }
    823     }
    824     if (xkb->compat != NULL) {
    825         XkbCompatMapPtr compat;
    826 
    827         compat = xkb->compat;
    828         for (i = 0; i < XkbNumKbdGroups; i++) {
    829             unsigned int newMask;
    830 
    831             XkbVirtualModsToReal(xkb, compat->groups[i].vmods, &newMask);
    832             newMask |= compat->groups[i].real_mods;
    833             if (compat->groups[i].mask != newMask) {
    834                 compat->groups[i].mask = newMask;
    835                 if (changes) {
    836                     changes->compat.changed_groups |= (1 << i);
    837                     checkState = TRUE;
    838                 }
    839             }
    840         }
    841     }
    842     if (xkb->map && xkb->server) {
    843         int highChange = 0, lowChange = -1;
    844 
    845         for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
    846             if (XkbKeyHasActions(xkb, i)) {
    847                 register XkbAction *pAct;
    848                 register int n;
    849 
    850                 pAct = XkbKeyActionsPtr(xkb, i);
    851                 for (n = XkbKeyNumActions(xkb, i); n > 0; n--, pAct++) {
    852                     if ((pAct->type != XkbSA_NoAction) &&
    853                         XkbUpdateActionVirtualMods(xkb, pAct, changed)) {
    854                         if (lowChange < 0)
    855                             lowChange = i;
    856                         highChange = i;
    857                     }
    858                 }
    859             }
    860         }
    861         if (changes && (lowChange > 0)) {       /* something changed */
    862             if (changes->map.changed & XkbKeyActionsMask) {
    863                 int last;
    864 
    865                 if (changes->map.first_key_act < lowChange)
    866                     lowChange = changes->map.first_key_act;
    867                 last =
    868                     changes->map.first_key_act + changes->map.num_key_acts - 1;
    869                 if (last > highChange)
    870                     highChange = last;
    871             }
    872             changes->map.changed |= XkbKeyActionsMask;
    873             changes->map.first_key_act = lowChange;
    874             changes->map.num_key_acts = (highChange - lowChange) + 1;
    875         }
    876     }
    877     return checkState;
    878 }