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 ********************************************************/
34 #include "indicators.h"
36 #include "parseutils.h"
38 typedef struct _SymInterpInfo
41 struct xkb_sym_interpret interp;
44 #define _SI_VirtualMod (1<<0)
45 #define _SI_Action (1<<1)
46 #define _SI_AutoRepeat (1<<2)
47 #define _SI_LockingKey (1<<3)
48 #define _SI_LevelOneOnly (1<<4)
50 typedef struct _GroupCompatInfo
54 unsigned char real_mods;
58 typedef struct _CompatInfo
64 SymInterpInfo *interps;
67 GroupCompatInfo groupCompat[XkbNumKbdGroups];
71 struct xkb_desc * 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_desc * 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_desc * 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 (merge != MergeAugment)
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_desc * /* xkb */ ,
393 unsigned /* merge */ ,
394 CompatInfo * /* info */
398 HandleIncludeCompatMap(IncludeStmt * stmt,
399 struct xkb_desc * xkb, CompatInfo * info, FileHandler hndlr)
407 if ((stmt->file == NULL) && (stmt->map == NULL))
411 memset(info, 0, sizeof(CompatInfo));
413 else if (ProcessIncludeFile(stmt, XkmCompatMapIndex, &rtrn, &newMerge))
415 InitCompatInfo(&included, xkb);
416 included.fileID = rtrn->id;
417 included.dflt = info->dflt;
418 included.dflt.defs.fileID = rtrn->id;
419 included.dflt.defs.merge = newMerge;
420 included.ledDflt.defs.fileID = rtrn->id;
421 included.ledDflt.defs.merge = newMerge;
422 included.act = info->act;
423 (*hndlr) (rtrn, xkb, MergeOverride, &included);
424 if (stmt->stmt != NULL)
427 included.name = stmt->stmt;
430 if (info->act != NULL)
436 info->errorCount += 10;
439 if ((stmt->next != NULL) && (included.errorCount < 1))
443 CompatInfo next_incl;
445 for (next = stmt->next; next != NULL; next = next->next)
447 if ((next->file == NULL) && (next->map == NULL))
450 MergeIncludedCompatMaps(&included, info, next->merge);
451 ClearCompatInfo(info, xkb);
453 else if (ProcessIncludeFile(next, XkmCompatMapIndex, &rtrn, &op))
455 InitCompatInfo(&next_incl, xkb);
456 next_incl.fileID = rtrn->id;
457 next_incl.dflt = info->dflt;
458 next_incl.dflt.defs.fileID = rtrn->id;
459 next_incl.dflt.defs.merge = op;
460 next_incl.ledDflt.defs.fileID = rtrn->id;
461 next_incl.ledDflt.defs.merge = op;
462 next_incl.act = info->act;
463 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
464 MergeIncludedCompatMaps(&included, &next_incl, op);
465 if (info->act != NULL)
466 next_incl.act = NULL;
467 ClearCompatInfo(&next_incl, xkb);
472 info->errorCount += 10;
481 MergeIncludedCompatMaps(info, &included, newMerge);
482 ClearCompatInfo(&included, xkb);
484 return (info->errorCount == 0);
487 static const LookupEntry useModMapValues[] = {
496 SetInterpField(SymInterpInfo * si,
497 struct xkb_desc * xkb,
499 ExprDef * arrayNdx, ExprDef * value, CompatInfo * info)
504 if (strcasecmp(field, "action") == 0)
506 if (arrayNdx != NULL)
507 return ReportSINotArray(si, field, info);
508 ok = HandleActionDef(value, xkb, &si->interp.act.any, si->defs.merge,
511 si->defs.defined |= _SI_Action;
513 else if ((strcasecmp(field, "virtualmodifier") == 0) ||
514 (strcasecmp(field, "virtualmod") == 0))
516 if (arrayNdx != NULL)
517 return ReportSINotArray(si, field, info);
518 ok = ResolveVirtualModifier(value, xkb, &tmp, &info->vmods);
521 si->interp.virtual_mod = tmp.uval;
522 si->defs.defined |= _SI_VirtualMod;
525 return ReportSIBadType(si, field, "virtual modifier", info);
527 else if (strcasecmp(field, "repeat") == 0)
529 if (arrayNdx != NULL)
530 return ReportSINotArray(si, field, info);
531 ok = ExprResolveBoolean(value, &tmp);
535 si->interp.flags |= XkbSI_AutoRepeat;
537 si->interp.flags &= ~XkbSI_AutoRepeat;
538 si->defs.defined |= _SI_AutoRepeat;
541 return ReportSIBadType(si, field, "boolean", info);
543 else if (strcasecmp(field, "locking") == 0)
545 if (arrayNdx != NULL)
546 return ReportSINotArray(si, field, info);
547 ok = ExprResolveBoolean(value, &tmp);
551 si->interp.flags |= XkbSI_LockingKey;
553 si->interp.flags &= ~XkbSI_LockingKey;
554 si->defs.defined |= _SI_LockingKey;
557 return ReportSIBadType(si, field, "boolean", info);
559 else if ((strcasecmp(field, "usemodmap") == 0) ||
560 (strcasecmp(field, "usemodmapmods") == 0))
562 if (arrayNdx != NULL)
563 return ReportSINotArray(si, field, info);
564 ok = ExprResolveEnum(value, &tmp, useModMapValues);
568 si->interp.match |= XkbSI_LevelOneOnly;
570 si->interp.match &= ~XkbSI_LevelOneOnly;
571 si->defs.defined |= _SI_LevelOneOnly;
574 return ReportSIBadType(si, field, "level specification", info);
578 ok = ReportBadField("symbol interpretation", field, siText(si, info));
584 HandleInterpVar(VarDef * stmt, struct xkb_desc * xkb, CompatInfo * info)
586 ExprResult elem, field;
590 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
591 ret = 0; /* internal error, already reported */
592 else if (elem.str && (strcasecmp(elem.str, "interpret") == 0))
593 ret = SetInterpField(&info->dflt, xkb, field.str, ndx, stmt->value,
595 else if (elem.str && (strcasecmp(elem.str, "indicator") == 0))
596 ret = SetIndicatorMapField(&info->ledDflt, xkb, field.str, ndx,
599 ret = SetActionField(xkb, elem.str, field.str, ndx, stmt->value,
607 HandleInterpBody(VarDef * def, struct xkb_desc * xkb, SymInterpInfo * si,
611 ExprResult tmp, field;
614 for (; def != NULL; def = (VarDef *) def->common.next)
616 if ((def->name) && (def->name->type == ExprFieldRef))
618 ok = HandleInterpVar(def, xkb, info);
621 ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx);
623 ok = SetInterpField(si, xkb, field.str, arrayNdx, def->value,
632 HandleInterpDef(InterpDef * def, struct xkb_desc * xkb, unsigned merge,
638 if (!ResolveStateAndPredicate(def->match, &pred, &mods, info))
640 ERROR("Couldn't determine matching modifiers\n");
641 ACTION("Symbol interpretation ignored\n");
644 if (def->merge != MergeDefault)
648 si.defs.merge = merge;
649 if (!LookupKeysym(def->sym, &si.interp.sym))
651 ERROR("Could not resolve keysym %s\n", def->sym);
652 ACTION("Symbol interpretation ignored\n");
655 si.interp.match = pred & XkbSI_OpMask;
656 si.interp.mods = mods;
657 if (!HandleInterpBody(def->def, xkb, &si, info))
663 if (!AddInterp(info, &si))
672 HandleGroupCompatDef(GroupCompatDef * def,
673 struct xkb_desc * xkb, unsigned merge, CompatInfo * info)
678 if (def->merge != MergeDefault)
680 if (!XkbIsLegalGroup(def->group - 1))
682 ERROR("Keyboard group must be in the range 1..%d\n",
683 XkbNumKbdGroups + 1);
684 ACTION("Compatibility map for illegal group %d ignored\n",
688 tmp.fileID = info->fileID;
690 if (!ExprResolveVModMask(def->def, &val, xkb))
692 ERROR("Expected a modifier mask in group compatibility definition\n");
693 ACTION("Ignoring illegal compatibility map for group %d\n",
697 tmp.real_mods = val.uval & 0xff;
698 tmp.vmods = (val.uval >> 8) & 0xffff;
699 return AddGroupCompat(info, def->group - 1, &tmp);
703 HandleCompatMapFile(XkbFile * file,
704 struct xkb_desc * xkb, unsigned merge, CompatInfo * info)
708 if (merge == MergeDefault)
709 merge = MergeAugment;
711 info->name = uDupString(file->name);
715 switch (stmt->stmtType)
718 if (!HandleIncludeCompatMap((IncludeStmt *) stmt, xkb, info,
719 HandleCompatMapFile))
723 if (!HandleInterpDef((InterpDef *) stmt, xkb, merge, info))
726 case StmtGroupCompatDef:
727 if (!HandleGroupCompatDef
728 ((GroupCompatDef *) stmt, xkb, merge, info))
731 case StmtIndicatorMapDef:
734 rtrn = HandleIndicatorMapDef((IndicatorMapDef *) stmt, xkb,
735 &info->ledDflt, info->leds, merge);
743 if (!HandleInterpVar((VarDef *) stmt, xkb, info))
747 if (!HandleVModDef((VModDef *) stmt, xkb, merge, &info->vmods))
751 ERROR("Interpretation files may not include other types\n");
752 ACTION("Ignoring definition of key name\n");
756 WSGO("Unexpected statement type %d in HandleCompatMapFile\n",
761 if (info->errorCount > 10)
764 ERROR("Too many errors\n");
766 ACTION("Abandoning compatibility map \"%s\"\n", file->topName);
773 CopyInterps(CompatInfo * info,
774 struct xkb_compat_map * compat, Bool needSymbol, unsigned pred)
778 for (si = info->interps; si; si = (SymInterpInfo *) si->defs.next)
780 if (((si->interp.match & XkbSI_OpMask) != pred) ||
781 (needSymbol && (si->interp.sym == NoSymbol)) ||
782 ((!needSymbol) && (si->interp.sym != NoSymbol)))
784 if (compat->num_si >= compat->size_si)
786 WSGO("No room to merge symbol interpretations\n");
787 ACTION("Symbol interpretations lost\n");
790 compat->sym_interpret[compat->num_si++] = si->interp;
795 CompileCompatMap(XkbFile *file, struct xkb_desc * xkb, unsigned merge,
796 LEDInfoPtr *unboundLEDs)
800 GroupCompatInfo *gcm;
802 InitCompatInfo(&info, xkb);
803 info.dflt.defs.merge = merge;
804 info.ledDflt.defs.merge = merge;
805 HandleCompatMapFile(file, xkb, merge, &info);
807 if (info.errorCount == 0)
810 if (XkbcAllocCompatMap(xkb, XkbAllCompatMask, info.nInterps) !=
813 WSGO("Couldn't allocate compatibility map\n");
816 size = info.nInterps * sizeof(struct xkb_sym_interpret);
819 CopyInterps(&info, xkb->compat, True, XkbSI_Exactly);
820 CopyInterps(&info, xkb->compat, True, XkbSI_AllOf | XkbSI_NoneOf);
821 CopyInterps(&info, xkb->compat, True, XkbSI_AnyOf);
822 CopyInterps(&info, xkb->compat, True, XkbSI_AnyOfOrNone);
823 CopyInterps(&info, xkb->compat, False, XkbSI_Exactly);
824 CopyInterps(&info, xkb->compat, False,
825 XkbSI_AllOf | XkbSI_NoneOf);
826 CopyInterps(&info, xkb->compat, False, XkbSI_AnyOf);
827 CopyInterps(&info, xkb->compat, False, XkbSI_AnyOfOrNone);
829 for (i = 0, gcm = &info.groupCompat[0]; i < XkbNumKbdGroups;
832 if ((gcm->fileID != 0) || (gcm->real_mods != 0)
833 || (gcm->vmods != 0))
835 xkb->compat->groups[i].mask = gcm->real_mods;
836 xkb->compat->groups[i].real_mods = gcm->real_mods;
837 xkb->compat->groups[i].vmods = gcm->vmods;
840 if (info.leds != NULL)
842 if (!CopyIndicatorMapDefs(xkb, info.leds, unboundLEDs))
846 ClearCompatInfo(&info, xkb);
854 VModsToReal(struct xkb_desc *xkb, uint32_t vmodmask)
862 for (i = 0; i < XkbNumVirtualMods; i++) {
863 if (!(vmodmask & (1 << i)))
865 ret |= xkb->server->vmods[i];
872 UpdateActionMods(struct xkb_desc *xkb, union xkb_action *act, uint32_t rmodmask)
876 case XkbSA_LatchMods:
878 if (act->mods.flags & XkbSA_UseModMapMods)
879 act->mods.real_mods = rmodmask;
880 act->mods.mask = act->mods.real_mods;
881 act->mods.mask |= VModsToReal(xkb, act->mods.vmods);
884 if (act->iso.flags & XkbSA_UseModMapMods)
885 act->iso.real_mods = rmodmask;
886 act->iso.mask = act->iso.real_mods;
887 act->iso.mask |= VModsToReal(xkb, act->iso.vmods);
895 * Find an interpretation which applies to this particular level, either by
896 * finding an exact match for the symbol and modifier combination, or a
897 * generic NoSymbol match.
899 static struct xkb_sym_interpret *
900 FindInterpForKey(struct xkb_desc *xkb, xkb_keycode_t key, uint32_t group, uint32_t level)
902 struct xkb_sym_interpret *ret = NULL;
907 num_syms = xkb_key_get_syms_by_level(xkb, key, group, level, &syms);
911 for (i = 0; i < xkb->compat->num_si; i++) {
912 struct xkb_sym_interpret *interp = &xkb->compat->sym_interpret[i];
916 if ((num_syms != 1 || interp->sym != syms[0]) &&
917 interp->sym != NoSymbol)
920 if (level == 0 || !(interp->match & XkbSI_LevelOneOnly))
921 mods = xkb->map->modmap[key];
925 switch (interp->match & XkbSI_OpMask) {
927 found = !(interp->mods & mods);
929 case XkbSI_AnyOfOrNone:
930 found = (!mods || (interp->mods & mods));
933 found = !!(interp->mods & mods);
936 found = ((interp->mods & mods) == mods);
939 found = (interp->mods == mods);
946 if (found && interp->sym != NoSymbol)
948 else if (found && !ret)
958 ApplyInterpsToKey(struct xkb_desc *xkb, xkb_keycode_t key)
960 #define INTERP_SIZE (8 * 4)
961 struct xkb_sym_interpret *interps[INTERP_SIZE];
962 union xkb_action *acts;
963 uint32_t vmodmask = 0;
966 int width = XkbKeyGroupsWidth(xkb, key);
969 /* If we've been told not to bind interps to this key, then don't. */
970 if (xkb->server->explicit[key] & XkbExplicitInterpretMask)
973 for (i = 0; i < INTERP_SIZE; i++)
976 for (group = 0; group < XkbKeyNumGroups(xkb, key); group++) {
977 for (level = 0; level < XkbKeyGroupWidth(xkb, key, group); level++) {
978 i = (group * width) + level;
979 if (i >= INTERP_SIZE) /* XXX FIXME */
981 interps[i] = FindInterpForKey(xkb, key, group, level);
988 num_acts = XkbKeyNumGroups(xkb, key) * width;
989 acts = XkbcResizeKeyActions(xkb, key, num_acts);
995 for (group = 0; group < XkbKeyNumGroups(xkb, key); group++) {
996 for (level = 0; level < XkbKeyGroupWidth(xkb, key, group); level++) {
997 struct xkb_sym_interpret *interp;
999 i = (group * width) + level;
1000 interp = interps[i];
1002 /* Infer default key behaviours from the base level. */
1003 if (group == 0 && level == 0) {
1004 if (!(xkb->server->explicit[key] & XkbExplicitAutoRepeatMask) &&
1005 (!interp || interp->flags & XkbSI_AutoRepeat))
1006 xkb->ctrls->per_key_repeat[key / 8] |= (1 << (key % 8));
1007 if (!(xkb->server->explicit[key] & XkbExplicitBehaviorMask) &&
1008 interp && (interp->flags & XkbSI_LockingKey))
1009 xkb->server->behaviors[key].type = XkbKB_Lock;
1015 if ((group == 0 && level == 0) ||
1016 !(interp->match & XkbSI_LevelOneOnly)) {
1017 if (interp->virtual_mod != XkbNoModifier)
1018 vmodmask |= (1 << interp->virtual_mod);
1020 acts[i] = interp->act;
1024 if (!(xkb->server->explicit[key] & XkbExplicitVModMapMask))
1025 xkb->server->vmodmap[key] = vmodmask;
1032 * This collects a bunch of disparate functions which was done in the server
1033 * at various points that really should've been done within xkbcomp. Turns out
1034 * your actions and types are a lot more useful when any of your modifiers
1035 * other than Shift actually do something ...
1038 UpdateModifiersFromCompat(struct xkb_desc *xkb)
1043 /* Find all the interprets for the key and bind them to actions,
1044 * which will also update the vmodmap. */
1045 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++)
1046 if (!ApplyInterpsToKey(xkb, key))
1049 /* Update xkb->server->vmods, the virtual -> real mod mapping. */
1050 for (i = 0; i < XkbNumVirtualMods; i++)
1051 xkb->server->vmods[i] = 0;
1052 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
1053 if (!xkb->server->vmodmap[key])
1055 for (i = 0; i < XkbNumVirtualMods; i++) {
1056 if (!(xkb->server->vmodmap[key] & (1 << i)))
1058 xkb->server->vmods[i] |= xkb->map->modmap[key];
1062 /* Now update the level masks for all the types to reflect the vmods. */
1063 for (i = 0; i < xkb->map->num_types; i++) {
1064 struct xkb_key_type *type = &xkb->map->types[i];
1067 type->mods.mask = type->mods.real_mods;
1068 type->mods.mask |= VModsToReal(xkb, type->mods.vmods);
1069 for (j = 0; j < XkbNumVirtualMods; j++) {
1070 if (!(type->mods.vmods & (1 << j)))
1072 mask |= xkb->server->vmods[j];
1074 for (j = 0; j < type->map_count; j++) {
1075 struct xkb_mods *mods = &type->map[j].mods;
1076 mods->mask = mods->real_mods | VModsToReal(xkb, mods->vmods);
1080 /* Update action modifiers. */
1081 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
1082 union xkb_action *acts = XkbKeyActionsPtr(xkb, key);
1083 for (i = 0; i < XkbKeyNumActions(xkb, key); i++) {
1084 if (acts[i].any.type == XkbSA_NoAction)
1086 UpdateActionMods(xkb, &acts[i], xkb->map->modmap[key]);
1090 /* Update group modifiers. */
1091 for (i = 0; i < XkbNumKbdGroups; i++) {
1092 struct xkb_mods *group = &xkb->compat->groups[i];
1093 group->mask = group->real_mods | VModsToReal(xkb, group->vmods);
1096 /* Update vmod -> indicator maps. */
1097 for (i = 0; i < XkbNumIndicators; i++) {
1098 struct xkb_mods *led = &xkb->indicators->maps[i].mods;
1099 led->mask = led->real_mods | VModsToReal(xkb, led->vmods);