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