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