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 ********************************************************/
35 #include "indicators.h"
38 #include "parseutils.h"
40 typedef struct _SymInterpInfo
43 struct xkb_sym_interpret interp;
46 #define _SI_VirtualMod (1<<0)
47 #define _SI_Action (1<<1)
48 #define _SI_AutoRepeat (1<<2)
49 #define _SI_LockingKey (1<<3)
50 #define _SI_LevelOneOnly (1<<4)
52 typedef struct _GroupCompatInfo
56 unsigned char real_mods;
60 typedef struct _CompatInfo
66 SymInterpInfo *interps;
69 GroupCompatInfo groupCompat[XkbNumKbdGroups];
73 struct xkb_desc * xkb;
76 /***====================================================================***/
78 #define ReportSINotArray(si,f,i) \
79 ReportNotArray("symbol interpretation",(f),siText((si),(i)))
80 #define ReportSIBadType(si,f,w,i) \
81 ReportBadType("symbol interpretation",(f),siText((si),(i)),(w))
83 /***====================================================================***/
86 siText(SymInterpInfo * si, CompatInfo * info)
90 if (si == &info->dflt)
92 snprintf(buf, sizeof(buf), "default");
96 snprintf(buf, sizeof(buf), "%s+%s(%s)",
97 XkbcKeysymText(si->interp.sym),
98 XkbcSIMatchText(si->interp.match),
99 XkbcModMaskText(si->interp.mods, False));
105 InitCompatInfo(CompatInfo * info, struct xkb_desc * xkb)
112 info->errorCount = 0;
114 info->interps = NULL;
116 info->dflt.defs.fileID = info->fileID;
117 info->dflt.defs.defined = 0;
118 info->dflt.defs.merge = MergeOverride;
119 info->dflt.interp.flags = 0;
120 info->dflt.interp.virtual_mod = XkbNoModifier;
121 info->dflt.interp.act.type = XkbSA_NoAction;
122 for (i = 0; i < sizeof info->dflt.interp.act.data; i++)
124 info->dflt.interp.act.data[i] = 0;
126 ClearIndicatorMapInfo(&info->ledDflt);
127 info->ledDflt.defs.fileID = info->fileID;
128 info->ledDflt.defs.defined = 0;
129 info->ledDflt.defs.merge = MergeOverride;
130 bzero((char *) &info->groupCompat[0],
131 XkbNumKbdGroups * sizeof(GroupCompatInfo));
133 InitVModInfo(&info->vmods, xkb);
138 ClearCompatInfo(CompatInfo * info, struct xkb_desc * xkb)
142 if (info->name != NULL)
145 info->dflt.defs.defined = 0;
146 info->dflt.defs.merge = MergeAugment;
147 info->dflt.interp.flags = 0;
148 info->dflt.interp.virtual_mod = XkbNoModifier;
149 info->dflt.interp.act.type = XkbSA_NoAction;
150 for (i = 0; i < sizeof info->dflt.interp.act.data; i++)
152 info->dflt.interp.act.data[i] = 0;
154 ClearIndicatorMapInfo(&info->ledDflt);
156 info->interps = (SymInterpInfo *) ClearCommonInfo(&info->interps->defs);
157 bzero((char *) &info->groupCompat[0],
158 XkbNumKbdGroups * sizeof(GroupCompatInfo));
159 info->leds = (LEDInfo *) ClearCommonInfo(&info->leds->defs);
160 /* 3/30/94 (ef) -- XXX! Should free action info here */
161 ClearVModInfo(&info->vmods, xkb);
165 static SymInterpInfo *
166 NextInterp(CompatInfo * info)
170 si = uTypedAlloc(SymInterpInfo);
173 bzero((char *) si, 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);
396 typedef void (*FileHandler) (XkbFile * /* rtrn */ ,
397 struct xkb_desc * /* xkb */ ,
398 unsigned /* merge */ ,
399 CompatInfo * /* info */
403 HandleIncludeCompatMap(IncludeStmt * stmt,
404 struct xkb_desc * xkb, CompatInfo * info, FileHandler hndlr)
412 if ((stmt->file == NULL) && (stmt->map == NULL))
416 bzero(info, sizeof(CompatInfo));
418 else if (ProcessIncludeFile(stmt, XkmCompatMapIndex, &rtrn, &newMerge))
420 InitCompatInfo(&included, xkb);
421 included.fileID = rtrn->id;
422 included.dflt = info->dflt;
423 included.dflt.defs.fileID = rtrn->id;
424 included.dflt.defs.merge = newMerge;
425 included.ledDflt.defs.fileID = rtrn->id;
426 included.ledDflt.defs.merge = newMerge;
427 included.act = info->act;
428 (*hndlr) (rtrn, xkb, MergeOverride, &included);
429 if (stmt->stmt != NULL)
431 if (included.name != NULL)
433 included.name = stmt->stmt;
439 info->errorCount += 10;
442 if ((stmt->next != NULL) && (included.errorCount < 1))
446 CompatInfo next_incl;
448 for (next = stmt->next; next != NULL; next = next->next)
450 if ((next->file == NULL) && (next->map == NULL))
453 MergeIncludedCompatMaps(&included, info, next->merge);
454 ClearCompatInfo(info, xkb);
456 else if (ProcessIncludeFile(next, XkmCompatMapIndex, &rtrn, &op))
458 InitCompatInfo(&next_incl, xkb);
459 next_incl.fileID = rtrn->id;
460 next_incl.dflt = info->dflt;
461 next_incl.dflt.defs.fileID = rtrn->id;
462 next_incl.dflt.defs.merge = op;
463 next_incl.ledDflt.defs.fileID = rtrn->id;
464 next_incl.ledDflt.defs.merge = op;
465 next_incl.act = info->act;
466 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
467 MergeIncludedCompatMaps(&included, &next_incl, op);
468 ClearCompatInfo(&next_incl, xkb);
472 info->errorCount += 10;
481 MergeIncludedCompatMaps(info, &included, newMerge);
482 ClearCompatInfo(&included, xkb);
484 return (info->errorCount == 0);
487 static LookupEntry useModMapValues[] = {
496 SetInterpField(SymInterpInfo * si,
497 struct xkb_desc * xkb,
499 ExprDef * arrayNdx, ExprDef * value, CompatInfo * info)
504 if (uStrCaseCmp(field, "action") == 0)
506 if (arrayNdx != NULL)
507 return ReportSINotArray(si, field, info);
508 ok = HandleActionDef(value, xkb, &si->interp.act, si->defs.merge,
511 si->defs.defined |= _SI_Action;
513 else if ((uStrCaseCmp(field, "virtualmodifier") == 0) ||
514 (uStrCaseCmp(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 (uStrCaseCmp(field, "repeat") == 0)
529 if (arrayNdx != NULL)
530 return ReportSINotArray(si, field, info);
531 ok = ExprResolveBoolean(value, &tmp, NULL, NULL);
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 (uStrCaseCmp(field, "locking") == 0)
545 if (arrayNdx != NULL)
546 return ReportSINotArray(si, field, info);
547 ok = ExprResolveBoolean(value, &tmp, NULL, NULL);
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 ((uStrCaseCmp(field, "usemodmap") == 0) ||
560 (uStrCaseCmp(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));
583 LookupEntry groupNames[] = {
608 HandleInterpVar(VarDef * stmt, struct xkb_desc * xkb, CompatInfo * info)
610 ExprResult elem, field;
614 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
615 ret = 0; /* internal error, already reported */
616 else if (elem.str && (uStrCaseCmp(elem.str, "interpret") == 0))
617 ret = SetInterpField(&info->dflt, xkb, field.str, ndx, stmt->value,
619 else if (elem.str && (uStrCaseCmp(elem.str, "indicator") == 0))
620 ret = SetIndicatorMapField(&info->ledDflt, xkb, field.str, ndx,
623 ret = SetActionField(xkb, elem.str, field.str, ndx, stmt->value,
631 HandleInterpBody(VarDef * def, struct xkb_desc * xkb, SymInterpInfo * si,
635 ExprResult tmp, field;
638 for (; def != NULL; def = (VarDef *) def->common.next)
640 if ((def->name) && (def->name->type == ExprFieldRef))
642 ok = HandleInterpVar(def, xkb, info);
645 ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx);
647 ok = SetInterpField(si, xkb, field.str, arrayNdx, def->value,
656 HandleInterpDef(InterpDef * def, struct xkb_desc * xkb, unsigned merge,
662 if (!ResolveStateAndPredicate(def->match, &pred, &mods, info))
664 ERROR("Couldn't determine matching modifiers\n");
665 ACTION("Symbol interpretation ignored\n");
668 if (def->merge != MergeDefault)
672 si.defs.merge = merge;
673 if (!LookupKeysym(def->sym, &si.interp.sym))
675 WARN("Could not resolve keysym %s\n", def->sym);
679 si.interp.match = pred & XkbSI_OpMask;
680 si.interp.mods = mods;
681 if (!HandleInterpBody(def->def, xkb, &si, info))
687 if (!AddInterp(info, &si))
696 HandleGroupCompatDef(GroupCompatDef * def,
697 struct xkb_desc * xkb, unsigned merge, CompatInfo * info)
702 if (def->merge != MergeDefault)
704 if (!XkbIsLegalGroup(def->group - 1))
706 ERROR("Keyboard group must be in the range 1..%d\n",
707 XkbNumKbdGroups + 1);
708 ACTION("Compatibility map for illegal group %d ignored\n",
712 tmp.fileID = info->fileID;
714 if (!ExprResolveVModMask(def->def, &val, xkb))
716 ERROR("Expected a modifier mask in group compatibility definition\n");
717 ACTION("Ignoring illegal compatibility map for group %d\n",
721 tmp.real_mods = val.uval & 0xff;
722 tmp.vmods = (val.uval >> 8) & 0xffff;
723 return AddGroupCompat(info, def->group - 1, &tmp);
727 HandleCompatMapFile(XkbFile * file,
728 struct xkb_desc * xkb, unsigned merge, CompatInfo * info)
732 if (merge == MergeDefault)
733 merge = MergeAugment;
734 info->name = _XkbDupString(file->name);
738 switch (stmt->stmtType)
741 if (!HandleIncludeCompatMap((IncludeStmt *) stmt, xkb, info,
742 HandleCompatMapFile))
746 if (!HandleInterpDef((InterpDef *) stmt, xkb, merge, info))
749 case StmtGroupCompatDef:
750 if (!HandleGroupCompatDef
751 ((GroupCompatDef *) stmt, xkb, merge, info))
754 case StmtIndicatorMapDef:
757 rtrn = HandleIndicatorMapDef((IndicatorMapDef *) stmt, xkb,
758 &info->ledDflt, info->leds, merge);
766 if (!HandleInterpVar((VarDef *) stmt, xkb, info))
770 if (!HandleVModDef((VModDef *) stmt, xkb, merge, &info->vmods))
774 ERROR("Interpretation files may not include other types\n");
775 ACTION("Ignoring definition of key name\n");
779 WSGO("Unexpected statement type %d in HandleCompatMapFile\n",
784 if (info->errorCount > 10)
787 ERROR("Too many errors\n");
789 ACTION("Abandoning compatibility map \"%s\"\n", file->topName);
797 CopyInterps(CompatInfo * info,
798 struct xkb_compat_map * compat, Bool needSymbol, unsigned pred)
802 for (si = info->interps; si; si = (SymInterpInfo *) si->defs.next)
804 if (((si->interp.match & XkbSI_OpMask) != pred) ||
805 (needSymbol && (si->interp.sym == NoSymbol)) ||
806 ((!needSymbol) && (si->interp.sym != NoSymbol)))
808 if (compat->num_si >= compat->size_si)
810 WSGO("No room to merge symbol interpretations\n");
811 ACTION("Symbol interpretations lost\n");
814 compat->sym_interpret[compat->num_si++] = si->interp;
820 CompileCompatMap(XkbFile *file, struct xkb_desc * xkb, unsigned merge,
821 LEDInfoPtr *unboundLEDs)
825 GroupCompatInfo *gcm;
827 InitCompatInfo(&info, xkb);
828 info.dflt.defs.merge = merge;
829 info.ledDflt.defs.merge = merge;
830 HandleCompatMapFile(file, xkb, merge, &info);
832 if (info.errorCount == 0)
835 if (XkbcAllocCompatMap(xkb, XkbAllCompatMask, info.nInterps) !=
838 WSGO("Couldn't allocate compatibility map\n");
841 if (info.name != NULL)
843 if (XkbcAllocNames(xkb, XkbCompatNameMask, 0, 0) == Success)
845 xkb_intern_atom(info.name);
848 WSGO("Couldn't allocate space for compat name\n");
849 ACTION("Name \"%s\" (from %s) NOT assigned\n",
850 scanFile, info.name);
853 size = info.nInterps * sizeof(struct xkb_sym_interpret);
856 CopyInterps(&info, xkb->compat, True, XkbSI_Exactly);
857 CopyInterps(&info, xkb->compat, True, XkbSI_AllOf | XkbSI_NoneOf);
858 CopyInterps(&info, xkb->compat, True, XkbSI_AnyOf);
859 CopyInterps(&info, xkb->compat, True, XkbSI_AnyOfOrNone);
860 CopyInterps(&info, xkb->compat, False, XkbSI_Exactly);
861 CopyInterps(&info, xkb->compat, False,
862 XkbSI_AllOf | XkbSI_NoneOf);
863 CopyInterps(&info, xkb->compat, False, XkbSI_AnyOf);
864 CopyInterps(&info, xkb->compat, False, XkbSI_AnyOfOrNone);
866 for (i = 0, gcm = &info.groupCompat[0]; i < XkbNumKbdGroups;
869 if ((gcm->fileID != 0) || (gcm->real_mods != 0)
870 || (gcm->vmods != 0))
872 xkb->compat->groups[i].mask = gcm->real_mods;
873 xkb->compat->groups[i].real_mods = gcm->real_mods;
874 xkb->compat->groups[i].vmods = gcm->vmods;
877 if (info.leds != NULL)
879 if (!CopyIndicatorMapDefs(xkb, info.leds, unboundLEDs))
883 ClearCompatInfo(&info, xkb);
886 if (info.interps != NULL)