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