Use CARD32 instead of Atom, drag in XkbClientMapRec
[profile/ivi/libxkbcommon.git] / src / xkbcomp / symbols.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 "tokens.h"
31 #include "expr.h"
32 #include "parseutils.h"
33
34 #include <X11/extensions/XKBfilecommon.h>
35 #include <X11/keysym.h>
36 #include <stdlib.h>
37
38 #include "expr.h"
39 #include "vmod.h"
40 #include "action.h"
41 #include "keycodes.h"
42 #include "misc.h"
43 #include "alias.h"
44
45 extern Atom tok_ONE_LEVEL;
46 extern Atom tok_TWO_LEVEL;
47 extern Atom tok_KEYPAD;
48
49 /***====================================================================***/
50
51 #define RepeatYes       1
52 #define RepeatNo        0
53 #define RepeatUndefined ~((unsigned)0)
54
55 #define _Key_Syms       (1<<0)
56 #define _Key_Acts       (1<<1)
57 #define _Key_Repeat     (1<<2)
58 #define _Key_Behavior   (1<<3)
59 #define _Key_Type_Dflt  (1<<4)
60 #define _Key_Types      (1<<5)
61 #define _Key_GroupInfo  (1<<6)
62 #define _Key_VModMap    (1<<7)
63
64 typedef struct _KeyInfo
65 {
66     CommonInfo defs;
67     unsigned long name; /* the 4 chars of the key name, as long */
68     unsigned char groupInfo;
69     unsigned char typesDefined;
70     unsigned char symsDefined;
71     unsigned char actsDefined;
72     short numLevels[XkbNumKbdGroups];
73     CARD32 *syms[XkbNumKbdGroups];
74     XkbcAction *acts[XkbNumKbdGroups];
75     Atom types[XkbNumKbdGroups];
76     unsigned repeat;
77     XkbBehavior behavior;
78     unsigned short vmodmap;
79     unsigned long nameForOverlayKey;
80     unsigned long allowNone;
81     Atom dfltType;
82 } KeyInfo;
83
84 /**
85  * Init the given key info to sane values.
86  */
87 static void
88 InitKeyInfo(KeyInfo * info)
89 {
90     register int i;
91     static char dflt[4] = "*";
92
93     info->defs.defined = 0;
94     info->defs.fileID = 0;
95     info->defs.merge = MergeOverride;
96     info->defs.next = NULL;
97     info->name = KeyNameToLong(dflt);
98     info->groupInfo = 0;
99     info->typesDefined = info->symsDefined = info->actsDefined = 0;
100     for (i = 0; i < XkbNumKbdGroups; i++)
101     {
102         info->numLevels[i] = 0;
103         info->types[i] = None;
104         info->syms[i] = NULL;
105         info->acts[i] = NULL;
106     }
107     info->dfltType = None;
108     info->behavior.type = XkbKB_Default;
109     info->behavior.data = 0;
110     info->vmodmap = 0;
111     info->nameForOverlayKey = 0;
112     info->repeat = RepeatUndefined;
113     info->allowNone = 0;
114     return;
115 }
116
117 /**
118  * Free memory associated with this key info and reset to sane values.
119  */
120 static void
121 FreeKeyInfo(KeyInfo * info)
122 {
123     register int i;
124
125     info->defs.defined = 0;
126     info->defs.fileID = 0;
127     info->defs.merge = MergeOverride;
128     info->defs.next = NULL;
129     info->groupInfo = 0;
130     info->typesDefined = info->symsDefined = info->actsDefined = 0;
131     for (i = 0; i < XkbNumKbdGroups; i++)
132     {
133         info->numLevels[i] = 0;
134         info->types[i] = None;
135         if (info->syms[i] != NULL)
136             uFree(info->syms[i]);
137         info->syms[i] = NULL;
138         if (info->acts[i] != NULL)
139             uFree(info->acts[i]);
140         info->acts[i] = NULL;
141     }
142     info->dfltType = None;
143     info->behavior.type = XkbKB_Default;
144     info->behavior.data = 0;
145     info->vmodmap = 0;
146     info->nameForOverlayKey = 0;
147     info->repeat = RepeatUndefined;
148     info->allowNone = 0;
149     return;
150 }
151
152 /**
153  * Copy old into new, optionally reset old to 0.
154  * If old is reset, new simply re-uses old's memory. Otherwise, the memory is
155  * newly allocated and new points to the new memory areas.
156  */
157 static Bool
158 CopyKeyInfo(KeyInfo * old, KeyInfo * new, Bool clearOld)
159 {
160     register int i;
161
162     *new = *old;
163     new->defs.next = NULL;
164     if (clearOld)
165     {
166         for (i = 0; i < XkbNumKbdGroups; i++)
167         {
168             old->numLevels[i] = 0;
169             old->syms[i] = NULL;
170             old->acts[i] = NULL;
171         }
172     }
173     else
174     {
175         int width;
176         for (i = 0; i < XkbNumKbdGroups; i++)
177         {
178             width = new->numLevels[i];
179             if (old->syms[i] != NULL)
180             {
181                 new->syms[i] = uTypedCalloc(width, CARD32);
182                 if (!new->syms[i])
183                 {
184                     new->syms[i] = NULL;
185                     new->numLevels[i] = 0;
186                     return False;
187                 }
188                 memcpy((char *) new->syms[i], (char *) old->syms[i],
189                        width * sizeof(CARD32));
190             }
191             if (old->acts[i] != NULL)
192             {
193                 new->acts[i] = uTypedCalloc(width, XkbcAction);
194                 if (!new->acts[i])
195                 {
196                     new->acts[i] = NULL;
197                     return False;
198                 }
199                 memcpy((char *) new->acts[i], (char *) old->acts[i],
200                        width * sizeof(XkbcAction));
201             }
202         }
203     }
204     return True;
205 }
206
207 /***====================================================================***/
208
209 typedef struct _ModMapEntry
210 {
211     CommonInfo defs;
212     Bool haveSymbol;
213     int modifier;
214     union
215     {
216         unsigned long keyName;
217         CARD32 keySym;
218     } u;
219 } ModMapEntry;
220
221 #define SYMBOLS_INIT_SIZE       110
222 #define SYMBOLS_CHUNK           20
223 typedef struct _SymbolsInfo
224 {
225     char *name;         /* e.g. pc+us+inet(evdev) */
226     int errorCount;
227     unsigned fileID;
228     unsigned merge;
229     unsigned explicit_group;
230     unsigned groupInfo;
231     unsigned szKeys;
232     unsigned nKeys;
233     KeyInfo *keys;
234     KeyInfo dflt;
235     VModInfo vmods;
236     ActionInfo *action;
237     Atom groupNames[XkbNumKbdGroups];
238
239     ModMapEntry *modMap;
240     AliasInfo *aliases;
241 } SymbolsInfo;
242
243 static void
244 InitSymbolsInfo(SymbolsInfo * info, XkbcDescPtr xkb)
245 {
246     register int i;
247
248     tok_ONE_LEVEL = XkbcInternAtom("ONE_LEVEL", False);
249     tok_TWO_LEVEL = XkbcInternAtom("TWO_LEVEL", False);
250     tok_KEYPAD = XkbcInternAtom("KEYPAD", False);
251     info->name = NULL;
252     info->explicit_group = 0;
253     info->errorCount = 0;
254     info->fileID = 0;
255     info->merge = MergeOverride;
256     info->groupInfo = 0;
257     info->szKeys = SYMBOLS_INIT_SIZE;
258     info->nKeys = 0;
259     info->keys = uTypedCalloc(SYMBOLS_INIT_SIZE, KeyInfo);
260     info->modMap = NULL;
261     for (i = 0; i < XkbNumKbdGroups; i++)
262         info->groupNames[i] = None;
263     InitKeyInfo(&info->dflt);
264     InitVModInfo(&info->vmods, xkb);
265     info->action = NULL;
266     info->aliases = NULL;
267     return;
268 }
269
270 static void
271 FreeSymbolsInfo(SymbolsInfo * info)
272 {
273     register int i;
274
275     if (info->name)
276         uFree(info->name);
277     info->name = NULL;
278     if (info->keys)
279     {
280         for (i = 0; i < info->nKeys; i++)
281         {
282             FreeKeyInfo(&info->keys[i]);
283         }
284         uFree(info->keys);
285         info->keys = NULL;
286     }
287     if (info->modMap)
288     {
289         ClearCommonInfo(&info->modMap->defs);
290         info->modMap = NULL;
291     }
292     if (info->aliases)
293     {
294         ClearAliases(&info->aliases);
295         info->aliases = NULL;
296     }
297     bzero((char *) info, sizeof(SymbolsInfo));
298     return;
299 }
300
301 static Bool
302 ResizeKeyGroup(KeyInfo * key,
303                unsigned group, unsigned atLeastSize, Bool forceActions)
304 {
305     Bool tooSmall;
306     unsigned newWidth;
307
308     tooSmall = (key->numLevels[group] < atLeastSize);
309     if (tooSmall)
310         newWidth = atLeastSize;
311     else
312         newWidth = key->numLevels[group];
313
314     if ((key->syms[group] == NULL) || tooSmall)
315     {
316         key->syms[group] = uTypedRecalloc(key->syms[group],
317                                           key->numLevels[group], newWidth,
318                                           CARD32);
319         if (!key->syms[group])
320             return False;
321     }
322     if (((forceActions) && (tooSmall || (key->acts[group] == NULL))) ||
323         (tooSmall && (key->acts[group] != NULL)))
324     {
325         key->acts[group] = uTypedRecalloc(key->acts[group],
326                                           key->numLevels[group], newWidth,
327                                           XkbcAction);
328         if (!key->acts[group])
329             return False;
330     }
331     key->numLevels[group] = newWidth;
332     return True;
333 }
334
335 static Bool
336 MergeKeyGroups(SymbolsInfo * info,
337                KeyInfo * into, KeyInfo * from, unsigned group)
338 {
339     CARD32 *resultSyms;
340     XkbcAction *resultActs;
341     int resultWidth;
342     register int i;
343     Bool report, clobber;
344
345     clobber = (from->defs.merge != MergeAugment);
346     report = (warningLevel > 9) ||
347         ((into->defs.fileID == from->defs.fileID) && (warningLevel > 0));
348     if (into->numLevels[group] >= from->numLevels[group])
349     {
350         resultSyms = into->syms[group];
351         resultActs = into->acts[group];
352         resultWidth = into->numLevels[group];
353     }
354     else
355     {
356         resultSyms = from->syms[group];
357         resultActs = from->acts[group];
358         resultWidth = from->numLevels[group];
359     }
360     if (resultSyms == NULL)
361     {
362         resultSyms = uTypedCalloc(resultWidth, CARD32);
363         if (!resultSyms)
364         {
365             WSGO("Could not allocate symbols for group merge\n");
366             ACTION("Group %d of key %s not merged\n", group,
367                     longText(into->name));
368             return False;
369         }
370     }
371     if ((resultActs == NULL) && (into->acts[group] || from->acts[group]))
372     {
373         resultActs = uTypedCalloc(resultWidth, XkbcAction);
374         if (!resultActs)
375         {
376             WSGO("Could not allocate actions for group merge\n");
377             ACTION("Group %d of key %s not merged\n", group,
378                     longText(into->name));
379             return False;
380         }
381     }
382     for (i = 0; i < resultWidth; i++)
383     {
384         CARD32 fromSym, toSym;
385         if (from->syms[group] && (i < from->numLevels[group]))
386             fromSym = from->syms[group][i];
387         else
388             fromSym = NoSymbol;
389         if (into->syms[group] && (i < into->numLevels[group]))
390             toSym = into->syms[group][i];
391         else
392             toSym = NoSymbol;
393         if ((fromSym == NoSymbol) || (fromSym == toSym))
394             resultSyms[i] = toSym;
395         else if (toSym == NoSymbol)
396             resultSyms[i] = fromSym;
397         else
398         {
399             CARD32 use, ignore;
400             if (clobber)
401             {
402                 use = fromSym;
403                 ignore = toSym;
404             }
405             else
406             {
407                 use = toSym;
408                 ignore = fromSym;
409             }
410             if (report)
411             {
412                 WARN
413                     ("Multiple symbols for level %d/group %d on key %s\n",
414                      i + 1, group + 1, longText(into->name));
415                 ACTION("Using %s, ignoring %s\n",
416                         XkbcKeysymText(use), XkbcKeysymText(ignore));
417             }
418             resultSyms[i] = use;
419         }
420         if (resultActs != NULL)
421         {
422             XkbcAction *fromAct, *toAct;
423             fromAct = (from->acts[group] ? &from->acts[group][i] : NULL);
424             toAct = (into->acts[group] ? &into->acts[group][i] : NULL);
425             if (((fromAct == NULL) || (fromAct->type == XkbSA_NoAction))
426                 && (toAct != NULL))
427             {
428                 resultActs[i] = *toAct;
429             }
430             else if (((toAct == NULL) || (toAct->type == XkbSA_NoAction))
431                      && (fromAct != NULL))
432             {
433                 resultActs[i] = *fromAct;
434             }
435             else
436             {
437                 XkbcAction *use, *ignore;
438                 if (clobber)
439                 {
440                     use = fromAct;
441                     ignore = toAct;
442                 }
443                 else
444                 {
445                     use = toAct;
446                     ignore = fromAct;
447                 }
448                 if (report)
449                 {
450                     WARN
451                         ("Multiple actions for level %d/group %d on key %s\n",
452                          i + 1, group + 1, longText(into->name));
453                     ACTION("Using %s, ignoring %s\n",
454                             XkbcActionTypeText(use->type),
455                             XkbcActionTypeText(ignore->type));
456                 }
457                 resultActs[i] = *use;
458             }
459         }
460     }
461     if ((into->syms[group] != NULL) && (resultSyms != into->syms[group]))
462         uFree(into->syms[group]);
463     if ((from->syms[group] != NULL) && (resultSyms != from->syms[group]))
464         uFree(from->syms[group]);
465     if ((into->acts[group] != NULL) && (resultActs != into->acts[group]))
466         uFree(into->acts[group]);
467     if ((from->acts[group] != NULL) && (resultActs != from->acts[group]))
468         uFree(from->acts[group]);
469     into->numLevels[group] = resultWidth;
470     into->syms[group] = resultSyms;
471     from->syms[group] = NULL;
472     into->acts[group] = resultActs;
473     from->acts[group] = NULL;
474     into->symsDefined |= (1 << group);
475     from->symsDefined &= ~(1 << group);
476     into->actsDefined |= (1 << group);
477     from->actsDefined &= ~(1 << group);
478     return True;
479 }
480
481 static Bool
482 MergeKeys(SymbolsInfo * info, KeyInfo * into, KeyInfo * from)
483 {
484     register int i;
485     unsigned collide = 0;
486     Bool report;
487
488     if (from->defs.merge == MergeReplace)
489     {
490         for (i = 0; i < XkbNumKbdGroups; i++)
491         {
492             if (into->numLevels[i] != 0)
493             {
494                 if (into->syms[i])
495                     uFree(into->syms[i]);
496                 if (into->acts[i])
497                     uFree(into->acts[i]);
498             }
499         }
500         *into = *from;
501         bzero(from, sizeof(KeyInfo));
502         return True;
503     }
504     report = ((warningLevel > 9) ||
505               ((into->defs.fileID == from->defs.fileID)
506                && (warningLevel > 0)));
507     for (i = 0; i < XkbNumKbdGroups; i++)
508     {
509         if (from->numLevels[i] > 0)
510         {
511             if (into->numLevels[i] == 0)
512             {
513                 into->numLevels[i] = from->numLevels[i];
514                 into->syms[i] = from->syms[i];
515                 into->acts[i] = from->acts[i];
516                 into->symsDefined |= (1 << i);
517                 from->syms[i] = NULL;
518                 from->acts[i] = NULL;
519                 from->numLevels[i] = 0;
520                 from->symsDefined &= ~(1 << i);
521                 if (into->syms[i])
522                     into->defs.defined |= _Key_Syms;
523                 if (into->acts[i])
524                     into->defs.defined |= _Key_Acts;
525             }
526             else
527             {
528                 if (report)
529                 {
530                     if (into->syms[i])
531                         collide |= _Key_Syms;
532                     if (into->acts[i])
533                         collide |= _Key_Acts;
534                 }
535                 MergeKeyGroups(info, into, from, (unsigned) i);
536             }
537         }
538         if (from->types[i] != None)
539         {
540             if ((into->types[i] != None) && (report) &&
541                 (into->types[i] != from->types[i]))
542             {
543                 Atom use, ignore;
544                 collide |= _Key_Types;
545                 if (from->defs.merge != MergeAugment)
546                 {
547                     use = from->types[i];
548                     ignore = into->types[i];
549                 }
550                 else
551                 {
552                     use = into->types[i];
553                     ignore = from->types[i];
554                 }
555                 WARN
556                     ("Multiple definitions for group %d type of key %s\n",
557                      i, longText(into->name));
558                 ACTION("Using %s, ignoring %s\n",
559                         XkbcAtomText(use),
560                         XkbcAtomText(ignore));
561             }
562             if ((from->defs.merge != MergeAugment)
563                 || (into->types[i] == None))
564             {
565                 into->types[i] = from->types[i];
566             }
567         }
568     }
569     if (UseNewField(_Key_Behavior, &into->defs, &from->defs, &collide))
570     {
571         into->behavior = from->behavior;
572         into->nameForOverlayKey = from->nameForOverlayKey;
573         into->defs.defined |= _Key_Behavior;
574     }
575     if (UseNewField(_Key_VModMap, &into->defs, &from->defs, &collide))
576     {
577         into->vmodmap = from->vmodmap;
578         into->defs.defined |= _Key_VModMap;
579     }
580     if (UseNewField(_Key_Repeat, &into->defs, &from->defs, &collide))
581     {
582         into->repeat = from->repeat;
583         into->defs.defined |= _Key_Repeat;
584     }
585     if (UseNewField(_Key_Type_Dflt, &into->defs, &from->defs, &collide))
586     {
587         into->dfltType = from->dfltType;
588         into->defs.defined |= _Key_Type_Dflt;
589     }
590     if (UseNewField(_Key_GroupInfo, &into->defs, &from->defs, &collide))
591     {
592         into->groupInfo = from->groupInfo;
593         into->defs.defined |= _Key_GroupInfo;
594     }
595     if (collide)
596     {
597         WARN("Symbol map for key %s redefined\n",
598               longText(into->name));
599         ACTION("Using %s definition for conflicting fields\n",
600                 (from->defs.merge == MergeAugment ? "first" : "last"));
601     }
602     return True;
603 }
604
605 static Bool
606 AddKeySymbols(SymbolsInfo * info, KeyInfo * key, XkbcDescPtr xkb)
607 {
608     register int i;
609     unsigned long real_name;
610
611     for (i = 0; i < info->nKeys; i++)
612     {
613         if (info->keys[i].name == key->name)
614             return MergeKeys(info, &info->keys[i], key);
615     }
616     if (FindKeyNameForAlias(xkb, key->name, &real_name))
617     {
618         for (i = 0; i < info->nKeys; i++)
619         {
620             if (info->keys[i].name == real_name)
621                 return MergeKeys(info, &info->keys[i], key);
622         }
623     }
624     if (info->nKeys >= info->szKeys)
625     {
626         info->szKeys += SYMBOLS_CHUNK;
627         info->keys =
628             uTypedRecalloc(info->keys, info->nKeys, info->szKeys, KeyInfo);
629         if (!info->keys)
630         {
631             WSGO("Could not allocate key symbols descriptions\n");
632             ACTION("Some key symbols definitions may be lost\n");
633             return False;
634         }
635     }
636     return CopyKeyInfo(key, &info->keys[info->nKeys++], True);
637 }
638
639 static Bool
640 AddModMapEntry(SymbolsInfo * info, ModMapEntry * new)
641 {
642     ModMapEntry *mm;
643     Bool clobber;
644
645     clobber = (new->defs.merge != MergeAugment);
646     for (mm = info->modMap; mm != NULL; mm = (ModMapEntry *) mm->defs.next)
647     {
648         if (new->haveSymbol && mm->haveSymbol
649             && (new->u.keySym == mm->u.keySym))
650         {
651             unsigned use, ignore;
652             if (mm->modifier != new->modifier)
653             {
654                 if (clobber)
655                 {
656                     use = new->modifier;
657                     ignore = mm->modifier;
658                 }
659                 else
660                 {
661                     use = mm->modifier;
662                     ignore = new->modifier;
663                 }
664                 ERROR
665                     ("%s added to symbol map for multiple modifiers\n",
666                      XkbcKeysymText(new->u.keySym));
667                 ACTION("Using %s, ignoring %s.\n",
668                         XkbcModIndexText(use),
669                         XkbcModIndexText(ignore));
670                 mm->modifier = use;
671             }
672             return True;
673         }
674         if ((!new->haveSymbol) && (!mm->haveSymbol) &&
675             (new->u.keyName == mm->u.keyName))
676         {
677             unsigned use, ignore;
678             if (mm->modifier != new->modifier)
679             {
680                 if (clobber)
681                 {
682                     use = new->modifier;
683                     ignore = mm->modifier;
684                 }
685                 else
686                 {
687                     use = mm->modifier;
688                     ignore = new->modifier;
689                 }
690                 ERROR("Key %s added to map for multiple modifiers\n",
691                        longText(new->u.keyName));
692                 ACTION("Using %s, ignoring %s.\n",
693                         XkbcModIndexText(use),
694                         XkbcModIndexText(ignore));
695                 mm->modifier = use;
696             }
697             return True;
698         }
699     }
700     mm = uTypedAlloc(ModMapEntry);
701     if (mm == NULL)
702     {
703         WSGO("Could not allocate modifier map entry\n");
704         ACTION("Modifier map for %s will be incomplete\n",
705                 XkbcModIndexText(new->modifier));
706         return False;
707     }
708     *mm = *new;
709     mm->defs.next = &info->modMap->defs;
710     info->modMap = mm;
711     return True;
712 }
713
714 /***====================================================================***/
715
716 static void
717 MergeIncludedSymbols(SymbolsInfo * into, SymbolsInfo * from,
718                      unsigned merge, XkbcDescPtr xkb)
719 {
720     register int i;
721     KeyInfo *key;
722
723     if (from->errorCount > 0)
724     {
725         into->errorCount += from->errorCount;
726         return;
727     }
728     if (into->name == NULL)
729     {
730         into->name = from->name;
731         from->name = NULL;
732     }
733     for (i = 0; i < XkbNumKbdGroups; i++)
734     {
735         if (from->groupNames[i] != None)
736         {
737             if ((merge != MergeAugment) || (into->groupNames[i] == None))
738                 into->groupNames[i] = from->groupNames[i];
739         }
740     }
741     for (i = 0, key = from->keys; i < from->nKeys; i++, key++)
742     {
743         if (merge != MergeDefault)
744             key->defs.merge = merge;
745         if (!AddKeySymbols(into, key, xkb))
746             into->errorCount++;
747     }
748     if (from->modMap != NULL)
749     {
750         ModMapEntry *mm, *next;
751         for (mm = from->modMap; mm != NULL; mm = next)
752         {
753             if (merge != MergeDefault)
754                 mm->defs.merge = merge;
755             if (!AddModMapEntry(into, mm))
756                 into->errorCount++;
757             next = (ModMapEntry *) mm->defs.next;
758             uFree(mm);
759         }
760         from->modMap = NULL;
761     }
762     if (!MergeAliases(&into->aliases, &from->aliases, merge))
763         into->errorCount++;
764     return;
765 }
766
767 typedef void (*FileHandler) (XkbFile * /* rtrn */ ,
768                              XkbcDescPtr /* xkb */ ,
769                              unsigned /* merge */ ,
770                              SymbolsInfo *      /* included */
771     );
772
773 static Bool
774 HandleIncludeSymbols(IncludeStmt * stmt,
775                      XkbcDescPtr xkb, SymbolsInfo * info, FileHandler hndlr)
776 {
777     unsigned newMerge;
778     XkbFile *rtrn;
779     SymbolsInfo included;
780     Bool haveSelf;
781
782     haveSelf = False;
783     if ((stmt->file == NULL) && (stmt->map == NULL))
784     {
785         haveSelf = True;
786         included = *info;
787         bzero(info, sizeof(SymbolsInfo));
788     }
789     else if (ProcessIncludeFile(stmt, XkmSymbolsIndex, &rtrn, &newMerge))
790     {
791         InitSymbolsInfo(&included, xkb);
792         included.fileID = included.dflt.defs.fileID = rtrn->id;
793         included.merge = included.dflt.defs.merge = MergeOverride;
794         if (stmt->modifier)
795         {
796             included.explicit_group = atoi(stmt->modifier) - 1;
797         }
798         else
799         {
800             included.explicit_group = info->explicit_group;
801         }
802         (*hndlr) (rtrn, xkb, MergeOverride, &included);
803         if (stmt->stmt != NULL)
804         {
805             if (included.name != NULL)
806                 uFree(included.name);
807             included.name = stmt->stmt;
808             stmt->stmt = NULL;
809         }
810     }
811     else
812     {
813         info->errorCount += 10;
814         return False;
815     }
816     if ((stmt->next != NULL) && (included.errorCount < 1))
817     {
818         IncludeStmt *next;
819         unsigned op;
820         SymbolsInfo next_incl;
821
822         for (next = stmt->next; next != NULL; next = next->next)
823         {
824             if ((next->file == NULL) && (next->map == NULL))
825             {
826                 haveSelf = True;
827                 MergeIncludedSymbols(&included, info, next->merge, xkb);
828                 FreeSymbolsInfo(info);
829             }
830             else if (ProcessIncludeFile(next, XkmSymbolsIndex, &rtrn, &op))
831             {
832                 InitSymbolsInfo(&next_incl, xkb);
833                 next_incl.fileID = next_incl.dflt.defs.fileID = rtrn->id;
834                 next_incl.merge = next_incl.dflt.defs.merge = MergeOverride;
835                 if (next->modifier)
836                 {
837                     next_incl.explicit_group = atoi(next->modifier) - 1;
838                 }
839                 else
840                 {
841                     next_incl.explicit_group = info->explicit_group;
842                 }
843                 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
844                 MergeIncludedSymbols(&included, &next_incl, op, xkb);
845                 FreeSymbolsInfo(&next_incl);
846             }
847             else
848             {
849                 info->errorCount += 10;
850                 return False;
851             }
852         }
853     }
854     if (haveSelf)
855         *info = included;
856     else
857     {
858         MergeIncludedSymbols(info, &included, newMerge, xkb);
859         FreeSymbolsInfo(&included);
860     }
861     return (info->errorCount == 0);
862 }
863
864 static LookupEntry groupNames[] = {
865     {"group1", 1},
866     {"group2", 2},
867     {"group3", 3},
868     {"group4", 4},
869     {"group5", 5},
870     {"group6", 6},
871     {"group7", 7},
872     {"group8", 8},
873     {NULL, 0}
874 };
875
876
877 #define SYMBOLS 1
878 #define ACTIONS 2
879
880 static Bool
881 GetGroupIndex(KeyInfo * key,
882               ExprDef * arrayNdx, unsigned what, unsigned *ndx_rtrn)
883 {
884     const char *name;
885     ExprResult tmp;
886
887     if (what == SYMBOLS)
888         name = "symbols";
889     else
890         name = "actions";
891
892     if (arrayNdx == NULL)
893     {
894         register int i;
895         unsigned defined;
896         if (what == SYMBOLS)
897             defined = key->symsDefined;
898         else
899             defined = key->actsDefined;
900
901         for (i = 0; i < XkbNumKbdGroups; i++)
902         {
903             if ((defined & (1 << i)) == 0)
904             {
905                 *ndx_rtrn = i;
906                 return True;
907             }
908         }
909         ERROR("Too many groups of %s for key %s (max %d)\n", name,
910                longText(key->name), XkbNumKbdGroups + 1);
911         ACTION("Ignoring %s defined for extra groups\n", name);
912         return False;
913     }
914     if (!ExprResolveInteger
915         (arrayNdx, &tmp, SimpleLookup, (char *) groupNames))
916     {
917         ERROR("Illegal group index for %s of key %s\n", name,
918                longText(key->name));
919         ACTION("Definition with non-integer array index ignored\n");
920         return False;
921     }
922     if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups))
923     {
924         ERROR("Group index for %s of key %s is out of range (1..%d)\n",
925                name, longText(key->name), XkbNumKbdGroups + 1);
926         ACTION("Ignoring %s for group %d\n", name, tmp.uval);
927         return False;
928     }
929     *ndx_rtrn = tmp.uval - 1;
930     return True;
931 }
932
933 static Bool
934 AddSymbolsToKey(KeyInfo * key,
935                 XkbcDescPtr xkb,
936                 char *field,
937                 ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info)
938 {
939     unsigned ndx, nSyms;
940     int i;
941
942     if (!GetGroupIndex(key, arrayNdx, SYMBOLS, &ndx))
943         return False;
944     if (value == NULL)
945     {
946         key->symsDefined |= (1 << ndx);
947         return True;
948     }
949     if (value->op != ExprKeysymList)
950     {
951         ERROR("Expected a list of symbols, found %s\n",
952                exprOpText(value->op));
953         ACTION("Ignoring symbols for group %d of %s\n", ndx,
954                 longText(key->name));
955         return False;
956     }
957     if (key->syms[ndx] != NULL)
958     {
959         WSGO("Symbols for key %s, group %d already defined\n",
960               longText(key->name), ndx);
961         return False;
962     }
963     nSyms = value->value.list.nSyms;
964     if (((key->numLevels[ndx] < nSyms) || (key->syms[ndx] == NULL)) &&
965         (!ResizeKeyGroup(key, ndx, nSyms, False)))
966     {
967         WSGO("Could not resize group %d of key %s\n", ndx,
968               longText(key->name));
969         ACTION("Symbols lost\n");
970         return False;
971     }
972     key->symsDefined |= (1 << ndx);
973     for (i = 0; i < nSyms; i++) {
974         if (!LookupKeysym(value->value.list.syms[i], &key->syms[ndx][i])) {
975             WSGO("Could not resolve keysym %s\n", value->value.list.syms[i]);
976             key->syms[ndx][i] = NoSymbol;
977         }
978     }
979     for (i = key->numLevels[ndx] - 1;
980          (i >= 0) && (key->syms[ndx][i] == NoSymbol); i--)
981     {
982         key->numLevels[ndx]--;
983     }
984     return True;
985 }
986
987 static Bool
988 AddActionsToKey(KeyInfo * key,
989                 XkbcDescPtr xkb,
990                 char *field,
991                 ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info)
992 {
993     register int i;
994     unsigned ndx, nActs;
995     ExprDef *act;
996     XkbAnyAction *toAct;
997
998     if (!GetGroupIndex(key, arrayNdx, ACTIONS, &ndx))
999         return False;
1000
1001     if (value == NULL)
1002     {
1003         key->actsDefined |= (1 << ndx);
1004         return True;
1005     }
1006     if (value->op != ExprActionList)
1007     {
1008         WSGO("Bad expression type (%d) for action list value\n", value->op);
1009         ACTION("Ignoring actions for group %d of %s\n", ndx,
1010                 longText(key->name));
1011         return False;
1012     }
1013     if (key->acts[ndx] != NULL)
1014     {
1015         WSGO("Actions for key %s, group %d already defined\n",
1016               longText(key->name), ndx);
1017         return False;
1018     }
1019     for (nActs = 0, act = value->value.child; act != NULL; nActs++)
1020     {
1021         act = (ExprDef *) act->common.next;
1022     }
1023     if (nActs < 1)
1024     {
1025         WSGO("Action list but not actions in AddActionsToKey\n");
1026         return False;
1027     }
1028     if (((key->numLevels[ndx] < nActs) || (key->acts[ndx] == NULL)) &&
1029         (!ResizeKeyGroup(key, ndx, nActs, True)))
1030     {
1031         WSGO("Could not resize group %d of key %s\n", ndx,
1032               longText(key->name));
1033         ACTION("Actions lost\n");
1034         return False;
1035     }
1036     key->actsDefined |= (1 << ndx);
1037
1038     toAct = (XkbAnyAction *) key->acts[ndx];
1039     act = value->value.child;
1040     for (i = 0; i < nActs; i++, toAct++)
1041     {
1042         if (!HandleActionDef(act, xkb, toAct, MergeOverride, info->action))
1043         {
1044             ERROR("Illegal action definition for %s\n",
1045                    longText(key->name));
1046             ACTION("Action for group %d/level %d ignored\n", ndx + 1, i + 1);
1047         }
1048         act = (ExprDef *) act->common.next;
1049     }
1050     return True;
1051 }
1052
1053 static int
1054 SetAllowNone(KeyInfo * key, ExprDef * arrayNdx, ExprDef * value)
1055 {
1056     ExprResult tmp;
1057     unsigned radio_groups = 0;
1058
1059     if (arrayNdx == NULL)
1060     {
1061         radio_groups = XkbAllRadioGroupsMask;
1062     }
1063     else
1064     {
1065         if (!ExprResolveInteger(arrayNdx, &tmp, RadioLookup, NULL))
1066         {
1067             ERROR("Illegal index in group name definition\n");
1068             ACTION("Definition with non-integer array index ignored\n");
1069             return False;
1070         }
1071         if ((tmp.uval < 1) || (tmp.uval > XkbMaxRadioGroups))
1072         {
1073             ERROR("Illegal radio group specified (must be 1..%d)\n",
1074                    XkbMaxRadioGroups + 1);
1075             ACTION("Value of \"allow none\" for group %d ignored\n",
1076                     tmp.uval);
1077             return False;
1078         }
1079         radio_groups |= (1 << (tmp.uval - 1));
1080     }
1081     if (!ExprResolveBoolean(value, &tmp, NULL, NULL))
1082     {
1083         ERROR("Illegal \"allow none\" value for %s\n",
1084                longText(key->name));
1085         ACTION("Non-boolean value ignored\n");
1086         return False;
1087     }
1088     if (tmp.uval)
1089         key->allowNone |= radio_groups;
1090     else
1091         key->allowNone &= ~radio_groups;
1092     return True;
1093 }
1094
1095
1096 static LookupEntry lockingEntries[] = {
1097     {"true", XkbKB_Lock},
1098     {"yes", XkbKB_Lock},
1099     {"on", XkbKB_Lock},
1100     {"false", XkbKB_Default},
1101     {"no", XkbKB_Default},
1102     {"off", XkbKB_Default},
1103     {"permanent", XkbKB_Lock | XkbKB_Permanent},
1104     {NULL, 0}
1105 };
1106
1107 static LookupEntry repeatEntries[] = {
1108     {"true", RepeatYes},
1109     {"yes", RepeatYes},
1110     {"on", RepeatYes},
1111     {"false", RepeatNo},
1112     {"no", RepeatNo},
1113     {"off", RepeatNo},
1114     {"default", RepeatUndefined},
1115     {NULL, 0}
1116 };
1117
1118 static LookupEntry rgEntries[] = {
1119     {"none", 0},
1120     {NULL, 0}
1121 };
1122
1123 static Bool
1124 SetSymbolsField(KeyInfo * key,
1125                 XkbcDescPtr xkb,
1126                 char *field,
1127                 ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info)
1128 {
1129     Bool ok = True;
1130     ExprResult tmp;
1131
1132     if (uStrCaseCmp(field, "type") == 0)
1133     {
1134         ExprResult ndx;
1135         if ((!ExprResolveString(value, &tmp, NULL, NULL))
1136             && (warningLevel > 0))
1137         {
1138             WARN("The type field of a key symbol map must be a string\n");
1139             ACTION("Ignoring illegal type definition\n");
1140         }
1141         if (arrayNdx == NULL)
1142         {
1143             key->dfltType = XkbcInternAtom(tmp.str, False);
1144             key->defs.defined |= _Key_Type_Dflt;
1145         }
1146         else if (!ExprResolveInteger(arrayNdx, &ndx, SimpleLookup,
1147                                      (char *) groupNames))
1148         {
1149             ERROR("Illegal group index for type of key %s\n",
1150                    longText(key->name));
1151             ACTION("Definition with non-integer array index ignored\n");
1152             free(tmp.str);
1153             return False;
1154         }
1155         else if ((ndx.uval < 1) || (ndx.uval > XkbNumKbdGroups))
1156         {
1157             ERROR
1158                 ("Group index for type of key %s is out of range (1..%d)\n",
1159                  longText(key->name), XkbNumKbdGroups + 1);
1160             ACTION("Ignoring type for group %d\n", ndx.uval);
1161             free(tmp.str);
1162             return False;
1163         }
1164         else
1165         {
1166             key->types[ndx.uval - 1] = XkbcInternAtom(tmp.str, False);
1167             key->typesDefined |= (1 << (ndx.uval - 1));
1168         }
1169         free(tmp.str);
1170     }
1171     else if (uStrCaseCmp(field, "symbols") == 0)
1172         return AddSymbolsToKey(key, xkb, field, arrayNdx, value, info);
1173     else if (uStrCaseCmp(field, "actions") == 0)
1174         return AddActionsToKey(key, xkb, field, arrayNdx, value, info);
1175     else if ((uStrCaseCmp(field, "vmods") == 0) ||
1176              (uStrCaseCmp(field, "virtualmods") == 0) ||
1177              (uStrCaseCmp(field, "virtualmodifiers") == 0))
1178     {
1179         ok = ExprResolveModMask(value, &tmp, LookupVModMask, (char *) xkb);
1180         if (ok)
1181         {
1182             key->vmodmap = (tmp.uval >> 8);
1183             key->defs.defined |= _Key_VModMap;
1184         }
1185         else
1186         {
1187             ERROR("Expected a virtual modifier mask, found %s\n",
1188                    exprOpText(value->op));
1189             ACTION("Ignoring virtual modifiers definition for key %s\n",
1190                     longText(key->name));
1191         }
1192     }
1193     else if ((uStrCaseCmp(field, "locking") == 0)
1194              || (uStrCaseCmp(field, "lock") == 0)
1195              || (uStrCaseCmp(field, "locks") == 0))
1196     {
1197         ok = ExprResolveEnum(value, &tmp, lockingEntries);
1198         if (ok)
1199             key->behavior.type = tmp.uval;
1200         key->defs.defined |= _Key_Behavior;
1201     }
1202     else if ((uStrCaseCmp(field, "radiogroup") == 0) ||
1203              (uStrCaseCmp(field, "permanentradiogroup") == 0))
1204     {
1205         Bool permanent = False;
1206         if (uStrCaseCmp(field, "permanentradiogroup") == 0)
1207             permanent = True;
1208         ok = ExprResolveInteger(value, &tmp, SimpleLookup,
1209                                 (char *) rgEntries);
1210         if (!ok)
1211         {
1212             ERROR("Illegal radio group specification for %s\n",
1213                    longText(key->name));
1214             ACTION("Non-integer radio group ignored\n");
1215             return False;
1216         }
1217         if (tmp.uval == 0)
1218         {
1219             key->behavior.type = XkbKB_Default;
1220             key->behavior.data = 0;
1221             return ok;
1222         }
1223         if ((tmp.uval < 1) || (tmp.uval > XkbMaxRadioGroups))
1224         {
1225             ERROR
1226                 ("Radio group specification for %s out of range (1..32)\n",
1227                  longText(key->name));
1228             ACTION("Illegal radio group %d ignored\n", tmp.uval);
1229             return False;
1230         }
1231         key->behavior.type =
1232             XkbKB_RadioGroup | (permanent ? XkbKB_Permanent : 0);
1233         key->behavior.data = tmp.uval - 1;
1234         if (key->allowNone & (1 << (tmp.uval - 1)))
1235             key->behavior.data |= XkbKB_RGAllowNone;
1236         key->defs.defined |= _Key_Behavior;
1237     }
1238     else if (uStrCaseEqual(field, "allownone"))
1239     {
1240         ok = SetAllowNone(key, arrayNdx, value);
1241     }
1242     else if (uStrCasePrefix("overlay", field) ||
1243              uStrCasePrefix("permanentoverlay", field))
1244     {
1245         Bool permanent = False;
1246         char *which;
1247         int overlayNdx;
1248         if (uStrCasePrefix("permanent", field))
1249         {
1250             permanent = True;
1251             which = &field[sizeof("permanentoverlay") - 1];
1252         }
1253         else
1254         {
1255             which = &field[sizeof("overlay") - 1];
1256         }
1257         if (sscanf(which, "%d", &overlayNdx) == 1)
1258         {
1259             if (((overlayNdx < 1) || (overlayNdx > 2)) && (warningLevel > 0))
1260             {
1261                 ERROR("Illegal overlay %d specified for %s\n",
1262                        overlayNdx, longText(key->name));
1263                 ACTION("Ignored\n");
1264                 return False;
1265             }
1266         }
1267         else if (*which == '\0')
1268             overlayNdx = 1;
1269         else if (warningLevel > 0)
1270         {
1271             ERROR("Illegal overlay \"%s\" specified for %s\n",
1272                    which, longText(key->name));
1273             ACTION("Ignored\n");
1274             return False;
1275         }
1276         ok = ExprResolveKeyName(value, &tmp, NULL, NULL);
1277         if (!ok)
1278         {
1279             ERROR("Illegal overlay key specification for %s\n",
1280                    longText(key->name));
1281             ACTION("Overlay key must be specified by name\n");
1282             return False;
1283         }
1284         if (overlayNdx == 1)
1285             key->behavior.type = XkbKB_Overlay1;
1286         else
1287             key->behavior.type = XkbKB_Overlay2;
1288         if (permanent)
1289             key->behavior.type |= XkbKB_Permanent;
1290
1291         key->behavior.data = 0;
1292         key->nameForOverlayKey = KeyNameToLong(tmp.keyName.name);
1293         key->defs.defined |= _Key_Behavior;
1294     }
1295     else if ((uStrCaseCmp(field, "repeating") == 0) ||
1296              (uStrCaseCmp(field, "repeats") == 0) ||
1297              (uStrCaseCmp(field, "repeat") == 0))
1298     {
1299         ok = ExprResolveEnum(value, &tmp, repeatEntries);
1300         if (!ok)
1301         {
1302             ERROR("Illegal repeat setting for %s\n",
1303                    longText(key->name));
1304             ACTION("Non-boolean repeat setting ignored\n");
1305             return False;
1306         }
1307         key->repeat = tmp.uval;
1308         key->defs.defined |= _Key_Repeat;
1309     }
1310     else if ((uStrCaseCmp(field, "groupswrap") == 0) ||
1311              (uStrCaseCmp(field, "wrapgroups") == 0))
1312     {
1313         ok = ExprResolveBoolean(value, &tmp, NULL, NULL);
1314         if (!ok)
1315         {
1316             ERROR("Illegal groupsWrap setting for %s\n",
1317                    longText(key->name));
1318             ACTION("Non-boolean value ignored\n");
1319             return False;
1320         }
1321         if (tmp.uval)
1322             key->groupInfo = XkbWrapIntoRange;
1323         else
1324             key->groupInfo = XkbClampIntoRange;
1325         key->defs.defined |= _Key_GroupInfo;
1326     }
1327     else if ((uStrCaseCmp(field, "groupsclamp") == 0) ||
1328              (uStrCaseCmp(field, "clampgroups") == 0))
1329     {
1330         ok = ExprResolveBoolean(value, &tmp, NULL, NULL);
1331         if (!ok)
1332         {
1333             ERROR("Illegal groupsClamp setting for %s\n",
1334                    longText(key->name));
1335             ACTION("Non-boolean value ignored\n");
1336             return False;
1337         }
1338         if (tmp.uval)
1339             key->groupInfo = XkbClampIntoRange;
1340         else
1341             key->groupInfo = XkbWrapIntoRange;
1342         key->defs.defined |= _Key_GroupInfo;
1343     }
1344     else if ((uStrCaseCmp(field, "groupsredirect") == 0) ||
1345              (uStrCaseCmp(field, "redirectgroups") == 0))
1346     {
1347         if (!ExprResolveInteger
1348             (value, &tmp, SimpleLookup, (char *) groupNames))
1349         {
1350             ERROR("Illegal group index for redirect of key %s\n",
1351                    longText(key->name));
1352             ACTION("Definition with non-integer group ignored\n");
1353             return False;
1354         }
1355         if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups))
1356         {
1357             ERROR("Out-of-range (1..%d) group for redirect of key %s\n",
1358                    XkbNumKbdGroups, longText(key->name));
1359             ERROR("Ignoring illegal group %d\n", tmp.uval);
1360             return False;
1361         }
1362         key->groupInfo =
1363             XkbSetGroupInfo(0, XkbRedirectIntoRange, tmp.uval - 1);
1364         key->defs.defined |= _Key_GroupInfo;
1365     }
1366     else
1367     {
1368         ERROR("Unknown field %s in a symbol interpretation\n", field);
1369         ACTION("Definition ignored\n");
1370         ok = False;
1371     }
1372     return ok;
1373 }
1374
1375 static int
1376 SetGroupName(SymbolsInfo * info, ExprDef * arrayNdx, ExprDef * value)
1377 {
1378     ExprResult tmp, name;
1379
1380     if ((arrayNdx == NULL) && (warningLevel > 0))
1381     {
1382         WARN("You must specify an index when specifying a group name\n");
1383         ACTION("Group name definition without array subscript ignored\n");
1384         return False;
1385     }
1386     if (!ExprResolveInteger
1387         (arrayNdx, &tmp, SimpleLookup, (char *) groupNames))
1388     {
1389         ERROR("Illegal index in group name definition\n");
1390         ACTION("Definition with non-integer array index ignored\n");
1391         return False;
1392     }
1393     if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups))
1394     {
1395         ERROR
1396             ("Attempt to specify name for illegal group (must be 1..%d)\n",
1397              XkbNumKbdGroups + 1);
1398         ACTION("Name for group %d ignored\n", tmp.uval);
1399         return False;
1400     }
1401     if (!ExprResolveString(value, &name, NULL, NULL))
1402     {
1403         ERROR("Group name must be a string\n");
1404         ACTION("Illegal name for group %d ignored\n", tmp.uval);
1405         return False;
1406     }
1407     info->groupNames[tmp.uval - 1 + info->explicit_group] =
1408         XkbcInternAtom(name.str, False);
1409
1410     return True;
1411 }
1412
1413 static int
1414 HandleSymbolsVar(VarDef * stmt, XkbcDescPtr xkb, SymbolsInfo * info)
1415 {
1416     ExprResult elem, field, tmp;
1417     ExprDef *arrayNdx;
1418     Bool ret;
1419
1420     if (ExprResolveLhs(stmt->name, &elem, &field, &arrayNdx) == 0)
1421         return 0;               /* internal error, already reported */
1422     if (elem.str && (uStrCaseCmp(elem.str, "key") == 0))
1423     {
1424         ret = SetSymbolsField(&info->dflt, xkb, field.str, arrayNdx,
1425                               stmt->value, info);
1426     }
1427     else if ((elem.str == NULL) && ((uStrCaseCmp(field.str, "name") == 0) ||
1428                                     (uStrCaseCmp(field.str, "groupname") ==
1429                                      0)))
1430     {
1431         ret = SetGroupName(info, arrayNdx, stmt->value);
1432     }
1433     else if ((elem.str == NULL)
1434              && ((uStrCaseCmp(field.str, "groupswrap") == 0)
1435                  || (uStrCaseCmp(field.str, "wrapgroups") == 0)))
1436     {
1437         if (!ExprResolveBoolean(stmt->value, &tmp, NULL, NULL))
1438         {
1439             ERROR("Illegal setting for global groupsWrap\n");
1440             ACTION("Non-boolean value ignored\n");
1441             ret = False;
1442         }
1443         else {
1444             if (tmp.uval)
1445                 info->groupInfo = XkbWrapIntoRange;
1446             else
1447                 info->groupInfo = XkbClampIntoRange;
1448             ret = True;
1449         }
1450     }
1451     else if ((elem.str == NULL)
1452              && ((uStrCaseCmp(field.str, "groupsclamp") == 0)
1453                  || (uStrCaseCmp(field.str, "clampgroups") == 0)))
1454     {
1455         if (!ExprResolveBoolean(stmt->value, &tmp, NULL, NULL))
1456         {
1457             ERROR("Illegal setting for global groupsClamp\n");
1458             ACTION("Non-boolean value ignored\n");
1459             return False;
1460         }
1461         else {
1462             if (tmp.uval)
1463                 info->groupInfo = XkbClampIntoRange;
1464             else
1465                 info->groupInfo = XkbWrapIntoRange;
1466             ret = True;
1467         }
1468     }
1469     else if ((elem.str == NULL)
1470              && ((uStrCaseCmp(field.str, "groupsredirect") == 0)
1471                  || (uStrCaseCmp(field.str, "redirectgroups") == 0)))
1472     {
1473         if (!ExprResolveInteger(stmt->value, &tmp,
1474                                 SimpleLookup, (char *) groupNames))
1475         {
1476             ERROR("Illegal group index for global groupsRedirect\n");
1477             ACTION("Definition with non-integer group ignored\n");
1478             ret = False;
1479         }
1480         else {
1481             if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups))
1482             {
1483                 ERROR
1484                     ("Out-of-range (1..%d) group for global groupsRedirect\n",
1485                      XkbNumKbdGroups);
1486                 ACTION("Ignoring illegal group %d\n", tmp.uval);
1487                 ret = False;
1488             }
1489             else {
1490                 info->groupInfo = XkbSetGroupInfo(0, XkbRedirectIntoRange,
1491                                                   tmp.uval);
1492                 ret = True;
1493             }
1494         }
1495     }
1496     else if ((elem.str == NULL) && (uStrCaseCmp(field.str, "allownone") == 0))
1497     {
1498         ret = SetAllowNone(&info->dflt, arrayNdx, stmt->value);
1499     }
1500     else {
1501         ret = SetActionField(xkb, elem.str, field.str, arrayNdx, stmt->value,
1502                              &info->action);
1503     }
1504
1505     free(elem.str);
1506     free(field.str);
1507     return ret;
1508 }
1509
1510 static Bool
1511 HandleSymbolsBody(VarDef * def,
1512                   XkbcDescPtr xkb, KeyInfo * key, SymbolsInfo * info)
1513 {
1514     Bool ok = True;
1515     ExprResult tmp, field;
1516     ExprDef *arrayNdx;
1517
1518     for (; def != NULL; def = (VarDef *) def->common.next)
1519     {
1520         if ((def->name) && (def->name->type == ExprFieldRef))
1521         {
1522             ok = HandleSymbolsVar(def, xkb, info);
1523             continue;
1524         }
1525         else
1526         {
1527             if (def->name == NULL)
1528             {
1529                 if ((def->value == NULL)
1530                     || (def->value->op == ExprKeysymList))
1531                     field.str = "symbols";
1532                 else
1533                     field.str = "actions";
1534                 arrayNdx = NULL;
1535             }
1536             else
1537             {
1538                 ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx);
1539             }
1540             if (ok)
1541                 ok = SetSymbolsField(key, xkb, field.str, arrayNdx,
1542                                      def->value, info);
1543         }
1544     }
1545     return ok;
1546 }
1547
1548 static Bool
1549 SetExplicitGroup(SymbolsInfo * info, KeyInfo * key)
1550 {
1551     unsigned group = info->explicit_group;
1552
1553     if (group == 0)
1554         return True;
1555
1556     if ((key->typesDefined | key->symsDefined | key->actsDefined) & ~1)
1557     {
1558         int i;
1559         WARN("For the map %s an explicit group specified\n", info->name);
1560         WARN("but key %s has more than one group defined\n",
1561               longText(key->name));
1562         ACTION("All groups except first one will be ignored\n");
1563         for (i = 1; i < XkbNumKbdGroups; i++)
1564         {
1565             key->numLevels[i] = 0;
1566             if (key->syms[i] != NULL)
1567                 uFree(key->syms[i]);
1568             key->syms[i] = (CARD32 *) NULL;
1569             if (key->acts[i] != NULL)
1570                 uFree(key->acts[i]);
1571             key->acts[i] = (XkbcAction *) NULL;
1572             key->types[i] = (Atom) 0;
1573         }
1574     }
1575     key->typesDefined = key->symsDefined = key->actsDefined = 1 << group;
1576
1577     key->numLevels[group] = key->numLevels[0];
1578     key->numLevels[0] = 0;
1579     key->syms[group] = key->syms[0];
1580     key->syms[0] = (CARD32 *) NULL;
1581     key->acts[group] = key->acts[0];
1582     key->acts[0] = (XkbcAction *) NULL;
1583     key->types[group] = key->types[0];
1584     key->types[0] = (Atom) 0;
1585     return True;
1586 }
1587
1588 static int
1589 HandleSymbolsDef(SymbolsDef * stmt,
1590                  XkbcDescPtr xkb, unsigned merge, SymbolsInfo * info)
1591 {
1592     KeyInfo key;
1593
1594     InitKeyInfo(&key);
1595     CopyKeyInfo(&info->dflt, &key, False);
1596     key.defs.merge = stmt->merge;
1597     key.name = KeyNameToLong(stmt->keyName);
1598     if (!HandleSymbolsBody((VarDef *) stmt->symbols, xkb, &key, info))
1599     {
1600         info->errorCount++;
1601         return False;
1602     }
1603
1604     if (!SetExplicitGroup(info, &key))
1605     {
1606         info->errorCount++;
1607         return False;
1608     }
1609
1610     if (!AddKeySymbols(info, &key, xkb))
1611     {
1612         info->errorCount++;
1613         return False;
1614     }
1615     return True;
1616 }
1617
1618 static Bool
1619 HandleModMapDef(ModMapDef * def,
1620                 XkbcDescPtr xkb, unsigned merge, SymbolsInfo * info)
1621 {
1622     ExprDef *key;
1623     ModMapEntry tmp;
1624     ExprResult rtrn;
1625     Bool ok;
1626
1627     if (!LookupModIndex(NULL, None, def->modifier, TypeInt, &rtrn))
1628     {
1629         ERROR("Illegal modifier map definition\n");
1630         ACTION("Ignoring map for non-modifier \"%s\"\n",
1631                 XkbcAtomText(def->modifier));
1632         return False;
1633     }
1634     ok = True;
1635     tmp.modifier = rtrn.uval;
1636     for (key = def->keys; key != NULL; key = (ExprDef *) key->common.next)
1637     {
1638         if ((key->op == ExprValue) && (key->type == TypeKeyName))
1639         {
1640             tmp.haveSymbol = False;
1641             tmp.u.keyName = KeyNameToLong(key->value.keyName);
1642         }
1643         else if (ExprResolveKeySym(key, &rtrn, NULL, NULL))
1644         {
1645             tmp.haveSymbol = True;
1646             tmp.u.keySym = rtrn.uval;
1647         }
1648         else
1649         {
1650             ERROR("Modmap entries may contain only key names or keysyms\n");
1651             ACTION("Illegal definition for %s modifier ignored\n",
1652                     XkbcModIndexText(tmp.modifier));
1653             continue;
1654         }
1655
1656         ok = AddModMapEntry(info, &tmp) && ok;
1657     }
1658     return ok;
1659 }
1660
1661 static void
1662 HandleSymbolsFile(XkbFile * file,
1663                   XkbcDescPtr xkb, unsigned merge, SymbolsInfo * info)
1664 {
1665     ParseCommon *stmt;
1666
1667     info->name = _XkbDupString(file->name);
1668     stmt = file->defs;
1669     while (stmt)
1670     {
1671         switch (stmt->stmtType)
1672         {
1673         case StmtInclude:
1674             if (!HandleIncludeSymbols((IncludeStmt *) stmt, xkb, info,
1675                                       HandleSymbolsFile))
1676                 info->errorCount++;
1677             break;
1678         case StmtSymbolsDef:
1679             if (!HandleSymbolsDef((SymbolsDef *) stmt, xkb, merge, info))
1680                 info->errorCount++;
1681             break;
1682         case StmtVarDef:
1683             if (!HandleSymbolsVar((VarDef *) stmt, xkb, info))
1684                 info->errorCount++;
1685             break;
1686         case StmtVModDef:
1687             if (!HandleVModDef((VModDef *) stmt, merge, &info->vmods))
1688                 info->errorCount++;
1689             break;
1690         case StmtInterpDef:
1691             ERROR("Interpretation files may not include other types\n");
1692             ACTION("Ignoring definition of symbol interpretation\n");
1693             info->errorCount++;
1694             break;
1695         case StmtKeycodeDef:
1696             ERROR("Interpretation files may not include other types\n");
1697             ACTION("Ignoring definition of key name\n");
1698             info->errorCount++;
1699             break;
1700         case StmtModMapDef:
1701             if (!HandleModMapDef((ModMapDef *) stmt, xkb, merge, info))
1702                 info->errorCount++;
1703             break;
1704         default:
1705             WSGO("Unexpected statement type %d in HandleSymbolsFile\n",
1706                   stmt->stmtType);
1707             break;
1708         }
1709         stmt = stmt->next;
1710         if (info->errorCount > 10)
1711         {
1712 #ifdef NOISY
1713             ERROR("Too many errors\n");
1714 #endif
1715             ACTION("Abandoning symbols file \"%s\"\n", file->topName);
1716             break;
1717         }
1718     }
1719     return;
1720 }
1721
1722 static Bool
1723 FindKeyForSymbol(XkbcDescPtr xkb, CARD32 sym, unsigned int *kc_rtrn)
1724 {
1725     register int i, j;
1726     register Bool gotOne;
1727
1728     j = 0;
1729     do
1730     {
1731         gotOne = False;
1732         for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++)
1733         {
1734             if (j < (int) XkbKeyNumSyms(xkb, i))
1735             {
1736                 gotOne = True;
1737                 if ((XkbKeySym(xkb, i, j) == sym))
1738                 {
1739                     *kc_rtrn = i;
1740                     return True;
1741                 }
1742             }
1743         }
1744         j++;
1745     }
1746     while (gotOne);
1747     return False;
1748 }
1749
1750 /**
1751  * Find the given name in the xkb->map->types and return its index.
1752  *
1753  * @param name The atom to search for.
1754  * @param type_rtrn Set to the index of the name if found.
1755  *
1756  * @return True if found, False otherwise.
1757  */
1758 static Bool
1759 FindNamedType(XkbcDescPtr xkb, Atom name, unsigned *type_rtrn)
1760 {
1761     register unsigned n;
1762
1763     if (xkb && xkb->map && xkb->map->types)
1764     {
1765         for (n = 0; n < xkb->map->num_types; n++)
1766         {
1767             if (xkb->map->types[n].name == (Atom) name)
1768             {
1769                 *type_rtrn = n;
1770                 return True;
1771             }
1772         }
1773     }
1774     return False;
1775 }
1776
1777 /**
1778  * Assign a type to the given sym and return the Atom for the type assigned.
1779  *
1780  * Simple recipe:
1781  * - ONE_LEVEL for width 0/1
1782  * - ALPHABETIC for 2 shift levels, with lower/upercase
1783  * - KEYPAD for keypad keys.
1784  * - TWO_LEVEL for other 2 shift level keys.
1785  * and the same for four level keys.
1786  *
1787  * @param width Number of sysms in syms.
1788  * @param syms The keysyms for the given key (must be size width).
1789  * @param typeNameRtrn Set to the Atom of the type name.
1790  *
1791  * @returns True if a type could be found, False otherwise.
1792  */
1793 static Bool
1794 FindAutomaticType(int width, CARD32 * syms, Atom * typeNameRtrn,
1795                   Bool * autoType)
1796 {
1797     *autoType = False;
1798     if ((width == 1) || (width == 0))
1799     {
1800         *typeNameRtrn = XkbcInternAtom("ONE_LEVEL", False);
1801         *autoType = True;
1802     }
1803     else if (width == 2)
1804     {
1805         if (syms && XkbcKSIsLower(syms[0]) && XkbcKSIsUpper(syms[1]))
1806         {
1807             *typeNameRtrn = XkbcInternAtom("ALPHABETIC", False);
1808         }
1809         else if (syms && (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1])))
1810         {
1811             *typeNameRtrn = XkbcInternAtom("KEYPAD", False);
1812             *autoType = True;
1813         }
1814         else
1815         {
1816             *typeNameRtrn = XkbcInternAtom("TWO_LEVEL", False);
1817             *autoType = True;
1818         }
1819     }
1820     else if (width <= 4)
1821     {
1822         if (syms && XkbcKSIsLower(syms[0]) && XkbcKSIsUpper(syms[1]))
1823             if (XkbcKSIsLower(syms[2]) && XkbcKSIsUpper(syms[3]))
1824                 *typeNameRtrn =
1825                     XkbcInternAtom("FOUR_LEVEL_ALPHABETIC", False);
1826             else
1827                 *typeNameRtrn = XkbcInternAtom("FOUR_LEVEL_SEMIALPHABETIC",
1828                                               False);
1829
1830         else if (syms && (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1])))
1831             *typeNameRtrn = XkbcInternAtom("FOUR_LEVEL_KEYPAD", False);
1832         else
1833             *typeNameRtrn = XkbcInternAtom("FOUR_LEVEL", False);
1834         /* XXX: why not set autoType here? */
1835     }
1836     return ((width >= 0) && (width <= 4));
1837 }
1838
1839 /**
1840  * Ensure the given KeyInfo is in a coherent state, i.e. no gaps between the
1841  * groups, and reduce to one group if all groups are identical anyway.
1842  */
1843 static void
1844 PrepareKeyDef(KeyInfo * key)
1845 {
1846     int i, j, width, defined, lastGroup;
1847     Bool identical;
1848
1849     defined = key->symsDefined | key->actsDefined | key->typesDefined;
1850     /* get highest group number */
1851     for (i = XkbNumKbdGroups - 1; i >= 0; i--)
1852     {
1853         if (defined & (1 << i))
1854             break;
1855     }
1856     lastGroup = i;
1857
1858     if (lastGroup == 0)
1859         return;
1860
1861     /* If there are empty groups between non-empty ones fill them with data */
1862     /* from the first group. */
1863     /* We can make a wrong assumption here. But leaving gaps is worse. */
1864     for (i = lastGroup; i > 0; i--)
1865     {
1866         if (defined & (1 << i))
1867             continue;
1868         width = key->numLevels[0];
1869         if (key->typesDefined & 1)
1870         {
1871             for (j = 0; j < width; j++)
1872             {
1873                 key->types[i] = key->types[0];
1874             }
1875             key->typesDefined |= 1 << i;
1876         }
1877         if ((key->actsDefined & 1) && key->acts[0])
1878         {
1879             key->acts[i] = uTypedCalloc(width, XkbcAction);
1880             if (key->acts[i] == NULL)
1881                 continue;
1882             memcpy((void *) key->acts[i], (void *) key->acts[0],
1883                    width * sizeof(XkbcAction));
1884             key->actsDefined |= 1 << i;
1885         }
1886         if ((key->symsDefined & 1) && key->syms[0])
1887         {
1888             key->syms[i] = uTypedCalloc(width, CARD32);
1889             if (key->syms[i] == NULL)
1890                 continue;
1891             memcpy((void *) key->syms[i], (void *) key->syms[0],
1892                    width * sizeof(CARD32));
1893             key->symsDefined |= 1 << i;
1894         }
1895         if (defined & 1)
1896         {
1897             key->numLevels[i] = key->numLevels[0];
1898         }
1899     }
1900     /* If all groups are completely identical remove them all */
1901     /* exept the first one. */
1902     identical = True;
1903     for (i = lastGroup; i > 0; i--)
1904     {
1905         if ((key->numLevels[i] != key->numLevels[0]) ||
1906             (key->types[i] != key->types[0]))
1907         {
1908             identical = False;
1909             break;
1910         }
1911         if ((key->syms[i] != key->syms[0]) &&
1912             (key->syms[i] == NULL || key->syms[0] == NULL ||
1913              memcmp((void *) key->syms[i], (void *) key->syms[0],
1914                     sizeof(CARD32) * key->numLevels[0])))
1915         {
1916             identical = False;
1917             break;
1918         }
1919         if ((key->acts[i] != key->acts[0]) &&
1920             (key->acts[i] == NULL || key->acts[0] == NULL ||
1921              memcmp((void *) key->acts[i], (void *) key->acts[0],
1922                     sizeof(XkbcAction) * key->numLevels[0])))
1923         {
1924             identical = False;
1925             break;
1926         }
1927     }
1928     if (identical)
1929     {
1930         for (i = lastGroup; i > 0; i--)
1931         {
1932             key->numLevels[i] = 0;
1933             if (key->syms[i] != NULL)
1934                 uFree(key->syms[i]);
1935             key->syms[i] = (CARD32 *) NULL;
1936             if (key->acts[i] != NULL)
1937                 uFree(key->acts[i]);
1938             key->acts[i] = (XkbcAction *) NULL;
1939             key->types[i] = (Atom) 0;
1940         }
1941         key->symsDefined &= 1;
1942         key->actsDefined &= 1;
1943         key->typesDefined &= 1;
1944     }
1945     return;
1946 }
1947
1948 /**
1949  * Copy the KeyInfo into the keyboard description.
1950  *
1951  * This function recurses.
1952  */
1953 static Bool
1954 CopySymbolsDef(XkbcDescPtr xkb, KeyInfo *key, int start_from)
1955 {
1956     register int i;
1957     unsigned okc, kc, width, tmp, nGroups;
1958     XkbKeyTypePtr type;
1959     Bool haveActions, autoType, useAlias;
1960     CARD32 *outSyms;
1961     XkbcAction *outActs;
1962     unsigned types[XkbNumKbdGroups];
1963
1964     useAlias = (start_from == 0);
1965
1966     /* get the keycode for the key. */
1967     if (!FindNamedKey(xkb, key->name, &kc, useAlias, CreateKeyNames(xkb),
1968                       start_from))
1969     {
1970         if ((start_from == 0) && (warningLevel >= 5))
1971         {
1972             WARN("Key %s not found in %s keycodes\n",
1973                   longText(key->name),
1974                   XkbcAtomText(xkb->names->keycodes));
1975             ACTION("Symbols ignored\n");
1976         }
1977         return False;
1978     }
1979
1980     haveActions = False;
1981     for (i = width = nGroups = 0; i < XkbNumKbdGroups; i++)
1982     {
1983         if (((i + 1) > nGroups)
1984             && (((key->symsDefined | key->actsDefined) & (1 << i))
1985                 || (key->typesDefined) & (1 << i)))
1986             nGroups = i + 1;
1987         if (key->acts[i])
1988             haveActions = True;
1989         autoType = False;
1990         /* Assign the type to the key, if it is missing. */
1991         if (key->types[i] == None)
1992         {
1993             if (key->dfltType != None)
1994                 key->types[i] = key->dfltType;
1995             else if (FindAutomaticType(key->numLevels[i], key->syms[i],
1996                                        &key->types[i], &autoType))
1997             {
1998             }
1999             else
2000             {
2001                 if (warningLevel >= 5)
2002                 {
2003                     WARN("No automatic type for %d symbols\n",
2004                           (unsigned int) key->numLevels[i]);
2005                     ACTION("Using %s for the %s key (keycode %d)\n",
2006                             XkbcAtomText(key->types[i]),
2007                             longText(key->name), kc);
2008                 }
2009             }
2010         }
2011         if (FindNamedType(xkb, key->types[i], &types[i]))
2012         {
2013             if (!autoType || key->numLevels[i] > 2)
2014                 xkb->server->explicit[kc] |= (1 << i);
2015         }
2016         else
2017         {
2018             if (warningLevel >= 3)
2019             {
2020                 WARN("Type \"%s\" is not defined\n",
2021                       XkbcAtomText(key->types[i]));
2022                 ACTION("Using TWO_LEVEL for the %s key (keycode %d)\n",
2023                         longText(key->name), kc);
2024             }
2025             types[i] = XkbTwoLevelIndex;
2026         }
2027         /* if the type specifies less syms than the key has, shrink the key */
2028         type = &xkb->map->types[types[i]];
2029         if (type->num_levels < key->numLevels[i])
2030         {
2031             if (warningLevel > 0)
2032             {
2033                 WARN
2034                     ("Type \"%s\" has %d levels, but %s has %d symbols\n",
2035                      XkbcAtomText(type->name),
2036                      (unsigned int) type->num_levels,
2037                      longText(key->name),
2038                      (unsigned int) key->numLevels[i]);
2039                 ACTION("Ignoring extra symbols\n");
2040             }
2041             key->numLevels[i] = type->num_levels;
2042         }
2043         if (key->numLevels[i] > width)
2044             width = key->numLevels[i];
2045         if (type->num_levels > width)
2046             width = type->num_levels;
2047     }
2048
2049     /* width is now the largest width found */
2050
2051     i = width * nGroups;
2052     outSyms = XkbcResizeKeySyms(xkb, kc, i);
2053     if (outSyms == NULL)
2054     {
2055         WSGO("Could not enlarge symbols for %s (keycode %d)\n",
2056               longText(key->name), kc);
2057         return False;
2058     }
2059     if (haveActions)
2060     {
2061         outActs = XkbcResizeKeyActions(xkb, kc, i);
2062         if (outActs == NULL)
2063         {
2064             WSGO("Could not enlarge actions for %s (key %d)\n",
2065                   longText(key->name), kc);
2066             return False;
2067         }
2068         xkb->server->explicit[kc] |= XkbExplicitInterpretMask;
2069     }
2070     else
2071         outActs = NULL;
2072     if (key->defs.defined & _Key_GroupInfo)
2073         i = key->groupInfo;
2074     else
2075         i = xkb->map->key_sym_map[kc].group_info;
2076
2077     xkb->map->key_sym_map[kc].group_info = XkbSetNumGroups(i, nGroups);
2078     xkb->map->key_sym_map[kc].width = width;
2079     for (i = 0; i < nGroups; i++)
2080     {
2081         /* assign kt_index[i] to the index of the type in map->types.
2082          * kt_index[i] may have been set by a previous run (if we have two
2083          * layouts specified). Let's not overwrite it with the ONE_LEVEL
2084          * default group if we dont even have keys for this group anyway.
2085          *
2086          * FIXME: There should be a better fix for this.
2087          */
2088         if (key->numLevels[i])
2089             xkb->map->key_sym_map[kc].kt_index[i] = types[i];
2090         if (key->syms[i] != NULL)
2091         {
2092             /* fill key to "width" symbols*/
2093             for (tmp = 0; tmp < width; tmp++)
2094             {
2095                 if (tmp < key->numLevels[i])
2096                     outSyms[tmp] = key->syms[i][tmp];
2097                 else
2098                     outSyms[tmp] = NoSymbol;
2099                 if ((outActs != NULL) && (key->acts[i] != NULL))
2100                 {
2101                     if (tmp < key->numLevels[i])
2102                         outActs[tmp] = key->acts[i][tmp];
2103                     else
2104                         outActs[tmp].type = XkbSA_NoAction;
2105                 }
2106             }
2107         }
2108         outSyms += width;
2109         if (outActs)
2110             outActs += width;
2111     }
2112     switch (key->behavior.type & XkbKB_OpMask)
2113     {
2114     case XkbKB_Default:
2115         break;
2116     case XkbKB_Overlay1:
2117     case XkbKB_Overlay2:
2118         /* find key by name! */
2119         if (!FindNamedKey(xkb, key->nameForOverlayKey, &okc, True,
2120                           CreateKeyNames(xkb), 0))
2121         {
2122             if (warningLevel >= 1)
2123             {
2124                 WARN("Key %s not found in %s keycodes\n",
2125                       longText(key->nameForOverlayKey),
2126                       XkbcAtomText(xkb->names->keycodes));
2127                 ACTION("Not treating %s as an overlay key \n",
2128                         longText(key->name));
2129             }
2130             break;
2131         }
2132         key->behavior.data = okc;
2133     default:
2134         xkb->server->behaviors[kc] = key->behavior;
2135         xkb->server->explicit[kc] |= XkbExplicitBehaviorMask;
2136         break;
2137     }
2138     if (key->defs.defined & _Key_VModMap)
2139     {
2140         xkb->server->vmodmap[kc] = key->vmodmap;
2141         xkb->server->explicit[kc] |= XkbExplicitVModMapMask;
2142     }
2143     if (key->repeat != RepeatUndefined)
2144     {
2145         if (key->repeat == RepeatYes)
2146             xkb->ctrls->per_key_repeat[kc / 8] |= (1 << (kc % 8));
2147         else
2148             xkb->ctrls->per_key_repeat[kc / 8] &= ~(1 << (kc % 8));
2149         xkb->server->explicit[kc] |= XkbExplicitAutoRepeatMask;
2150     }
2151
2152     /* do the same thing for the next key */
2153     CopySymbolsDef(xkb, key, kc + 1);
2154     return True;
2155 }
2156
2157 static Bool
2158 CopyModMapDef(XkbcDescPtr xkb, ModMapEntry *entry)
2159 {
2160     unsigned kc;
2161
2162     if ((!entry->haveSymbol)
2163         &&
2164         (!FindNamedKey
2165          (xkb, entry->u.keyName, &kc, True, CreateKeyNames(xkb), 0)))
2166     {
2167         if (warningLevel >= 5)
2168         {
2169             WARN("Key %s not found in %s keycodes\n",
2170                   longText(entry->u.keyName),
2171                   XkbcAtomText(xkb->names->keycodes));
2172             ACTION("Modifier map entry for %s not updated\n",
2173                     XkbcModIndexText(entry->modifier));
2174         }
2175         return False;
2176     }
2177     else if (entry->haveSymbol
2178              && (!FindKeyForSymbol(xkb, entry->u.keySym, &kc)))
2179     {
2180         if (warningLevel > 5)
2181         {
2182             WARN("Key \"%s\" not found in %s symbol map\n",
2183                   XkbcKeysymText(entry->u.keySym),
2184                   XkbcAtomText(xkb->names->symbols));
2185             ACTION("Modifier map entry for %s not updated\n",
2186                     XkbcModIndexText(entry->modifier));
2187         }
2188         return False;
2189     }
2190     xkb->map->modmap[kc] |= (1 << entry->modifier);
2191     return True;
2192 }
2193
2194 /**
2195  * Handle the xkb_symbols section of an xkb file.
2196  *
2197  * @param file The parsed xkb_symbols section of the xkb file.
2198  * @param xkb Handle to the keyboard description to store the symbols in.
2199  * @param merge Merge strategy (e.g. MergeOverride).
2200  */
2201 Bool
2202 CompileSymbols(XkbFile *file, XkbcDescPtr xkb, unsigned merge)
2203 {
2204     register int i;
2205     SymbolsInfo info;
2206
2207     InitSymbolsInfo(&info, xkb);
2208     info.dflt.defs.fileID = file->id;
2209     info.dflt.defs.merge = merge;
2210     HandleSymbolsFile(file, xkb, merge, &info);
2211
2212     if (info.nKeys == 0)
2213         return True;
2214     if (info.errorCount == 0)
2215     {
2216         KeyInfo *key;
2217
2218         /* alloc memory in the xkb struct */
2219         if (XkbcAllocNames(xkb, XkbSymbolsNameMask | XkbGroupNamesMask, 0, 0)
2220             != Success)
2221         {
2222             WSGO("Can not allocate names in CompileSymbols\n");
2223             ACTION("Symbols not added\n");
2224             return False;
2225         }
2226         if (XkbcAllocClientMap(xkb, XkbKeySymsMask | XkbModifierMapMask, 0)
2227             != Success)
2228         {
2229             WSGO("Could not allocate client map in CompileSymbols\n");
2230             ACTION("Symbols not added\n");
2231             return False;
2232         }
2233         if (XkbcAllocServerMap(xkb, XkbAllServerInfoMask, 32) != Success)
2234         {
2235             WSGO("Could not allocate server map in CompileSymbols\n");
2236             ACTION("Symbols not added\n");
2237             return False;
2238         }
2239         if (XkbcAllocControls(xkb, XkbPerKeyRepeatMask) != Success)
2240         {
2241             WSGO("Could not allocate controls in CompileSymbols\n");
2242             ACTION("Symbols not added\n");
2243             return False;
2244         }
2245
2246         /* now copy info into xkb. */
2247         xkb->names->symbols = XkbcInternAtom(info.name, False);
2248         if (info.aliases)
2249             ApplyAliases(xkb, False, &info.aliases);
2250         for (i = 0; i < XkbNumKbdGroups; i++)
2251         {
2252             if (info.groupNames[i] != None)
2253                 xkb->names->groups[i] = info.groupNames[i];
2254         }
2255         /* sanitize keys */
2256         for (key = info.keys, i = 0; i < info.nKeys; i++, key++)
2257         {
2258             PrepareKeyDef(key);
2259         }
2260         /* copy! */
2261         for (key = info.keys, i = 0; i < info.nKeys; i++, key++)
2262         {
2263             if (!CopySymbolsDef(xkb, key, 0))
2264                 info.errorCount++;
2265         }
2266         if (warningLevel > 3)
2267         {
2268             for (i = xkb->min_key_code; i <= xkb->max_key_code; i++)
2269             {
2270                 if (xkb->names->keys[i].name[0] == '\0')
2271                     continue;
2272                 if (XkbKeyNumGroups(xkb, i) < 1)
2273                 {
2274                     char buf[5];
2275                     memcpy(buf, xkb->names->keys[i].name, 4);
2276                     buf[4] = '\0';
2277                     WARN
2278                         ("No symbols defined for <%s> (keycode %d)\n",
2279                          buf, i);
2280                 }
2281             }
2282         }
2283         if (info.modMap)
2284         {
2285             ModMapEntry *mm, *next;
2286             for (mm = info.modMap; mm != NULL; mm = next)
2287             {
2288                 if (!CopyModMapDef(xkb, mm))
2289                     info.errorCount++;
2290                 next = (ModMapEntry *) mm->defs.next;
2291             }
2292         }
2293         return True;
2294     }
2295     return False;
2296 }