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 */ ,
392 struct xkb_keymap * /* xkb */ ,
393 unsigned /* merge */ ,
394 CompatInfo * /* info */
398 HandleIncludeCompatMap(IncludeStmt * stmt,
399 struct xkb_keymap * xkb, CompatInfo * info, FileHandler hndlr)
407 if ((stmt->file == NULL) && (stmt->map == NULL))
411 memset(info, 0, sizeof(CompatInfo));
413 else if (ProcessIncludeFile(xkb->context, stmt, XkmCompatMapIndex, &rtrn,
416 InitCompatInfo(&included, xkb);
417 included.fileID = rtrn->id;
418 included.dflt = info->dflt;
419 included.dflt.defs.fileID = rtrn->id;
420 included.dflt.defs.merge = newMerge;
421 included.ledDflt.defs.fileID = rtrn->id;
422 included.ledDflt.defs.merge = newMerge;
423 included.act = info->act;
424 (*hndlr) (rtrn, xkb, MergeOverride, &included);
425 if (stmt->stmt != NULL)
428 included.name = stmt->stmt;
431 if (info->act != NULL)
437 info->errorCount += 10;
440 if ((stmt->next != NULL) && (included.errorCount < 1))
444 CompatInfo next_incl;
446 for (next = stmt->next; next != NULL; next = next->next)
448 if ((next->file == NULL) && (next->map == NULL))
451 MergeIncludedCompatMaps(&included, info, next->merge);
452 ClearCompatInfo(info, xkb);
454 else if (ProcessIncludeFile(xkb->context, next, XkmCompatMapIndex,
457 InitCompatInfo(&next_incl, xkb);
458 next_incl.fileID = rtrn->id;
459 next_incl.dflt = info->dflt;
460 next_incl.dflt.defs.fileID = rtrn->id;
461 next_incl.dflt.defs.merge = op;
462 next_incl.ledDflt.defs.fileID = rtrn->id;
463 next_incl.ledDflt.defs.merge = op;
464 next_incl.act = info->act;
465 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
466 MergeIncludedCompatMaps(&included, &next_incl, op);
467 if (info->act != NULL)
468 next_incl.act = NULL;
469 ClearCompatInfo(&next_incl, xkb);
474 info->errorCount += 10;
483 MergeIncludedCompatMaps(info, &included, newMerge);
484 ClearCompatInfo(&included, xkb);
486 return (info->errorCount == 0);
489 static const LookupEntry useModMapValues[] = {
498 SetInterpField(SymInterpInfo * si,
499 struct xkb_keymap * xkb,
501 ExprDef * arrayNdx, ExprDef * value, CompatInfo * info)
506 if (strcasecmp(field, "action") == 0)
508 if (arrayNdx != NULL)
509 return ReportSINotArray(si, field, info);
510 ok = HandleActionDef(value, xkb, &si->interp.act.any, si->defs.merge,
513 si->defs.defined |= _SI_Action;
515 else if ((strcasecmp(field, "virtualmodifier") == 0) ||
516 (strcasecmp(field, "virtualmod") == 0))
518 if (arrayNdx != NULL)
519 return ReportSINotArray(si, field, info);
520 ok = ResolveVirtualModifier(value, xkb, &tmp, &info->vmods);
523 si->interp.virtual_mod = tmp.uval;
524 si->defs.defined |= _SI_VirtualMod;
527 return ReportSIBadType(si, field, "virtual modifier", info);
529 else if (strcasecmp(field, "repeat") == 0)
531 if (arrayNdx != NULL)
532 return ReportSINotArray(si, field, info);
533 ok = ExprResolveBoolean(value, &tmp);
537 si->interp.flags |= XkbSI_AutoRepeat;
539 si->interp.flags &= ~XkbSI_AutoRepeat;
540 si->defs.defined |= _SI_AutoRepeat;
543 return ReportSIBadType(si, field, "boolean", info);
545 else if (strcasecmp(field, "locking") == 0)
547 if (arrayNdx != NULL)
548 return ReportSINotArray(si, field, info);
549 ok = ExprResolveBoolean(value, &tmp);
553 si->interp.flags |= XkbSI_LockingKey;
555 si->interp.flags &= ~XkbSI_LockingKey;
556 si->defs.defined |= _SI_LockingKey;
559 return ReportSIBadType(si, field, "boolean", info);
561 else if ((strcasecmp(field, "usemodmap") == 0) ||
562 (strcasecmp(field, "usemodmapmods") == 0))
564 if (arrayNdx != NULL)
565 return ReportSINotArray(si, field, info);
566 ok = ExprResolveEnum(value, &tmp, useModMapValues);
570 si->interp.match |= XkbSI_LevelOneOnly;
572 si->interp.match &= ~XkbSI_LevelOneOnly;
573 si->defs.defined |= _SI_LevelOneOnly;
576 return ReportSIBadType(si, field, "level specification", info);
580 ok = ReportBadField("symbol interpretation", field, siText(si, info));
586 HandleInterpVar(VarDef * stmt, struct xkb_keymap * xkb, CompatInfo * info)
588 ExprResult elem, field;
592 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
593 ret = 0; /* internal error, already reported */
594 else if (elem.str && (strcasecmp(elem.str, "interpret") == 0))
595 ret = SetInterpField(&info->dflt, xkb, field.str, ndx, stmt->value,
597 else if (elem.str && (strcasecmp(elem.str, "indicator") == 0))
598 ret = SetIndicatorMapField(&info->ledDflt, xkb, field.str, ndx,
601 ret = SetActionField(xkb, elem.str, field.str, ndx, stmt->value,
609 HandleInterpBody(VarDef * def, struct xkb_keymap * xkb, SymInterpInfo * si,
613 ExprResult tmp, field;
616 for (; def != NULL; def = (VarDef *) def->common.next)
618 if ((def->name) && (def->name->type == ExprFieldRef))
620 ok = HandleInterpVar(def, xkb, info);
623 ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx);
625 ok = SetInterpField(si, xkb, field.str, arrayNdx, def->value,
634 HandleInterpDef(InterpDef * def, struct xkb_keymap * xkb, unsigned merge,
640 if (!ResolveStateAndPredicate(def->match, &pred, &mods, info))
642 ERROR("Couldn't determine matching modifiers\n");
643 ACTION("Symbol interpretation ignored\n");
646 if (def->merge != MergeDefault)
650 si.defs.merge = merge;
651 if (!LookupKeysym(def->sym, &si.interp.sym))
653 ERROR("Could not resolve keysym %s\n", def->sym);
654 ACTION("Symbol interpretation ignored\n");
657 si.interp.match = pred & XkbSI_OpMask;
658 si.interp.mods = mods;
659 if (!HandleInterpBody(def->def, xkb, &si, info))
665 if (!AddInterp(info, &si))
674 HandleGroupCompatDef(GroupCompatDef * def,
675 struct xkb_keymap * xkb, unsigned merge, CompatInfo * info)
680 if (def->merge != MergeDefault)
682 if (!XkbIsLegalGroup(def->group - 1))
684 ERROR("Keyboard group must be in the range 1..%d\n",
685 XkbNumKbdGroups + 1);
686 ACTION("Compatibility map for illegal group %d ignored\n",
690 tmp.fileID = info->fileID;
692 if (!ExprResolveVModMask(def->def, &val, xkb))
694 ERROR("Expected a modifier mask in group compatibility definition\n");
695 ACTION("Ignoring illegal compatibility map for group %d\n",
699 tmp.real_mods = val.uval & 0xff;
700 tmp.vmods = (val.uval >> 8) & 0xffff;
702 return AddGroupCompat(info, def->group - 1, &tmp);
706 HandleCompatMapFile(XkbFile * file,
707 struct xkb_keymap * xkb, unsigned merge, CompatInfo * info)
711 if (merge == MergeDefault)
712 merge = MergeAugment;
714 info->name = uDupString(file->name);
718 switch (stmt->stmtType)
721 if (!HandleIncludeCompatMap((IncludeStmt *) stmt, xkb, info,
722 HandleCompatMapFile))
726 if (!HandleInterpDef((InterpDef *) stmt, xkb, merge, info))
729 case StmtGroupCompatDef:
730 if (!HandleGroupCompatDef
731 ((GroupCompatDef *) stmt, xkb, merge, info))
734 case StmtIndicatorMapDef:
737 rtrn = HandleIndicatorMapDef((IndicatorMapDef *) stmt, xkb,
738 &info->ledDflt, info->leds, merge);
746 if (!HandleInterpVar((VarDef *) stmt, xkb, info))
750 if (!HandleVModDef((VModDef *) stmt, xkb, merge, &info->vmods))
754 ERROR("Interpretation files may not include other types\n");
755 ACTION("Ignoring definition of key name\n");
759 WSGO("Unexpected statement type %d in HandleCompatMapFile\n",
764 if (info->errorCount > 10)
767 ERROR("Too many errors\n");
769 ACTION("Abandoning compatibility map \"%s\"\n", file->topName);
776 CopyInterps(CompatInfo * info,
777 struct xkb_compat_map * compat, Bool needSymbol, unsigned pred)
781 for (si = info->interps; si; si = (SymInterpInfo *) si->defs.next)
783 if (((si->interp.match & XkbSI_OpMask) != pred) ||
784 (needSymbol && (si->interp.sym == XKB_KEYSYM_NO_SYMBOL)) ||
785 ((!needSymbol) && (si->interp.sym != XKB_KEYSYM_NO_SYMBOL)))
787 if (compat->num_si >= compat->size_si)
789 WSGO("No room to merge symbol interpretations\n");
790 ACTION("Symbol interpretations lost\n");
793 compat->sym_interpret[compat->num_si++] = si->interp;
798 CompileCompatMap(XkbFile *file, struct xkb_keymap * xkb, unsigned merge,
799 LEDInfoPtr *unboundLEDs)
803 GroupCompatInfo *gcm;
805 InitCompatInfo(&info, xkb);
806 info.dflt.defs.merge = merge;
807 info.ledDflt.defs.merge = merge;
808 HandleCompatMapFile(file, xkb, merge, &info);
810 if (info.errorCount == 0)
813 if (XkbcAllocCompatMap(xkb, XkbAllCompatMask, info.nInterps) !=
816 WSGO("Couldn't allocate compatibility map\n");
819 size = info.nInterps * sizeof(struct xkb_sym_interpret);
822 CopyInterps(&info, xkb->compat, True, XkbSI_Exactly);
823 CopyInterps(&info, xkb->compat, True, XkbSI_AllOf | XkbSI_NoneOf);
824 CopyInterps(&info, xkb->compat, True, XkbSI_AnyOf);
825 CopyInterps(&info, xkb->compat, True, XkbSI_AnyOfOrNone);
826 CopyInterps(&info, xkb->compat, False, XkbSI_Exactly);
827 CopyInterps(&info, xkb->compat, False,
828 XkbSI_AllOf | XkbSI_NoneOf);
829 CopyInterps(&info, xkb->compat, False, XkbSI_AnyOf);
830 CopyInterps(&info, xkb->compat, False, XkbSI_AnyOfOrNone);
832 for (i = 0, gcm = &info.groupCompat[0]; i < XkbNumKbdGroups;
835 if ((gcm->fileID != 0) || (gcm->real_mods != 0)
836 || (gcm->vmods != 0))
838 xkb->compat->groups[i].mask = gcm->real_mods;
839 xkb->compat->groups[i].real_mods = gcm->real_mods;
840 xkb->compat->groups[i].vmods = gcm->vmods;
843 if (info.leds != NULL)
845 if (!CopyIndicatorMapDefs(xkb, info.leds, unboundLEDs))
849 ClearCompatInfo(&info, xkb);
857 VModsToReal(struct xkb_keymap *xkb, uint32_t vmodmask)
865 for (i = 0; i < XkbNumVirtualMods; i++) {
866 if (!(vmodmask & (1 << i)))
868 ret |= xkb->server->vmods[i];
875 UpdateActionMods(struct xkb_keymap *xkb, union xkb_action *act, uint32_t rmodmask)
879 case XkbSA_LatchMods:
881 if (act->mods.flags & XkbSA_UseModMapMods)
882 act->mods.real_mods = rmodmask;
883 act->mods.mask = act->mods.real_mods;
884 act->mods.mask |= VModsToReal(xkb, act->mods.vmods);
887 if (act->iso.flags & XkbSA_UseModMapMods)
888 act->iso.real_mods = rmodmask;
889 act->iso.mask = act->iso.real_mods;
890 act->iso.mask |= VModsToReal(xkb, act->iso.vmods);
898 * Find an interpretation which applies to this particular level, either by
899 * finding an exact match for the symbol and modifier combination, or a
900 * generic XKB_KEYSYM_NO_SYMBOL match.
902 static struct xkb_sym_interpret *
903 FindInterpForKey(struct xkb_keymap *xkb, xkb_keycode_t key, uint32_t group, uint32_t level)
905 struct xkb_sym_interpret *ret = NULL;
906 const xkb_keysym_t *syms;
910 num_syms = xkb_key_get_syms_by_level(xkb, key, group, level, &syms);
914 for (i = 0; i < xkb->compat->num_si; i++) {
915 struct xkb_sym_interpret *interp = &xkb->compat->sym_interpret[i];
919 if ((num_syms > 1 || interp->sym != syms[0]) &&
920 interp->sym != XKB_KEYSYM_NO_SYMBOL)
923 if (level == 0 || !(interp->match & XkbSI_LevelOneOnly))
924 mods = xkb->map->modmap[key];
928 switch (interp->match & XkbSI_OpMask) {
930 found = !(interp->mods & mods);
932 case XkbSI_AnyOfOrNone:
933 found = (!mods || (interp->mods & mods));
936 found = !!(interp->mods & mods);
939 found = ((interp->mods & mods) == mods);
942 found = (interp->mods == mods);
949 if (found && interp->sym != XKB_KEYSYM_NO_SYMBOL)
951 else if (found && !ret)
961 ApplyInterpsToKey(struct xkb_keymap *xkb, xkb_keycode_t key)
963 #define INTERP_SIZE (8 * 4)
964 struct xkb_sym_interpret *interps[INTERP_SIZE];
965 union xkb_action *acts;
966 uint32_t vmodmask = 0;
969 int width = XkbKeyGroupsWidth(xkb, key);
972 /* If we've been told not to bind interps to this key, then don't. */
973 if (xkb->server->explicit[key] & XkbExplicitInterpretMask)
976 for (i = 0; i < INTERP_SIZE; i++)
979 for (group = 0; group < XkbKeyNumGroups(xkb, key); group++) {
980 for (level = 0; level < XkbKeyGroupWidth(xkb, key, group); level++) {
981 i = (group * width) + level;
982 if (i >= INTERP_SIZE) /* XXX FIXME */
984 interps[i] = FindInterpForKey(xkb, key, group, level);
991 num_acts = XkbKeyNumGroups(xkb, key) * width;
992 acts = XkbcResizeKeyActions(xkb, key, num_acts);
998 for (group = 0; group < XkbKeyNumGroups(xkb, key); group++) {
999 for (level = 0; level < XkbKeyGroupWidth(xkb, key, group); level++) {
1000 struct xkb_sym_interpret *interp;
1002 i = (group * width) + level;
1003 interp = interps[i];
1005 /* Infer default key behaviours from the base level. */
1006 if (group == 0 && level == 0) {
1007 if (!(xkb->server->explicit[key] & XkbExplicitAutoRepeatMask) &&
1008 (!interp || interp->flags & XkbSI_AutoRepeat))
1009 xkb->ctrls->per_key_repeat[key / 8] |= (1 << (key % 8));
1010 if (!(xkb->server->explicit[key] & XkbExplicitBehaviorMask) &&
1011 interp && (interp->flags & XkbSI_LockingKey))
1012 xkb->server->behaviors[key].type = XkbKB_Lock;
1018 if ((group == 0 && level == 0) ||
1019 !(interp->match & XkbSI_LevelOneOnly)) {
1020 if (interp->virtual_mod != XkbNoModifier)
1021 vmodmask |= (1 << interp->virtual_mod);
1023 acts[i] = interp->act;
1027 if (!(xkb->server->explicit[key] & XkbExplicitVModMapMask))
1028 xkb->server->vmodmap[key] = vmodmask;
1035 * This collects a bunch of disparate functions which was done in the server
1036 * at various points that really should've been done within xkbcomp. Turns out
1037 * your actions and types are a lot more useful when any of your modifiers
1038 * other than Shift actually do something ...
1041 UpdateModifiersFromCompat(struct xkb_keymap *xkb)
1046 /* Find all the interprets for the key and bind them to actions,
1047 * which will also update the vmodmap. */
1048 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++)
1049 if (!ApplyInterpsToKey(xkb, key))
1052 /* Update xkb->server->vmods, the virtual -> real mod mapping. */
1053 for (i = 0; i < XkbNumVirtualMods; i++)
1054 xkb->server->vmods[i] = 0;
1055 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
1056 if (!xkb->server->vmodmap[key])
1058 for (i = 0; i < XkbNumVirtualMods; i++) {
1059 if (!(xkb->server->vmodmap[key] & (1 << i)))
1061 xkb->server->vmods[i] |= xkb->map->modmap[key];
1065 /* Now update the level masks for all the types to reflect the vmods. */
1066 for (i = 0; i < xkb->map->num_types; i++) {
1067 struct xkb_key_type *type = &xkb->map->types[i];
1070 type->mods.mask = type->mods.real_mods;
1071 type->mods.mask |= VModsToReal(xkb, type->mods.vmods);
1072 for (j = 0; j < XkbNumVirtualMods; j++) {
1073 if (!(type->mods.vmods & (1 << j)))
1075 mask |= xkb->server->vmods[j];
1077 for (j = 0; j < type->map_count; j++) {
1078 struct xkb_mods *mods = &type->map[j].mods;
1079 mods->mask = mods->real_mods | VModsToReal(xkb, mods->vmods);
1083 /* Update action modifiers. */
1084 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
1085 union xkb_action *acts = XkbKeyActionsPtr(xkb, key);
1086 for (i = 0; i < XkbKeyNumActions(xkb, key); i++) {
1087 if (acts[i].any.type == XkbSA_NoAction)
1089 UpdateActionMods(xkb, &acts[i], xkb->map->modmap[key]);
1093 /* Update group modifiers. */
1094 for (i = 0; i < XkbNumKbdGroups; i++) {
1095 struct xkb_mods *group = &xkb->compat->groups[i];
1096 group->mask = group->real_mods | VModsToReal(xkb, group->vmods);
1099 /* Update vmod -> indicator maps. */
1100 for (i = 0; i < XkbNumIndicators; i++) {
1101 struct xkb_mods *led = &xkb->indicators->maps[i].mods;
1102 led->mask = led->real_mods | VModsToReal(xkb, led->vmods);