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.data; i++)
122 info->dflt.interp.act.data[i] = 0;
124 ClearIndicatorMapInfo(&info->ledDflt);
125 info->ledDflt.defs.fileID = info->fileID;
126 info->ledDflt.defs.defined = 0;
127 info->ledDflt.defs.merge = MergeOverride;
128 memset(&info->groupCompat[0], 0,
129 XkbNumKbdGroups * sizeof(GroupCompatInfo));
131 InitVModInfo(&info->vmods, xkb);
135 ClearCompatInfo(CompatInfo * info, struct xkb_desc * xkb)
142 info->dflt.defs.defined = 0;
143 info->dflt.defs.merge = MergeAugment;
144 info->dflt.interp.flags = 0;
145 info->dflt.interp.virtual_mod = XkbNoModifier;
146 info->dflt.interp.act.type = XkbSA_NoAction;
147 for (i = 0; i < sizeof info->dflt.interp.act.data; i++)
149 info->dflt.interp.act.data[i] = 0;
151 ClearIndicatorMapInfo(&info->ledDflt);
153 info->interps = (SymInterpInfo *) ClearCommonInfo(&info->interps->defs);
154 memset(&info->groupCompat[0], 0,
155 XkbNumKbdGroups * sizeof(GroupCompatInfo));
156 info->leds = (LEDInfo *) ClearCommonInfo(&info->leds->defs);
158 next = info->act->next;
162 ClearVModInfo(&info->vmods, xkb);
165 static SymInterpInfo *
166 NextInterp(CompatInfo * info)
170 si = uTypedAlloc(SymInterpInfo);
173 memset(si, 0, sizeof(SymInterpInfo));
175 (SymInterpInfo *) AddCommonInfo(&info->interps->defs,
182 static SymInterpInfo *
183 FindMatchingInterp(CompatInfo * info, SymInterpInfo * new)
187 for (old = info->interps; old != NULL;
188 old = (SymInterpInfo *) old->defs.next)
190 if ((old->interp.sym == new->interp.sym) &&
191 (old->interp.mods == new->interp.mods) &&
192 (old->interp.match == new->interp.match))
201 AddInterp(CompatInfo * info, SymInterpInfo * new)
207 old = FindMatchingInterp(info, new);
210 if (new->defs.merge == MergeReplace)
212 SymInterpInfo *next = (SymInterpInfo *) old->defs.next;
213 if (((old->defs.fileID == new->defs.fileID)
214 && (warningLevel > 0)) || (warningLevel > 9))
216 WARN("Multiple definitions for \"%s\"\n", siText(new, info));
217 ACTION("Earlier interpretation ignored\n");
220 old->defs.next = &next->defs;
223 if (UseNewField(_SI_VirtualMod, &old->defs, &new->defs, &collide))
225 old->interp.virtual_mod = new->interp.virtual_mod;
226 old->defs.defined |= _SI_VirtualMod;
228 if (UseNewField(_SI_Action, &old->defs, &new->defs, &collide))
230 old->interp.act = new->interp.act;
231 old->defs.defined |= _SI_Action;
233 if (UseNewField(_SI_AutoRepeat, &old->defs, &new->defs, &collide))
235 old->interp.flags &= ~XkbSI_AutoRepeat;
236 old->interp.flags |= (new->interp.flags & XkbSI_AutoRepeat);
237 old->defs.defined |= _SI_AutoRepeat;
239 if (UseNewField(_SI_LockingKey, &old->defs, &new->defs, &collide))
241 old->interp.flags &= ~XkbSI_LockingKey;
242 old->interp.flags |= (new->interp.flags & XkbSI_LockingKey);
243 old->defs.defined |= _SI_LockingKey;
245 if (UseNewField(_SI_LevelOneOnly, &old->defs, &new->defs, &collide))
247 old->interp.match &= ~XkbSI_LevelOneOnly;
248 old->interp.match |= (new->interp.match & XkbSI_LevelOneOnly);
249 old->defs.defined |= _SI_LevelOneOnly;
253 WARN("Multiple interpretations of \"%s\"\n", siText(new, info));
254 ACTION("Using %s definition for duplicate fields\n",
255 (new->defs.merge != MergeAugment ? "last" : "first"));
260 if ((new = NextInterp(info)) == NULL)
263 new->defs.next = NULL;
268 AddGroupCompat(CompatInfo * info, unsigned group, GroupCompatInfo * newGC)
273 merge = newGC->merge;
274 gc = &info->groupCompat[group];
275 if (((gc->real_mods == newGC->real_mods) && (gc->vmods == newGC->vmods)))
279 if (((gc->fileID == newGC->fileID) && (warningLevel > 0))
280 || (warningLevel > 9))
282 WARN("Compat map for group %d redefined\n", group + 1);
283 ACTION("Using %s definition\n",
284 (merge == MergeAugment ? "old" : "new"));
286 if (merge != MergeAugment)
291 /***====================================================================***/
294 ResolveStateAndPredicate(ExprDef * expr,
296 unsigned *mods_rtrn, CompatInfo * info)
302 *pred_rtrn = XkbSI_AnyOfOrNone;
307 *pred_rtrn = XkbSI_Exactly;
308 if (expr->op == ExprActionDecl)
310 const char *pred_txt = XkbcAtomText(expr->value.action.name);
311 if (uStrCaseCmp(pred_txt, "noneof") == 0)
312 *pred_rtrn = XkbSI_NoneOf;
313 else if (uStrCaseCmp(pred_txt, "anyofornone") == 0)
314 *pred_rtrn = XkbSI_AnyOfOrNone;
315 else if (uStrCaseCmp(pred_txt, "anyof") == 0)
316 *pred_rtrn = XkbSI_AnyOf;
317 else if (uStrCaseCmp(pred_txt, "allof") == 0)
318 *pred_rtrn = XkbSI_AllOf;
319 else if (uStrCaseCmp(pred_txt, "exactly") == 0)
320 *pred_rtrn = XkbSI_Exactly;
323 ERROR("Illegal modifier predicate \"%s\"\n", pred_txt);
327 expr = expr->value.action.args;
329 else if (expr->op == ExprIdent)
331 const char *pred_txt = XkbcAtomText(expr->value.str);
332 if ((pred_txt) && (uStrCaseCmp(pred_txt, "any") == 0))
334 *pred_rtrn = XkbSI_AnyOf;
340 if (ExprResolveModMask(expr, &result))
342 *mods_rtrn = result.uval;
348 /***====================================================================***/
351 MergeIncludedCompatMaps(CompatInfo * into, CompatInfo * from, unsigned merge)
354 LEDInfo *led, *rtrn, *next;
355 GroupCompatInfo *gcm;
358 if (from->errorCount > 0)
360 into->errorCount += from->errorCount;
363 if (into->name == NULL)
365 into->name = from->name;
368 for (si = from->interps; si; si = (SymInterpInfo *) si->defs.next)
370 if (merge != MergeDefault)
371 si->defs.merge = merge;
372 if (!AddInterp(into, si))
375 for (i = 0, gcm = &from->groupCompat[0]; i < XkbNumKbdGroups; i++, gcm++)
377 if (merge != MergeDefault)
379 if (!AddGroupCompat(into, i, gcm))
382 for (led = from->leds; led != NULL; led = next)
384 next = (LEDInfo *) led->defs.next;
385 if (merge != MergeDefault)
386 led->defs.merge = merge;
387 rtrn = AddIndicatorMap(into->leds, led);
395 typedef void (*FileHandler) (XkbFile * /* rtrn */ ,
396 struct xkb_desc * /* xkb */ ,
397 unsigned /* merge */ ,
398 CompatInfo * /* info */
402 HandleIncludeCompatMap(IncludeStmt * stmt,
403 struct xkb_desc * xkb, CompatInfo * info, FileHandler hndlr)
411 if ((stmt->file == NULL) && (stmt->map == NULL))
415 memset(info, 0, sizeof(CompatInfo));
417 else if (ProcessIncludeFile(stmt, XkmCompatMapIndex, &rtrn, &newMerge))
419 InitCompatInfo(&included, xkb);
420 included.fileID = rtrn->id;
421 included.dflt = info->dflt;
422 included.dflt.defs.fileID = rtrn->id;
423 included.dflt.defs.merge = newMerge;
424 included.ledDflt.defs.fileID = rtrn->id;
425 included.ledDflt.defs.merge = newMerge;
426 included.act = info->act;
427 (*hndlr) (rtrn, xkb, MergeOverride, &included);
428 if (stmt->stmt != NULL)
431 included.name = stmt->stmt;
434 if (info->act != NULL)
440 info->errorCount += 10;
443 if ((stmt->next != NULL) && (included.errorCount < 1))
447 CompatInfo next_incl;
449 for (next = stmt->next; next != NULL; next = next->next)
451 if ((next->file == NULL) && (next->map == NULL))
454 MergeIncludedCompatMaps(&included, info, next->merge);
455 ClearCompatInfo(info, xkb);
457 else if (ProcessIncludeFile(next, XkmCompatMapIndex, &rtrn, &op))
459 InitCompatInfo(&next_incl, xkb);
460 next_incl.fileID = rtrn->id;
461 next_incl.dflt = info->dflt;
462 next_incl.dflt.defs.fileID = rtrn->id;
463 next_incl.dflt.defs.merge = op;
464 next_incl.ledDflt.defs.fileID = rtrn->id;
465 next_incl.ledDflt.defs.merge = op;
466 next_incl.act = info->act;
467 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
468 MergeIncludedCompatMaps(&included, &next_incl, op);
469 if (info->act != NULL)
470 next_incl.act = NULL;
471 ClearCompatInfo(&next_incl, xkb);
476 info->errorCount += 10;
485 MergeIncludedCompatMaps(info, &included, newMerge);
486 ClearCompatInfo(&included, xkb);
488 return (info->errorCount == 0);
491 static const LookupEntry useModMapValues[] = {
500 SetInterpField(SymInterpInfo * si,
501 struct xkb_desc * xkb,
503 ExprDef * arrayNdx, ExprDef * value, CompatInfo * info)
508 if (uStrCaseCmp(field, "action") == 0)
510 if (arrayNdx != NULL)
511 return ReportSINotArray(si, field, info);
512 ok = HandleActionDef(value, xkb, &si->interp.act, si->defs.merge,
515 si->defs.defined |= _SI_Action;
517 else if ((uStrCaseCmp(field, "virtualmodifier") == 0) ||
518 (uStrCaseCmp(field, "virtualmod") == 0))
520 if (arrayNdx != NULL)
521 return ReportSINotArray(si, field, info);
522 ok = ResolveVirtualModifier(value, xkb, &tmp, &info->vmods);
525 si->interp.virtual_mod = tmp.uval;
526 si->defs.defined |= _SI_VirtualMod;
529 return ReportSIBadType(si, field, "virtual modifier", info);
531 else if (uStrCaseCmp(field, "repeat") == 0)
533 if (arrayNdx != NULL)
534 return ReportSINotArray(si, field, info);
535 ok = ExprResolveBoolean(value, &tmp);
539 si->interp.flags |= XkbSI_AutoRepeat;
541 si->interp.flags &= ~XkbSI_AutoRepeat;
542 si->defs.defined |= _SI_AutoRepeat;
545 return ReportSIBadType(si, field, "boolean", info);
547 else if (uStrCaseCmp(field, "locking") == 0)
549 if (arrayNdx != NULL)
550 return ReportSINotArray(si, field, info);
551 ok = ExprResolveBoolean(value, &tmp);
555 si->interp.flags |= XkbSI_LockingKey;
557 si->interp.flags &= ~XkbSI_LockingKey;
558 si->defs.defined |= _SI_LockingKey;
561 return ReportSIBadType(si, field, "boolean", info);
563 else if ((uStrCaseCmp(field, "usemodmap") == 0) ||
564 (uStrCaseCmp(field, "usemodmapmods") == 0))
566 if (arrayNdx != NULL)
567 return ReportSINotArray(si, field, info);
568 ok = ExprResolveEnum(value, &tmp, useModMapValues);
572 si->interp.match |= XkbSI_LevelOneOnly;
574 si->interp.match &= ~XkbSI_LevelOneOnly;
575 si->defs.defined |= _SI_LevelOneOnly;
578 return ReportSIBadType(si, field, "level specification", info);
582 ok = ReportBadField("symbol interpretation", field, siText(si, info));
588 HandleInterpVar(VarDef * stmt, struct xkb_desc * xkb, CompatInfo * info)
590 ExprResult elem, field;
594 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
595 ret = 0; /* internal error, already reported */
596 else if (elem.str && (uStrCaseCmp(elem.str, "interpret") == 0))
597 ret = SetInterpField(&info->dflt, xkb, field.str, ndx, stmt->value,
599 else if (elem.str && (uStrCaseCmp(elem.str, "indicator") == 0))
600 ret = SetIndicatorMapField(&info->ledDflt, xkb, field.str, ndx,
603 ret = SetActionField(xkb, elem.str, field.str, ndx, stmt->value,
611 HandleInterpBody(VarDef * def, struct xkb_desc * xkb, SymInterpInfo * si,
615 ExprResult tmp, field;
618 for (; def != NULL; def = (VarDef *) def->common.next)
620 if ((def->name) && (def->name->type == ExprFieldRef))
622 ok = HandleInterpVar(def, xkb, info);
625 ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx);
627 ok = SetInterpField(si, xkb, field.str, arrayNdx, def->value,
636 HandleInterpDef(InterpDef * def, struct xkb_desc * xkb, unsigned merge,
642 if (!ResolveStateAndPredicate(def->match, &pred, &mods, info))
644 ERROR("Couldn't determine matching modifiers\n");
645 ACTION("Symbol interpretation ignored\n");
648 if (def->merge != MergeDefault)
652 si.defs.merge = merge;
653 if (!LookupKeysym(def->sym, &si.interp.sym))
655 WARN("Could not resolve keysym %s\n", def->sym);
659 si.interp.match = pred & XkbSI_OpMask;
660 si.interp.mods = mods;
661 if (!HandleInterpBody(def->def, xkb, &si, info))
667 if (!AddInterp(info, &si))
676 HandleGroupCompatDef(GroupCompatDef * def,
677 struct xkb_desc * xkb, unsigned merge, CompatInfo * info)
682 if (def->merge != MergeDefault)
684 if (!XkbIsLegalGroup(def->group - 1))
686 ERROR("Keyboard group must be in the range 1..%d\n",
687 XkbNumKbdGroups + 1);
688 ACTION("Compatibility map for illegal group %d ignored\n",
692 tmp.fileID = info->fileID;
694 if (!ExprResolveVModMask(def->def, &val, xkb))
696 ERROR("Expected a modifier mask in group compatibility definition\n");
697 ACTION("Ignoring illegal compatibility map for group %d\n",
701 tmp.real_mods = val.uval & 0xff;
702 tmp.vmods = (val.uval >> 8) & 0xffff;
703 return AddGroupCompat(info, def->group - 1, &tmp);
707 HandleCompatMapFile(XkbFile * file,
708 struct xkb_desc * xkb, unsigned merge, CompatInfo * info)
712 if (merge == MergeDefault)
713 merge = MergeAugment;
715 info->name = _XkbDupString(file->name);
719 switch (stmt->stmtType)
722 if (!HandleIncludeCompatMap((IncludeStmt *) stmt, xkb, info,
723 HandleCompatMapFile))
727 if (!HandleInterpDef((InterpDef *) stmt, xkb, merge, info))
730 case StmtGroupCompatDef:
731 if (!HandleGroupCompatDef
732 ((GroupCompatDef *) stmt, xkb, merge, info))
735 case StmtIndicatorMapDef:
738 rtrn = HandleIndicatorMapDef((IndicatorMapDef *) stmt, xkb,
739 &info->ledDflt, info->leds, merge);
747 if (!HandleInterpVar((VarDef *) stmt, xkb, info))
751 if (!HandleVModDef((VModDef *) stmt, xkb, merge, &info->vmods))
755 ERROR("Interpretation files may not include other types\n");
756 ACTION("Ignoring definition of key name\n");
760 WSGO("Unexpected statement type %d in HandleCompatMapFile\n",
765 if (info->errorCount > 10)
768 ERROR("Too many errors\n");
770 ACTION("Abandoning compatibility map \"%s\"\n", file->topName);
777 CopyInterps(CompatInfo * info,
778 struct xkb_compat_map * compat, Bool needSymbol, unsigned pred)
782 for (si = info->interps; si; si = (SymInterpInfo *) si->defs.next)
784 if (((si->interp.match & XkbSI_OpMask) != pred) ||
785 (needSymbol && (si->interp.sym == NoSymbol)) ||
786 ((!needSymbol) && (si->interp.sym != NoSymbol)))
788 if (compat->num_si >= compat->size_si)
790 WSGO("No room to merge symbol interpretations\n");
791 ACTION("Symbol interpretations lost\n");
794 compat->sym_interpret[compat->num_si++] = si->interp;
799 CompileCompatMap(XkbFile *file, struct xkb_desc * xkb, unsigned merge,
800 LEDInfoPtr *unboundLEDs)
804 GroupCompatInfo *gcm;
806 InitCompatInfo(&info, xkb);
807 info.dflt.defs.merge = merge;
808 info.ledDflt.defs.merge = merge;
809 HandleCompatMapFile(file, xkb, merge, &info);
811 if (info.errorCount == 0)
814 if (XkbcAllocCompatMap(xkb, XkbAllCompatMask, info.nInterps) !=
817 WSGO("Couldn't allocate compatibility map\n");
820 size = info.nInterps * sizeof(struct xkb_sym_interpret);
823 CopyInterps(&info, xkb->compat, True, XkbSI_Exactly);
824 CopyInterps(&info, xkb->compat, True, XkbSI_AllOf | XkbSI_NoneOf);
825 CopyInterps(&info, xkb->compat, True, XkbSI_AnyOf);
826 CopyInterps(&info, xkb->compat, True, XkbSI_AnyOfOrNone);
827 CopyInterps(&info, xkb->compat, False, XkbSI_Exactly);
828 CopyInterps(&info, xkb->compat, False,
829 XkbSI_AllOf | XkbSI_NoneOf);
830 CopyInterps(&info, xkb->compat, False, XkbSI_AnyOf);
831 CopyInterps(&info, xkb->compat, False, XkbSI_AnyOfOrNone);
833 for (i = 0, gcm = &info.groupCompat[0]; i < XkbNumKbdGroups;
836 if ((gcm->fileID != 0) || (gcm->real_mods != 0)
837 || (gcm->vmods != 0))
839 xkb->compat->groups[i].mask = gcm->real_mods;
840 xkb->compat->groups[i].real_mods = gcm->real_mods;
841 xkb->compat->groups[i].vmods = gcm->vmods;
844 if (info.leds != NULL)
846 if (!CopyIndicatorMapDefs(xkb, info.leds, unboundLEDs))
850 ClearCompatInfo(&info, xkb);