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
XkbKeyTypesForCoreSymbols(XkbDescPtr xkb,int map_width,KeySym * core_syms,unsigned int protected,int * types_inout,KeySym * xkb_syms_rtrn)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
_XkbFindMatchingInterp(XkbDescPtr xkb,KeySym sym,unsigned int real_mods,unsigned int level)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
_XkbAddKeyChange(KeyCode * pFirst,unsigned char * pNum,KeyCode newKey)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
_XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction * act,unsigned mods)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
XkbApplyCompatMapToKey(XkbDescPtr xkb,KeyCode key,XkbChangesPtr changes)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
XkbChangeTypesOfKey(XkbDescPtr xkb,int key,int nGroups,unsigned groups,int * newTypesIn,XkbMapChangesPtr changes)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
XkbVirtualModsToReal(XkbDescPtr xkb,unsigned virtual_mask,unsigned * mask_rtrn)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)
667         return FALSE;
668     if (virtual_mask == 0) {
669         *mask_rtrn = 0;
670         return TRUE;
671     }
672     if (xkb->server == NULL)
673         return FALSE;
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
XkbUpdateActionVirtualMods(XkbDescPtr xkb,XkbAction * act,unsigned changed)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
XkbUpdateKeyTypeVirtualMods(XkbDescPtr xkb,XkbKeyTypePtr type,unsigned int changed,XkbChangesPtr changes)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
XkbApplyVirtualModChanges(XkbDescPtr xkb,unsigned changed,XkbChangesPtr changes)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 }
879