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