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