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 ********************************************************/
27 #include "xkbcomp-priv.h"
28 #include "parseutils.h"
30 #include "indicators.h"
33 typedef struct _SymInterpInfo
36 struct xkb_sym_interpret interp;
39 #define _SI_VirtualMod (1<<0)
40 #define _SI_Action (1<<1)
41 #define _SI_AutoRepeat (1<<2)
42 #define _SI_LockingKey (1<<3)
43 #define _SI_LevelOneOnly (1<<4)
45 typedef struct _GroupCompatInfo
50 unsigned char real_mods;
54 typedef struct _CompatInfo
60 SymInterpInfo *interps;
63 GroupCompatInfo groupCompat[XkbNumKbdGroups];
67 struct xkb_keymap *keymap;
70 /***====================================================================***/
72 #define ReportSINotArray(si,f,i) \
73 ReportNotArray("symbol interpretation",(f),siText((si),(i)))
74 #define ReportSIBadType(si,f,w,i) \
75 ReportBadType("symbol interpretation",(f),siText((si),(i)),(w))
77 /***====================================================================***/
80 siText(SymInterpInfo * si, CompatInfo * info)
84 if (si == &info->dflt)
86 snprintf(buf, sizeof(buf), "default");
90 snprintf(buf, sizeof(buf), "%s+%s(%s)",
91 XkbcKeysymText(si->interp.sym),
92 XkbcSIMatchText(si->interp.match),
93 XkbcModMaskText(si->interp.mods, false));
99 InitCompatInfo(CompatInfo *info, struct xkb_keymap *keymap)
103 info->keymap = keymap;
106 info->errorCount = 0;
108 info->interps = NULL;
110 info->dflt.defs.fileID = info->fileID;
111 info->dflt.defs.defined = 0;
112 info->dflt.defs.merge = MergeOverride;
113 info->dflt.interp.flags = 0;
114 info->dflt.interp.virtual_mod = XkbNoModifier;
115 info->dflt.interp.act.type = XkbSA_NoAction;
116 for (i = 0; i < sizeof(info->dflt.interp.act.any.data); i++)
117 info->dflt.interp.act.any.data[i] = 0;
118 ClearIndicatorMapInfo(keymap->ctx, &info->ledDflt);
119 info->ledDflt.defs.fileID = info->fileID;
120 info->ledDflt.defs.defined = 0;
121 info->ledDflt.defs.merge = MergeOverride;
122 memset(&info->groupCompat[0], 0,
123 XkbNumKbdGroups * sizeof(GroupCompatInfo));
125 InitVModInfo(&info->vmods, keymap);
129 ClearCompatInfo(CompatInfo *info, struct xkb_keymap *keymap)
136 info->dflt.defs.defined = 0;
137 info->dflt.defs.merge = MergeAugment;
138 info->dflt.interp.flags = 0;
139 info->dflt.interp.virtual_mod = XkbNoModifier;
140 info->dflt.interp.act.type = XkbSA_NoAction;
141 for (i = 0; i < sizeof(info->dflt.interp.act.any.data); i++)
142 info->dflt.interp.act.any.data[i] = 0;
143 ClearIndicatorMapInfo(keymap->ctx, &info->ledDflt);
145 info->interps = (SymInterpInfo *) ClearCommonInfo(&info->interps->defs);
146 memset(&info->groupCompat[0], 0,
147 XkbNumKbdGroups * sizeof(GroupCompatInfo));
148 info->leds = (LEDInfo *) ClearCommonInfo(&info->leds->defs);
150 next = info->act->next;
154 ClearVModInfo(&info->vmods, keymap);
157 static SymInterpInfo *
158 NextInterp(CompatInfo * info)
162 si = uTypedAlloc(SymInterpInfo);
165 memset(si, 0, sizeof(SymInterpInfo));
167 (SymInterpInfo *) AddCommonInfo(&info->interps->defs,
174 static SymInterpInfo *
175 FindMatchingInterp(CompatInfo * info, SymInterpInfo * new)
179 for (old = info->interps; old != NULL;
180 old = (SymInterpInfo *) old->defs.next)
182 if ((old->interp.sym == new->interp.sym) &&
183 (old->interp.mods == new->interp.mods) &&
184 (old->interp.match == new->interp.match))
193 AddInterp(CompatInfo * info, SymInterpInfo * new)
199 old = FindMatchingInterp(info, new);
202 if (new->defs.merge == MergeReplace)
204 SymInterpInfo *next = (SymInterpInfo *) old->defs.next;
205 if (((old->defs.fileID == new->defs.fileID)
206 && (warningLevel > 0)) || (warningLevel > 9))
208 WARN("Multiple definitions for \"%s\"\n", siText(new, info));
209 ACTION("Earlier interpretation ignored\n");
212 old->defs.next = &next->defs;
215 if (UseNewField(_SI_VirtualMod, &old->defs, &new->defs, &collide))
217 old->interp.virtual_mod = new->interp.virtual_mod;
218 old->defs.defined |= _SI_VirtualMod;
220 if (UseNewField(_SI_Action, &old->defs, &new->defs, &collide))
222 old->interp.act = new->interp.act;
223 old->defs.defined |= _SI_Action;
225 if (UseNewField(_SI_AutoRepeat, &old->defs, &new->defs, &collide))
227 old->interp.flags &= ~XkbSI_AutoRepeat;
228 old->interp.flags |= (new->interp.flags & XkbSI_AutoRepeat);
229 old->defs.defined |= _SI_AutoRepeat;
231 if (UseNewField(_SI_LockingKey, &old->defs, &new->defs, &collide))
233 old->interp.flags &= ~XkbSI_LockingKey;
234 old->interp.flags |= (new->interp.flags & XkbSI_LockingKey);
235 old->defs.defined |= _SI_LockingKey;
237 if (UseNewField(_SI_LevelOneOnly, &old->defs, &new->defs, &collide))
239 old->interp.match &= ~XkbSI_LevelOneOnly;
240 old->interp.match |= (new->interp.match & XkbSI_LevelOneOnly);
241 old->defs.defined |= _SI_LevelOneOnly;
245 WARN("Multiple interpretations of \"%s\"\n", siText(new, info));
246 ACTION("Using %s definition for duplicate fields\n",
247 (new->defs.merge != MergeAugment ? "last" : "first"));
252 if ((new = NextInterp(info)) == NULL)
255 new->defs.next = NULL;
260 AddGroupCompat(CompatInfo * info, unsigned group, GroupCompatInfo * newGC)
265 merge = newGC->merge;
266 gc = &info->groupCompat[group];
267 if (((gc->real_mods == newGC->real_mods) && (gc->vmods == newGC->vmods)))
271 if (((gc->fileID == newGC->fileID) && (warningLevel > 0))
272 || (warningLevel > 9))
274 WARN("Compat map for group %d redefined\n", group + 1);
275 ACTION("Using %s definition\n",
276 (merge == MergeAugment ? "old" : "new"));
278 if (newGC->defined && (merge != MergeAugment || !gc->defined))
283 /***====================================================================***/
286 ResolveStateAndPredicate(ExprDef * expr,
288 unsigned *mods_rtrn, CompatInfo * info)
294 *pred_rtrn = XkbSI_AnyOfOrNone;
299 *pred_rtrn = XkbSI_Exactly;
300 if (expr->op == ExprActionDecl)
302 const char *pred_txt = xkb_atom_text(info->keymap->ctx,
303 expr->value.action.name);
304 if (strcasecmp(pred_txt, "noneof") == 0)
305 *pred_rtrn = XkbSI_NoneOf;
306 else if (strcasecmp(pred_txt, "anyofornone") == 0)
307 *pred_rtrn = XkbSI_AnyOfOrNone;
308 else if (strcasecmp(pred_txt, "anyof") == 0)
309 *pred_rtrn = XkbSI_AnyOf;
310 else if (strcasecmp(pred_txt, "allof") == 0)
311 *pred_rtrn = XkbSI_AllOf;
312 else if (strcasecmp(pred_txt, "exactly") == 0)
313 *pred_rtrn = XkbSI_Exactly;
316 ERROR("Illegal modifier predicate \"%s\"\n", pred_txt);
320 expr = expr->value.action.args;
322 else if (expr->op == ExprIdent)
324 const char *pred_txt = xkb_atom_text(info->keymap->ctx,
326 if ((pred_txt) && (strcasecmp(pred_txt, "any") == 0))
328 *pred_rtrn = XkbSI_AnyOf;
334 if (ExprResolveModMask(info->keymap->ctx, expr, &result))
336 *mods_rtrn = result.uval;
342 /***====================================================================***/
345 MergeIncludedCompatMaps(CompatInfo * into, CompatInfo * from, unsigned merge)
348 LEDInfo *led, *rtrn, *next;
349 GroupCompatInfo *gcm;
352 if (from->errorCount > 0)
354 into->errorCount += from->errorCount;
357 if (into->name == NULL)
359 into->name = from->name;
362 for (si = from->interps; si; si = (SymInterpInfo *) si->defs.next)
364 if (merge != MergeDefault)
365 si->defs.merge = merge;
366 if (!AddInterp(into, si))
369 for (i = 0, gcm = &from->groupCompat[0]; i < XkbNumKbdGroups; i++, gcm++)
371 if (merge != MergeDefault)
373 if (!AddGroupCompat(into, i, gcm))
376 for (led = from->leds; led != NULL; led = next)
378 next = (LEDInfo *) led->defs.next;
379 if (merge != MergeDefault)
380 led->defs.merge = merge;
381 rtrn = AddIndicatorMap(from->keymap, into->leds, led);
390 HandleCompatMapFile(XkbFile *file, struct xkb_keymap *keymap, unsigned merge,
394 HandleIncludeCompatMap(IncludeStmt *stmt, struct xkb_keymap *keymap,
403 if ((stmt->file == NULL) && (stmt->map == NULL))
407 memset(info, 0, sizeof(CompatInfo));
409 else if (ProcessIncludeFile(keymap->ctx, stmt, XkmCompatMapIndex, &rtrn,
412 InitCompatInfo(&included, keymap);
413 included.fileID = rtrn->id;
414 included.dflt = info->dflt;
415 included.dflt.defs.fileID = rtrn->id;
416 included.dflt.defs.merge = newMerge;
417 included.ledDflt.defs.fileID = rtrn->id;
418 included.ledDflt.defs.merge = newMerge;
419 included.act = info->act;
420 HandleCompatMapFile(rtrn, keymap, MergeOverride, &included);
421 if (stmt->stmt != NULL)
424 included.name = stmt->stmt;
427 if (info->act != NULL)
433 info->errorCount += 10;
436 if ((stmt->next != NULL) && (included.errorCount < 1))
440 CompatInfo next_incl;
442 for (next = stmt->next; next != NULL; next = next->next)
444 if ((next->file == NULL) && (next->map == NULL))
447 MergeIncludedCompatMaps(&included, info, next->merge);
448 ClearCompatInfo(info, keymap);
450 else if (ProcessIncludeFile(keymap->ctx, next, XkmCompatMapIndex,
453 InitCompatInfo(&next_incl, keymap);
454 next_incl.fileID = rtrn->id;
455 next_incl.dflt = info->dflt;
456 next_incl.dflt.defs.fileID = rtrn->id;
457 next_incl.dflt.defs.merge = op;
458 next_incl.ledDflt.defs.fileID = rtrn->id;
459 next_incl.ledDflt.defs.merge = op;
460 next_incl.act = info->act;
461 HandleCompatMapFile(rtrn, keymap, MergeOverride, &next_incl);
462 MergeIncludedCompatMaps(&included, &next_incl, op);
463 if (info->act != NULL)
464 next_incl.act = NULL;
465 ClearCompatInfo(&next_incl, keymap);
470 info->errorCount += 10;
479 MergeIncludedCompatMaps(info, &included, newMerge);
480 ClearCompatInfo(&included, keymap);
482 return (info->errorCount == 0);
485 static const LookupEntry useModMapValues[] = {
494 SetInterpField(SymInterpInfo *si, struct xkb_keymap *keymap, char *field,
495 ExprDef *arrayNdx, ExprDef *value, CompatInfo *info)
500 if (strcasecmp(field, "action") == 0)
502 if (arrayNdx != NULL)
503 return ReportSINotArray(si, field, info);
504 ok = HandleActionDef(value, keymap, &si->interp.act.any, info->act);
506 si->defs.defined |= _SI_Action;
508 else if ((strcasecmp(field, "virtualmodifier") == 0) ||
509 (strcasecmp(field, "virtualmod") == 0))
511 if (arrayNdx != NULL)
512 return ReportSINotArray(si, field, info);
513 ok = ResolveVirtualModifier(value, keymap, &tmp, &info->vmods);
516 si->interp.virtual_mod = tmp.uval;
517 si->defs.defined |= _SI_VirtualMod;
520 return ReportSIBadType(si, field, "virtual modifier", info);
522 else if (strcasecmp(field, "repeat") == 0)
524 if (arrayNdx != NULL)
525 return ReportSINotArray(si, field, info);
526 ok = ExprResolveBoolean(keymap->ctx, value, &tmp);
530 si->interp.flags |= XkbSI_AutoRepeat;
532 si->interp.flags &= ~XkbSI_AutoRepeat;
533 si->defs.defined |= _SI_AutoRepeat;
536 return ReportSIBadType(si, field, "boolean", info);
538 else if (strcasecmp(field, "locking") == 0)
540 if (arrayNdx != NULL)
541 return ReportSINotArray(si, field, info);
542 ok = ExprResolveBoolean(keymap->ctx, value, &tmp);
546 si->interp.flags |= XkbSI_LockingKey;
548 si->interp.flags &= ~XkbSI_LockingKey;
549 si->defs.defined |= _SI_LockingKey;
552 return ReportSIBadType(si, field, "boolean", info);
554 else if ((strcasecmp(field, "usemodmap") == 0) ||
555 (strcasecmp(field, "usemodmapmods") == 0))
557 if (arrayNdx != NULL)
558 return ReportSINotArray(si, field, info);
559 ok = ExprResolveEnum(keymap->ctx, value, &tmp, useModMapValues);
563 si->interp.match |= XkbSI_LevelOneOnly;
565 si->interp.match &= ~XkbSI_LevelOneOnly;
566 si->defs.defined |= _SI_LevelOneOnly;
569 return ReportSIBadType(si, field, "level specification", info);
573 ok = ReportBadField("symbol interpretation", field, siText(si, info));
579 HandleInterpVar(VarDef * stmt, struct xkb_keymap *keymap, CompatInfo * info)
581 ExprResult elem, field;
585 if (ExprResolveLhs(keymap, stmt->name, &elem, &field, &ndx) == 0)
586 ret = 0; /* internal error, already reported */
587 else if (elem.str && (strcasecmp(elem.str, "interpret") == 0))
588 ret = SetInterpField(&info->dflt, keymap, field.str, ndx, stmt->value,
590 else if (elem.str && (strcasecmp(elem.str, "indicator") == 0))
591 ret = SetIndicatorMapField(&info->ledDflt, keymap, field.str, ndx,
594 ret = SetActionField(keymap, elem.str, field.str, ndx, stmt->value,
602 HandleInterpBody(VarDef *def, struct xkb_keymap *keymap, SymInterpInfo *si,
606 ExprResult tmp, field;
609 for (; def != NULL; def = (VarDef *) def->common.next)
611 if ((def->name) && (def->name->type == ExprFieldRef))
613 ok = HandleInterpVar(def, keymap, info);
616 ok = ExprResolveLhs(keymap, def->name, &tmp, &field, &arrayNdx);
618 ok = SetInterpField(si, keymap, field.str, arrayNdx, def->value,
627 HandleInterpDef(InterpDef *def, struct xkb_keymap *keymap, unsigned merge,
633 if (!ResolveStateAndPredicate(def->match, &pred, &mods, info))
635 ERROR("Couldn't determine matching modifiers\n");
636 ACTION("Symbol interpretation ignored\n");
639 if (def->merge != MergeDefault)
643 si.defs.merge = merge;
644 if (!LookupKeysym(def->sym, &si.interp.sym))
646 ERROR("Could not resolve keysym %s\n", def->sym);
647 ACTION("Symbol interpretation ignored\n");
650 si.interp.match = pred & XkbSI_OpMask;
651 si.interp.mods = mods;
652 if (!HandleInterpBody(def->def, keymap, &si, info))
658 if (!AddInterp(info, &si))
667 HandleGroupCompatDef(GroupCompatDef *def, struct xkb_keymap *keymap,
668 unsigned merge, CompatInfo *info)
673 if (def->merge != MergeDefault)
675 if (!XkbIsLegalGroup(def->group - 1))
677 ERROR("Keyboard group must be in the range 1..%d\n",
678 XkbNumKbdGroups + 1);
679 ACTION("Compatibility map for illegal group %d ignored\n",
683 tmp.fileID = info->fileID;
685 if (!ExprResolveVModMask(def->def, &val, keymap))
687 ERROR("Expected a modifier mask in group compatibility definition\n");
688 ACTION("Ignoring illegal compatibility map for group %d\n",
692 tmp.real_mods = val.uval & 0xff;
693 tmp.vmods = (val.uval >> 8) & 0xffff;
695 return AddGroupCompat(info, def->group - 1, &tmp);
699 HandleCompatMapFile(XkbFile *file, struct xkb_keymap *keymap, unsigned merge,
704 if (merge == MergeDefault)
705 merge = MergeAugment;
707 info->name = uDupString(file->name);
711 switch (stmt->stmtType)
714 if (!HandleIncludeCompatMap((IncludeStmt *) stmt, keymap, info))
718 if (!HandleInterpDef((InterpDef *) stmt, keymap, merge, info))
721 case StmtGroupCompatDef:
722 if (!HandleGroupCompatDef
723 ((GroupCompatDef *) stmt, keymap, merge, info))
726 case StmtIndicatorMapDef:
729 rtrn = HandleIndicatorMapDef((IndicatorMapDef *) stmt, keymap,
730 &info->ledDflt, info->leds, merge);
738 if (!HandleInterpVar((VarDef *) stmt, keymap, info))
742 if (!HandleVModDef((VModDef *) stmt, keymap, merge, &info->vmods))
746 ERROR("Interpretation files may not include other types\n");
747 ACTION("Ignoring definition of key name\n");
751 WSGO("Unexpected statement type %d in HandleCompatMapFile\n",
756 if (info->errorCount > 10)
759 ERROR("Too many errors\n");
761 ACTION("Abandoning compatibility map \"%s\"\n", file->topName);
768 CopyInterps(CompatInfo * info,
769 struct xkb_compat_map * compat, bool needSymbol, unsigned pred)
773 for (si = info->interps; si; si = (SymInterpInfo *) si->defs.next)
775 if (((si->interp.match & XkbSI_OpMask) != pred) ||
776 (needSymbol && (si->interp.sym == XKB_KEY_NoSymbol)) ||
777 ((!needSymbol) && (si->interp.sym != XKB_KEY_NoSymbol)))
779 darray_append(compat->sym_interpret, si->interp);
784 CompileCompatMap(XkbFile *file, struct xkb_keymap *keymap, unsigned merge,
785 LEDInfoPtr *unboundLEDs)
789 GroupCompatInfo *gcm;
791 InitCompatInfo(&info, keymap);
792 info.dflt.defs.merge = merge;
793 info.ledDflt.defs.merge = merge;
795 HandleCompatMapFile(file, keymap, merge, &info);
797 if (info.errorCount != 0)
800 if (XkbcAllocCompatMap(keymap, info.nInterps) != Success) {
801 WSGO("Couldn't allocate compatibility map\n");
805 if (info.nInterps > 0) {
806 CopyInterps(&info, keymap->compat, true, XkbSI_Exactly);
807 CopyInterps(&info, keymap->compat, true, XkbSI_AllOf | XkbSI_NoneOf);
808 CopyInterps(&info, keymap->compat, true, XkbSI_AnyOf);
809 CopyInterps(&info, keymap->compat, true, XkbSI_AnyOfOrNone);
810 CopyInterps(&info, keymap->compat, false, XkbSI_Exactly);
811 CopyInterps(&info, keymap->compat, false, XkbSI_AllOf | XkbSI_NoneOf);
812 CopyInterps(&info, keymap->compat, false, XkbSI_AnyOf);
813 CopyInterps(&info, keymap->compat, false, XkbSI_AnyOfOrNone);
816 for (i = 0, gcm = &info.groupCompat[0]; i < XkbNumKbdGroups; i++, gcm++) {
817 if ((gcm->fileID != 0) || (gcm->real_mods != 0) || (gcm->vmods != 0)) {
818 keymap->compat->groups[i].mask = gcm->real_mods;
819 keymap->compat->groups[i].real_mods = gcm->real_mods;
820 keymap->compat->groups[i].vmods = gcm->vmods;
824 if (info.leds != NULL) {
825 if (!CopyIndicatorMapDefs(keymap, info.leds, unboundLEDs))
830 ClearCompatInfo(&info, keymap);
834 ClearCompatInfo(&info, keymap);
839 VModsToReal(struct xkb_keymap *keymap, uint32_t vmodmask)
847 for (i = 0; i < XkbNumVirtualMods; i++) {
848 if (!(vmodmask & (1 << i)))
850 ret |= keymap->server->vmods[i];
857 UpdateActionMods(struct xkb_keymap *keymap, union xkb_action *act,
862 case XkbSA_LatchMods:
864 if (act->mods.flags & XkbSA_UseModMapMods)
865 act->mods.real_mods = rmodmask;
866 act->mods.mask = act->mods.real_mods;
867 act->mods.mask |= VModsToReal(keymap, act->mods.vmods);
870 if (act->iso.flags & XkbSA_UseModMapMods)
871 act->iso.real_mods = rmodmask;
872 act->iso.mask = act->iso.real_mods;
873 act->iso.mask |= VModsToReal(keymap, act->iso.vmods);
881 * Find an interpretation which applies to this particular level, either by
882 * finding an exact match for the symbol and modifier combination, or a
883 * generic XKB_KEY_NoSymbol match.
885 static struct xkb_sym_interpret *
886 FindInterpForKey(struct xkb_keymap *keymap, xkb_keycode_t key,
887 uint32_t group, uint32_t level)
889 struct xkb_sym_interpret *ret = NULL;
890 struct xkb_sym_interpret *interp;
891 const xkb_keysym_t *syms;
894 num_syms = xkb_key_get_syms_by_level(keymap, key, group, level, &syms);
898 darray_foreach(interp, keymap->compat->sym_interpret) {
902 if ((num_syms > 1 || interp->sym != syms[0]) &&
903 interp->sym != XKB_KEY_NoSymbol)
906 if (level == 0 || !(interp->match & XkbSI_LevelOneOnly))
907 mods = keymap->map->modmap[key];
911 switch (interp->match & XkbSI_OpMask) {
913 found = !(interp->mods & mods);
915 case XkbSI_AnyOfOrNone:
916 found = (!mods || (interp->mods & mods));
919 found = !!(interp->mods & mods);
922 found = ((interp->mods & mods) == mods);
925 found = (interp->mods == mods);
932 if (found && interp->sym != XKB_KEY_NoSymbol)
934 else if (found && !ret)
944 ApplyInterpsToKey(struct xkb_keymap *keymap, xkb_keycode_t key)
946 #define INTERP_SIZE (8 * 4)
947 struct xkb_sym_interpret *interps[INTERP_SIZE];
948 union xkb_action *acts;
949 uint32_t vmodmask = 0;
952 int width = XkbKeyGroupsWidth(keymap, key);
955 /* If we've been told not to bind interps to this key, then don't. */
956 if (keymap->server->explicit[key] & XkbExplicitInterpretMask)
959 for (i = 0; i < INTERP_SIZE; i++)
962 for (group = 0; group < XkbKeyNumGroups(keymap, key); group++) {
963 for (level = 0; level < XkbKeyGroupWidth(keymap, key, group); level++) {
964 i = (group * width) + level;
965 if (i >= INTERP_SIZE) /* XXX FIXME */
967 interps[i] = FindInterpForKey(keymap, key, group, level);
974 num_acts = XkbKeyNumGroups(keymap, key) * width;
975 acts = XkbcResizeKeyActions(keymap, key, num_acts);
981 for (group = 0; group < XkbKeyNumGroups(keymap, key); group++) {
982 for (level = 0; level < XkbKeyGroupWidth(keymap, key, group); level++) {
983 struct xkb_sym_interpret *interp;
985 i = (group * width) + level;
988 /* Infer default key behaviours from the base level. */
989 if (group == 0 && level == 0) {
990 if (!(keymap->server->explicit[key] & XkbExplicitAutoRepeatMask) &&
991 (!interp || interp->flags & XkbSI_AutoRepeat))
992 keymap->ctrls->per_key_repeat[key / 8] |= (1 << (key % 8));
993 if (!(keymap->server->explicit[key] & XkbExplicitBehaviorMask) &&
994 interp && (interp->flags & XkbSI_LockingKey))
995 keymap->server->behaviors[key].type = XkbKB_Lock;
1001 if ((group == 0 && level == 0) ||
1002 !(interp->match & XkbSI_LevelOneOnly)) {
1003 if (interp->virtual_mod != XkbNoModifier)
1004 vmodmask |= (1 << interp->virtual_mod);
1006 acts[i] = interp->act;
1010 if (!(keymap->server->explicit[key] & XkbExplicitVModMapMask))
1011 keymap->server->vmodmap[key] = vmodmask;
1018 * This collects a bunch of disparate functions which was done in the server
1019 * at various points that really should've been done within xkbcomp. Turns out
1020 * your actions and types are a lot more useful when any of your modifiers
1021 * other than Shift actually do something ...
1024 UpdateModifiersFromCompat(struct xkb_keymap *keymap)
1029 /* Find all the interprets for the key and bind them to actions,
1030 * which will also update the vmodmap. */
1031 for (key = keymap->min_key_code; key <= keymap->max_key_code; key++)
1032 if (!ApplyInterpsToKey(keymap, key))
1035 /* Update keymap->server->vmods, the virtual -> real mod mapping. */
1036 for (i = 0; i < XkbNumVirtualMods; i++)
1037 keymap->server->vmods[i] = 0;
1038 for (key = keymap->min_key_code; key <= keymap->max_key_code; key++) {
1039 if (!keymap->server->vmodmap[key])
1041 for (i = 0; i < XkbNumVirtualMods; i++) {
1042 if (!(keymap->server->vmodmap[key] & (1 << i)))
1044 keymap->server->vmods[i] |= keymap->map->modmap[key];
1048 /* Now update the level masks for all the types to reflect the vmods. */
1049 for (i = 0; i < keymap->map->num_types; i++) {
1050 struct xkb_key_type *type = &keymap->map->types[i];
1053 type->mods.mask = type->mods.real_mods;
1054 type->mods.mask |= VModsToReal(keymap, type->mods.vmods);
1055 for (j = 0; j < XkbNumVirtualMods; j++) {
1056 if (!(type->mods.vmods & (1 << j)))
1058 mask |= keymap->server->vmods[j];
1060 for (j = 0; j < type->map_count; j++) {
1061 struct xkb_mods *mods = &type->map[j].mods;
1062 mods->mask = mods->real_mods | VModsToReal(keymap, mods->vmods);
1066 /* Update action modifiers. */
1067 for (key = keymap->min_key_code; key <= keymap->max_key_code; key++) {
1068 union xkb_action *acts = XkbKeyActionsPtr(keymap, key);
1069 for (i = 0; i < XkbKeyNumActions(keymap, key); i++) {
1070 if (acts[i].any.type == XkbSA_NoAction)
1072 UpdateActionMods(keymap, &acts[i], keymap->map->modmap[key]);
1076 /* Update group modifiers. */
1077 for (i = 0; i < XkbNumKbdGroups; i++) {
1078 struct xkb_mods *group = &keymap->compat->groups[i];
1079 group->mask = group->real_mods | VModsToReal(keymap, group->vmods);
1082 /* Update vmod -> indicator maps. */
1083 for (i = 0; i < XkbNumIndicators; i++) {
1084 struct xkb_mods *led = &keymap->indicators->maps[i].mods;
1085 led->mask = led->real_mods | VModsToReal(keymap, led->vmods);