Fix formatting in xkbcomp headers
[platform/upstream/libxkbcommon.git] / src / xkbcomp / compat.c
1 /************************************************************
2  Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3
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.
15
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.
24
25  ********************************************************/
26
27 #include "xkbcomp.h"
28 #include "xkballoc.h"
29 #include "xkbmisc.h"
30 #include "expr.h"
31 #include "vmod.h"
32 #include "misc.h"
33 #include "indicators.h"
34 #include "action.h"
35 #include "parseutils.h"
36
37 typedef struct _SymInterpInfo
38 {
39     CommonInfo defs;
40     struct xkb_sym_interpret interp;
41 } SymInterpInfo;
42
43 #define _SI_VirtualMod          (1<<0)
44 #define _SI_Action              (1<<1)
45 #define _SI_AutoRepeat          (1<<2)
46 #define _SI_LockingKey          (1<<3)
47 #define _SI_LevelOneOnly        (1<<4)
48
49 typedef struct _GroupCompatInfo
50 {
51     unsigned char fileID;
52     unsigned char merge;
53     Bool defined;
54     unsigned char real_mods;
55     xkb_atom_t vmods;
56 } GroupCompatInfo;
57
58 typedef struct _CompatInfo
59 {
60     char *name;
61     unsigned fileID;
62     int errorCount;
63     int nInterps;
64     SymInterpInfo *interps;
65     SymInterpInfo dflt;
66     LEDInfo ledDflt;
67     GroupCompatInfo groupCompat[XkbNumKbdGroups];
68     LEDInfo *leds;
69     VModInfo vmods;
70     ActionInfo *act;
71     struct xkb_keymap * xkb;
72 } CompatInfo;
73
74 /***====================================================================***/
75
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))
80
81 /***====================================================================***/
82
83 static const char *
84 siText(SymInterpInfo * si, CompatInfo * info)
85 {
86     static char buf[128];
87
88     if (si == &info->dflt)
89     {
90         snprintf(buf, sizeof(buf), "default");
91     }
92     else
93     {
94         snprintf(buf, sizeof(buf), "%s+%s(%s)",
95                 XkbcKeysymText(si->interp.sym),
96                 XkbcSIMatchText(si->interp.match),
97                 XkbcModMaskText(si->interp.mods, False));
98     }
99     return buf;
100 }
101
102 static void
103 InitCompatInfo(CompatInfo * info, struct xkb_keymap * xkb)
104 {
105     unsigned int i;
106
107     info->xkb = xkb;
108     info->name = NULL;
109     info->fileID = 0;
110     info->errorCount = 0;
111     info->nInterps = 0;
112     info->interps = NULL;
113     info->act = 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));
128     info->leds = NULL;
129     InitVModInfo(&info->vmods, xkb);
130 }
131
132 static void
133 ClearCompatInfo(CompatInfo * info, struct xkb_keymap * xkb)
134 {
135     unsigned int i;
136     ActionInfo *next;
137
138     free(info->name);
139     info->name = NULL;
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);
148     info->nInterps = 0;
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);
153     while (info->act) {
154             next = info->act->next;
155             free(info->act);
156             info->act = next;
157     }
158     ClearVModInfo(&info->vmods, xkb);
159 }
160
161 static SymInterpInfo *
162 NextInterp(CompatInfo * info)
163 {
164     SymInterpInfo *si;
165
166     si = uTypedAlloc(SymInterpInfo);
167     if (si)
168     {
169         memset(si, 0, sizeof(SymInterpInfo));
170         info->interps =
171             (SymInterpInfo *) AddCommonInfo(&info->interps->defs,
172                                             (CommonInfo *) si);
173         info->nInterps++;
174     }
175     return si;
176 }
177
178 static SymInterpInfo *
179 FindMatchingInterp(CompatInfo * info, SymInterpInfo * new)
180 {
181     SymInterpInfo *old;
182
183     for (old = info->interps; old != NULL;
184          old = (SymInterpInfo *) old->defs.next)
185     {
186         if ((old->interp.sym == new->interp.sym) &&
187             (old->interp.mods == new->interp.mods) &&
188             (old->interp.match == new->interp.match))
189         {
190             return old;
191         }
192     }
193     return NULL;
194 }
195
196 static Bool
197 AddInterp(CompatInfo * info, SymInterpInfo * new)
198 {
199     unsigned collide;
200     SymInterpInfo *old;
201
202     collide = 0;
203     old = FindMatchingInterp(info, new);
204     if (old != NULL)
205     {
206         if (new->defs.merge == MergeReplace)
207         {
208             SymInterpInfo *next = (SymInterpInfo *) old->defs.next;
209             if (((old->defs.fileID == new->defs.fileID)
210                  && (warningLevel > 0)) || (warningLevel > 9))
211             {
212                 WARN("Multiple definitions for \"%s\"\n", siText(new, info));
213                 ACTION("Earlier interpretation ignored\n");
214             }
215             *old = *new;
216             old->defs.next = &next->defs;
217             return True;
218         }
219         if (UseNewField(_SI_VirtualMod, &old->defs, &new->defs, &collide))
220         {
221             old->interp.virtual_mod = new->interp.virtual_mod;
222             old->defs.defined |= _SI_VirtualMod;
223         }
224         if (UseNewField(_SI_Action, &old->defs, &new->defs, &collide))
225         {
226             old->interp.act = new->interp.act;
227             old->defs.defined |= _SI_Action;
228         }
229         if (UseNewField(_SI_AutoRepeat, &old->defs, &new->defs, &collide))
230         {
231             old->interp.flags &= ~XkbSI_AutoRepeat;
232             old->interp.flags |= (new->interp.flags & XkbSI_AutoRepeat);
233             old->defs.defined |= _SI_AutoRepeat;
234         }
235         if (UseNewField(_SI_LockingKey, &old->defs, &new->defs, &collide))
236         {
237             old->interp.flags &= ~XkbSI_LockingKey;
238             old->interp.flags |= (new->interp.flags & XkbSI_LockingKey);
239             old->defs.defined |= _SI_LockingKey;
240         }
241         if (UseNewField(_SI_LevelOneOnly, &old->defs, &new->defs, &collide))
242         {
243             old->interp.match &= ~XkbSI_LevelOneOnly;
244             old->interp.match |= (new->interp.match & XkbSI_LevelOneOnly);
245             old->defs.defined |= _SI_LevelOneOnly;
246         }
247         if (collide)
248         {
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"));
252         }
253         return True;
254     }
255     old = new;
256     if ((new = NextInterp(info)) == NULL)
257         return False;
258     *new = *old;
259     new->defs.next = NULL;
260     return True;
261 }
262
263 static Bool
264 AddGroupCompat(CompatInfo * info, unsigned group, GroupCompatInfo * newGC)
265 {
266     GroupCompatInfo *gc;
267     unsigned merge;
268
269     merge = newGC->merge;
270     gc = &info->groupCompat[group];
271     if (((gc->real_mods == newGC->real_mods) && (gc->vmods == newGC->vmods)))
272     {
273         return True;
274     }
275     if (((gc->fileID == newGC->fileID) && (warningLevel > 0))
276         || (warningLevel > 9))
277     {
278         WARN("Compat map for group %d redefined\n", group + 1);
279         ACTION("Using %s definition\n",
280                 (merge == MergeAugment ? "old" : "new"));
281     }
282     if (newGC->defined && (merge != MergeAugment || !gc->defined))
283         *gc = *newGC;
284     return True;
285 }
286
287 /***====================================================================***/
288
289 static Bool
290 ResolveStateAndPredicate(ExprDef * expr,
291                          unsigned *pred_rtrn,
292                          unsigned *mods_rtrn, CompatInfo * info)
293 {
294     ExprResult result;
295
296     if (expr == NULL)
297     {
298         *pred_rtrn = XkbSI_AnyOfOrNone;
299         *mods_rtrn = ~0;
300         return True;
301     }
302
303     *pred_rtrn = XkbSI_Exactly;
304     if (expr->op == ExprActionDecl)
305     {
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;
317         else
318         {
319             ERROR("Illegal modifier predicate \"%s\"\n", pred_txt);
320             ACTION("Ignored\n");
321             return False;
322         }
323         expr = expr->value.action.args;
324     }
325     else if (expr->op == ExprIdent)
326     {
327         const char *pred_txt = XkbcAtomText(expr->value.str);
328         if ((pred_txt) && (strcasecmp(pred_txt, "any") == 0))
329         {
330             *pred_rtrn = XkbSI_AnyOf;
331             *mods_rtrn = 0xff;
332             return True;
333         }
334     }
335
336     if (ExprResolveModMask(expr, &result))
337     {
338         *mods_rtrn = result.uval;
339         return True;
340     }
341     return False;
342 }
343
344 /***====================================================================***/
345
346 static void
347 MergeIncludedCompatMaps(CompatInfo * into, CompatInfo * from, unsigned merge)
348 {
349     SymInterpInfo *si;
350     LEDInfo *led, *rtrn, *next;
351     GroupCompatInfo *gcm;
352     int i;
353
354     if (from->errorCount > 0)
355     {
356         into->errorCount += from->errorCount;
357         return;
358     }
359     if (into->name == NULL)
360     {
361         into->name = from->name;
362         from->name = NULL;
363     }
364     for (si = from->interps; si; si = (SymInterpInfo *) si->defs.next)
365     {
366         if (merge != MergeDefault)
367             si->defs.merge = merge;
368         if (!AddInterp(into, si))
369             into->errorCount++;
370     }
371     for (i = 0, gcm = &from->groupCompat[0]; i < XkbNumKbdGroups; i++, gcm++)
372     {
373         if (merge != MergeDefault)
374             gcm->merge = merge;
375         if (!AddGroupCompat(into, i, gcm))
376             into->errorCount++;
377     }
378     for (led = from->leds; led != NULL; led = next)
379     {
380         next = (LEDInfo *) led->defs.next;
381         if (merge != MergeDefault)
382             led->defs.merge = merge;
383         rtrn = AddIndicatorMap(into->leds, led);
384         if (rtrn != NULL)
385             into->leds = rtrn;
386         else
387             into->errorCount++;
388     }
389 }
390
391 typedef void (*FileHandler) (XkbFile *rtrn, struct xkb_keymap *xkb,
392                              unsigned merge, CompatInfo *info);
393
394 static Bool
395 HandleIncludeCompatMap(IncludeStmt * stmt,
396                        struct xkb_keymap * xkb, CompatInfo * info, FileHandler hndlr)
397 {
398     unsigned newMerge;
399     XkbFile *rtrn;
400     CompatInfo included;
401     Bool haveSelf;
402
403     haveSelf = False;
404     if ((stmt->file == NULL) && (stmt->map == NULL))
405     {
406         haveSelf = True;
407         included = *info;
408         memset(info, 0, sizeof(CompatInfo));
409     }
410     else if (ProcessIncludeFile(xkb->context, stmt, XkmCompatMapIndex, &rtrn,
411                                 &newMerge))
412     {
413         InitCompatInfo(&included, xkb);
414         included.fileID = rtrn->id;
415         included.dflt = info->dflt;
416         included.dflt.defs.fileID = rtrn->id;
417         included.dflt.defs.merge = newMerge;
418         included.ledDflt.defs.fileID = rtrn->id;
419         included.ledDflt.defs.merge = newMerge;
420         included.act = info->act;
421         (*hndlr) (rtrn, xkb, MergeOverride, &included);
422         if (stmt->stmt != NULL)
423         {
424             free(included.name);
425             included.name = stmt->stmt;
426             stmt->stmt = NULL;
427         }
428         if (info->act != NULL)
429                 included.act = NULL;
430         FreeXKBFile(rtrn);
431     }
432     else
433     {
434         info->errorCount += 10;
435         return False;
436     }
437     if ((stmt->next != NULL) && (included.errorCount < 1))
438     {
439         IncludeStmt *next;
440         unsigned op;
441         CompatInfo next_incl;
442
443         for (next = stmt->next; next != NULL; next = next->next)
444         {
445             if ((next->file == NULL) && (next->map == NULL))
446             {
447                 haveSelf = True;
448                 MergeIncludedCompatMaps(&included, info, next->merge);
449                 ClearCompatInfo(info, xkb);
450             }
451             else if (ProcessIncludeFile(xkb->context, next, XkmCompatMapIndex,
452                                         &rtrn, &op))
453             {
454                 InitCompatInfo(&next_incl, xkb);
455                 next_incl.fileID = rtrn->id;
456                 next_incl.dflt = info->dflt;
457                 next_incl.dflt.defs.fileID = rtrn->id;
458                 next_incl.dflt.defs.merge = op;
459                 next_incl.ledDflt.defs.fileID = rtrn->id;
460                 next_incl.ledDflt.defs.merge = op;
461                 next_incl.act = info->act;
462                 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
463                 MergeIncludedCompatMaps(&included, &next_incl, op);
464                 if (info->act != NULL)
465                         next_incl.act = NULL;
466                 ClearCompatInfo(&next_incl, xkb);
467                 FreeXKBFile(rtrn);
468             }
469             else
470             {
471                 info->errorCount += 10;
472                 return False;
473             }
474         }
475     }
476     if (haveSelf)
477         *info = included;
478     else
479     {
480         MergeIncludedCompatMaps(info, &included, newMerge);
481         ClearCompatInfo(&included, xkb);
482     }
483     return (info->errorCount == 0);
484 }
485
486 static const LookupEntry useModMapValues[] = {
487     {"levelone", 1},
488     {"level1", 1},
489     {"anylevel", 0},
490     {"any", 0},
491     {NULL, 0}
492 };
493
494 static int
495 SetInterpField(SymInterpInfo * si,
496                struct xkb_keymap * xkb,
497                char *field,
498                ExprDef * arrayNdx, ExprDef * value, CompatInfo * info)
499 {
500     int ok = 1;
501     ExprResult tmp;
502
503     if (strcasecmp(field, "action") == 0)
504     {
505         if (arrayNdx != NULL)
506             return ReportSINotArray(si, field, info);
507         ok = HandleActionDef(value, xkb, &si->interp.act.any, si->defs.merge,
508                              info->act);
509         if (ok)
510             si->defs.defined |= _SI_Action;
511     }
512     else if ((strcasecmp(field, "virtualmodifier") == 0) ||
513              (strcasecmp(field, "virtualmod") == 0))
514     {
515         if (arrayNdx != NULL)
516             return ReportSINotArray(si, field, info);
517         ok = ResolveVirtualModifier(value, xkb, &tmp, &info->vmods);
518         if (ok)
519         {
520             si->interp.virtual_mod = tmp.uval;
521             si->defs.defined |= _SI_VirtualMod;
522         }
523         else
524             return ReportSIBadType(si, field, "virtual modifier", info);
525     }
526     else if (strcasecmp(field, "repeat") == 0)
527     {
528         if (arrayNdx != NULL)
529             return ReportSINotArray(si, field, info);
530         ok = ExprResolveBoolean(value, &tmp);
531         if (ok)
532         {
533             if (tmp.uval)
534                 si->interp.flags |= XkbSI_AutoRepeat;
535             else
536                 si->interp.flags &= ~XkbSI_AutoRepeat;
537             si->defs.defined |= _SI_AutoRepeat;
538         }
539         else
540             return ReportSIBadType(si, field, "boolean", info);
541     }
542     else if (strcasecmp(field, "locking") == 0)
543     {
544         if (arrayNdx != NULL)
545             return ReportSINotArray(si, field, info);
546         ok = ExprResolveBoolean(value, &tmp);
547         if (ok)
548         {
549             if (tmp.uval)
550                 si->interp.flags |= XkbSI_LockingKey;
551             else
552                 si->interp.flags &= ~XkbSI_LockingKey;
553             si->defs.defined |= _SI_LockingKey;
554         }
555         else
556             return ReportSIBadType(si, field, "boolean", info);
557     }
558     else if ((strcasecmp(field, "usemodmap") == 0) ||
559              (strcasecmp(field, "usemodmapmods") == 0))
560     {
561         if (arrayNdx != NULL)
562             return ReportSINotArray(si, field, info);
563         ok = ExprResolveEnum(value, &tmp, useModMapValues);
564         if (ok)
565         {
566             if (tmp.uval)
567                 si->interp.match |= XkbSI_LevelOneOnly;
568             else
569                 si->interp.match &= ~XkbSI_LevelOneOnly;
570             si->defs.defined |= _SI_LevelOneOnly;
571         }
572         else
573             return ReportSIBadType(si, field, "level specification", info);
574     }
575     else
576     {
577         ok = ReportBadField("symbol interpretation", field, siText(si, info));
578     }
579     return ok;
580 }
581
582 static int
583 HandleInterpVar(VarDef * stmt, struct xkb_keymap * xkb, CompatInfo * info)
584 {
585     ExprResult elem, field;
586     ExprDef *ndx;
587     int ret;
588
589     if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
590         ret = 0;               /* internal error, already reported */
591     else if (elem.str && (strcasecmp(elem.str, "interpret") == 0))
592         ret = SetInterpField(&info->dflt, xkb, field.str, ndx, stmt->value,
593                               info);
594     else if (elem.str && (strcasecmp(elem.str, "indicator") == 0))
595         ret = SetIndicatorMapField(&info->ledDflt, xkb, field.str, ndx,
596                                   stmt->value);
597     else
598         ret = SetActionField(xkb, elem.str, field.str, ndx, stmt->value,
599                             &info->act);
600     free(elem.str);
601     free(field.str);
602     return ret;
603 }
604
605 static int
606 HandleInterpBody(VarDef * def, struct xkb_keymap * xkb, SymInterpInfo * si,
607                  CompatInfo * info)
608 {
609     int ok = 1;
610     ExprResult tmp, field;
611     ExprDef *arrayNdx;
612
613     for (; def != NULL; def = (VarDef *) def->common.next)
614     {
615         if ((def->name) && (def->name->type == ExprFieldRef))
616         {
617             ok = HandleInterpVar(def, xkb, info);
618             continue;
619         }
620         ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx);
621         if (ok) {
622             ok = SetInterpField(si, xkb, field.str, arrayNdx, def->value,
623                                 info);
624             free(field.str);
625         }
626     }
627     return ok;
628 }
629
630 static int
631 HandleInterpDef(InterpDef * def, struct xkb_keymap * xkb, unsigned merge,
632                 CompatInfo * info)
633 {
634     unsigned pred, mods;
635     SymInterpInfo si;
636
637     if (!ResolveStateAndPredicate(def->match, &pred, &mods, info))
638     {
639         ERROR("Couldn't determine matching modifiers\n");
640         ACTION("Symbol interpretation ignored\n");
641         return False;
642     }
643     if (def->merge != MergeDefault)
644         merge = def->merge;
645
646     si = info->dflt;
647     si.defs.merge = merge;
648     if (!LookupKeysym(def->sym, &si.interp.sym))
649     {
650         ERROR("Could not resolve keysym %s\n", def->sym);
651         ACTION("Symbol interpretation ignored\n");
652         return False;
653     }
654     si.interp.match = pred & XkbSI_OpMask;
655     si.interp.mods = mods;
656     if (!HandleInterpBody(def->def, xkb, &si, info))
657     {
658         info->errorCount++;
659         return False;
660     }
661
662     if (!AddInterp(info, &si))
663     {
664         info->errorCount++;
665         return False;
666     }
667     return True;
668 }
669
670 static int
671 HandleGroupCompatDef(GroupCompatDef * def,
672                      struct xkb_keymap * xkb, unsigned merge, CompatInfo * info)
673 {
674     ExprResult val;
675     GroupCompatInfo tmp;
676
677     if (def->merge != MergeDefault)
678         merge = def->merge;
679     if (!XkbIsLegalGroup(def->group - 1))
680     {
681         ERROR("Keyboard group must be in the range 1..%d\n",
682                XkbNumKbdGroups + 1);
683         ACTION("Compatibility map for illegal group %d ignored\n",
684                 def->group);
685         return False;
686     }
687     tmp.fileID = info->fileID;
688     tmp.merge = merge;
689     if (!ExprResolveVModMask(def->def, &val, xkb))
690     {
691         ERROR("Expected a modifier mask in group compatibility definition\n");
692         ACTION("Ignoring illegal compatibility map for group %d\n",
693                 def->group);
694         return False;
695     }
696     tmp.real_mods = val.uval & 0xff;
697     tmp.vmods = (val.uval >> 8) & 0xffff;
698     tmp.defined = True;
699     return AddGroupCompat(info, def->group - 1, &tmp);
700 }
701
702 static void
703 HandleCompatMapFile(XkbFile * file,
704                     struct xkb_keymap * xkb, unsigned merge, CompatInfo * info)
705 {
706     ParseCommon *stmt;
707
708     if (merge == MergeDefault)
709         merge = MergeAugment;
710     free(info->name);
711     info->name = uDupString(file->name);
712     stmt = file->defs;
713     while (stmt)
714     {
715         switch (stmt->stmtType)
716         {
717         case StmtInclude:
718             if (!HandleIncludeCompatMap((IncludeStmt *) stmt, xkb, info,
719                                         HandleCompatMapFile))
720                 info->errorCount++;
721             break;
722         case StmtInterpDef:
723             if (!HandleInterpDef((InterpDef *) stmt, xkb, merge, info))
724                 info->errorCount++;
725             break;
726         case StmtGroupCompatDef:
727             if (!HandleGroupCompatDef
728                 ((GroupCompatDef *) stmt, xkb, merge, info))
729                 info->errorCount++;
730             break;
731         case StmtIndicatorMapDef:
732         {
733             LEDInfo *rtrn;
734             rtrn = HandleIndicatorMapDef((IndicatorMapDef *) stmt, xkb,
735                                          &info->ledDflt, info->leds, merge);
736             if (rtrn != NULL)
737                 info->leds = rtrn;
738             else
739                 info->errorCount++;
740         }
741             break;
742         case StmtVarDef:
743             if (!HandleInterpVar((VarDef *) stmt, xkb, info))
744                 info->errorCount++;
745             break;
746         case StmtVModDef:
747             if (!HandleVModDef((VModDef *) stmt, xkb, merge, &info->vmods))
748                 info->errorCount++;
749             break;
750         case StmtKeycodeDef:
751             ERROR("Interpretation files may not include other types\n");
752             ACTION("Ignoring definition of key name\n");
753             info->errorCount++;
754             break;
755         default:
756             WSGO("Unexpected statement type %d in HandleCompatMapFile\n",
757                   stmt->stmtType);
758             break;
759         }
760         stmt = stmt->next;
761         if (info->errorCount > 10)
762         {
763 #ifdef NOISY
764             ERROR("Too many errors\n");
765 #endif
766             ACTION("Abandoning compatibility map \"%s\"\n", file->topName);
767             break;
768         }
769     }
770 }
771
772 static void
773 CopyInterps(CompatInfo * info,
774             struct xkb_compat_map * compat, Bool needSymbol, unsigned pred)
775 {
776     SymInterpInfo *si;
777
778     for (si = info->interps; si; si = (SymInterpInfo *) si->defs.next)
779     {
780         if (((si->interp.match & XkbSI_OpMask) != pred) ||
781             (needSymbol && (si->interp.sym == XKB_KEYSYM_NO_SYMBOL)) ||
782             ((!needSymbol) && (si->interp.sym != XKB_KEYSYM_NO_SYMBOL)))
783             continue;
784         if (compat->num_si >= compat->size_si)
785         {
786             WSGO("No room to merge symbol interpretations\n");
787             ACTION("Symbol interpretations lost\n");
788             return;
789         }
790         compat->sym_interpret[compat->num_si++] = si->interp;
791     }
792 }
793
794 Bool
795 CompileCompatMap(XkbFile *file, struct xkb_keymap * xkb, unsigned merge,
796                  LEDInfoPtr *unboundLEDs)
797 {
798     int i;
799     CompatInfo info;
800     GroupCompatInfo *gcm;
801
802     InitCompatInfo(&info, xkb);
803     info.dflt.defs.merge = merge;
804     info.ledDflt.defs.merge = merge;
805     HandleCompatMapFile(file, xkb, merge, &info);
806
807     if (info.errorCount == 0)
808     {
809         int size;
810         if (XkbcAllocCompatMap(xkb, XkbAllCompatMask, info.nInterps) !=
811             Success)
812         {
813             WSGO("Couldn't allocate compatibility map\n");
814             return False;
815         }
816         size = info.nInterps * sizeof(struct xkb_sym_interpret);
817         if (size > 0)
818         {
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);
828         }
829         for (i = 0, gcm = &info.groupCompat[0]; i < XkbNumKbdGroups;
830              i++, gcm++)
831         {
832             if ((gcm->fileID != 0) || (gcm->real_mods != 0)
833                 || (gcm->vmods != 0))
834             {
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;
838             }
839         }
840         if (info.leds != NULL)
841         {
842             if (!CopyIndicatorMapDefs(xkb, info.leds, unboundLEDs))
843                 info.errorCount++;
844             info.leds = NULL;
845         }
846         ClearCompatInfo(&info, xkb);
847         return True;
848     }
849     free(info.interps);
850     return False;
851 }
852
853 static uint32_t
854 VModsToReal(struct xkb_keymap *xkb, uint32_t vmodmask)
855 {
856     uint32_t ret = 0;
857     int i;
858
859     if (!vmodmask)
860         return 0;
861
862     for (i = 0; i < XkbNumVirtualMods; i++) {
863         if (!(vmodmask & (1 << i)))
864             continue;
865         ret |= xkb->server->vmods[i];
866     }
867
868     return ret;
869 }
870
871 static void
872 UpdateActionMods(struct xkb_keymap *xkb, union xkb_action *act, uint32_t rmodmask)
873 {
874     switch (act->type) {
875     case XkbSA_SetMods:
876     case XkbSA_LatchMods:
877     case XkbSA_LockMods:
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);
882         break;
883     case XkbSA_ISOLock:
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);
888         break;
889     default:
890         break;
891     }
892 }
893
894 /**
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 XKB_KEYSYM_NO_SYMBOL match.
898  */
899 static struct xkb_sym_interpret *
900 FindInterpForKey(struct xkb_keymap *xkb, xkb_keycode_t key, uint32_t group, uint32_t level)
901 {
902     struct xkb_sym_interpret *ret = NULL;
903     const xkb_keysym_t *syms;
904     int num_syms;
905     int i;
906
907     num_syms = xkb_key_get_syms_by_level(xkb, key, group, level, &syms);
908     if (num_syms == 0)
909         return NULL;
910
911     for (i = 0; i < xkb->compat->num_si; i++) {
912         struct xkb_sym_interpret *interp = &xkb->compat->sym_interpret[i];
913         uint32_t mods;
914         Bool found;
915
916         if ((num_syms > 1 || interp->sym != syms[0]) &&
917             interp->sym != XKB_KEYSYM_NO_SYMBOL)
918             continue;
919
920         if (level == 0 || !(interp->match & XkbSI_LevelOneOnly))
921             mods = xkb->map->modmap[key];
922         else
923             mods = 0;
924
925         switch (interp->match & XkbSI_OpMask) {
926         case XkbSI_NoneOf:
927             found = !(interp->mods & mods);
928             break;
929         case XkbSI_AnyOfOrNone:
930             found = (!mods || (interp->mods & mods));
931             break;
932         case XkbSI_AnyOf:
933             found = !!(interp->mods & mods);
934             break;
935         case XkbSI_AllOf:
936             found = ((interp->mods & mods) == mods);
937             break;
938         case XkbSI_Exactly:
939             found = (interp->mods == mods);
940             break;
941         default:
942             found = False;
943             break;
944         }
945
946         if (found && interp->sym != XKB_KEYSYM_NO_SYMBOL)
947             return interp;
948         else if (found && !ret)
949             ret = interp;
950     }
951
952     return ret;
953 }
954
955 /**
956  */
957 static Bool
958 ApplyInterpsToKey(struct xkb_keymap *xkb, xkb_keycode_t key)
959 {
960 #define INTERP_SIZE (8 * 4)
961     struct xkb_sym_interpret *interps[INTERP_SIZE];
962     union xkb_action *acts;
963     uint32_t vmodmask = 0;
964     int num_acts = 0;
965     int group, level;
966     int width = XkbKeyGroupsWidth(xkb, key);
967     int i;
968
969     /* If we've been told not to bind interps to this key, then don't. */
970     if (xkb->server->explicit[key] & XkbExplicitInterpretMask)
971         return True;
972
973     for (i = 0; i < INTERP_SIZE; i++)
974         interps[i] = NULL;
975
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 */
980                 return False;
981             interps[i] = FindInterpForKey(xkb, key, group, level);
982             if (interps[i])
983                 num_acts++;
984         }
985     }
986
987     if (num_acts)
988         num_acts = XkbKeyNumGroups(xkb, key) * width;
989     acts = XkbcResizeKeyActions(xkb, key, num_acts);
990     if (!num_acts)
991         return True;
992     else if (!acts)
993         return False;
994
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;
998
999             i = (group * width) + level;
1000             interp = interps[i];
1001
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;
1010             }
1011
1012             if (!interp)
1013                 continue;
1014
1015             if ((group == 0 && level == 0) ||
1016                 !(interp->match & XkbSI_LevelOneOnly)) {
1017                 if (interp->virtual_mod != XkbNoModifier)
1018                     vmodmask |= (1 << interp->virtual_mod);
1019             }
1020             acts[i] = interp->act;
1021         }
1022     }
1023
1024     if (!(xkb->server->explicit[key] & XkbExplicitVModMapMask))
1025         xkb->server->vmodmap[key] = vmodmask;
1026
1027     return True;
1028 #undef INTERP_SIZE
1029 }
1030
1031 /**
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 ...
1036  */
1037 Bool
1038 UpdateModifiersFromCompat(struct xkb_keymap *xkb)
1039 {
1040     xkb_keycode_t key;
1041     int i;
1042
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))
1047             return False;
1048
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])
1054             continue;
1055         for (i = 0; i < XkbNumVirtualMods; i++) {
1056             if (!(xkb->server->vmodmap[key] & (1 << i)))
1057                 continue;
1058             xkb->server->vmods[i] |= xkb->map->modmap[key];
1059         }
1060     }
1061
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];
1065         uint32_t mask = 0;
1066         int j;
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)))
1071                 continue;
1072             mask |= xkb->server->vmods[j];
1073         }
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);
1077         }
1078     }
1079
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)
1085                 continue;
1086             UpdateActionMods(xkb, &acts[i], xkb->map->modmap[key]);
1087         }
1088     }
1089
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);
1094     }
1095
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);
1100     }
1101
1102     return True;
1103 }