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)
141 info->dflt.defs.defined = 0;
142 info->dflt.defs.merge = MergeAugment;
143 info->dflt.interp.flags = 0;
144 info->dflt.interp.virtual_mod = XkbNoModifier;
145 info->dflt.interp.act.type = XkbSA_NoAction;
146 for (i = 0; i < sizeof info->dflt.interp.act.data; i++)
148 info->dflt.interp.act.data[i] = 0;
150 ClearIndicatorMapInfo(&info->ledDflt);
152 info->interps = (SymInterpInfo *) ClearCommonInfo(&info->interps->defs);
153 memset(&info->groupCompat[0], 0,
154 XkbNumKbdGroups * sizeof(GroupCompatInfo));
155 info->leds = (LEDInfo *) ClearCommonInfo(&info->leds->defs);
156 /* 3/30/94 (ef) -- XXX! Should free action info here */
157 ClearVModInfo(&info->vmods, xkb);
160 static SymInterpInfo *
161 NextInterp(CompatInfo * info)
165 si = uTypedAlloc(SymInterpInfo);
168 memset(si, 0, sizeof(SymInterpInfo));
170 (SymInterpInfo *) AddCommonInfo(&info->interps->defs,
177 static SymInterpInfo *
178 FindMatchingInterp(CompatInfo * info, SymInterpInfo * new)
182 for (old = info->interps; old != NULL;
183 old = (SymInterpInfo *) old->defs.next)
185 if ((old->interp.sym == new->interp.sym) &&
186 (old->interp.mods == new->interp.mods) &&
187 (old->interp.match == new->interp.match))
196 AddInterp(CompatInfo * info, SymInterpInfo * new)
202 old = FindMatchingInterp(info, new);
205 if (new->defs.merge == MergeReplace)
207 SymInterpInfo *next = (SymInterpInfo *) old->defs.next;
208 if (((old->defs.fileID == new->defs.fileID)
209 && (warningLevel > 0)) || (warningLevel > 9))
211 WARN("Multiple definitions for \"%s\"\n", siText(new, info));
212 ACTION("Earlier interpretation ignored\n");
215 old->defs.next = &next->defs;
218 if (UseNewField(_SI_VirtualMod, &old->defs, &new->defs, &collide))
220 old->interp.virtual_mod = new->interp.virtual_mod;
221 old->defs.defined |= _SI_VirtualMod;
223 if (UseNewField(_SI_Action, &old->defs, &new->defs, &collide))
225 old->interp.act = new->interp.act;
226 old->defs.defined |= _SI_Action;
228 if (UseNewField(_SI_AutoRepeat, &old->defs, &new->defs, &collide))
230 old->interp.flags &= ~XkbSI_AutoRepeat;
231 old->interp.flags |= (new->interp.flags & XkbSI_AutoRepeat);
232 old->defs.defined |= _SI_AutoRepeat;
234 if (UseNewField(_SI_LockingKey, &old->defs, &new->defs, &collide))
236 old->interp.flags &= ~XkbSI_LockingKey;
237 old->interp.flags |= (new->interp.flags & XkbSI_LockingKey);
238 old->defs.defined |= _SI_LockingKey;
240 if (UseNewField(_SI_LevelOneOnly, &old->defs, &new->defs, &collide))
242 old->interp.match &= ~XkbSI_LevelOneOnly;
243 old->interp.match |= (new->interp.match & XkbSI_LevelOneOnly);
244 old->defs.defined |= _SI_LevelOneOnly;
248 WARN("Multiple interpretations of \"%s\"\n", siText(new, info));
249 ACTION("Using %s definition for duplicate fields\n",
250 (new->defs.merge != MergeAugment ? "last" : "first"));
255 if ((new = NextInterp(info)) == NULL)
258 new->defs.next = NULL;
263 AddGroupCompat(CompatInfo * info, unsigned group, GroupCompatInfo * newGC)
268 merge = newGC->merge;
269 gc = &info->groupCompat[group];
270 if (((gc->real_mods == newGC->real_mods) && (gc->vmods == newGC->vmods)))
274 if (((gc->fileID == newGC->fileID) && (warningLevel > 0))
275 || (warningLevel > 9))
277 WARN("Compat map for group %d redefined\n", group + 1);
278 ACTION("Using %s definition\n",
279 (merge == MergeAugment ? "old" : "new"));
281 if (merge != MergeAugment)
286 /***====================================================================***/
289 ResolveStateAndPredicate(ExprDef * expr,
291 unsigned *mods_rtrn, CompatInfo * info)
297 *pred_rtrn = XkbSI_AnyOfOrNone;
302 *pred_rtrn = XkbSI_Exactly;
303 if (expr->op == ExprActionDecl)
305 const char *pred_txt = XkbcAtomText(expr->value.action.name);
306 if (uStrCaseCmp(pred_txt, "noneof") == 0)
307 *pred_rtrn = XkbSI_NoneOf;
308 else if (uStrCaseCmp(pred_txt, "anyofornone") == 0)
309 *pred_rtrn = XkbSI_AnyOfOrNone;
310 else if (uStrCaseCmp(pred_txt, "anyof") == 0)
311 *pred_rtrn = XkbSI_AnyOf;
312 else if (uStrCaseCmp(pred_txt, "allof") == 0)
313 *pred_rtrn = XkbSI_AllOf;
314 else if (uStrCaseCmp(pred_txt, "exactly") == 0)
315 *pred_rtrn = XkbSI_Exactly;
318 ERROR("Illegal modifier predicate \"%s\"\n", pred_txt);
322 expr = expr->value.action.args;
324 else if (expr->op == ExprIdent)
326 const char *pred_txt = XkbcAtomText(expr->value.str);
327 if ((pred_txt) && (uStrCaseCmp(pred_txt, "any") == 0))
329 *pred_rtrn = XkbSI_AnyOf;
335 if (ExprResolveModMask(expr, &result))
337 *mods_rtrn = result.uval;
343 /***====================================================================***/
346 MergeIncludedCompatMaps(CompatInfo * into, CompatInfo * from, unsigned merge)
349 LEDInfo *led, *rtrn, *next;
350 GroupCompatInfo *gcm;
353 if (from->errorCount > 0)
355 into->errorCount += from->errorCount;
358 if (into->name == NULL)
360 into->name = from->name;
363 for (si = from->interps; si; si = (SymInterpInfo *) si->defs.next)
365 if (merge != MergeDefault)
366 si->defs.merge = merge;
367 if (!AddInterp(into, si))
370 for (i = 0, gcm = &from->groupCompat[0]; i < XkbNumKbdGroups; i++, gcm++)
372 if (merge != MergeDefault)
374 if (!AddGroupCompat(into, i, gcm))
377 for (led = from->leds; led != NULL; led = next)
379 next = (LEDInfo *) led->defs.next;
380 if (merge != MergeDefault)
381 led->defs.merge = merge;
382 rtrn = AddIndicatorMap(into->leds, led);
390 typedef void (*FileHandler) (XkbFile * /* rtrn */ ,
391 struct xkb_desc * /* xkb */ ,
392 unsigned /* merge */ ,
393 CompatInfo * /* info */
397 HandleIncludeCompatMap(IncludeStmt * stmt,
398 struct xkb_desc * xkb, CompatInfo * info, FileHandler hndlr)
406 if ((stmt->file == NULL) && (stmt->map == NULL))
410 memset(info, 0, sizeof(CompatInfo));
412 else if (ProcessIncludeFile(stmt, XkmCompatMapIndex, &rtrn, &newMerge))
414 InitCompatInfo(&included, xkb);
415 included.fileID = rtrn->id;
416 included.dflt = info->dflt;
417 included.dflt.defs.fileID = rtrn->id;
418 included.dflt.defs.merge = newMerge;
419 included.ledDflt.defs.fileID = rtrn->id;
420 included.ledDflt.defs.merge = newMerge;
421 included.act = info->act;
422 (*hndlr) (rtrn, xkb, MergeOverride, &included);
423 if (stmt->stmt != NULL)
426 included.name = stmt->stmt;
433 info->errorCount += 10;
436 if ((stmt->next != NULL) && (included.errorCount < 1))
440 CompatInfo next_incl;
442 for (next = stmt->next; next != NULL; next = next->next)
444 if ((next->file == NULL) && (next->map == NULL))
447 MergeIncludedCompatMaps(&included, info, next->merge);
448 ClearCompatInfo(info, xkb);
450 else if (ProcessIncludeFile(next, XkmCompatMapIndex, &rtrn, &op))
452 InitCompatInfo(&next_incl, xkb);
453 next_incl.fileID = rtrn->id;
454 next_incl.dflt = info->dflt;
455 next_incl.dflt.defs.fileID = rtrn->id;
456 next_incl.dflt.defs.merge = op;
457 next_incl.ledDflt.defs.fileID = rtrn->id;
458 next_incl.ledDflt.defs.merge = op;
459 next_incl.act = info->act;
460 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
461 MergeIncludedCompatMaps(&included, &next_incl, op);
462 ClearCompatInfo(&next_incl, xkb);
467 info->errorCount += 10;
476 MergeIncludedCompatMaps(info, &included, newMerge);
477 ClearCompatInfo(&included, xkb);
479 return (info->errorCount == 0);
482 static const LookupEntry useModMapValues[] = {
491 SetInterpField(SymInterpInfo * si,
492 struct xkb_desc * xkb,
494 ExprDef * arrayNdx, ExprDef * value, CompatInfo * info)
499 if (uStrCaseCmp(field, "action") == 0)
501 if (arrayNdx != NULL)
502 return ReportSINotArray(si, field, info);
503 ok = HandleActionDef(value, xkb, &si->interp.act, si->defs.merge,
506 si->defs.defined |= _SI_Action;
508 else if ((uStrCaseCmp(field, "virtualmodifier") == 0) ||
509 (uStrCaseCmp(field, "virtualmod") == 0))
511 if (arrayNdx != NULL)
512 return ReportSINotArray(si, field, info);
513 ok = ResolveVirtualModifier(value, xkb, &tmp, &info->vmods);
516 si->interp.virtual_mod = tmp.uval;
517 si->defs.defined |= _SI_VirtualMod;
520 return ReportSIBadType(si, field, "virtual modifier", info);
522 else if (uStrCaseCmp(field, "repeat") == 0)
524 if (arrayNdx != NULL)
525 return ReportSINotArray(si, field, info);
526 ok = ExprResolveBoolean(value, &tmp);
530 si->interp.flags |= XkbSI_AutoRepeat;
532 si->interp.flags &= ~XkbSI_AutoRepeat;
533 si->defs.defined |= _SI_AutoRepeat;
536 return ReportSIBadType(si, field, "boolean", info);
538 else if (uStrCaseCmp(field, "locking") == 0)
540 if (arrayNdx != NULL)
541 return ReportSINotArray(si, field, info);
542 ok = ExprResolveBoolean(value, &tmp);
546 si->interp.flags |= XkbSI_LockingKey;
548 si->interp.flags &= ~XkbSI_LockingKey;
549 si->defs.defined |= _SI_LockingKey;
552 return ReportSIBadType(si, field, "boolean", info);
554 else if ((uStrCaseCmp(field, "usemodmap") == 0) ||
555 (uStrCaseCmp(field, "usemodmapmods") == 0))
557 if (arrayNdx != NULL)
558 return ReportSINotArray(si, field, info);
559 ok = ExprResolveEnum(value, &tmp, useModMapValues);
563 si->interp.match |= XkbSI_LevelOneOnly;
565 si->interp.match &= ~XkbSI_LevelOneOnly;
566 si->defs.defined |= _SI_LevelOneOnly;
569 return ReportSIBadType(si, field, "level specification", info);
573 ok = ReportBadField("symbol interpretation", field, siText(si, info));
579 HandleInterpVar(VarDef * stmt, struct xkb_desc * xkb, CompatInfo * info)
581 ExprResult elem, field;
585 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
586 ret = 0; /* internal error, already reported */
587 else if (elem.str && (uStrCaseCmp(elem.str, "interpret") == 0))
588 ret = SetInterpField(&info->dflt, xkb, field.str, ndx, stmt->value,
590 else if (elem.str && (uStrCaseCmp(elem.str, "indicator") == 0))
591 ret = SetIndicatorMapField(&info->ledDflt, xkb, field.str, ndx,
594 ret = SetActionField(xkb, elem.str, field.str, ndx, stmt->value,
602 HandleInterpBody(VarDef * def, struct xkb_desc * xkb, SymInterpInfo * si,
606 ExprResult tmp, field;
609 for (; def != NULL; def = (VarDef *) def->common.next)
611 if ((def->name) && (def->name->type == ExprFieldRef))
613 ok = HandleInterpVar(def, xkb, info);
616 ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx);
618 ok = SetInterpField(si, xkb, field.str, arrayNdx, def->value,
627 HandleInterpDef(InterpDef * def, struct xkb_desc * xkb, unsigned merge,
633 if (!ResolveStateAndPredicate(def->match, &pred, &mods, info))
635 ERROR("Couldn't determine matching modifiers\n");
636 ACTION("Symbol interpretation ignored\n");
639 if (def->merge != MergeDefault)
643 si.defs.merge = merge;
644 if (!LookupKeysym(def->sym, &si.interp.sym))
646 WARN("Could not resolve keysym %s\n", def->sym);
650 si.interp.match = pred & XkbSI_OpMask;
651 si.interp.mods = mods;
652 if (!HandleInterpBody(def->def, xkb, &si, info))
658 if (!AddInterp(info, &si))
667 HandleGroupCompatDef(GroupCompatDef * def,
668 struct xkb_desc * xkb, unsigned merge, CompatInfo * info)
673 if (def->merge != MergeDefault)
675 if (!XkbIsLegalGroup(def->group - 1))
677 ERROR("Keyboard group must be in the range 1..%d\n",
678 XkbNumKbdGroups + 1);
679 ACTION("Compatibility map for illegal group %d ignored\n",
683 tmp.fileID = info->fileID;
685 if (!ExprResolveVModMask(def->def, &val, xkb))
687 ERROR("Expected a modifier mask in group compatibility definition\n");
688 ACTION("Ignoring illegal compatibility map for group %d\n",
692 tmp.real_mods = val.uval & 0xff;
693 tmp.vmods = (val.uval >> 8) & 0xffff;
694 return AddGroupCompat(info, def->group - 1, &tmp);
698 HandleCompatMapFile(XkbFile * file,
699 struct xkb_desc * xkb, unsigned merge, CompatInfo * info)
703 if (merge == MergeDefault)
704 merge = MergeAugment;
705 info->name = _XkbDupString(file->name);
709 switch (stmt->stmtType)
712 if (!HandleIncludeCompatMap((IncludeStmt *) stmt, xkb, info,
713 HandleCompatMapFile))
717 if (!HandleInterpDef((InterpDef *) stmt, xkb, merge, info))
720 case StmtGroupCompatDef:
721 if (!HandleGroupCompatDef
722 ((GroupCompatDef *) stmt, xkb, merge, info))
725 case StmtIndicatorMapDef:
728 rtrn = HandleIndicatorMapDef((IndicatorMapDef *) stmt, xkb,
729 &info->ledDflt, info->leds, merge);
737 if (!HandleInterpVar((VarDef *) stmt, xkb, info))
741 if (!HandleVModDef((VModDef *) stmt, xkb, merge, &info->vmods))
745 ERROR("Interpretation files may not include other types\n");
746 ACTION("Ignoring definition of key name\n");
750 WSGO("Unexpected statement type %d in HandleCompatMapFile\n",
755 if (info->errorCount > 10)
758 ERROR("Too many errors\n");
760 ACTION("Abandoning compatibility map \"%s\"\n", file->topName);
767 CopyInterps(CompatInfo * info,
768 struct xkb_compat_map * compat, Bool needSymbol, unsigned pred)
772 for (si = info->interps; si; si = (SymInterpInfo *) si->defs.next)
774 if (((si->interp.match & XkbSI_OpMask) != pred) ||
775 (needSymbol && (si->interp.sym == NoSymbol)) ||
776 ((!needSymbol) && (si->interp.sym != NoSymbol)))
778 if (compat->num_si >= compat->size_si)
780 WSGO("No room to merge symbol interpretations\n");
781 ACTION("Symbol interpretations lost\n");
784 compat->sym_interpret[compat->num_si++] = si->interp;
789 CompileCompatMap(XkbFile *file, struct xkb_desc * xkb, unsigned merge,
790 LEDInfoPtr *unboundLEDs)
794 GroupCompatInfo *gcm;
796 InitCompatInfo(&info, xkb);
797 info.dflt.defs.merge = merge;
798 info.ledDflt.defs.merge = merge;
799 HandleCompatMapFile(file, xkb, merge, &info);
801 if (info.errorCount == 0)
804 if (XkbcAllocCompatMap(xkb, XkbAllCompatMask, info.nInterps) !=
807 WSGO("Couldn't allocate compatibility map\n");
810 if (info.name != NULL)
812 if (XkbcAllocNames(xkb, XkbCompatNameMask, 0, 0) == Success)
814 xkb_intern_atom(info.name);
817 WSGO("Couldn't allocate space for compat name\n");
818 ACTION("Name \"%s\" (from %s) NOT assigned\n",
819 scanFile, info.name);
822 size = info.nInterps * sizeof(struct xkb_sym_interpret);
825 CopyInterps(&info, xkb->compat, True, XkbSI_Exactly);
826 CopyInterps(&info, xkb->compat, True, XkbSI_AllOf | XkbSI_NoneOf);
827 CopyInterps(&info, xkb->compat, True, XkbSI_AnyOf);
828 CopyInterps(&info, xkb->compat, True, XkbSI_AnyOfOrNone);
829 CopyInterps(&info, xkb->compat, False, XkbSI_Exactly);
830 CopyInterps(&info, xkb->compat, False,
831 XkbSI_AllOf | XkbSI_NoneOf);
832 CopyInterps(&info, xkb->compat, False, XkbSI_AnyOf);
833 CopyInterps(&info, xkb->compat, False, XkbSI_AnyOfOrNone);
835 for (i = 0, gcm = &info.groupCompat[0]; i < XkbNumKbdGroups;
838 if ((gcm->fileID != 0) || (gcm->real_mods != 0)
839 || (gcm->vmods != 0))
841 xkb->compat->groups[i].mask = gcm->real_mods;
842 xkb->compat->groups[i].real_mods = gcm->real_mods;
843 xkb->compat->groups[i].vmods = gcm->vmods;
846 if (info.leds != NULL)
848 if (!CopyIndicatorMapDefs(xkb, info.leds, unboundLEDs))
852 ClearCompatInfo(&info, xkb);