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;
432 info->errorCount += 10;
435 if ((stmt->next != NULL) && (included.errorCount < 1))
439 CompatInfo next_incl;
441 for (next = stmt->next; next != NULL; next = next->next)
443 if ((next->file == NULL) && (next->map == NULL))
446 MergeIncludedCompatMaps(&included, info, next->merge);
447 ClearCompatInfo(info, xkb);
449 else if (ProcessIncludeFile(next, XkmCompatMapIndex, &rtrn, &op))
451 InitCompatInfo(&next_incl, xkb);
452 next_incl.fileID = rtrn->id;
453 next_incl.dflt = info->dflt;
454 next_incl.dflt.defs.fileID = rtrn->id;
455 next_incl.dflt.defs.merge = op;
456 next_incl.ledDflt.defs.fileID = rtrn->id;
457 next_incl.ledDflt.defs.merge = op;
458 next_incl.act = info->act;
459 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
460 MergeIncludedCompatMaps(&included, &next_incl, op);
461 ClearCompatInfo(&next_incl, xkb);
465 info->errorCount += 10;
474 MergeIncludedCompatMaps(info, &included, newMerge);
475 ClearCompatInfo(&included, xkb);
477 return (info->errorCount == 0);
480 static const LookupEntry useModMapValues[] = {
489 SetInterpField(SymInterpInfo * si,
490 struct xkb_desc * xkb,
492 ExprDef * arrayNdx, ExprDef * value, CompatInfo * info)
497 if (uStrCaseCmp(field, "action") == 0)
499 if (arrayNdx != NULL)
500 return ReportSINotArray(si, field, info);
501 ok = HandleActionDef(value, xkb, &si->interp.act, si->defs.merge,
504 si->defs.defined |= _SI_Action;
506 else if ((uStrCaseCmp(field, "virtualmodifier") == 0) ||
507 (uStrCaseCmp(field, "virtualmod") == 0))
509 if (arrayNdx != NULL)
510 return ReportSINotArray(si, field, info);
511 ok = ResolveVirtualModifier(value, xkb, &tmp, &info->vmods);
514 si->interp.virtual_mod = tmp.uval;
515 si->defs.defined |= _SI_VirtualMod;
518 return ReportSIBadType(si, field, "virtual modifier", info);
520 else if (uStrCaseCmp(field, "repeat") == 0)
522 if (arrayNdx != NULL)
523 return ReportSINotArray(si, field, info);
524 ok = ExprResolveBoolean(value, &tmp);
528 si->interp.flags |= XkbSI_AutoRepeat;
530 si->interp.flags &= ~XkbSI_AutoRepeat;
531 si->defs.defined |= _SI_AutoRepeat;
534 return ReportSIBadType(si, field, "boolean", info);
536 else if (uStrCaseCmp(field, "locking") == 0)
538 if (arrayNdx != NULL)
539 return ReportSINotArray(si, field, info);
540 ok = ExprResolveBoolean(value, &tmp);
544 si->interp.flags |= XkbSI_LockingKey;
546 si->interp.flags &= ~XkbSI_LockingKey;
547 si->defs.defined |= _SI_LockingKey;
550 return ReportSIBadType(si, field, "boolean", info);
552 else if ((uStrCaseCmp(field, "usemodmap") == 0) ||
553 (uStrCaseCmp(field, "usemodmapmods") == 0))
555 if (arrayNdx != NULL)
556 return ReportSINotArray(si, field, info);
557 ok = ExprResolveEnum(value, &tmp, useModMapValues);
561 si->interp.match |= XkbSI_LevelOneOnly;
563 si->interp.match &= ~XkbSI_LevelOneOnly;
564 si->defs.defined |= _SI_LevelOneOnly;
567 return ReportSIBadType(si, field, "level specification", info);
571 ok = ReportBadField("symbol interpretation", field, siText(si, info));
577 HandleInterpVar(VarDef * stmt, struct xkb_desc * xkb, CompatInfo * info)
579 ExprResult elem, field;
583 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
584 ret = 0; /* internal error, already reported */
585 else if (elem.str && (uStrCaseCmp(elem.str, "interpret") == 0))
586 ret = SetInterpField(&info->dflt, xkb, field.str, ndx, stmt->value,
588 else if (elem.str && (uStrCaseCmp(elem.str, "indicator") == 0))
589 ret = SetIndicatorMapField(&info->ledDflt, xkb, field.str, ndx,
592 ret = SetActionField(xkb, elem.str, field.str, ndx, stmt->value,
600 HandleInterpBody(VarDef * def, struct xkb_desc * xkb, SymInterpInfo * si,
604 ExprResult tmp, field;
607 for (; def != NULL; def = (VarDef *) def->common.next)
609 if ((def->name) && (def->name->type == ExprFieldRef))
611 ok = HandleInterpVar(def, xkb, info);
614 ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx);
616 ok = SetInterpField(si, xkb, field.str, arrayNdx, def->value,
625 HandleInterpDef(InterpDef * def, struct xkb_desc * xkb, unsigned merge,
631 if (!ResolveStateAndPredicate(def->match, &pred, &mods, info))
633 ERROR("Couldn't determine matching modifiers\n");
634 ACTION("Symbol interpretation ignored\n");
637 if (def->merge != MergeDefault)
641 si.defs.merge = merge;
642 if (!LookupKeysym(def->sym, &si.interp.sym))
644 WARN("Could not resolve keysym %s\n", def->sym);
648 si.interp.match = pred & XkbSI_OpMask;
649 si.interp.mods = mods;
650 if (!HandleInterpBody(def->def, xkb, &si, info))
656 if (!AddInterp(info, &si))
665 HandleGroupCompatDef(GroupCompatDef * def,
666 struct xkb_desc * xkb, unsigned merge, CompatInfo * info)
671 if (def->merge != MergeDefault)
673 if (!XkbIsLegalGroup(def->group - 1))
675 ERROR("Keyboard group must be in the range 1..%d\n",
676 XkbNumKbdGroups + 1);
677 ACTION("Compatibility map for illegal group %d ignored\n",
681 tmp.fileID = info->fileID;
683 if (!ExprResolveVModMask(def->def, &val, xkb))
685 ERROR("Expected a modifier mask in group compatibility definition\n");
686 ACTION("Ignoring illegal compatibility map for group %d\n",
690 tmp.real_mods = val.uval & 0xff;
691 tmp.vmods = (val.uval >> 8) & 0xffff;
692 return AddGroupCompat(info, def->group - 1, &tmp);
696 HandleCompatMapFile(XkbFile * file,
697 struct xkb_desc * xkb, unsigned merge, CompatInfo * info)
701 if (merge == MergeDefault)
702 merge = MergeAugment;
703 info->name = _XkbDupString(file->name);
707 switch (stmt->stmtType)
710 if (!HandleIncludeCompatMap((IncludeStmt *) stmt, xkb, info,
711 HandleCompatMapFile))
715 if (!HandleInterpDef((InterpDef *) stmt, xkb, merge, info))
718 case StmtGroupCompatDef:
719 if (!HandleGroupCompatDef
720 ((GroupCompatDef *) stmt, xkb, merge, info))
723 case StmtIndicatorMapDef:
726 rtrn = HandleIndicatorMapDef((IndicatorMapDef *) stmt, xkb,
727 &info->ledDflt, info->leds, merge);
735 if (!HandleInterpVar((VarDef *) stmt, xkb, info))
739 if (!HandleVModDef((VModDef *) stmt, xkb, merge, &info->vmods))
743 ERROR("Interpretation files may not include other types\n");
744 ACTION("Ignoring definition of key name\n");
748 WSGO("Unexpected statement type %d in HandleCompatMapFile\n",
753 if (info->errorCount > 10)
756 ERROR("Too many errors\n");
758 ACTION("Abandoning compatibility map \"%s\"\n", file->topName);
765 CopyInterps(CompatInfo * info,
766 struct xkb_compat_map * compat, Bool needSymbol, unsigned pred)
770 for (si = info->interps; si; si = (SymInterpInfo *) si->defs.next)
772 if (((si->interp.match & XkbSI_OpMask) != pred) ||
773 (needSymbol && (si->interp.sym == NoSymbol)) ||
774 ((!needSymbol) && (si->interp.sym != NoSymbol)))
776 if (compat->num_si >= compat->size_si)
778 WSGO("No room to merge symbol interpretations\n");
779 ACTION("Symbol interpretations lost\n");
782 compat->sym_interpret[compat->num_si++] = si->interp;
787 CompileCompatMap(XkbFile *file, struct xkb_desc * xkb, unsigned merge,
788 LEDInfoPtr *unboundLEDs)
792 GroupCompatInfo *gcm;
794 InitCompatInfo(&info, xkb);
795 info.dflt.defs.merge = merge;
796 info.ledDflt.defs.merge = merge;
797 HandleCompatMapFile(file, xkb, merge, &info);
799 if (info.errorCount == 0)
802 if (XkbcAllocCompatMap(xkb, XkbAllCompatMask, info.nInterps) !=
805 WSGO("Couldn't allocate compatibility map\n");
808 if (info.name != NULL)
810 if (XkbcAllocNames(xkb, XkbCompatNameMask, 0, 0) == Success)
812 xkb_intern_atom(info.name);
815 WSGO("Couldn't allocate space for compat name\n");
816 ACTION("Name \"%s\" (from %s) NOT assigned\n",
817 scanFile, info.name);
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);