symbols.c revision a57d84fe
1/************************************************************
2 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
15
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25 ********************************************************/
26
27#include "xkbcomp.h"
28#include "tokens.h"
29#include "expr.h"
30#include "parseutils.h"
31
32#include <X11/keysym.h>
33#include <X11/Xutil.h>
34#include <stdlib.h>
35
36#include "expr.h"
37#include "vmod.h"
38#include "action.h"
39#include "keycodes.h"
40#include "misc.h"
41#include "alias.h"
42
43/***====================================================================***/
44
45#define	RepeatYes	1
46#define	RepeatNo	0
47#define	RepeatUndefined	~((unsigned)0)
48
49#define	_Key_Syms	(1<<0)
50#define	_Key_Acts	(1<<1)
51#define	_Key_Repeat	(1<<2)
52#define	_Key_Behavior	(1<<3)
53#define	_Key_Type_Dflt	(1<<4)
54#define	_Key_Types	(1<<5)
55#define	_Key_GroupInfo	(1<<6)
56#define	_Key_VModMap	(1<<7)
57
58typedef struct _KeyInfo
59{
60    CommonInfo defs;
61    unsigned long name; /* the 4 chars of the key name, as long */
62    unsigned char groupInfo;
63    unsigned char typesDefined;
64    unsigned char symsDefined;
65    unsigned char actsDefined;
66    short numLevels[XkbNumKbdGroups];
67    KeySym *syms[XkbNumKbdGroups];
68    XkbAction *acts[XkbNumKbdGroups];
69    Atom types[XkbNumKbdGroups];
70    unsigned repeat;
71    XkbBehavior behavior;
72    unsigned short vmodmap;
73    unsigned long nameForOverlayKey;
74    unsigned long allowNone;
75    Atom dfltType;
76} KeyInfo;
77
78/**
79 * Init the given key info to sane values.
80 */
81static void
82InitKeyInfo(KeyInfo * info)
83{
84    register int i;
85    static char dflt[4] = "*";
86
87    info->defs.defined = 0;
88    info->defs.fileID = 0;
89    info->defs.merge = MergeOverride;
90    info->defs.next = NULL;
91    info->name = KeyNameToLong(dflt);
92    info->groupInfo = 0;
93    info->typesDefined = info->symsDefined = info->actsDefined = 0;
94    for (i = 0; i < XkbNumKbdGroups; i++)
95    {
96        info->numLevels[i] = 0;
97        info->types[i] = None;
98        info->syms[i] = NULL;
99        info->acts[i] = NULL;
100    }
101    info->dfltType = None;
102    info->behavior.type = XkbKB_Default;
103    info->behavior.data = 0;
104    info->vmodmap = 0;
105    info->nameForOverlayKey = 0;
106    info->repeat = RepeatUndefined;
107    info->allowNone = 0;
108    return;
109}
110
111/**
112 * Free memory associated with this key info and reset to sane values.
113 */
114static void
115FreeKeyInfo(KeyInfo * info)
116{
117    register int i;
118
119    info->defs.defined = 0;
120    info->defs.fileID = 0;
121    info->defs.merge = MergeOverride;
122    info->defs.next = NULL;
123    info->groupInfo = 0;
124    info->typesDefined = info->symsDefined = info->actsDefined = 0;
125    for (i = 0; i < XkbNumKbdGroups; i++)
126    {
127        info->numLevels[i] = 0;
128        info->types[i] = None;
129        if (info->syms[i] != NULL)
130            uFree(info->syms[i]);
131        info->syms[i] = NULL;
132        if (info->acts[i] != NULL)
133            uFree(info->acts[i]);
134        info->acts[i] = NULL;
135    }
136    info->dfltType = None;
137    info->behavior.type = XkbKB_Default;
138    info->behavior.data = 0;
139    info->vmodmap = 0;
140    info->nameForOverlayKey = 0;
141    info->repeat = RepeatUndefined;
142    info->allowNone = 0;
143    return;
144}
145
146/**
147 * Copy old into new, optionally reset old to 0.
148 * If old is reset, new simply re-uses old's memory. Otherwise, the memory is
149 * newly allocated and new points to the new memory areas.
150 */
151static Bool
152CopyKeyInfo(KeyInfo * old, KeyInfo * new, Bool clearOld)
153{
154    register int i;
155
156    *new = *old;
157    new->defs.next = NULL;
158    if (clearOld)
159    {
160        for (i = 0; i < XkbNumKbdGroups; i++)
161        {
162            old->numLevels[i] = 0;
163            old->syms[i] = NULL;
164            old->acts[i] = NULL;
165        }
166    }
167    else
168    {
169        int width;
170        for (i = 0; i < XkbNumKbdGroups; i++)
171        {
172            width = new->numLevels[i];
173            if (old->syms[i] != NULL)
174            {
175                new->syms[i] = uTypedCalloc(width, KeySym);
176                if (!new->syms[i])
177                {
178                    new->syms[i] = NULL;
179                    new->numLevels[i] = 0;
180                    return False;
181                }
182                memcpy((char *) new->syms[i], (char *) old->syms[i],
183                       width * sizeof(KeySym));
184            }
185            if (old->acts[i] != NULL)
186            {
187                new->acts[i] = uTypedCalloc(width, XkbAction);
188                if (!new->acts[i])
189                {
190                    new->acts[i] = NULL;
191                    return False;
192                }
193                memcpy((char *) new->acts[i], (char *) old->acts[i],
194                       width * sizeof(XkbAction));
195            }
196        }
197    }
198    return True;
199}
200
201/***====================================================================***/
202
203typedef struct _ModMapEntry
204{
205    CommonInfo defs;
206    Bool haveSymbol;
207    int modifier;
208    union
209    {
210        unsigned long keyName;
211        KeySym keySym;
212    } u;
213} ModMapEntry;
214
215#define	SYMBOLS_INIT_SIZE	110
216#define	SYMBOLS_CHUNK		20
217typedef struct _SymbolsInfo
218{
219    char *name;         /* e.g. pc+us+inet(evdev) */
220    int errorCount;
221    unsigned fileID;
222    unsigned merge;
223    unsigned explicit_group;
224    unsigned groupInfo;
225    unsigned szKeys;
226    unsigned nKeys;
227    KeyInfo *keys;
228    KeyInfo dflt;
229    VModInfo vmods;
230    ActionInfo *action;
231    Atom groupNames[XkbNumKbdGroups];
232
233    ModMapEntry *modMap;
234    AliasInfo *aliases;
235} SymbolsInfo;
236
237static void
238InitSymbolsInfo(SymbolsInfo * info, XkbDescPtr xkb)
239{
240    register int i;
241
242    tok_ONE_LEVEL = XkbInternAtom(NULL, "ONE_LEVEL", False);
243    tok_TWO_LEVEL = XkbInternAtom(NULL, "TWO_LEVEL", False);
244    tok_KEYPAD = XkbInternAtom(NULL, "KEYPAD", False);
245    info->name = NULL;
246    info->explicit_group = 0;
247    info->errorCount = 0;
248    info->fileID = 0;
249    info->merge = MergeOverride;
250    info->groupInfo = 0;
251    info->szKeys = SYMBOLS_INIT_SIZE;
252    info->nKeys = 0;
253    info->keys = uTypedCalloc(SYMBOLS_INIT_SIZE, KeyInfo);
254    info->modMap = NULL;
255    for (i = 0; i < XkbNumKbdGroups; i++)
256        info->groupNames[i] = None;
257    InitKeyInfo(&info->dflt);
258    InitVModInfo(&info->vmods, xkb);
259    info->action = NULL;
260    info->aliases = NULL;
261    return;
262}
263
264static void
265FreeSymbolsInfo(SymbolsInfo * info)
266{
267    register int i;
268
269    if (info->name)
270        uFree(info->name);
271    info->name = NULL;
272    if (info->keys)
273    {
274        for (i = 0; i < info->nKeys; i++)
275        {
276            FreeKeyInfo(&info->keys[i]);
277        }
278        uFree(info->keys);
279        info->keys = NULL;
280    }
281    if (info->modMap)
282    {
283        ClearCommonInfo(&info->modMap->defs);
284        info->modMap = NULL;
285    }
286    if (info->aliases)
287    {
288        ClearAliases(&info->aliases);
289        info->aliases = NULL;
290    }
291    bzero((char *) info, sizeof(SymbolsInfo));
292    return;
293}
294
295static Bool
296ResizeKeyGroup(KeyInfo * key,
297               unsigned group, unsigned atLeastSize, Bool forceActions)
298{
299    Bool tooSmall;
300    unsigned newWidth;
301
302    tooSmall = (key->numLevels[group] < atLeastSize);
303    if (tooSmall)
304        newWidth = atLeastSize;
305    else
306        newWidth = key->numLevels[group];
307
308    if ((key->syms[group] == NULL) || tooSmall)
309    {
310        key->syms[group] = uTypedRecalloc(key->syms[group],
311                                          key->numLevels[group], newWidth,
312                                          KeySym);
313        if (!key->syms[group])
314            return False;
315    }
316    if (((forceActions) && (tooSmall || (key->acts[group] == NULL))) ||
317        (tooSmall && (key->acts[group] != NULL)))
318    {
319        key->acts[group] = uTypedRecalloc(key->acts[group],
320                                          key->numLevels[group], newWidth,
321                                          XkbAction);
322        if (!key->acts[group])
323            return False;
324    }
325    key->numLevels[group] = newWidth;
326    return True;
327}
328
329static Bool
330MergeKeyGroups(SymbolsInfo * info,
331               KeyInfo * into, KeyInfo * from, unsigned group)
332{
333    KeySym *resultSyms;
334    XkbAction *resultActs;
335    int resultWidth;
336    register int i;
337    Bool report, clobber;
338
339    clobber = (from->defs.merge != MergeAugment);
340    report = (warningLevel > 9) ||
341        ((into->defs.fileID == from->defs.fileID) && (warningLevel > 0));
342    if ((from->numLevels[group] > into->numLevels[group])
343        || (clobber && (from->types[group] != None)))
344    {
345        resultSyms = from->syms[group];
346        resultActs = from->acts[group];
347        resultWidth = from->numLevels[group];
348    }
349    else
350    {
351        resultSyms = into->syms[group];
352        resultActs = into->acts[group];
353        resultWidth = into->numLevels[group];
354    }
355    if (resultSyms == NULL)
356    {
357        resultSyms = uTypedCalloc(resultWidth, KeySym);
358        if (!resultSyms)
359        {
360            WSGO("Could not allocate symbols for group merge\n");
361            ACTION("Group %d of key %s not merged\n", group,
362                    longText(into->name, XkbMessage));
363            return False;
364        }
365    }
366    if ((resultActs == NULL) && (into->acts[group] || from->acts[group]))
367    {
368        resultActs = uTypedCalloc(resultWidth, XkbAction);
369        if (!resultActs)
370        {
371            WSGO("Could not allocate actions for group merge\n");
372            ACTION("Group %d of key %s not merged\n", group,
373                    longText(into->name, XkbMessage));
374            return False;
375        }
376    }
377    for (i = 0; i < resultWidth; i++)
378    {
379        KeySym fromSym, toSym;
380        if (from->syms[group] && (i < from->numLevels[group]))
381            fromSym = from->syms[group][i];
382        else
383            fromSym = NoSymbol;
384        if (into->syms[group] && (i < into->numLevels[group]))
385            toSym = into->syms[group][i];
386        else
387            toSym = NoSymbol;
388        if ((fromSym == NoSymbol) || (fromSym == toSym))
389            resultSyms[i] = toSym;
390        else if (toSym == NoSymbol)
391            resultSyms[i] = fromSym;
392        else
393        {
394            KeySym use, ignore;
395            if (clobber)
396            {
397                use = fromSym;
398                ignore = toSym;
399            }
400            else
401            {
402                use = toSym;
403                ignore = fromSym;
404            }
405            if (report)
406            {
407                WARN
408                    ("Multiple symbols for level %d/group %d on key %s\n",
409                     i + 1, group + 1, longText(into->name, XkbMessage));
410                ACTION("Using %s, ignoring %s\n",
411                        XkbKeysymText(use, XkbMessage),
412                        XkbKeysymText(ignore, XkbMessage));
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, XkbMessage));
449                    ACTION("Using %s, ignoring %s\n",
450                            XkbActionTypeText(use->type, XkbMessage),
451                            XkbActionTypeText(ignore->type, XkbMessage));
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
477static Bool
478MergeKeys(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, XkbMessage));
554                ACTION("Using %s, ignoring %s\n",
555                        XkbAtomText(NULL, use, XkbMessage),
556                        XkbAtomText(NULL, ignore, XkbMessage));
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 && (warningLevel > 0))
592    {
593        WARN("Symbol map for key %s redefined\n",
594              longText(into->name, XkbMessage));
595        ACTION("Using %s definition for conflicting fields\n",
596                (from->defs.merge == MergeAugment ? "first" : "last"));
597    }
598    return True;
599}
600
601static Bool
602AddKeySymbols(SymbolsInfo * info, KeyInfo * key, XkbDescPtr 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
635static Bool
636AddModMapEntry(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                     XkbKeysymText(new->u.keySym, XkbMessage));
663                ACTION("Using %s, ignoring %s.\n",
664                        XkbModIndexText(use, XkbMessage),
665                        XkbModIndexText(ignore, XkbMessage));
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, XkbMessage));
688                ACTION("Using %s, ignoring %s.\n",
689                        XkbModIndexText(use, XkbMessage),
690                        XkbModIndexText(ignore, XkbMessage));
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                XkbModIndexText(new->modifier, XkbMessage));
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
712static void
713MergeIncludedSymbols(SymbolsInfo * into, SymbolsInfo * from,
714                     unsigned merge, XkbDescPtr 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
763typedef void (*FileHandler) (XkbFile * /* rtrn */ ,
764                             XkbDescPtr /* xkb */ ,
765                             unsigned /* merge */ ,
766                             SymbolsInfo *      /* included */
767    );
768
769static Bool
770HandleIncludeSymbols(IncludeStmt * stmt,
771                     XkbDescPtr 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
860static 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
876static Bool
877GetGroupIndex(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, XkbMessage), XkbNumKbdGroups + 1);
907        ACTION("Ignoring %s defined for extra groups\n", name);
908        return False;
909    }
910    if (!ExprResolveInteger
911        (arrayNdx, &tmp, SimpleLookup, (XPointer) groupNames))
912    {
913        ERROR("Illegal group index for %s of key %s\n", name,
914               longText(key->name, XkbMessage));
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, XkbMessage), 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
929static Bool
930AddSymbolsToKey(KeyInfo * key,
931                XkbDescPtr xkb,
932                const 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, XkbMessage));
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, XkbMessage), 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, XkbMessage));
965        ACTION("Symbols lost\n");
966        return False;
967    }
968    key->symsDefined |= (1 << ndx);
969    for (i = 0; i < nSyms; i++) {
970        if (!LookupKeysym(value->value.list.syms[i], &key->syms[ndx][i])) {
971            if (warningLevel > 0)
972            {
973                WARN("Could not resolve keysym %s\n",
974                      value->value.list.syms[i]);
975            }
976            key->syms[ndx][i] = NoSymbol;
977        }
978    }
979    for (i = key->numLevels[ndx] - 1;
980         (i >= 0) && (key->syms[ndx][i] == NoSymbol); i--)
981    {
982        key->numLevels[ndx]--;
983    }
984    return True;
985}
986
987static Bool
988AddActionsToKey(KeyInfo * key,
989                XkbDescPtr xkb,
990                const char *field,
991                ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info)
992{
993    register int i;
994    unsigned ndx, nActs;
995    ExprDef *act;
996    XkbAnyAction *toAct;
997
998    if (!GetGroupIndex(key, arrayNdx, ACTIONS, &ndx))
999        return False;
1000
1001    if (value == NULL)
1002    {
1003        key->actsDefined |= (1 << ndx);
1004        return True;
1005    }
1006    if (value->op != ExprActionList)
1007    {
1008        WSGO("Bad expression type (%d) for action list value\n", value->op);
1009        ACTION("Ignoring actions for group %d of %s\n", ndx,
1010                longText(key->name, XkbMessage));
1011        return False;
1012    }
1013    if (key->acts[ndx] != NULL)
1014    {
1015        WSGO("Actions for key %s, group %d already defined\n",
1016              longText(key->name, XkbMessage), ndx);
1017        return False;
1018    }
1019    for (nActs = 0, act = value->value.child; act != NULL; nActs++)
1020    {
1021        act = (ExprDef *) act->common.next;
1022    }
1023    if (nActs < 1)
1024    {
1025        WSGO("Action list but not actions in AddActionsToKey\n");
1026        return False;
1027    }
1028    if (((key->numLevels[ndx] < nActs) || (key->acts[ndx] == NULL)) &&
1029        (!ResizeKeyGroup(key, ndx, nActs, True)))
1030    {
1031        WSGO("Could not resize group %d of key %s\n", ndx,
1032              longText(key->name, XkbMessage));
1033        ACTION("Actions lost\n");
1034        return False;
1035    }
1036    key->actsDefined |= (1 << ndx);
1037
1038    toAct = (XkbAnyAction *) key->acts[ndx];
1039    act = value->value.child;
1040    for (i = 0; i < nActs; i++, toAct++)
1041    {
1042        if (!HandleActionDef(act, xkb, toAct, MergeOverride, info->action))
1043        {
1044            ERROR("Illegal action definition for %s\n",
1045                   longText(key->name, XkbMessage));
1046            ACTION("Action for group %d/level %d ignored\n", ndx + 1, i + 1);
1047        }
1048        act = (ExprDef *) act->common.next;
1049    }
1050    return True;
1051}
1052
1053static int
1054SetAllowNone(KeyInfo * key, ExprDef * arrayNdx, ExprDef * value)
1055{
1056    ExprResult tmp;
1057    unsigned radio_groups = 0;
1058
1059    if (arrayNdx == NULL)
1060    {
1061        radio_groups = XkbAllRadioGroupsMask;
1062    }
1063    else
1064    {
1065        if (!ExprResolveInteger(arrayNdx, &tmp, RadioLookup, NULL))
1066        {
1067            ERROR("Illegal index in group name definition\n");
1068            ACTION("Definition with non-integer array index ignored\n");
1069            return False;
1070        }
1071        if ((tmp.uval < 1) || (tmp.uval > XkbMaxRadioGroups))
1072        {
1073            ERROR("Illegal radio group specified (must be 1..%d)\n",
1074                   XkbMaxRadioGroups + 1);
1075            ACTION("Value of \"allow none\" for group %d ignored\n",
1076                    tmp.uval);
1077            return False;
1078        }
1079        radio_groups |= (1 << (tmp.uval - 1));
1080    }
1081    if (!ExprResolveBoolean(value, &tmp, NULL, NULL))
1082    {
1083        ERROR("Illegal \"allow none\" value for %s\n",
1084               longText(key->name, XkbMessage));
1085        ACTION("Non-boolean value ignored\n");
1086        return False;
1087    }
1088    if (tmp.uval)
1089        key->allowNone |= radio_groups;
1090    else
1091        key->allowNone &= ~radio_groups;
1092    return True;
1093}
1094
1095
1096static LookupEntry lockingEntries[] = {
1097    {"true", XkbKB_Lock},
1098    {"yes", XkbKB_Lock},
1099    {"on", XkbKB_Lock},
1100    {"false", XkbKB_Default},
1101    {"no", XkbKB_Default},
1102    {"off", XkbKB_Default},
1103    {"permanent", XkbKB_Lock | XkbKB_Permanent},
1104    {NULL, 0}
1105};
1106
1107static LookupEntry repeatEntries[] = {
1108    {"true", RepeatYes},
1109    {"yes", RepeatYes},
1110    {"on", RepeatYes},
1111    {"false", RepeatNo},
1112    {"no", RepeatNo},
1113    {"off", RepeatNo},
1114    {"default", RepeatUndefined},
1115    {NULL, 0}
1116};
1117
1118static LookupEntry rgEntries[] = {
1119    {"none", 0},
1120    {NULL, 0}
1121};
1122
1123static Bool
1124SetSymbolsField(KeyInfo * key,
1125                XkbDescPtr xkb,
1126                const char *field,
1127                ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info)
1128{
1129    Bool ok = True;
1130    ExprResult tmp;
1131
1132    if (uStrCaseCmp(field, "type") == 0)
1133    {
1134        ExprResult ndx;
1135        if ((!ExprResolveString(value, &tmp, NULL, NULL))
1136            && (warningLevel > 0))
1137        {
1138            WARN("The type field of a key symbol map must be a string\n");
1139            ACTION("Ignoring illegal type definition\n");
1140        }
1141        if (arrayNdx == NULL)
1142        {
1143            key->dfltType = XkbInternAtom(NULL, tmp.str, False);
1144            key->defs.defined |= _Key_Type_Dflt;
1145        }
1146        else if (!ExprResolveInteger(arrayNdx, &ndx, SimpleLookup,
1147                                     (XPointer) groupNames))
1148        {
1149            ERROR("Illegal group index for type of key %s\n",
1150                   longText(key->name, XkbMessage));
1151            ACTION("Definition with non-integer array index ignored\n");
1152            return False;
1153        }
1154        else if ((ndx.uval < 1) || (ndx.uval > XkbNumKbdGroups))
1155        {
1156            ERROR
1157                ("Group index for type of key %s is out of range (1..%d)\n",
1158                 longText(key->name, XkbMessage), XkbNumKbdGroups + 1);
1159            ACTION("Ignoring type for group %d\n", ndx.uval);
1160            return False;
1161        }
1162        else
1163        {
1164            key->types[ndx.uval - 1] = XkbInternAtom(NULL, tmp.str, False);
1165            key->typesDefined |= (1 << (ndx.uval - 1));
1166        }
1167    }
1168    else if (uStrCaseCmp(field, "symbols") == 0)
1169        return AddSymbolsToKey(key, xkb, field, arrayNdx, value, info);
1170    else if (uStrCaseCmp(field, "actions") == 0)
1171        return AddActionsToKey(key, xkb, field, arrayNdx, value, info);
1172    else if ((uStrCaseCmp(field, "vmods") == 0) ||
1173             (uStrCaseCmp(field, "virtualmods") == 0) ||
1174             (uStrCaseCmp(field, "virtualmodifiers") == 0))
1175    {
1176        ok = ExprResolveModMask(value, &tmp, LookupVModMask, (XPointer) xkb);
1177        if (ok)
1178        {
1179            key->vmodmap = (tmp.uval >> 8);
1180            key->defs.defined |= _Key_VModMap;
1181        }
1182        else
1183        {
1184            ERROR("Expected a virtual modifier mask, found %s\n",
1185                   exprOpText(value->op));
1186            ACTION("Ignoring virtual modifiers definition for key %s\n",
1187                    longText(key->name, XkbMessage));
1188        }
1189    }
1190    else if ((uStrCaseCmp(field, "locking") == 0)
1191             || (uStrCaseCmp(field, "lock") == 0)
1192             || (uStrCaseCmp(field, "locks") == 0))
1193    {
1194        ok = ExprResolveEnum(value, &tmp, lockingEntries);
1195        if (ok)
1196            key->behavior.type = tmp.uval;
1197        key->defs.defined |= _Key_Behavior;
1198    }
1199    else if ((uStrCaseCmp(field, "radiogroup") == 0) ||
1200             (uStrCaseCmp(field, "permanentradiogroup") == 0))
1201    {
1202        Bool permanent = False;
1203        if (uStrCaseCmp(field, "permanentradiogroup") == 0)
1204            permanent = True;
1205        ok = ExprResolveInteger(value, &tmp, SimpleLookup,
1206                                (XPointer) rgEntries);
1207        if (!ok)
1208        {
1209            ERROR("Illegal radio group specification for %s\n",
1210                   longText(key->name, XkbMessage));
1211            ACTION("Non-integer radio group ignored\n");
1212            return False;
1213        }
1214        if (tmp.uval == 0)
1215        {
1216            key->behavior.type = XkbKB_Default;
1217            key->behavior.data = 0;
1218            return ok;
1219        }
1220        if ((tmp.uval < 1) || (tmp.uval > XkbMaxRadioGroups))
1221        {
1222            ERROR
1223                ("Radio group specification for %s out of range (1..32)\n",
1224                 longText(key->name, XkbMessage));
1225            ACTION("Illegal radio group %d ignored\n", tmp.uval);
1226            return False;
1227        }
1228        key->behavior.type =
1229            XkbKB_RadioGroup | (permanent ? XkbKB_Permanent : 0);
1230        key->behavior.data = tmp.uval - 1;
1231        if (key->allowNone & (1 << (tmp.uval - 1)))
1232            key->behavior.data |= XkbKB_RGAllowNone;
1233        key->defs.defined |= _Key_Behavior;
1234    }
1235    else if (uStrCaseEqual(field, "allownone"))
1236    {
1237        ok = SetAllowNone(key, arrayNdx, value);
1238    }
1239    else if (uStrCasePrefix("overlay", field) ||
1240             uStrCasePrefix("permanentoverlay", field))
1241    {
1242        Bool permanent = False;
1243        const char *which;
1244        int overlayNdx;
1245        if (uStrCasePrefix("permanent", field))
1246        {
1247            permanent = True;
1248            which = &field[sizeof("permanentoverlay") - 1];
1249        }
1250        else
1251        {
1252            which = &field[sizeof("overlay") - 1];
1253        }
1254        if (sscanf(which, "%d", &overlayNdx) == 1)
1255        {
1256            if (((overlayNdx < 1) || (overlayNdx > 2)) && (warningLevel > 0))
1257            {
1258                ERROR("Illegal overlay %d specified for %s\n",
1259                       overlayNdx, longText(key->name, XkbMessage));
1260                ACTION("Ignored\n");
1261                return False;
1262            }
1263        }
1264        else if (*which == '\0')
1265            overlayNdx = 1;
1266        else if (warningLevel > 0)
1267        {
1268            ERROR("Illegal overlay \"%s\" specified for %s\n",
1269                   which, longText(key->name, XkbMessage));
1270            ACTION("Ignored\n");
1271            return False;
1272        }
1273        ok = ExprResolveKeyName(value, &tmp, NULL, NULL);
1274        if (!ok)
1275        {
1276            ERROR("Illegal overlay key specification for %s\n",
1277                   longText(key->name, XkbMessage));
1278            ACTION("Overlay key must be specified by name\n");
1279            return False;
1280        }
1281        if (overlayNdx == 1)
1282            key->behavior.type = XkbKB_Overlay1;
1283        else
1284            key->behavior.type = XkbKB_Overlay2;
1285        if (permanent)
1286            key->behavior.type |= XkbKB_Permanent;
1287
1288        key->behavior.data = 0;
1289        key->nameForOverlayKey = KeyNameToLong(tmp.keyName.name);
1290        key->defs.defined |= _Key_Behavior;
1291    }
1292    else if ((uStrCaseCmp(field, "repeating") == 0) ||
1293             (uStrCaseCmp(field, "repeats") == 0) ||
1294             (uStrCaseCmp(field, "repeat") == 0))
1295    {
1296        ok = ExprResolveEnum(value, &tmp, repeatEntries);
1297        if (!ok)
1298        {
1299            ERROR("Illegal repeat setting for %s\n",
1300                   longText(key->name, XkbMessage));
1301            ACTION("Non-boolean repeat setting ignored\n");
1302            return False;
1303        }
1304        key->repeat = tmp.uval;
1305        key->defs.defined |= _Key_Repeat;
1306    }
1307    else if ((uStrCaseCmp(field, "groupswrap") == 0) ||
1308             (uStrCaseCmp(field, "wrapgroups") == 0))
1309    {
1310        ok = ExprResolveBoolean(value, &tmp, NULL, NULL);
1311        if (!ok)
1312        {
1313            ERROR("Illegal groupsWrap setting for %s\n",
1314                   longText(key->name, XkbMessage));
1315            ACTION("Non-boolean value ignored\n");
1316            return False;
1317        }
1318        if (tmp.uval)
1319            key->groupInfo = XkbWrapIntoRange;
1320        else
1321            key->groupInfo = XkbClampIntoRange;
1322        key->defs.defined |= _Key_GroupInfo;
1323    }
1324    else if ((uStrCaseCmp(field, "groupsclamp") == 0) ||
1325             (uStrCaseCmp(field, "clampgroups") == 0))
1326    {
1327        ok = ExprResolveBoolean(value, &tmp, NULL, NULL);
1328        if (!ok)
1329        {
1330            ERROR("Illegal groupsClamp setting for %s\n",
1331                   longText(key->name, XkbMessage));
1332            ACTION("Non-boolean value ignored\n");
1333            return False;
1334        }
1335        if (tmp.uval)
1336            key->groupInfo = XkbClampIntoRange;
1337        else
1338            key->groupInfo = XkbWrapIntoRange;
1339        key->defs.defined |= _Key_GroupInfo;
1340    }
1341    else if ((uStrCaseCmp(field, "groupsredirect") == 0) ||
1342             (uStrCaseCmp(field, "redirectgroups") == 0))
1343    {
1344        if (!ExprResolveInteger
1345            (value, &tmp, SimpleLookup, (XPointer) groupNames))
1346        {
1347            ERROR("Illegal group index for redirect of key %s\n",
1348                   longText(key->name, XkbMessage));
1349            ACTION("Definition with non-integer group ignored\n");
1350            return False;
1351        }
1352        if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups))
1353        {
1354            ERROR("Out-of-range (1..%d) group for redirect of key %s\n",
1355                   XkbNumKbdGroups, longText(key->name, XkbMessage));
1356            ERROR("Ignoring illegal group %d\n", tmp.uval);
1357            return False;
1358        }
1359        key->groupInfo =
1360            XkbSetGroupInfo(0, XkbRedirectIntoRange, tmp.uval - 1);
1361        key->defs.defined |= _Key_GroupInfo;
1362    }
1363    else
1364    {
1365        ERROR("Unknown field %s in a symbol interpretation\n", field);
1366        ACTION("Definition ignored\n");
1367        ok = False;
1368    }
1369    return ok;
1370}
1371
1372static int
1373SetGroupName(SymbolsInfo * info, ExprDef * arrayNdx, ExprDef * value)
1374{
1375    ExprResult tmp, name;
1376
1377    if ((arrayNdx == NULL) && (warningLevel > 0))
1378    {
1379        WARN("You must specify an index when specifying a group name\n");
1380        ACTION("Group name definition without array subscript ignored\n");
1381        return False;
1382    }
1383    if (!ExprResolveInteger
1384        (arrayNdx, &tmp, SimpleLookup, (XPointer) groupNames))
1385    {
1386        ERROR("Illegal index in group name definition\n");
1387        ACTION("Definition with non-integer array index ignored\n");
1388        return False;
1389    }
1390    if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups))
1391    {
1392        ERROR
1393            ("Attempt to specify name for illegal group (must be 1..%d)\n",
1394             XkbNumKbdGroups + 1);
1395        ACTION("Name for group %d ignored\n", tmp.uval);
1396        return False;
1397    }
1398    if (!ExprResolveString(value, &name, NULL, NULL))
1399    {
1400        ERROR("Group name must be a string\n");
1401        ACTION("Illegal name for group %d ignored\n", tmp.uval);
1402        return False;
1403    }
1404    info->groupNames[tmp.uval - 1 + info->explicit_group] =
1405        XkbInternAtom(NULL, name.str, False);
1406
1407    return True;
1408}
1409
1410static int
1411HandleSymbolsVar(VarDef * stmt, XkbDescPtr xkb, SymbolsInfo * info)
1412{
1413    ExprResult elem, field, tmp;
1414    ExprDef *arrayNdx;
1415
1416    if (ExprResolveLhs(stmt->name, &elem, &field, &arrayNdx) == 0)
1417        return 0;               /* internal error, already reported */
1418    if (elem.str && (uStrCaseCmp(elem.str, "key") == 0))
1419    {
1420        return SetSymbolsField(&info->dflt, xkb, field.str, arrayNdx,
1421                               stmt->value, info);
1422    }
1423    else if ((elem.str == NULL) && ((uStrCaseCmp(field.str, "name") == 0) ||
1424                                    (uStrCaseCmp(field.str, "groupname") ==
1425                                     0)))
1426    {
1427        return SetGroupName(info, arrayNdx, stmt->value);
1428    }
1429    else if ((elem.str == NULL)
1430             && ((uStrCaseCmp(field.str, "groupswrap") == 0)
1431                 || (uStrCaseCmp(field.str, "wrapgroups") == 0)))
1432    {
1433        if (!ExprResolveBoolean(stmt->value, &tmp, NULL, NULL))
1434        {
1435            ERROR("Illegal setting for global groupsWrap\n");
1436            ACTION("Non-boolean value ignored\n");
1437            return False;
1438        }
1439        if (tmp.uval)
1440            info->groupInfo = XkbWrapIntoRange;
1441        else
1442            info->groupInfo = XkbClampIntoRange;
1443        return True;
1444    }
1445    else if ((elem.str == NULL)
1446             && ((uStrCaseCmp(field.str, "groupsclamp") == 0)
1447                 || (uStrCaseCmp(field.str, "clampgroups") == 0)))
1448    {
1449        if (!ExprResolveBoolean(stmt->value, &tmp, NULL, NULL))
1450        {
1451            ERROR("Illegal setting for global groupsClamp\n");
1452            ACTION("Non-boolean value ignored\n");
1453            return False;
1454        }
1455        if (tmp.uval)
1456            info->groupInfo = XkbClampIntoRange;
1457        else
1458            info->groupInfo = XkbWrapIntoRange;
1459        return True;
1460    }
1461    else if ((elem.str == NULL)
1462             && ((uStrCaseCmp(field.str, "groupsredirect") == 0)
1463                 || (uStrCaseCmp(field.str, "redirectgroups") == 0)))
1464    {
1465        if (!ExprResolveInteger(stmt->value, &tmp,
1466                                SimpleLookup, (XPointer) groupNames))
1467        {
1468            ERROR("Illegal group index for global groupsRedirect\n");
1469            ACTION("Definition with non-integer group ignored\n");
1470            return False;
1471        }
1472        if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups))
1473        {
1474            ERROR
1475                ("Out-of-range (1..%d) group for global groupsRedirect\n",
1476                 XkbNumKbdGroups);
1477            ACTION("Ignoring illegal group %d\n", tmp.uval);
1478            return False;
1479        }
1480        info->groupInfo = XkbSetGroupInfo(0, XkbRedirectIntoRange, tmp.uval);
1481        return True;
1482    }
1483    else if ((elem.str == NULL) && (uStrCaseCmp(field.str, "allownone") == 0))
1484    {
1485        return SetAllowNone(&info->dflt, arrayNdx, stmt->value);
1486    }
1487    return SetActionField(xkb, elem.str, field.str, arrayNdx, stmt->value,
1488                          &info->action);
1489}
1490
1491static Bool
1492HandleSymbolsBody(VarDef * def,
1493                  XkbDescPtr xkb, KeyInfo * key, SymbolsInfo * info)
1494{
1495    Bool ok = True;
1496    ExprResult tmp, field;
1497    ExprDef *arrayNdx;
1498
1499    for (; def != NULL; def = (VarDef *) def->common.next)
1500    {
1501        if ((def->name) && (def->name->type == ExprFieldRef))
1502        {
1503            ok = HandleSymbolsVar(def, xkb, info);
1504            continue;
1505        }
1506        else
1507        {
1508            if (def->name == NULL)
1509            {
1510                if ((def->value == NULL)
1511                    || (def->value->op == ExprKeysymList))
1512                    field.str = "symbols";
1513                else
1514                    field.str = "actions";
1515                arrayNdx = NULL;
1516            }
1517            else
1518            {
1519                ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx);
1520            }
1521            if (ok)
1522                ok = SetSymbolsField(key, xkb, field.str, arrayNdx,
1523                                     def->value, info);
1524        }
1525    }
1526    return ok;
1527}
1528
1529static Bool
1530SetExplicitGroup(SymbolsInfo * info, KeyInfo * key)
1531{
1532    unsigned group = info->explicit_group;
1533
1534    if (group == 0)
1535        return True;
1536
1537    if ((key->typesDefined | key->symsDefined | key->actsDefined) & ~1)
1538    {
1539        int i;
1540        if (warningLevel > 0)
1541        {
1542            WARN("For map %s an explicit group is specified\n", info->name);
1543            WARN("but key %s has more than one group defined\n",
1544                  longText(key->name, XkbMessage));
1545            ACTION("All groups except first one will be ignored\n");
1546        }
1547        for (i = 1; i < XkbNumKbdGroups; i++)
1548        {
1549            key->numLevels[i] = 0;
1550            if (key->syms[i] != NULL)
1551                uFree(key->syms[i]);
1552            key->syms[i] = (KeySym *) NULL;
1553            if (key->acts[i] != NULL)
1554                uFree(key->acts[i]);
1555            key->acts[i] = (XkbAction *) NULL;
1556            key->types[i] = (Atom) 0;
1557        }
1558    }
1559    key->typesDefined = key->symsDefined = key->actsDefined = 1 << group;
1560
1561    key->numLevels[group] = key->numLevels[0];
1562    key->numLevels[0] = 0;
1563    key->syms[group] = key->syms[0];
1564    key->syms[0] = (KeySym *) NULL;
1565    key->acts[group] = key->acts[0];
1566    key->acts[0] = (XkbAction *) NULL;
1567    key->types[group] = key->types[0];
1568    key->types[0] = (Atom) 0;
1569    return True;
1570}
1571
1572static int
1573HandleSymbolsDef(SymbolsDef * stmt,
1574                 XkbDescPtr xkb, unsigned merge, SymbolsInfo * info)
1575{
1576    KeyInfo key;
1577
1578    InitKeyInfo(&key);
1579    CopyKeyInfo(&info->dflt, &key, False);
1580    key.defs.merge = stmt->merge;
1581    key.name = KeyNameToLong(stmt->keyName);
1582    if (!HandleSymbolsBody((VarDef *) stmt->symbols, xkb, &key, info))
1583    {
1584        info->errorCount++;
1585        return False;
1586    }
1587
1588    if (!SetExplicitGroup(info, &key))
1589    {
1590        info->errorCount++;
1591        return False;
1592    }
1593
1594    if (!AddKeySymbols(info, &key, xkb))
1595    {
1596        info->errorCount++;
1597        return False;
1598    }
1599    return True;
1600}
1601
1602static Bool
1603HandleModMapDef(ModMapDef * def,
1604                XkbDescPtr xkb, unsigned merge, SymbolsInfo * info)
1605{
1606    ExprDef *key;
1607    ModMapEntry tmp;
1608    ExprResult rtrn;
1609    Bool ok;
1610
1611    if (!LookupModIndex(NULL, None, def->modifier, TypeInt, &rtrn))
1612    {
1613        ERROR("Illegal modifier map definition\n");
1614        ACTION("Ignoring map for non-modifier \"%s\"\n",
1615                XkbAtomText(NULL, def->modifier, XkbMessage));
1616        return False;
1617    }
1618    ok = True;
1619    tmp.modifier = rtrn.uval;
1620    for (key = def->keys; key != NULL; key = (ExprDef *) key->common.next)
1621    {
1622        if ((key->op == ExprValue) && (key->type == TypeKeyName))
1623        {
1624            tmp.haveSymbol = False;
1625            tmp.u.keyName = KeyNameToLong(key->value.keyName);
1626        }
1627        else if (ExprResolveKeySym(key, &rtrn, NULL, NULL))
1628        {
1629            tmp.haveSymbol = True;
1630            tmp.u.keySym = rtrn.uval;
1631        }
1632        else
1633        {
1634            ERROR("Modmap entries may contain only key names or keysyms\n");
1635            ACTION("Illegal definition for %s modifier ignored\n",
1636                    XkbModIndexText(tmp.modifier, XkbMessage));
1637            continue;
1638        }
1639
1640        ok = AddModMapEntry(info, &tmp) && ok;
1641    }
1642    return ok;
1643}
1644
1645static void
1646HandleSymbolsFile(XkbFile * file,
1647                  XkbDescPtr xkb, unsigned merge, SymbolsInfo * info)
1648{
1649    ParseCommon *stmt;
1650
1651    info->name = uStringDup(file->name);
1652    stmt = file->defs;
1653    while (stmt)
1654    {
1655        switch (stmt->stmtType)
1656        {
1657        case StmtInclude:
1658            if (!HandleIncludeSymbols((IncludeStmt *) stmt, xkb, info,
1659                                      HandleSymbolsFile))
1660                info->errorCount++;
1661            break;
1662        case StmtSymbolsDef:
1663            if (!HandleSymbolsDef((SymbolsDef *) stmt, xkb, merge, info))
1664                info->errorCount++;
1665            break;
1666        case StmtVarDef:
1667            if (!HandleSymbolsVar((VarDef *) stmt, xkb, info))
1668                info->errorCount++;
1669            break;
1670        case StmtVModDef:
1671            if (!HandleVModDef((VModDef *) stmt, merge, &info->vmods))
1672                info->errorCount++;
1673            break;
1674        case StmtInterpDef:
1675            ERROR("Interpretation files may not include other types\n");
1676            ACTION("Ignoring definition of symbol interpretation\n");
1677            info->errorCount++;
1678            break;
1679        case StmtKeycodeDef:
1680            ERROR("Interpretation files may not include other types\n");
1681            ACTION("Ignoring definition of key name\n");
1682            info->errorCount++;
1683            break;
1684        case StmtModMapDef:
1685            if (!HandleModMapDef((ModMapDef *) stmt, xkb, merge, info))
1686                info->errorCount++;
1687            break;
1688        default:
1689            WSGO("Unexpected statement type %d in HandleSymbolsFile\n",
1690                  stmt->stmtType);
1691            break;
1692        }
1693        stmt = stmt->next;
1694        if (info->errorCount > 10)
1695        {
1696#ifdef NOISY
1697            ERROR("Too many errors\n");
1698#endif
1699            ACTION("Abandoning symbols file \"%s\"\n", file->topName);
1700            break;
1701        }
1702    }
1703    return;
1704}
1705
1706static Bool
1707FindKeyForSymbol(XkbDescPtr xkb, KeySym sym, unsigned int *kc_rtrn)
1708{
1709    register int i, j;
1710    register Bool gotOne;
1711
1712    j = 0;
1713    do
1714    {
1715        gotOne = False;
1716        for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++)
1717        {
1718            if (j < (int) XkbKeyNumSyms(xkb, i))
1719            {
1720                gotOne = True;
1721                if (XkbKeySym(xkb, i, j) == sym)
1722                {
1723                    *kc_rtrn = i;
1724                    return True;
1725                }
1726            }
1727        }
1728        j++;
1729    }
1730    while (gotOne);
1731    return False;
1732}
1733
1734/**
1735 * Find the given name in the xkb->map->types and return its index.
1736 *
1737 * @param name The atom to search for.
1738 * @param type_rtrn Set to the index of the name if found.
1739 *
1740 * @return True if found, False otherwise.
1741 */
1742static Bool
1743FindNamedType(XkbDescPtr xkb, Atom name, unsigned *type_rtrn)
1744{
1745    register unsigned n;
1746
1747    if (xkb && xkb->map && xkb->map->types)
1748    {
1749        for (n = 0; n < xkb->map->num_types; n++)
1750        {
1751            if (xkb->map->types[n].name == (Atom) name)
1752            {
1753                *type_rtrn = n;
1754                return True;
1755            }
1756        }
1757    }
1758    return False;
1759}
1760
1761static Bool
1762KSIsLower(KeySym ks)
1763{
1764    KeySym lower, upper;
1765    XConvertCase(ks, &lower, &upper);
1766
1767    if (lower == upper)
1768        return False;
1769    return (ks == lower ? True : False);
1770}
1771
1772static Bool
1773KSIsUpper(KeySym ks)
1774{
1775    KeySym lower, upper;
1776    XConvertCase(ks, &lower, &upper);
1777
1778    if (lower == upper)
1779        return False;
1780    return (ks == upper ? True : False);
1781}
1782
1783/**
1784 * Assign a type to the given sym and return the Atom for the type assigned.
1785 *
1786 * Simple recipe:
1787 * - ONE_LEVEL for width 0/1
1788 * - ALPHABETIC for 2 shift levels, with lower/uppercase
1789 * - KEYPAD for keypad keys.
1790 * - TWO_LEVEL for other 2 shift level keys.
1791 * and the same for four level keys.
1792 *
1793 * @param width Number of sysms in syms.
1794 * @param syms The keysyms for the given key (must be size width).
1795 * @param typeNameRtrn Set to the Atom of the type name.
1796 *
1797 * @returns True if a type could be found, False otherwise.
1798 */
1799static Bool
1800FindAutomaticType(int width, KeySym * syms, Atom * typeNameRtrn,
1801                  Bool * autoType)
1802{
1803    *autoType = False;
1804    if ((width == 1) || (width == 0))
1805    {
1806        *typeNameRtrn = XkbInternAtom(NULL, "ONE_LEVEL", False);
1807        *autoType = True;
1808    }
1809    else if (width == 2)
1810    {
1811        if (syms && KSIsLower(syms[0]) && KSIsUpper(syms[1]))
1812        {
1813            *typeNameRtrn = XkbInternAtom(NULL, "ALPHABETIC", False);
1814        }
1815        else if (syms && (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1])))
1816        {
1817            *typeNameRtrn = XkbInternAtom(NULL, "KEYPAD", False);
1818            *autoType = True;
1819        }
1820        else
1821        {
1822            *typeNameRtrn = XkbInternAtom(NULL, "TWO_LEVEL", False);
1823            *autoType = True;
1824        }
1825    }
1826    else if (width <= 4)
1827    {
1828        if (syms && KSIsLower(syms[0]) && KSIsUpper(syms[1]))
1829            if (KSIsLower(syms[2]) && KSIsUpper(syms[3]))
1830                *typeNameRtrn =
1831                    XkbInternAtom(NULL, "FOUR_LEVEL_ALPHABETIC", False);
1832            else
1833                *typeNameRtrn = XkbInternAtom(NULL,
1834                                              "FOUR_LEVEL_SEMIALPHABETIC",
1835                                              False);
1836
1837        else if (syms && (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1])))
1838            *typeNameRtrn = XkbInternAtom(NULL, "FOUR_LEVEL_KEYPAD", False);
1839        else
1840            *typeNameRtrn = XkbInternAtom(NULL, "FOUR_LEVEL", False);
1841        /* XXX: why not set autoType here? */
1842    }
1843    return ((width >= 0) && (width <= 4));
1844}
1845
1846/**
1847 * Ensure the given KeyInfo is in a coherent state, i.e. no gaps between the
1848 * groups, and reduce to one group if all groups are identical anyway.
1849 */
1850static void
1851PrepareKeyDef(KeyInfo * key)
1852{
1853    int i, j, width, defined, lastGroup;
1854    Bool identical;
1855
1856    defined = key->symsDefined | key->actsDefined | key->typesDefined;
1857    /* get highest group number */
1858    for (i = XkbNumKbdGroups - 1; i >= 0; i--)
1859    {
1860        if (defined & (1 << i))
1861            break;
1862    }
1863    lastGroup = i;
1864
1865    if (lastGroup == 0)
1866        return;
1867
1868    /* If there are empty groups between non-empty ones fill them with data */
1869    /* from the first group. */
1870    /* We can make a wrong assumption here. But leaving gaps is worse. */
1871    for (i = lastGroup; i > 0; i--)
1872    {
1873        if (defined & (1 << i))
1874            continue;
1875        width = key->numLevels[0];
1876        if (key->typesDefined & 1)
1877        {
1878            for (j = 0; j < width; j++)
1879            {
1880                key->types[i] = key->types[0];
1881            }
1882            key->typesDefined |= 1 << i;
1883        }
1884        if ((key->actsDefined & 1) && key->acts[0])
1885        {
1886            key->acts[i] = uTypedCalloc(width, XkbAction);
1887            if (key->acts[i] == NULL)
1888                continue;
1889            memcpy((void *) key->acts[i], (void *) key->acts[0],
1890                   width * sizeof(XkbAction));
1891            key->actsDefined |= 1 << i;
1892        }
1893        if ((key->symsDefined & 1) && key->syms[0])
1894        {
1895            key->syms[i] = uTypedCalloc(width, KeySym);
1896            if (key->syms[i] == NULL)
1897                continue;
1898            memcpy((void *) key->syms[i], (void *) key->syms[0],
1899                   width * sizeof(KeySym));
1900            key->symsDefined |= 1 << i;
1901        }
1902        if (defined & 1)
1903        {
1904            key->numLevels[i] = key->numLevels[0];
1905        }
1906    }
1907    /* If all groups are completely identical remove them all */
1908    /* except the first one. */
1909    identical = True;
1910    for (i = lastGroup; i > 0; i--)
1911    {
1912        if ((key->numLevels[i] != key->numLevels[0]) ||
1913            (key->types[i] != key->types[0]))
1914        {
1915            identical = False;
1916            break;
1917        }
1918        if ((key->syms[i] != key->syms[0]) &&
1919            (key->syms[i] == NULL || key->syms[0] == NULL ||
1920             memcmp((void *) key->syms[i], (void *) key->syms[0],
1921                    sizeof(KeySym) * key->numLevels[0])))
1922        {
1923            identical = False;
1924            break;
1925        }
1926        if ((key->acts[i] != key->acts[0]) &&
1927            (key->acts[i] == NULL || key->acts[0] == NULL ||
1928             memcmp((void *) key->acts[i], (void *) key->acts[0],
1929                    sizeof(XkbAction) * key->numLevels[0])))
1930        {
1931            identical = False;
1932            break;
1933        }
1934    }
1935    if (identical)
1936    {
1937        for (i = lastGroup; i > 0; i--)
1938        {
1939            key->numLevels[i] = 0;
1940            if (key->syms[i] != NULL)
1941                uFree(key->syms[i]);
1942            key->syms[i] = (KeySym *) NULL;
1943            if (key->acts[i] != NULL)
1944                uFree(key->acts[i]);
1945            key->acts[i] = (XkbAction *) NULL;
1946            key->types[i] = (Atom) 0;
1947        }
1948        key->symsDefined &= 1;
1949        key->actsDefined &= 1;
1950        key->typesDefined &= 1;
1951    }
1952    return;
1953}
1954
1955/**
1956 * Copy the KeyInfo into result.
1957 *
1958 * This function recurses.
1959 */
1960static Bool
1961CopySymbolsDef(XkbFileInfo * result, KeyInfo * key, int start_from)
1962{
1963    register int i;
1964    unsigned okc, kc, width, tmp, nGroups;
1965    XkbKeyTypePtr type;
1966    Bool haveActions, autoType, useAlias;
1967    KeySym *outSyms;
1968    XkbAction *outActs;
1969    XkbDescPtr xkb;
1970    unsigned types[XkbNumKbdGroups];
1971
1972    xkb = result->xkb;
1973    useAlias = (start_from == 0);
1974
1975    /* get the keycode for the key. */
1976    if (!FindNamedKey(xkb, key->name, &kc, useAlias, CreateKeyNames(xkb),
1977                      start_from))
1978    {
1979        if ((start_from == 0) && (warningLevel >= 5))
1980        {
1981            WARN("Key %s not found in %s keycodes\n",
1982                  longText(key->name, XkbMessage),
1983                  XkbAtomText(NULL, xkb->names->keycodes, XkbMessage));
1984            ACTION("Symbols ignored\n");
1985        }
1986        return False;
1987    }
1988
1989    haveActions = False;
1990    for (i = width = nGroups = 0; i < XkbNumKbdGroups; i++)
1991    {
1992        if (((i + 1) > nGroups)
1993            && (((key->symsDefined | key->actsDefined) & (1 << i))
1994                || (key->typesDefined) & (1 << i)))
1995            nGroups = i + 1;
1996        if (key->acts[i])
1997            haveActions = True;
1998        autoType = False;
1999        /* Assign the type to the key, if it is missing. */
2000        if (key->types[i] == None)
2001        {
2002            if (key->dfltType != None)
2003                key->types[i] = key->dfltType;
2004            else if (FindAutomaticType(key->numLevels[i], key->syms[i],
2005                                       &key->types[i], &autoType))
2006            {
2007            }
2008            else
2009            {
2010                if (warningLevel >= 5)
2011                {
2012                    WARN("No automatic type for %d symbols\n",
2013                          (unsigned int) key->numLevels[i]);
2014                    ACTION("Using %s for the %s key (keycode %d)\n",
2015                            XkbAtomText(NULL, key->types[i],
2016                                        XkbMessage),
2017                            longText(key->name, XkbMessage), kc);
2018                }
2019            }
2020        }
2021        if (FindNamedType(xkb, key->types[i], &types[i]))
2022        {
2023            if (!autoType || key->numLevels[i] > 2)
2024                xkb->server->explicit[kc] |= (1 << i);
2025        }
2026        else
2027        {
2028            if (warningLevel >= 3)
2029            {
2030                WARN("Type \"%s\" is not defined\n",
2031                      XkbAtomText(NULL, key->types[i], XkbMessage));
2032                ACTION("Using TWO_LEVEL for the %s key (keycode %d)\n",
2033                        longText(key->name, XkbMessage), kc);
2034            }
2035            types[i] = XkbTwoLevelIndex;
2036        }
2037        /* if the type specifies less syms than the key has, shrink the key */
2038        type = &xkb->map->types[types[i]];
2039        if (type->num_levels < key->numLevels[i])
2040        {
2041            if (warningLevel > 5)
2042            {
2043                WARN
2044                    ("Type \"%s\" has %d levels, but %s has %d symbols\n",
2045                     XkbAtomText(NULL, type->name, XkbMessage),
2046                     (unsigned int) type->num_levels,
2047                     longText(key->name, XkbMessage),
2048                     (unsigned int) key->numLevels[i]);
2049                ACTION("Ignoring extra symbols\n");
2050            }
2051            key->numLevels[i] = type->num_levels;
2052        }
2053        if (key->numLevels[i] > width)
2054            width = key->numLevels[i];
2055        if (type->num_levels > width)
2056            width = type->num_levels;
2057    }
2058
2059    /* width is now the largest width found */
2060
2061    i = width * nGroups;
2062    outSyms = XkbResizeKeySyms(xkb, kc, i);
2063    if (outSyms == NULL)
2064    {
2065        WSGO("Could not enlarge symbols for %s (keycode %d)\n",
2066              longText(key->name, XkbMessage), kc);
2067        return False;
2068    }
2069    if (haveActions)
2070    {
2071        outActs = XkbResizeKeyActions(xkb, kc, i);
2072        if (outActs == NULL)
2073        {
2074            WSGO("Could not enlarge actions for %s (key %d)\n",
2075                  longText(key->name, XkbMessage), kc);
2076            return False;
2077        }
2078        xkb->server->explicit[kc] |= XkbExplicitInterpretMask;
2079    }
2080    else
2081        outActs = NULL;
2082    if (key->defs.defined & _Key_GroupInfo)
2083        i = key->groupInfo;
2084    else
2085        i = xkb->map->key_sym_map[kc].group_info;
2086
2087    xkb->map->key_sym_map[kc].group_info = XkbSetNumGroups(i, nGroups);
2088    xkb->map->key_sym_map[kc].width = width;
2089    for (i = 0; i < nGroups; i++)
2090    {
2091        /* assign kt_index[i] to the index of the type in map->types.
2092         * kt_index[i] may have been set by a previous run (if we have two
2093         * layouts specified). Let's not overwrite it with the ONE_LEVEL
2094         * default group if we don't even have keys for this group anyway.
2095         *
2096         * FIXME: There should be a better fix for this.
2097         */
2098        if (key->numLevels[i])
2099            xkb->map->key_sym_map[kc].kt_index[i] = types[i];
2100        if (key->syms[i] != NULL)
2101        {
2102            /* fill key to "width" symbols*/
2103            for (tmp = 0; tmp < width; tmp++)
2104            {
2105                if (tmp < key->numLevels[i])
2106                    outSyms[tmp] = key->syms[i][tmp];
2107                else
2108                    outSyms[tmp] = NoSymbol;
2109                if ((outActs != NULL) && (key->acts[i] != NULL))
2110                {
2111                    if (tmp < key->numLevels[i])
2112                        outActs[tmp] = key->acts[i][tmp];
2113                    else
2114                        outActs[tmp].type = XkbSA_NoAction;
2115                }
2116            }
2117        }
2118        outSyms += width;
2119        if (outActs)
2120            outActs += width;
2121    }
2122    switch (key->behavior.type & XkbKB_OpMask)
2123    {
2124    case XkbKB_Default:
2125        break;
2126    case XkbKB_Overlay1:
2127    case XkbKB_Overlay2:
2128        /* find key by name! */
2129        if (!FindNamedKey(xkb, key->nameForOverlayKey, &okc, True,
2130                          CreateKeyNames(xkb), 0))
2131        {
2132            if (warningLevel >= 1)
2133            {
2134                WARN("Key %s not found in %s keycodes\n",
2135                      longText(key->nameForOverlayKey, XkbMessage),
2136                      XkbAtomText(NULL, xkb->names->keycodes, XkbMessage));
2137                ACTION("Not treating %s as an overlay key \n",
2138                        longText(key->name, XkbMessage));
2139            }
2140            break;
2141        }
2142        key->behavior.data = okc;
2143    default:
2144        xkb->server->behaviors[kc] = key->behavior;
2145        xkb->server->explicit[kc] |= XkbExplicitBehaviorMask;
2146        break;
2147    }
2148    if (key->defs.defined & _Key_VModMap)
2149    {
2150        xkb->server->vmodmap[kc] = key->vmodmap;
2151        xkb->server->explicit[kc] |= XkbExplicitVModMapMask;
2152    }
2153    if (key->repeat != RepeatUndefined)
2154    {
2155        if (key->repeat == RepeatYes)
2156            xkb->ctrls->per_key_repeat[kc / 8] |= (1 << (kc % 8));
2157        else
2158            xkb->ctrls->per_key_repeat[kc / 8] &= ~(1 << (kc % 8));
2159        xkb->server->explicit[kc] |= XkbExplicitAutoRepeatMask;
2160    }
2161
2162    /* do the same thing for the next key */
2163    CopySymbolsDef(result, key, kc + 1);
2164    return True;
2165}
2166
2167static Bool
2168CopyModMapDef(XkbFileInfo * result, ModMapEntry * entry)
2169{
2170    unsigned kc;
2171    XkbDescPtr xkb;
2172
2173    xkb = result->xkb;
2174    if ((!entry->haveSymbol)
2175        &&
2176        (!FindNamedKey
2177         (xkb, entry->u.keyName, &kc, True, CreateKeyNames(xkb), 0)))
2178    {
2179        if (warningLevel >= 5)
2180        {
2181            WARN("Key %s not found in %s keycodes\n",
2182                  longText(entry->u.keyName, XkbMessage),
2183                  XkbAtomText(NULL, xkb->names->keycodes, XkbMessage));
2184            ACTION("Modifier map entry for %s not updated\n",
2185                    XkbModIndexText(entry->modifier, XkbMessage));
2186        }
2187        return False;
2188    }
2189    else if (entry->haveSymbol
2190             && (!FindKeyForSymbol(xkb, entry->u.keySym, &kc)))
2191    {
2192        if (warningLevel > 5)
2193        {
2194            WARN("Key \"%s\" not found in %s symbol map\n",
2195                  XkbKeysymText(entry->u.keySym, XkbMessage),
2196                  XkbAtomText(NULL, xkb->names->symbols, XkbMessage));
2197            ACTION("Modifier map entry for %s not updated\n",
2198                    XkbModIndexText(entry->modifier, XkbMessage));
2199        }
2200        return False;
2201    }
2202    xkb->map->modmap[kc] |= (1 << entry->modifier);
2203    return True;
2204}
2205
2206/**
2207 * Handle the xkb_symbols section of an xkb file.
2208 *
2209 * @param file The parsed xkb_symbols section of the xkb file.
2210 * @param result Handle to the data to store the result in.
2211 * @param merge Merge strategy (e.g. MergeOverride).
2212 */
2213Bool
2214CompileSymbols(XkbFile * file, XkbFileInfo * result, unsigned merge)
2215{
2216    register int i;
2217    SymbolsInfo info;
2218    XkbDescPtr xkb;
2219
2220    xkb = result->xkb;
2221    InitSymbolsInfo(&info, xkb);
2222    info.dflt.defs.fileID = file->id;
2223    info.dflt.defs.merge = merge;
2224    HandleSymbolsFile(file, xkb, merge, &info);
2225
2226    if (info.nKeys == 0)
2227        return True;
2228    if (info.errorCount == 0)
2229    {
2230        KeyInfo *key;
2231
2232        /* alloc memory in the xkb struct */
2233        if (XkbAllocNames(xkb, XkbSymbolsNameMask | XkbGroupNamesMask, 0, 0)
2234            != Success)
2235        {
2236            WSGO("Can not allocate names in CompileSymbols\n");
2237            ACTION("Symbols not added\n");
2238            return False;
2239        }
2240        if (XkbAllocClientMap(xkb, XkbKeySymsMask | XkbModifierMapMask, 0)
2241            != Success)
2242        {
2243            WSGO("Could not allocate client map in CompileSymbols\n");
2244            ACTION("Symbols not added\n");
2245            return False;
2246        }
2247        if (XkbAllocServerMap(xkb, XkbAllServerInfoMask, 32) != Success)
2248        {
2249            WSGO("Could not allocate server map in CompileSymbols\n");
2250            ACTION("Symbols not added\n");
2251            return False;
2252        }
2253        if (XkbAllocControls(xkb, XkbPerKeyRepeatMask) != Success)
2254        {
2255            WSGO("Could not allocate controls in CompileSymbols\n");
2256            ACTION("Symbols not added\n");
2257            return False;
2258        }
2259
2260        /* now copy info into xkb. */
2261        xkb->names->symbols = XkbInternAtom(xkb->dpy, info.name, False);
2262        if (info.aliases)
2263            ApplyAliases(xkb, False, &info.aliases);
2264        for (i = 0; i < XkbNumKbdGroups; i++)
2265        {
2266            if (info.groupNames[i] != None)
2267                xkb->names->groups[i] = info.groupNames[i];
2268        }
2269        /* sanitize keys */
2270        for (key = info.keys, i = 0; i < info.nKeys; i++, key++)
2271        {
2272            PrepareKeyDef(key);
2273        }
2274        /* copy! */
2275        for (key = info.keys, i = 0; i < info.nKeys; i++, key++)
2276        {
2277            if (!CopySymbolsDef(result, key, 0))
2278                info.errorCount++;
2279        }
2280        if (warningLevel > 3)
2281        {
2282            for (i = xkb->min_key_code; i <= xkb->max_key_code; i++)
2283            {
2284                if (xkb->names->keys[i].name[0] == '\0')
2285                    continue;
2286                if (XkbKeyNumGroups(xkb, i) < 1)
2287                {
2288                    char buf[5];
2289                    memcpy(buf, xkb->names->keys[i].name, 4);
2290                    buf[4] = '\0';
2291                    INFO("No symbols defined for <%s> (keycode %d)\n",
2292                         buf, i);
2293                }
2294            }
2295        }
2296        if (info.modMap)
2297        {
2298            ModMapEntry *mm, *next;
2299            for (mm = info.modMap; mm != NULL; mm = next)
2300            {
2301                if (!CopyModMapDef(result, mm))
2302                    info.errorCount++;
2303                next = (ModMapEntry *) mm->defs.next;
2304            }
2305        }
2306        return True;
2307    }
2308    return False;
2309}
2310