1 /************************************************************
2 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
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.
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.
25 ********************************************************/
33 #include "indicators.h"
35 #include "parseutils.h"
37 typedef struct _SymInterpInfo
40 struct xkb_sym_interpret interp;
43 #define _SI_VirtualMod (1<<0)
44 #define _SI_Action (1<<1)
45 #define _SI_AutoRepeat (1<<2)
46 #define _SI_LockingKey (1<<3)
47 #define _SI_LevelOneOnly (1<<4)
49 typedef struct _GroupCompatInfo
54 unsigned char real_mods;
58 typedef struct _CompatInfo
64 SymInterpInfo *interps;
67 GroupCompatInfo groupCompat[XkbNumKbdGroups];
71 struct xkb_keymap * xkb;
74 /***====================================================================***/
76 #define ReportSINotArray(si,f,i) \
77 ReportNotArray("symbol interpretation",(f),siText((si),(i)))
78 #define ReportSIBadType(si,f,w,i) \
79 ReportBadType("symbol interpretation",(f),siText((si),(i)),(w))
81 /***====================================================================***/
84 siText(SymInterpInfo * si, CompatInfo * info)
88 if (si == &info->dflt)
90 snprintf(buf, sizeof(buf), "default");
94 snprintf(buf, sizeof(buf), "%s+%s(%s)",
95 XkbcKeysymText(si->interp.sym),
96 XkbcSIMatchText(si->interp.match),
97 XkbcModMaskText(si->interp.mods, False));
103 InitCompatInfo(CompatInfo * info, struct xkb_keymap * xkb)
110 info->errorCount = 0;
112 info->interps = NULL;
114 info->dflt.defs.fileID = info->fileID;
115 info->dflt.defs.defined = 0;
116 info->dflt.defs.merge = MergeOverride;
117 info->dflt.interp.flags = 0;
118 info->dflt.interp.virtual_mod = XkbNoModifier;
119 info->dflt.interp.act.type = XkbSA_NoAction;
120 for (i = 0; i < sizeof(info->dflt.interp.act.any.data); i++)
121 info->dflt.interp.act.any.data[i] = 0;
122 ClearIndicatorMapInfo(&info->ledDflt);
123 info->ledDflt.defs.fileID = info->fileID;
124 info->ledDflt.defs.defined = 0;
125 info->ledDflt.defs.merge = MergeOverride;
126 memset(&info->groupCompat[0], 0,
127 XkbNumKbdGroups * sizeof(GroupCompatInfo));
129 InitVModInfo(&info->vmods, xkb);
133 ClearCompatInfo(CompatInfo * info, struct xkb_keymap * xkb)
140 info->dflt.defs.defined = 0;
141 info->dflt.defs.merge = MergeAugment;
142 info->dflt.interp.flags = 0;
143 info->dflt.interp.virtual_mod = XkbNoModifier;
144 info->dflt.interp.act.type = XkbSA_NoAction;
145 for (i = 0; i < sizeof(info->dflt.interp.act.any.data); i++)
146 info->dflt.interp.act.any.data[i] = 0;
147 ClearIndicatorMapInfo(&info->ledDflt);
149 info->interps = (SymInterpInfo *) ClearCommonInfo(&info->interps->defs);
150 memset(&info->groupCompat[0], 0,
151 XkbNumKbdGroups * sizeof(GroupCompatInfo));
152 info->leds = (LEDInfo *) ClearCommonInfo(&info->leds->defs);
154 next = info->act->next;
158 ClearVModInfo(&info->vmods, xkb);
161 static SymInterpInfo *
162 NextInterp(CompatInfo * info)
166 si = uTypedAlloc(SymInterpInfo);
169 memset(si, 0, sizeof(SymInterpInfo));
171 (SymInterpInfo *) AddCommonInfo(&info->interps->defs,
178 static SymInterpInfo *
179 FindMatchingInterp(CompatInfo * info, SymInterpInfo * new)
183 for (old = info->interps; old != NULL;
184 old = (SymInterpInfo *) old->defs.next)
186 if ((old->interp.sym == new->interp.sym) &&
187 (old->interp.mods == new->interp.mods) &&
188 (old->interp.match == new->interp.match))
197 AddInterp(CompatInfo * info, SymInterpInfo * new)
203 old = FindMatchingInterp(info, new);
206 if (new->defs.merge == MergeReplace)
208 SymInterpInfo *next = (SymInterpInfo *) old->defs.next;
209 if (((old->defs.fileID == new->defs.fileID)
210 && (warningLevel > 0)) || (warningLevel > 9))
212 WARN("Multiple definitions for \"%s\"\n", siText(new, info));
213 ACTION("Earlier interpretation ignored\n");
216 old->defs.next = &next->defs;
219 if (UseNewField(_SI_VirtualMod, &old->defs, &new->defs, &collide))
221 old->interp.virtual_mod = new->interp.virtual_mod;
222 old->defs.defined |= _SI_VirtualMod;
224 if (UseNewField(_SI_Action, &old->defs, &new->defs, &collide))
226 old->interp.act = new->interp.act;
227 old->defs.defined |= _SI_Action;
229 if (UseNewField(_SI_AutoRepeat, &old->defs, &new->defs, &collide))
231 old->interp.flags &= ~XkbSI_AutoRepeat;
232 old->interp.flags |= (new->interp.flags & XkbSI_AutoRepeat);
233 old->defs.defined |= _SI_AutoRepeat;
235 if (UseNewField(_SI_LockingKey, &old->defs, &new->defs, &collide))
237 old->interp.flags &= ~XkbSI_LockingKey;
238 old->interp.flags |= (new->interp.flags & XkbSI_LockingKey);
239 old->defs.defined |= _SI_LockingKey;
241 if (UseNewField(_SI_LevelOneOnly, &old->defs, &new->defs, &collide))
243 old->interp.match &= ~XkbSI_LevelOneOnly;
244 old->interp.match |= (new->interp.match & XkbSI_LevelOneOnly);
245 old->defs.defined |= _SI_LevelOneOnly;
249 WARN("Multiple interpretations of \"%s\"\n", siText(new, info));
250 ACTION("Using %s definition for duplicate fields\n",
251 (new->defs.merge != MergeAugment ? "last" : "first"));
256 if ((new = NextInterp(info)) == NULL)
259 new->defs.next = NULL;
264 AddGroupCompat(CompatInfo * info, unsigned group, GroupCompatInfo * newGC)
269 merge = newGC->merge;
270 gc = &info->groupCompat[group];
271 if (((gc->real_mods == newGC->real_mods) && (gc->vmods == newGC->vmods)))
275 if (((gc->fileID == newGC->fileID) && (warningLevel > 0))
276 || (warningLevel > 9))
278 WARN("Compat map for group %d redefined\n", group + 1);
279 ACTION("Using %s definition\n",
280 (merge == MergeAugment ? "old" : "new"));
282 if (newGC->defined && (merge != MergeAugment || !gc->defined))
287 /***====================================================================***/
290 ResolveStateAndPredicate(ExprDef * expr,
292 unsigned *mods_rtrn, CompatInfo * info)
298 *pred_rtrn = XkbSI_AnyOfOrNone;
303 *pred_rtrn = XkbSI_Exactly;
304 if (expr->op == ExprActionDecl)
306 const char *pred_txt = XkbcAtomText(expr->value.action.name);
307 if (strcasecmp(pred_txt, "noneof") == 0)
308 *pred_rtrn = XkbSI_NoneOf;
309 else if (strcasecmp(pred_txt, "anyofornone") == 0)
310 *pred_rtrn = XkbSI_AnyOfOrNone;
311 else if (strcasecmp(pred_txt, "anyof") == 0)
312 *pred_rtrn = XkbSI_AnyOf;
313 else if (strcasecmp(pred_txt, "allof") == 0)
314 *pred_rtrn = XkbSI_AllOf;
315 else if (strcasecmp(pred_txt, "exactly") == 0)
316 *pred_rtrn = XkbSI_Exactly;
319 ERROR("Illegal modifier predicate \"%s\"\n", pred_txt);
323 expr = expr->value.action.args;
325 else if (expr->op == ExprIdent)
327 const char *pred_txt = XkbcAtomText(expr->value.str);
328 if ((pred_txt) && (strcasecmp(pred_txt, "any") == 0))
330 *pred_rtrn = XkbSI_AnyOf;
336 if (ExprResolveModMask(expr, &result))
338 *mods_rtrn = result.uval;
344 /***====================================================================***/
347 MergeIncludedCompatMaps(CompatInfo * into, CompatInfo * from, unsigned merge)
350 LEDInfo *led, *rtrn, *next;
351 GroupCompatInfo *gcm;
354 if (from->errorCount > 0)
356 into->errorCount += from->errorCount;
359 if (into->name == NULL)
361 into->name = from->name;
364 for (si = from->interps; si; si = (SymInterpInfo *) si->defs.next)
366 if (merge != MergeDefault)
367 si->defs.merge = merge;
368 if (!AddInterp(into, si))
371 for (i = 0, gcm = &from->groupCompat[0]; i < XkbNumKbdGroups; i++, gcm++)
373 if (merge != MergeDefault)
375 if (!AddGroupCompat(into, i, gcm))
378 for (led = from->leds; led != NULL; led = next)
380 next = (LEDInfo *) led->defs.next;
381 if (merge != MergeDefault)
382 led->defs.merge = merge;
383 rtrn = AddIndicatorMap(into->leds, led);
391 typedef void (*FileHandler) (XkbFile *rtrn, struct xkb_keymap *xkb,
392 unsigned merge, CompatInfo *info);
395 HandleIncludeCompatMap(IncludeStmt * stmt,
396 struct xkb_keymap * xkb, CompatInfo * info, FileHandler hndlr)
404 if ((stmt->file == NULL) && (stmt->map == NULL))
408 memset(info, 0, sizeof(CompatInfo));
410 else if (ProcessIncludeFile(xkb->context, stmt, XkmCompatMapIndex, &rtrn,
413 InitCompatInfo(&included, xkb);
414 included.fileID = rtrn->id;
415 included.dflt = info->dflt;
416 included.dflt.defs.fileID = rtrn->id;
417 included.dflt.defs.merge = newMerge;
418 included.ledDflt.defs.fileID = rtrn->id;
419 included.ledDflt.defs.merge = newMerge;
420 included.act = info->act;
421 (*hndlr) (rtrn, xkb, MergeOverride, &included);
422 if (stmt->stmt != NULL)
425 included.name = stmt->stmt;
428 if (info->act != NULL)
434 info->errorCount += 10;
437 if ((stmt->next != NULL) && (included.errorCount < 1))
441 CompatInfo next_incl;
443 for (next = stmt->next; next != NULL; next = next->next)
445 if ((next->file == NULL) && (next->map == NULL))
448 MergeIncludedCompatMaps(&included, info, next->merge);
449 ClearCompatInfo(info, xkb);
451 else if (ProcessIncludeFile(xkb->context, next, XkmCompatMapIndex,
454 InitCompatInfo(&next_incl, xkb);
455 next_incl.fileID = rtrn->id;
456 next_incl.dflt = info->dflt;
457 next_incl.dflt.defs.fileID = rtrn->id;
458 next_incl.dflt.defs.merge = op;
459 next_incl.ledDflt.defs.fileID = rtrn->id;
460 next_incl.ledDflt.defs.merge = op;
461 next_incl.act = info->act;
462 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
463 MergeIncludedCompatMaps(&included, &next_incl, op);
464 if (info->act != NULL)
465 next_incl.act = NULL;
466 ClearCompatInfo(&next_incl, xkb);
471 info->errorCount += 10;
480 MergeIncludedCompatMaps(info, &included, newMerge);
481 ClearCompatInfo(&included, xkb);
483 return (info->errorCount == 0);
486 static const LookupEntry useModMapValues[] = {
495 SetInterpField(SymInterpInfo * si,
496 struct xkb_keymap * xkb,
498 ExprDef * arrayNdx, ExprDef * value, CompatInfo * info)
503 if (strcasecmp(field, "action") == 0)
505 if (arrayNdx != NULL)
506 return ReportSINotArray(si, field, info);
507 ok = HandleActionDef(value, xkb, &si->interp.act.any, si->defs.merge,
510 si->defs.defined |= _SI_Action;
512 else if ((strcasecmp(field, "virtualmodifier") == 0) ||
513 (strcasecmp(field, "virtualmod") == 0))
515 if (arrayNdx != NULL)
516 return ReportSINotArray(si, field, info);
517 ok = ResolveVirtualModifier(value, xkb, &tmp, &info->vmods);
520 si->interp.virtual_mod = tmp.uval;
521 si->defs.defined |= _SI_VirtualMod;
524 return ReportSIBadType(si, field, "virtual modifier", info);
526 else if (strcasecmp(field, "repeat") == 0)
528 if (arrayNdx != NULL)
529 return ReportSINotArray(si, field, info);
530 ok = ExprResolveBoolean(value, &tmp);
534 si->interp.flags |= XkbSI_AutoRepeat;
536 si->interp.flags &= ~XkbSI_AutoRepeat;
537 si->defs.defined |= _SI_AutoRepeat;
540 return ReportSIBadType(si, field, "boolean", info);
542 else if (strcasecmp(field, "locking") == 0)
544 if (arrayNdx != NULL)
545 return ReportSINotArray(si, field, info);
546 ok = ExprResolveBoolean(value, &tmp);
550 si->interp.flags |= XkbSI_LockingKey;
552 si->interp.flags &= ~XkbSI_LockingKey;
553 si->defs.defined |= _SI_LockingKey;
556 return ReportSIBadType(si, field, "boolean", info);
558 else if ((strcasecmp(field, "usemodmap") == 0) ||
559 (strcasecmp(field, "usemodmapmods") == 0))
561 if (arrayNdx != NULL)
562 return ReportSINotArray(si, field, info);
563 ok = ExprResolveEnum(value, &tmp, useModMapValues);
567 si->interp.match |= XkbSI_LevelOneOnly;
569 si->interp.match &= ~XkbSI_LevelOneOnly;
570 si->defs.defined |= _SI_LevelOneOnly;
573 return ReportSIBadType(si, field, "level specification", info);
577 ok = ReportBadField("symbol interpretation", field, siText(si, info));
583 HandleInterpVar(VarDef * stmt, struct xkb_keymap * xkb, CompatInfo * info)
585 ExprResult elem, field;
589 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
590 ret = 0; /* internal error, already reported */
591 else if (elem.str && (strcasecmp(elem.str, "interpret") == 0))
592 ret = SetInterpField(&info->dflt, xkb, field.str, ndx, stmt->value,
594 else if (elem.str && (strcasecmp(elem.str, "indicator") == 0))
595 ret = SetIndicatorMapField(&info->ledDflt, xkb, field.str, ndx,
598 ret = SetActionField(xkb, elem.str, field.str, ndx, stmt->value,
606 HandleInterpBody(VarDef * def, struct xkb_keymap * xkb, SymInterpInfo * si,
610 ExprResult tmp, field;
613 for (; def != NULL; def = (VarDef *) def->common.next)
615 if ((def->name) && (def->name->type == ExprFieldRef))
617 ok = HandleInterpVar(def, xkb, info);
620 ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx);
622 ok = SetInterpField(si, xkb, field.str, arrayNdx, def->value,
631 HandleInterpDef(InterpDef * def, struct xkb_keymap * xkb, unsigned merge,
637 if (!ResolveStateAndPredicate(def->match, &pred, &mods, info))
639 ERROR("Couldn't determine matching modifiers\n");
640 ACTION("Symbol interpretation ignored\n");
643 if (def->merge != MergeDefault)
647 si.defs.merge = merge;
648 if (!LookupKeysym(def->sym, &si.interp.sym))
650 ERROR("Could not resolve keysym %s\n", def->sym);
651 ACTION("Symbol interpretation ignored\n");
654 si.interp.match = pred & XkbSI_OpMask;
655 si.interp.mods = mods;
656 if (!HandleInterpBody(def->def, xkb, &si, info))
662 if (!AddInterp(info, &si))
671 HandleGroupCompatDef(GroupCompatDef * def,
672 struct xkb_keymap * xkb, unsigned merge, CompatInfo * info)
677 if (def->merge != MergeDefault)
679 if (!XkbIsLegalGroup(def->group - 1))
681 ERROR("Keyboard group must be in the range 1..%d\n",
682 XkbNumKbdGroups + 1);
683 ACTION("Compatibility map for illegal group %d ignored\n",
687 tmp.fileID = info->fileID;
689 if (!ExprResolveVModMask(def->def, &val, xkb))
691 ERROR("Expected a modifier mask in group compatibility definition\n");
692 ACTION("Ignoring illegal compatibility map for group %d\n",
696 tmp.real_mods = val.uval & 0xff;
697 tmp.vmods = (val.uval >> 8) & 0xffff;
699 return AddGroupCompat(info, def->group - 1, &tmp);
703 HandleCompatMapFile(XkbFile * file,
704 struct xkb_keymap * xkb, unsigned merge, CompatInfo * info)
708 if (merge == MergeDefault)
709 merge = MergeAugment;
711 info->name = uDupString(file->name);
715 switch (stmt->stmtType)
718 if (!HandleIncludeCompatMap((IncludeStmt *) stmt, xkb, info,
719 HandleCompatMapFile))
723 if (!HandleInterpDef((InterpDef *) stmt, xkb, merge, info))
726 case StmtGroupCompatDef:
727 if (!HandleGroupCompatDef
728 ((GroupCompatDef *) stmt, xkb, merge, info))
731 case StmtIndicatorMapDef:
734 rtrn = HandleIndicatorMapDef((IndicatorMapDef *) stmt, xkb,
735 &info->ledDflt, info->leds, merge);
743 if (!HandleInterpVar((VarDef *) stmt, xkb, info))
747 if (!HandleVModDef((VModDef *) stmt, xkb, merge, &info->vmods))
751 ERROR("Interpretation files may not include other types\n");
752 ACTION("Ignoring definition of key name\n");
756 WSGO("Unexpected statement type %d in HandleCompatMapFile\n",
761 if (info->errorCount > 10)
764 ERROR("Too many errors\n");
766 ACTION("Abandoning compatibility map \"%s\"\n", file->topName);
773 CopyInterps(CompatInfo * info,
774 struct xkb_compat_map * compat, Bool needSymbol, unsigned pred)
778 for (si = info->interps; si; si = (SymInterpInfo *) si->defs.next)
780 if (((si->interp.match & XkbSI_OpMask) != pred) ||
781 (needSymbol && (si->interp.sym == XKB_KEYSYM_NO_SYMBOL)) ||
782 ((!needSymbol) && (si->interp.sym != XKB_KEYSYM_NO_SYMBOL)))
784 if (compat->num_si >= compat->size_si)
786 WSGO("No room to merge symbol interpretations\n");
787 ACTION("Symbol interpretations lost\n");
790 compat->sym_interpret[compat->num_si++] = si->interp;
795 CompileCompatMap(XkbFile *file, struct xkb_keymap * xkb, unsigned merge,
796 LEDInfoPtr *unboundLEDs)
800 GroupCompatInfo *gcm;
802 InitCompatInfo(&info, xkb);
803 info.dflt.defs.merge = merge;
804 info.ledDflt.defs.merge = merge;
805 HandleCompatMapFile(file, xkb, merge, &info);
807 if (info.errorCount == 0)
810 if (XkbcAllocCompatMap(xkb, XkbAllCompatMask, info.nInterps) !=
813 WSGO("Couldn't allocate compatibility map\n");
816 size = info.nInterps * sizeof(struct xkb_sym_interpret);
819 CopyInterps(&info, xkb->compat, True, XkbSI_Exactly);
820 CopyInterps(&info, xkb->compat, True, XkbSI_AllOf | XkbSI_NoneOf);
821 CopyInterps(&info, xkb->compat, True, XkbSI_AnyOf);
822 CopyInterps(&info, xkb->compat, True, XkbSI_AnyOfOrNone);
823 CopyInterps(&info, xkb->compat, False, XkbSI_Exactly);
824 CopyInterps(&info, xkb->compat, False,
825 XkbSI_AllOf | XkbSI_NoneOf);
826 CopyInterps(&info, xkb->compat, False, XkbSI_AnyOf);
827 CopyInterps(&info, xkb->compat, False, XkbSI_AnyOfOrNone);
829 for (i = 0, gcm = &info.groupCompat[0]; i < XkbNumKbdGroups;
832 if ((gcm->fileID != 0) || (gcm->real_mods != 0)
833 || (gcm->vmods != 0))
835 xkb->compat->groups[i].mask = gcm->real_mods;
836 xkb->compat->groups[i].real_mods = gcm->real_mods;
837 xkb->compat->groups[i].vmods = gcm->vmods;
840 if (info.leds != NULL)
842 if (!CopyIndicatorMapDefs(xkb, info.leds, unboundLEDs))
846 ClearCompatInfo(&info, xkb);
854 VModsToReal(struct xkb_keymap *xkb, uint32_t vmodmask)
862 for (i = 0; i < XkbNumVirtualMods; i++) {
863 if (!(vmodmask & (1 << i)))
865 ret |= xkb->server->vmods[i];
872 UpdateActionMods(struct xkb_keymap *xkb, union xkb_action *act, uint32_t rmodmask)
876 case XkbSA_LatchMods:
878 if (act->mods.flags & XkbSA_UseModMapMods)
879 act->mods.real_mods = rmodmask;
880 act->mods.mask = act->mods.real_mods;
881 act->mods.mask |= VModsToReal(xkb, act->mods.vmods);
884 if (act->iso.flags & XkbSA_UseModMapMods)
885 act->iso.real_mods = rmodmask;
886 act->iso.mask = act->iso.real_mods;
887 act->iso.mask |= VModsToReal(xkb, act->iso.vmods);
895 * Find an interpretation which applies to this particular level, either by
896 * finding an exact match for the symbol and modifier combination, or a
897 * generic XKB_KEYSYM_NO_SYMBOL match.
899 static struct xkb_sym_interpret *
900 FindInterpForKey(struct xkb_keymap *xkb, xkb_keycode_t key, uint32_t group, uint32_t level)
902 struct xkb_sym_interpret *ret = NULL;
903 const xkb_keysym_t *syms;
907 num_syms = xkb_key_get_syms_by_level(xkb, key, group, level, &syms);
911 for (i = 0; i < xkb->compat->num_si; i++) {
912 struct xkb_sym_interpret *interp = &xkb->compat->sym_interpret[i];
916 if ((num_syms > 1 || interp->sym != syms[0]) &&
917 interp->sym != XKB_KEYSYM_NO_SYMBOL)
920 if (level == 0 || !(interp->match & XkbSI_LevelOneOnly))
921 mods = xkb->map->modmap[key];
925 switch (interp->match & XkbSI_OpMask) {
927 found = !(interp->mods & mods);
929 case XkbSI_AnyOfOrNone:
930 found = (!mods || (interp->mods & mods));
933 found = !!(interp->mods & mods);
936 found = ((interp->mods & mods) == mods);
939 found = (interp->mods == mods);
946 if (found && interp->sym != XKB_KEYSYM_NO_SYMBOL)
948 else if (found && !ret)
958 ApplyInterpsToKey(struct xkb_keymap *xkb, xkb_keycode_t key)
960 #define INTERP_SIZE (8 * 4)
961 struct xkb_sym_interpret *interps[INTERP_SIZE];
962 union xkb_action *acts;
963 uint32_t vmodmask = 0;
966 int width = XkbKeyGroupsWidth(xkb, key);
969 /* If we've been told not to bind interps to this key, then don't. */
970 if (xkb->server->explicit[key] & XkbExplicitInterpretMask)
973 for (i = 0; i < INTERP_SIZE; i++)
976 for (group = 0; group < XkbKeyNumGroups(xkb, key); group++) {
977 for (level = 0; level < XkbKeyGroupWidth(xkb, key, group); level++) {
978 i = (group * width) + level;
979 if (i >= INTERP_SIZE) /* XXX FIXME */
981 interps[i] = FindInterpForKey(xkb, key, group, level);
988 num_acts = XkbKeyNumGroups(xkb, key) * width;
989 acts = XkbcResizeKeyActions(xkb, key, num_acts);
995 for (group = 0; group < XkbKeyNumGroups(xkb, key); group++) {
996 for (level = 0; level < XkbKeyGroupWidth(xkb, key, group); level++) {
997 struct xkb_sym_interpret *interp;
999 i = (group * width) + level;
1000 interp = interps[i];
1002 /* Infer default key behaviours from the base level. */
1003 if (group == 0 && level == 0) {
1004 if (!(xkb->server->explicit[key] & XkbExplicitAutoRepeatMask) &&
1005 (!interp || interp->flags & XkbSI_AutoRepeat))
1006 xkb->ctrls->per_key_repeat[key / 8] |= (1 << (key % 8));
1007 if (!(xkb->server->explicit[key] & XkbExplicitBehaviorMask) &&
1008 interp && (interp->flags & XkbSI_LockingKey))
1009 xkb->server->behaviors[key].type = XkbKB_Lock;
1015 if ((group == 0 && level == 0) ||
1016 !(interp->match & XkbSI_LevelOneOnly)) {
1017 if (interp->virtual_mod != XkbNoModifier)
1018 vmodmask |= (1 << interp->virtual_mod);
1020 acts[i] = interp->act;
1024 if (!(xkb->server->explicit[key] & XkbExplicitVModMapMask))
1025 xkb->server->vmodmap[key] = vmodmask;
1032 * This collects a bunch of disparate functions which was done in the server
1033 * at various points that really should've been done within xkbcomp. Turns out
1034 * your actions and types are a lot more useful when any of your modifiers
1035 * other than Shift actually do something ...
1038 UpdateModifiersFromCompat(struct xkb_keymap *xkb)
1043 /* Find all the interprets for the key and bind them to actions,
1044 * which will also update the vmodmap. */
1045 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++)
1046 if (!ApplyInterpsToKey(xkb, key))
1049 /* Update xkb->server->vmods, the virtual -> real mod mapping. */
1050 for (i = 0; i < XkbNumVirtualMods; i++)
1051 xkb->server->vmods[i] = 0;
1052 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
1053 if (!xkb->server->vmodmap[key])
1055 for (i = 0; i < XkbNumVirtualMods; i++) {
1056 if (!(xkb->server->vmodmap[key] & (1 << i)))
1058 xkb->server->vmods[i] |= xkb->map->modmap[key];
1062 /* Now update the level masks for all the types to reflect the vmods. */
1063 for (i = 0; i < xkb->map->num_types; i++) {
1064 struct xkb_key_type *type = &xkb->map->types[i];
1067 type->mods.mask = type->mods.real_mods;
1068 type->mods.mask |= VModsToReal(xkb, type->mods.vmods);
1069 for (j = 0; j < XkbNumVirtualMods; j++) {
1070 if (!(type->mods.vmods & (1 << j)))
1072 mask |= xkb->server->vmods[j];
1074 for (j = 0; j < type->map_count; j++) {
1075 struct xkb_mods *mods = &type->map[j].mods;
1076 mods->mask = mods->real_mods | VModsToReal(xkb, mods->vmods);
1080 /* Update action modifiers. */
1081 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
1082 union xkb_action *acts = XkbKeyActionsPtr(xkb, key);
1083 for (i = 0; i < XkbKeyNumActions(xkb, key); i++) {
1084 if (acts[i].any.type == XkbSA_NoAction)
1086 UpdateActionMods(xkb, &acts[i], xkb->map->modmap[key]);
1090 /* Update group modifiers. */
1091 for (i = 0; i < XkbNumKbdGroups; i++) {
1092 struct xkb_mods *group = &xkb->compat->groups[i];
1093 group->mask = group->real_mods | VModsToReal(xkb, group->vmods);
1096 /* Update vmod -> indicator maps. */
1097 for (i = 0; i < XkbNumIndicators; i++) {
1098 struct xkb_mods *led = &xkb->indicators->maps[i].mods;
1099 led->mask = led->real_mods | VModsToReal(xkb, led->vmods);