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