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;
805 HandleCompatMapFile(file, xkb, merge, &info);
807 if (info.errorCount != 0)
810 if (XkbcAllocCompatMap(xkb, info.nInterps) != Success) {
811 WSGO("Couldn't allocate compatibility map\n");
815 if (info.nInterps > 0) {
816 CopyInterps(&info, xkb->compat, true, XkbSI_Exactly);
817 CopyInterps(&info, xkb->compat, true, XkbSI_AllOf | XkbSI_NoneOf);
818 CopyInterps(&info, xkb->compat, true, XkbSI_AnyOf);
819 CopyInterps(&info, xkb->compat, true, XkbSI_AnyOfOrNone);
820 CopyInterps(&info, xkb->compat, false, XkbSI_Exactly);
821 CopyInterps(&info, xkb->compat, false, XkbSI_AllOf | XkbSI_NoneOf);
822 CopyInterps(&info, xkb->compat, false, XkbSI_AnyOf);
823 CopyInterps(&info, xkb->compat, false, XkbSI_AnyOfOrNone);
826 for (i = 0, gcm = &info.groupCompat[0]; i < XkbNumKbdGroups; i++, gcm++) {
827 if ((gcm->fileID != 0) || (gcm->real_mods != 0) || (gcm->vmods != 0)) {
828 xkb->compat->groups[i].mask = gcm->real_mods;
829 xkb->compat->groups[i].real_mods = gcm->real_mods;
830 xkb->compat->groups[i].vmods = gcm->vmods;
834 if (info.leds != NULL) {
835 if (!CopyIndicatorMapDefs(xkb, info.leds, unboundLEDs))
840 ClearCompatInfo(&info, xkb);
844 ClearCompatInfo(&info, xkb);
849 VModsToReal(struct xkb_keymap *xkb, uint32_t vmodmask)
857 for (i = 0; i < XkbNumVirtualMods; i++) {
858 if (!(vmodmask & (1 << i)))
860 ret |= xkb->server->vmods[i];
867 UpdateActionMods(struct xkb_keymap *xkb, union xkb_action *act, uint32_t rmodmask)
871 case XkbSA_LatchMods:
873 if (act->mods.flags & XkbSA_UseModMapMods)
874 act->mods.real_mods = rmodmask;
875 act->mods.mask = act->mods.real_mods;
876 act->mods.mask |= VModsToReal(xkb, act->mods.vmods);
879 if (act->iso.flags & XkbSA_UseModMapMods)
880 act->iso.real_mods = rmodmask;
881 act->iso.mask = act->iso.real_mods;
882 act->iso.mask |= VModsToReal(xkb, act->iso.vmods);
890 * Find an interpretation which applies to this particular level, either by
891 * finding an exact match for the symbol and modifier combination, or a
892 * generic XKB_KEYSYM_NO_SYMBOL match.
894 static struct xkb_sym_interpret *
895 FindInterpForKey(struct xkb_keymap *xkb, xkb_keycode_t key, uint32_t group, uint32_t level)
897 struct xkb_sym_interpret *ret = NULL;
898 const xkb_keysym_t *syms;
902 num_syms = xkb_key_get_syms_by_level(xkb, key, group, level, &syms);
906 for (i = 0; i < xkb->compat->num_si; i++) {
907 struct xkb_sym_interpret *interp = &xkb->compat->sym_interpret[i];
911 if ((num_syms > 1 || interp->sym != syms[0]) &&
912 interp->sym != XKB_KEYSYM_NO_SYMBOL)
915 if (level == 0 || !(interp->match & XkbSI_LevelOneOnly))
916 mods = xkb->map->modmap[key];
920 switch (interp->match & XkbSI_OpMask) {
922 found = !(interp->mods & mods);
924 case XkbSI_AnyOfOrNone:
925 found = (!mods || (interp->mods & mods));
928 found = !!(interp->mods & mods);
931 found = ((interp->mods & mods) == mods);
934 found = (interp->mods == mods);
941 if (found && interp->sym != XKB_KEYSYM_NO_SYMBOL)
943 else if (found && !ret)
953 ApplyInterpsToKey(struct xkb_keymap *xkb, xkb_keycode_t key)
955 #define INTERP_SIZE (8 * 4)
956 struct xkb_sym_interpret *interps[INTERP_SIZE];
957 union xkb_action *acts;
958 uint32_t vmodmask = 0;
961 int width = XkbKeyGroupsWidth(xkb, key);
964 /* If we've been told not to bind interps to this key, then don't. */
965 if (xkb->server->explicit[key] & XkbExplicitInterpretMask)
968 for (i = 0; i < INTERP_SIZE; i++)
971 for (group = 0; group < XkbKeyNumGroups(xkb, key); group++) {
972 for (level = 0; level < XkbKeyGroupWidth(xkb, key, group); level++) {
973 i = (group * width) + level;
974 if (i >= INTERP_SIZE) /* XXX FIXME */
976 interps[i] = FindInterpForKey(xkb, key, group, level);
983 num_acts = XkbKeyNumGroups(xkb, key) * width;
984 acts = XkbcResizeKeyActions(xkb, key, num_acts);
990 for (group = 0; group < XkbKeyNumGroups(xkb, key); group++) {
991 for (level = 0; level < XkbKeyGroupWidth(xkb, key, group); level++) {
992 struct xkb_sym_interpret *interp;
994 i = (group * width) + level;
997 /* Infer default key behaviours from the base level. */
998 if (group == 0 && level == 0) {
999 if (!(xkb->server->explicit[key] & XkbExplicitAutoRepeatMask) &&
1000 (!interp || interp->flags & XkbSI_AutoRepeat))
1001 xkb->ctrls->per_key_repeat[key / 8] |= (1 << (key % 8));
1002 if (!(xkb->server->explicit[key] & XkbExplicitBehaviorMask) &&
1003 interp && (interp->flags & XkbSI_LockingKey))
1004 xkb->server->behaviors[key].type = XkbKB_Lock;
1010 if ((group == 0 && level == 0) ||
1011 !(interp->match & XkbSI_LevelOneOnly)) {
1012 if (interp->virtual_mod != XkbNoModifier)
1013 vmodmask |= (1 << interp->virtual_mod);
1015 acts[i] = interp->act;
1019 if (!(xkb->server->explicit[key] & XkbExplicitVModMapMask))
1020 xkb->server->vmodmap[key] = vmodmask;
1027 * This collects a bunch of disparate functions which was done in the server
1028 * at various points that really should've been done within xkbcomp. Turns out
1029 * your actions and types are a lot more useful when any of your modifiers
1030 * other than Shift actually do something ...
1033 UpdateModifiersFromCompat(struct xkb_keymap *xkb)
1038 /* Find all the interprets for the key and bind them to actions,
1039 * which will also update the vmodmap. */
1040 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++)
1041 if (!ApplyInterpsToKey(xkb, key))
1044 /* Update xkb->server->vmods, the virtual -> real mod mapping. */
1045 for (i = 0; i < XkbNumVirtualMods; i++)
1046 xkb->server->vmods[i] = 0;
1047 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
1048 if (!xkb->server->vmodmap[key])
1050 for (i = 0; i < XkbNumVirtualMods; i++) {
1051 if (!(xkb->server->vmodmap[key] & (1 << i)))
1053 xkb->server->vmods[i] |= xkb->map->modmap[key];
1057 /* Now update the level masks for all the types to reflect the vmods. */
1058 for (i = 0; i < xkb->map->num_types; i++) {
1059 struct xkb_key_type *type = &xkb->map->types[i];
1062 type->mods.mask = type->mods.real_mods;
1063 type->mods.mask |= VModsToReal(xkb, type->mods.vmods);
1064 for (j = 0; j < XkbNumVirtualMods; j++) {
1065 if (!(type->mods.vmods & (1 << j)))
1067 mask |= xkb->server->vmods[j];
1069 for (j = 0; j < type->map_count; j++) {
1070 struct xkb_mods *mods = &type->map[j].mods;
1071 mods->mask = mods->real_mods | VModsToReal(xkb, mods->vmods);
1075 /* Update action modifiers. */
1076 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
1077 union xkb_action *acts = XkbKeyActionsPtr(xkb, key);
1078 for (i = 0; i < XkbKeyNumActions(xkb, key); i++) {
1079 if (acts[i].any.type == XkbSA_NoAction)
1081 UpdateActionMods(xkb, &acts[i], xkb->map->modmap[key]);
1085 /* Update group modifiers. */
1086 for (i = 0; i < XkbNumKbdGroups; i++) {
1087 struct xkb_mods *group = &xkb->compat->groups[i];
1088 group->mask = group->real_mods | VModsToReal(xkb, group->vmods);
1091 /* Update vmod -> indicator maps. */
1092 for (i = 0; i < XkbNumIndicators; i++) {
1093 struct xkb_mods *led = &xkb->indicators->maps[i].mods;
1094 led->mask = led->real_mods | VModsToReal(xkb, led->vmods);