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, info->act);
509 si->defs.defined |= _SI_Action;
511 else if ((strcasecmp(field, "virtualmodifier") == 0) ||
512 (strcasecmp(field, "virtualmod") == 0))
514 if (arrayNdx != NULL)
515 return ReportSINotArray(si, field, info);
516 ok = ResolveVirtualModifier(value, xkb, &tmp, &info->vmods);
519 si->interp.virtual_mod = tmp.uval;
520 si->defs.defined |= _SI_VirtualMod;
523 return ReportSIBadType(si, field, "virtual modifier", info);
525 else if (strcasecmp(field, "repeat") == 0)
527 if (arrayNdx != NULL)
528 return ReportSINotArray(si, field, info);
529 ok = ExprResolveBoolean(value, &tmp);
533 si->interp.flags |= XkbSI_AutoRepeat;
535 si->interp.flags &= ~XkbSI_AutoRepeat;
536 si->defs.defined |= _SI_AutoRepeat;
539 return ReportSIBadType(si, field, "boolean", info);
541 else if (strcasecmp(field, "locking") == 0)
543 if (arrayNdx != NULL)
544 return ReportSINotArray(si, field, info);
545 ok = ExprResolveBoolean(value, &tmp);
549 si->interp.flags |= XkbSI_LockingKey;
551 si->interp.flags &= ~XkbSI_LockingKey;
552 si->defs.defined |= _SI_LockingKey;
555 return ReportSIBadType(si, field, "boolean", info);
557 else if ((strcasecmp(field, "usemodmap") == 0) ||
558 (strcasecmp(field, "usemodmapmods") == 0))
560 if (arrayNdx != NULL)
561 return ReportSINotArray(si, field, info);
562 ok = ExprResolveEnum(value, &tmp, useModMapValues);
566 si->interp.match |= XkbSI_LevelOneOnly;
568 si->interp.match &= ~XkbSI_LevelOneOnly;
569 si->defs.defined |= _SI_LevelOneOnly;
572 return ReportSIBadType(si, field, "level specification", info);
576 ok = ReportBadField("symbol interpretation", field, siText(si, info));
582 HandleInterpVar(VarDef * stmt, struct xkb_keymap * xkb, CompatInfo * info)
584 ExprResult elem, field;
588 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
589 ret = 0; /* internal error, already reported */
590 else if (elem.str && (strcasecmp(elem.str, "interpret") == 0))
591 ret = SetInterpField(&info->dflt, xkb, field.str, ndx, stmt->value,
593 else if (elem.str && (strcasecmp(elem.str, "indicator") == 0))
594 ret = SetIndicatorMapField(&info->ledDflt, xkb, field.str, ndx,
597 ret = SetActionField(xkb, elem.str, field.str, ndx, stmt->value,
605 HandleInterpBody(VarDef * def, struct xkb_keymap * xkb, SymInterpInfo * si,
609 ExprResult tmp, field;
612 for (; def != NULL; def = (VarDef *) def->common.next)
614 if ((def->name) && (def->name->type == ExprFieldRef))
616 ok = HandleInterpVar(def, xkb, info);
619 ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx);
621 ok = SetInterpField(si, xkb, field.str, arrayNdx, def->value,
630 HandleInterpDef(InterpDef * def, struct xkb_keymap * xkb, unsigned merge,
636 if (!ResolveStateAndPredicate(def->match, &pred, &mods, info))
638 ERROR("Couldn't determine matching modifiers\n");
639 ACTION("Symbol interpretation ignored\n");
642 if (def->merge != MergeDefault)
646 si.defs.merge = merge;
647 if (!LookupKeysym(def->sym, &si.interp.sym))
649 ERROR("Could not resolve keysym %s\n", def->sym);
650 ACTION("Symbol interpretation ignored\n");
653 si.interp.match = pred & XkbSI_OpMask;
654 si.interp.mods = mods;
655 if (!HandleInterpBody(def->def, xkb, &si, info))
661 if (!AddInterp(info, &si))
670 HandleGroupCompatDef(GroupCompatDef * def,
671 struct xkb_keymap * xkb, unsigned merge, CompatInfo * info)
676 if (def->merge != MergeDefault)
678 if (!XkbIsLegalGroup(def->group - 1))
680 ERROR("Keyboard group must be in the range 1..%d\n",
681 XkbNumKbdGroups + 1);
682 ACTION("Compatibility map for illegal group %d ignored\n",
686 tmp.fileID = info->fileID;
688 if (!ExprResolveVModMask(def->def, &val, xkb))
690 ERROR("Expected a modifier mask in group compatibility definition\n");
691 ACTION("Ignoring illegal compatibility map for group %d\n",
695 tmp.real_mods = val.uval & 0xff;
696 tmp.vmods = (val.uval >> 8) & 0xffff;
698 return AddGroupCompat(info, def->group - 1, &tmp);
702 HandleCompatMapFile(XkbFile * file,
703 struct xkb_keymap * xkb, unsigned merge, CompatInfo * info)
707 if (merge == MergeDefault)
708 merge = MergeAugment;
710 info->name = uDupString(file->name);
714 switch (stmt->stmtType)
717 if (!HandleIncludeCompatMap((IncludeStmt *) stmt, xkb, info,
718 HandleCompatMapFile))
722 if (!HandleInterpDef((InterpDef *) stmt, xkb, merge, info))
725 case StmtGroupCompatDef:
726 if (!HandleGroupCompatDef
727 ((GroupCompatDef *) stmt, xkb, merge, info))
730 case StmtIndicatorMapDef:
733 rtrn = HandleIndicatorMapDef((IndicatorMapDef *) stmt, xkb,
734 &info->ledDflt, info->leds, merge);
742 if (!HandleInterpVar((VarDef *) stmt, xkb, info))
746 if (!HandleVModDef((VModDef *) stmt, xkb, merge, &info->vmods))
750 ERROR("Interpretation files may not include other types\n");
751 ACTION("Ignoring definition of key name\n");
755 WSGO("Unexpected statement type %d in HandleCompatMapFile\n",
760 if (info->errorCount > 10)
763 ERROR("Too many errors\n");
765 ACTION("Abandoning compatibility map \"%s\"\n", file->topName);
772 CopyInterps(CompatInfo * info,
773 struct xkb_compat_map * compat, bool needSymbol, unsigned pred)
777 for (si = info->interps; si; si = (SymInterpInfo *) si->defs.next)
779 if (((si->interp.match & XkbSI_OpMask) != pred) ||
780 (needSymbol && (si->interp.sym == XKB_KEYSYM_NO_SYMBOL)) ||
781 ((!needSymbol) && (si->interp.sym != XKB_KEYSYM_NO_SYMBOL)))
783 if (compat->num_si >= compat->size_si)
785 WSGO("No room to merge symbol interpretations\n");
786 ACTION("Symbol interpretations lost\n");
789 compat->sym_interpret[compat->num_si++] = si->interp;
794 CompileCompatMap(XkbFile *file, struct xkb_keymap * xkb, unsigned merge,
795 LEDInfoPtr *unboundLEDs)
799 GroupCompatInfo *gcm;
801 InitCompatInfo(&info, xkb);
802 info.dflt.defs.merge = merge;
803 info.ledDflt.defs.merge = merge;
804 HandleCompatMapFile(file, xkb, merge, &info);
806 if (info.errorCount == 0)
809 if (XkbcAllocCompatMap(xkb, info.nInterps) != Success)
811 WSGO("Couldn't allocate compatibility map\n");
814 size = info.nInterps * sizeof(struct xkb_sym_interpret);
817 CopyInterps(&info, xkb->compat, true, XkbSI_Exactly);
818 CopyInterps(&info, xkb->compat, true, XkbSI_AllOf | XkbSI_NoneOf);
819 CopyInterps(&info, xkb->compat, true, XkbSI_AnyOf);
820 CopyInterps(&info, xkb->compat, true, XkbSI_AnyOfOrNone);
821 CopyInterps(&info, xkb->compat, false, XkbSI_Exactly);
822 CopyInterps(&info, xkb->compat, false,
823 XkbSI_AllOf | XkbSI_NoneOf);
824 CopyInterps(&info, xkb->compat, false, XkbSI_AnyOf);
825 CopyInterps(&info, xkb->compat, false, XkbSI_AnyOfOrNone);
827 for (i = 0, gcm = &info.groupCompat[0]; i < XkbNumKbdGroups;
830 if ((gcm->fileID != 0) || (gcm->real_mods != 0)
831 || (gcm->vmods != 0))
833 xkb->compat->groups[i].mask = gcm->real_mods;
834 xkb->compat->groups[i].real_mods = gcm->real_mods;
835 xkb->compat->groups[i].vmods = gcm->vmods;
838 if (info.leds != NULL)
840 if (!CopyIndicatorMapDefs(xkb, info.leds, unboundLEDs))
844 ClearCompatInfo(&info, xkb);
852 VModsToReal(struct xkb_keymap *xkb, uint32_t vmodmask)
860 for (i = 0; i < XkbNumVirtualMods; i++) {
861 if (!(vmodmask & (1 << i)))
863 ret |= xkb->server->vmods[i];
870 UpdateActionMods(struct xkb_keymap *xkb, union xkb_action *act, uint32_t rmodmask)
874 case XkbSA_LatchMods:
876 if (act->mods.flags & XkbSA_UseModMapMods)
877 act->mods.real_mods = rmodmask;
878 act->mods.mask = act->mods.real_mods;
879 act->mods.mask |= VModsToReal(xkb, act->mods.vmods);
882 if (act->iso.flags & XkbSA_UseModMapMods)
883 act->iso.real_mods = rmodmask;
884 act->iso.mask = act->iso.real_mods;
885 act->iso.mask |= VModsToReal(xkb, act->iso.vmods);
893 * Find an interpretation which applies to this particular level, either by
894 * finding an exact match for the symbol and modifier combination, or a
895 * generic XKB_KEYSYM_NO_SYMBOL match.
897 static struct xkb_sym_interpret *
898 FindInterpForKey(struct xkb_keymap *xkb, xkb_keycode_t key, uint32_t group, uint32_t level)
900 struct xkb_sym_interpret *ret = NULL;
901 const xkb_keysym_t *syms;
905 num_syms = xkb_key_get_syms_by_level(xkb, key, group, level, &syms);
909 for (i = 0; i < xkb->compat->num_si; i++) {
910 struct xkb_sym_interpret *interp = &xkb->compat->sym_interpret[i];
914 if ((num_syms > 1 || interp->sym != syms[0]) &&
915 interp->sym != XKB_KEYSYM_NO_SYMBOL)
918 if (level == 0 || !(interp->match & XkbSI_LevelOneOnly))
919 mods = xkb->map->modmap[key];
923 switch (interp->match & XkbSI_OpMask) {
925 found = !(interp->mods & mods);
927 case XkbSI_AnyOfOrNone:
928 found = (!mods || (interp->mods & mods));
931 found = !!(interp->mods & mods);
934 found = ((interp->mods & mods) == mods);
937 found = (interp->mods == mods);
944 if (found && interp->sym != XKB_KEYSYM_NO_SYMBOL)
946 else if (found && !ret)
956 ApplyInterpsToKey(struct xkb_keymap *xkb, xkb_keycode_t key)
958 #define INTERP_SIZE (8 * 4)
959 struct xkb_sym_interpret *interps[INTERP_SIZE];
960 union xkb_action *acts;
961 uint32_t vmodmask = 0;
964 int width = XkbKeyGroupsWidth(xkb, key);
967 /* If we've been told not to bind interps to this key, then don't. */
968 if (xkb->server->explicit[key] & XkbExplicitInterpretMask)
971 for (i = 0; i < INTERP_SIZE; i++)
974 for (group = 0; group < XkbKeyNumGroups(xkb, key); group++) {
975 for (level = 0; level < XkbKeyGroupWidth(xkb, key, group); level++) {
976 i = (group * width) + level;
977 if (i >= INTERP_SIZE) /* XXX FIXME */
979 interps[i] = FindInterpForKey(xkb, key, group, level);
986 num_acts = XkbKeyNumGroups(xkb, key) * width;
987 acts = XkbcResizeKeyActions(xkb, key, num_acts);
993 for (group = 0; group < XkbKeyNumGroups(xkb, key); group++) {
994 for (level = 0; level < XkbKeyGroupWidth(xkb, key, group); level++) {
995 struct xkb_sym_interpret *interp;
997 i = (group * width) + level;
1000 /* Infer default key behaviours from the base level. */
1001 if (group == 0 && level == 0) {
1002 if (!(xkb->server->explicit[key] & XkbExplicitAutoRepeatMask) &&
1003 (!interp || interp->flags & XkbSI_AutoRepeat))
1004 xkb->ctrls->per_key_repeat[key / 8] |= (1 << (key % 8));
1005 if (!(xkb->server->explicit[key] & XkbExplicitBehaviorMask) &&
1006 interp && (interp->flags & XkbSI_LockingKey))
1007 xkb->server->behaviors[key].type = XkbKB_Lock;
1013 if ((group == 0 && level == 0) ||
1014 !(interp->match & XkbSI_LevelOneOnly)) {
1015 if (interp->virtual_mod != XkbNoModifier)
1016 vmodmask |= (1 << interp->virtual_mod);
1018 acts[i] = interp->act;
1022 if (!(xkb->server->explicit[key] & XkbExplicitVModMapMask))
1023 xkb->server->vmodmap[key] = vmodmask;
1030 * This collects a bunch of disparate functions which was done in the server
1031 * at various points that really should've been done within xkbcomp. Turns out
1032 * your actions and types are a lot more useful when any of your modifiers
1033 * other than Shift actually do something ...
1036 UpdateModifiersFromCompat(struct xkb_keymap *xkb)
1041 /* Find all the interprets for the key and bind them to actions,
1042 * which will also update the vmodmap. */
1043 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++)
1044 if (!ApplyInterpsToKey(xkb, key))
1047 /* Update xkb->server->vmods, the virtual -> real mod mapping. */
1048 for (i = 0; i < XkbNumVirtualMods; i++)
1049 xkb->server->vmods[i] = 0;
1050 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
1051 if (!xkb->server->vmodmap[key])
1053 for (i = 0; i < XkbNumVirtualMods; i++) {
1054 if (!(xkb->server->vmodmap[key] & (1 << i)))
1056 xkb->server->vmods[i] |= xkb->map->modmap[key];
1060 /* Now update the level masks for all the types to reflect the vmods. */
1061 for (i = 0; i < xkb->map->num_types; i++) {
1062 struct xkb_key_type *type = &xkb->map->types[i];
1065 type->mods.mask = type->mods.real_mods;
1066 type->mods.mask |= VModsToReal(xkb, type->mods.vmods);
1067 for (j = 0; j < XkbNumVirtualMods; j++) {
1068 if (!(type->mods.vmods & (1 << j)))
1070 mask |= xkb->server->vmods[j];
1072 for (j = 0; j < type->map_count; j++) {
1073 struct xkb_mods *mods = &type->map[j].mods;
1074 mods->mask = mods->real_mods | VModsToReal(xkb, mods->vmods);
1078 /* Update action modifiers. */
1079 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
1080 union xkb_action *acts = XkbKeyActionsPtr(xkb, key);
1081 for (i = 0; i < XkbKeyNumActions(xkb, key); i++) {
1082 if (acts[i].any.type == XkbSA_NoAction)
1084 UpdateActionMods(xkb, &acts[i], xkb->map->modmap[key]);
1088 /* Update group modifiers. */
1089 for (i = 0; i < XkbNumKbdGroups; i++) {
1090 struct xkb_mods *group = &xkb->compat->groups[i];
1091 group->mask = group->real_mods | VModsToReal(xkb, group->vmods);
1094 /* Update vmod -> indicator maps. */
1095 for (i = 0; i < XkbNumIndicators; i++) {
1096 struct xkb_mods *led = &xkb->indicators->maps[i].mods;
1097 led->mask = led->real_mods | VModsToReal(xkb, led->vmods);