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