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