symbols.c revision f757b1e9
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            ACTION2("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            ACTION2("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                WARN3
408                    ("Multiple symbols for level %d/group %d on key %s\n",
409                     i + 1, group + 1, longText(into->name, XkbMessage));
410                ACTION2("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                    WARN3
447                        ("Multiple actions for level %d/group %d on key %s\n",
448                         i + 1, group + 1, longText(into->name, XkbMessage));
449                    ACTION2("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                WARN2
552                    ("Multiple definitions for group %d type of key %s\n",
553                     i, longText(into->name, XkbMessage));
554                ACTION2("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)
592    {
593        WARN1("Symbol map for key %s redefined\n",
594              longText(into->name, XkbMessage));
595        ACTION1("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                ERROR1
661                    ("%s added to symbol map for multiple modifiers\n",
662                     XkbKeysymText(new->u.keySym, XkbMessage));
663                ACTION2("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                ERROR1("Key %s added to map for multiple modifiers\n",
687                       longText(new->u.keyName, XkbMessage));
688                ACTION2("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        ACTION1("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        ERROR3("Too many groups of %s for key %s (max %d)\n", name,
906               longText(key->name, XkbMessage), XkbNumKbdGroups + 1);
907        ACTION1("Ignoring %s defined for extra groups\n", name);
908        return False;
909    }
910    if (!ExprResolveInteger
911        (arrayNdx, &tmp, SimpleLookup, (XPointer) groupNames))
912    {
913        ERROR2("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        ERROR3("Group index for %s of key %s is out of range (1..%d)\n",
921               name, longText(key->name, XkbMessage), XkbNumKbdGroups + 1);
922        ACTION2("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        ERROR1("Expected a list of symbols, found %s\n",
948               exprOpText(value->op));
949        ACTION2("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        WSGO2("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        WSGO2("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            WSGO1("Could not resolve keysym %s\n", value->value.list.syms[i]);
972            key->syms[ndx][i] = NoSymbol;
973        }
974    }
975    for (i = key->numLevels[ndx] - 1;
976         (i >= 0) && (key->syms[ndx][i] == NoSymbol); i--)
977    {
978        key->numLevels[ndx]--;
979    }
980    return True;
981}
982
983static Bool
984AddActionsToKey(KeyInfo * key,
985                XkbDescPtr xkb,
986                const char *field,
987                ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info)
988{
989    register int i;
990    unsigned ndx, nActs;
991    ExprDef *act;
992    XkbAnyAction *toAct;
993
994    if (!GetGroupIndex(key, arrayNdx, ACTIONS, &ndx))
995        return False;
996
997    if (value == NULL)
998    {
999        key->actsDefined |= (1 << ndx);
1000        return True;
1001    }
1002    if (value->op != ExprActionList)
1003    {
1004        WSGO1("Bad expression type (%d) for action list value\n", value->op);
1005        ACTION2("Ignoring actions for group %d of %s\n", ndx,
1006                longText(key->name, XkbMessage));
1007        return False;
1008    }
1009    if (key->acts[ndx] != NULL)
1010    {
1011        WSGO2("Actions for key %s, group %d already defined\n",
1012              longText(key->name, XkbMessage), ndx);
1013        return False;
1014    }
1015    for (nActs = 0, act = value->value.child; act != NULL; nActs++)
1016    {
1017        act = (ExprDef *) act->common.next;
1018    }
1019    if (nActs < 1)
1020    {
1021        WSGO("Action list but not actions in AddActionsToKey\n");
1022        return False;
1023    }
1024    if (((key->numLevels[ndx] < nActs) || (key->acts[ndx] == NULL)) &&
1025        (!ResizeKeyGroup(key, ndx, nActs, True)))
1026    {
1027        WSGO2("Could not resize group %d of key %s\n", ndx,
1028              longText(key->name, XkbMessage));
1029        ACTION("Actions lost\n");
1030        return False;
1031    }
1032    key->actsDefined |= (1 << ndx);
1033
1034    toAct = (XkbAnyAction *) key->acts[ndx];
1035    act = value->value.child;
1036    for (i = 0; i < nActs; i++, toAct++)
1037    {
1038        if (!HandleActionDef(act, xkb, toAct, MergeOverride, info->action))
1039        {
1040            ERROR1("Illegal action definition for %s\n",
1041                   longText(key->name, XkbMessage));
1042            ACTION2("Action for group %d/level %d ignored\n", ndx + 1, i + 1);
1043        }
1044        act = (ExprDef *) act->common.next;
1045    }
1046    return True;
1047}
1048
1049static int
1050SetAllowNone(KeyInfo * key, ExprDef * arrayNdx, ExprDef * value)
1051{
1052    ExprResult tmp;
1053    unsigned radio_groups = 0;
1054
1055    if (arrayNdx == NULL)
1056    {
1057        radio_groups = XkbAllRadioGroupsMask;
1058    }
1059    else
1060    {
1061        if (!ExprResolveInteger(arrayNdx, &tmp, RadioLookup, NULL))
1062        {
1063            ERROR("Illegal index in group name definition\n");
1064            ACTION("Definition with non-integer array index ignored\n");
1065            return False;
1066        }
1067        if ((tmp.uval < 1) || (tmp.uval > XkbMaxRadioGroups))
1068        {
1069            ERROR1("Illegal radio group specified (must be 1..%d)\n",
1070                   XkbMaxRadioGroups + 1);
1071            ACTION1("Value of \"allow none\" for group %d ignored\n",
1072                    tmp.uval);
1073            return False;
1074        }
1075        radio_groups |= (1 << (tmp.uval - 1));
1076    }
1077    if (!ExprResolveBoolean(value, &tmp, NULL, NULL))
1078    {
1079        ERROR1("Illegal \"allow none\" value for %s\n",
1080               longText(key->name, XkbMessage));
1081        ACTION("Non-boolean value ignored\n");
1082        return False;
1083    }
1084    if (tmp.uval)
1085        key->allowNone |= radio_groups;
1086    else
1087        key->allowNone &= ~radio_groups;
1088    return True;
1089}
1090
1091
1092static LookupEntry lockingEntries[] = {
1093    {"true", XkbKB_Lock},
1094    {"yes", XkbKB_Lock},
1095    {"on", XkbKB_Lock},
1096    {"false", XkbKB_Default},
1097    {"no", XkbKB_Default},
1098    {"off", XkbKB_Default},
1099    {"permanent", XkbKB_Lock | XkbKB_Permanent},
1100    {NULL, 0}
1101};
1102
1103static LookupEntry repeatEntries[] = {
1104    {"true", RepeatYes},
1105    {"yes", RepeatYes},
1106    {"on", RepeatYes},
1107    {"false", RepeatNo},
1108    {"no", RepeatNo},
1109    {"off", RepeatNo},
1110    {"default", RepeatUndefined},
1111    {NULL, 0}
1112};
1113
1114static LookupEntry rgEntries[] = {
1115    {"none", 0},
1116    {NULL, 0}
1117};
1118
1119static Bool
1120SetSymbolsField(KeyInfo * key,
1121                XkbDescPtr xkb,
1122                const char *field,
1123                ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info)
1124{
1125    Bool ok = True;
1126    ExprResult tmp;
1127
1128    if (uStrCaseCmp(field, "type") == 0)
1129    {
1130        ExprResult ndx;
1131        if ((!ExprResolveString(value, &tmp, NULL, NULL))
1132            && (warningLevel > 0))
1133        {
1134            WARN("The type field of a key symbol map must be a string\n");
1135            ACTION("Ignoring illegal type definition\n");
1136        }
1137        if (arrayNdx == NULL)
1138        {
1139            key->dfltType = XkbInternAtom(NULL, tmp.str, False);
1140            key->defs.defined |= _Key_Type_Dflt;
1141        }
1142        else if (!ExprResolveInteger(arrayNdx, &ndx, SimpleLookup,
1143                                     (XPointer) groupNames))
1144        {
1145            ERROR1("Illegal group index for type of key %s\n",
1146                   longText(key->name, XkbMessage));
1147            ACTION("Definition with non-integer array index ignored\n");
1148            return False;
1149        }
1150        else if ((ndx.uval < 1) || (ndx.uval > XkbNumKbdGroups))
1151        {
1152            ERROR2
1153                ("Group index for type of key %s is out of range (1..%d)\n",
1154                 longText(key->name, XkbMessage), XkbNumKbdGroups + 1);
1155            ACTION1("Ignoring type for group %d\n", ndx.uval);
1156            return False;
1157        }
1158        else
1159        {
1160            key->types[ndx.uval - 1] = XkbInternAtom(NULL, tmp.str, False);
1161            key->typesDefined |= (1 << (ndx.uval - 1));
1162        }
1163    }
1164    else if (uStrCaseCmp(field, "symbols") == 0)
1165        return AddSymbolsToKey(key, xkb, field, arrayNdx, value, info);
1166    else if (uStrCaseCmp(field, "actions") == 0)
1167        return AddActionsToKey(key, xkb, field, arrayNdx, value, info);
1168    else if ((uStrCaseCmp(field, "vmods") == 0) ||
1169             (uStrCaseCmp(field, "virtualmods") == 0) ||
1170             (uStrCaseCmp(field, "virtualmodifiers") == 0))
1171    {
1172        ok = ExprResolveModMask(value, &tmp, LookupVModMask, (XPointer) xkb);
1173        if (ok)
1174        {
1175            key->vmodmap = (tmp.uval >> 8);
1176            key->defs.defined |= _Key_VModMap;
1177        }
1178        else
1179        {
1180            ERROR1("Expected a virtual modifier mask, found %s\n",
1181                   exprOpText(value->op));
1182            ACTION1("Ignoring virtual modifiers definition for key %s\n",
1183                    longText(key->name, XkbMessage));
1184        }
1185    }
1186    else if ((uStrCaseCmp(field, "locking") == 0)
1187             || (uStrCaseCmp(field, "lock") == 0)
1188             || (uStrCaseCmp(field, "locks") == 0))
1189    {
1190        ok = ExprResolveEnum(value, &tmp, lockingEntries);
1191        if (ok)
1192            key->behavior.type = tmp.uval;
1193        key->defs.defined |= _Key_Behavior;
1194    }
1195    else if ((uStrCaseCmp(field, "radiogroup") == 0) ||
1196             (uStrCaseCmp(field, "permanentradiogroup") == 0))
1197    {
1198        Bool permanent = False;
1199        if (uStrCaseCmp(field, "permanentradiogroup") == 0)
1200            permanent = True;
1201        ok = ExprResolveInteger(value, &tmp, SimpleLookup,
1202                                (XPointer) rgEntries);
1203        if (!ok)
1204        {
1205            ERROR1("Illegal radio group specification for %s\n",
1206                   longText(key->name, XkbMessage));
1207            ACTION("Non-integer radio group ignored\n");
1208            return False;
1209        }
1210        if (tmp.uval == 0)
1211        {
1212            key->behavior.type = XkbKB_Default;
1213            key->behavior.data = 0;
1214            return ok;
1215        }
1216        if ((tmp.uval < 1) || (tmp.uval > XkbMaxRadioGroups))
1217        {
1218            ERROR1
1219                ("Radio group specification for %s out of range (1..32)\n",
1220                 longText(key->name, XkbMessage));
1221            ACTION1("Illegal radio group %d ignored\n", tmp.uval);
1222            return False;
1223        }
1224        key->behavior.type =
1225            XkbKB_RadioGroup | (permanent ? XkbKB_Permanent : 0);
1226        key->behavior.data = tmp.uval - 1;
1227        if (key->allowNone & (1 << (tmp.uval - 1)))
1228            key->behavior.data |= XkbKB_RGAllowNone;
1229        key->defs.defined |= _Key_Behavior;
1230    }
1231    else if (uStrCaseEqual(field, "allownone"))
1232    {
1233        ok = SetAllowNone(key, arrayNdx, value);
1234    }
1235    else if (uStrCasePrefix("overlay", field) ||
1236             uStrCasePrefix("permanentoverlay", field))
1237    {
1238        Bool permanent = False;
1239        const char *which;
1240        int overlayNdx;
1241        if (uStrCasePrefix("permanent", field))
1242        {
1243            permanent = True;
1244            which = &field[sizeof("permanentoverlay") - 1];
1245        }
1246        else
1247        {
1248            which = &field[sizeof("overlay") - 1];
1249        }
1250        if (sscanf(which, "%d", &overlayNdx) == 1)
1251        {
1252            if (((overlayNdx < 1) || (overlayNdx > 2)) && (warningLevel > 0))
1253            {
1254                ERROR2("Illegal overlay %d specified for %s\n",
1255                       overlayNdx, longText(key->name, XkbMessage));
1256                ACTION("Ignored\n");
1257                return False;
1258            }
1259        }
1260        else if (*which == '\0')
1261            overlayNdx = 1;
1262        else if (warningLevel > 0)
1263        {
1264            ERROR2("Illegal overlay \"%s\" specified for %s\n",
1265                   which, longText(key->name, XkbMessage));
1266            ACTION("Ignored\n");
1267            return False;
1268        }
1269        ok = ExprResolveKeyName(value, &tmp, NULL, NULL);
1270        if (!ok)
1271        {
1272            ERROR1("Illegal overlay key specification for %s\n",
1273                   longText(key->name, XkbMessage));
1274            ACTION("Overlay key must be specified by name\n");
1275            return False;
1276        }
1277        if (overlayNdx == 1)
1278            key->behavior.type = XkbKB_Overlay1;
1279        else
1280            key->behavior.type = XkbKB_Overlay2;
1281        if (permanent)
1282            key->behavior.type |= XkbKB_Permanent;
1283
1284        key->behavior.data = 0;
1285        key->nameForOverlayKey = KeyNameToLong(tmp.keyName.name);
1286        key->defs.defined |= _Key_Behavior;
1287    }
1288    else if ((uStrCaseCmp(field, "repeating") == 0) ||
1289             (uStrCaseCmp(field, "repeats") == 0) ||
1290             (uStrCaseCmp(field, "repeat") == 0))
1291    {
1292        ok = ExprResolveEnum(value, &tmp, repeatEntries);
1293        if (!ok)
1294        {
1295            ERROR1("Illegal repeat setting for %s\n",
1296                   longText(key->name, XkbMessage));
1297            ACTION("Non-boolean repeat setting ignored\n");
1298            return False;
1299        }
1300        key->repeat = tmp.uval;
1301        key->defs.defined |= _Key_Repeat;
1302    }
1303    else if ((uStrCaseCmp(field, "groupswrap") == 0) ||
1304             (uStrCaseCmp(field, "wrapgroups") == 0))
1305    {
1306        ok = ExprResolveBoolean(value, &tmp, NULL, NULL);
1307        if (!ok)
1308        {
1309            ERROR1("Illegal groupsWrap setting for %s\n",
1310                   longText(key->name, XkbMessage));
1311            ACTION("Non-boolean value ignored\n");
1312            return False;
1313        }
1314        if (tmp.uval)
1315            key->groupInfo = XkbWrapIntoRange;
1316        else
1317            key->groupInfo = XkbClampIntoRange;
1318        key->defs.defined |= _Key_GroupInfo;
1319    }
1320    else if ((uStrCaseCmp(field, "groupsclamp") == 0) ||
1321             (uStrCaseCmp(field, "clampgroups") == 0))
1322    {
1323        ok = ExprResolveBoolean(value, &tmp, NULL, NULL);
1324        if (!ok)
1325        {
1326            ERROR1("Illegal groupsClamp setting for %s\n",
1327                   longText(key->name, XkbMessage));
1328            ACTION("Non-boolean value ignored\n");
1329            return False;
1330        }
1331        if (tmp.uval)
1332            key->groupInfo = XkbClampIntoRange;
1333        else
1334            key->groupInfo = XkbWrapIntoRange;
1335        key->defs.defined |= _Key_GroupInfo;
1336    }
1337    else if ((uStrCaseCmp(field, "groupsredirect") == 0) ||
1338             (uStrCaseCmp(field, "redirectgroups") == 0))
1339    {
1340        if (!ExprResolveInteger
1341            (value, &tmp, SimpleLookup, (XPointer) groupNames))
1342        {
1343            ERROR1("Illegal group index for redirect of key %s\n",
1344                   longText(key->name, XkbMessage));
1345            ACTION("Definition with non-integer group ignored\n");
1346            return False;
1347        }
1348        if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups))
1349        {
1350            ERROR2("Out-of-range (1..%d) group for redirect of key %s\n",
1351                   XkbNumKbdGroups, longText(key->name, XkbMessage));
1352            ERROR1("Ignoring illegal group %d\n", tmp.uval);
1353            return False;
1354        }
1355        key->groupInfo =
1356            XkbSetGroupInfo(0, XkbRedirectIntoRange, tmp.uval - 1);
1357        key->defs.defined |= _Key_GroupInfo;
1358    }
1359    else
1360    {
1361        ERROR1("Unknown field %s in a symbol interpretation\n", field);
1362        ACTION("Definition ignored\n");
1363        ok = False;
1364    }
1365    return ok;
1366}
1367
1368static int
1369SetGroupName(SymbolsInfo * info, ExprDef * arrayNdx, ExprDef * value)
1370{
1371    ExprResult tmp, name;
1372
1373    if ((arrayNdx == NULL) && (warningLevel > 0))
1374    {
1375        WARN("You must specify an index when specifying a group name\n");
1376        ACTION("Group name definition without array subscript ignored\n");
1377        return False;
1378    }
1379    if (!ExprResolveInteger
1380        (arrayNdx, &tmp, SimpleLookup, (XPointer) groupNames))
1381    {
1382        ERROR("Illegal index in group name definition\n");
1383        ACTION("Definition with non-integer array index ignored\n");
1384        return False;
1385    }
1386    if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups))
1387    {
1388        ERROR1
1389            ("Attempt to specify name for illegal group (must be 1..%d)\n",
1390             XkbNumKbdGroups + 1);
1391        ACTION1("Name for group %d ignored\n", tmp.uval);
1392        return False;
1393    }
1394    if (!ExprResolveString(value, &name, NULL, NULL))
1395    {
1396        ERROR("Group name must be a string\n");
1397        ACTION1("Illegal name for group %d ignored\n", tmp.uval);
1398        return False;
1399    }
1400    info->groupNames[tmp.uval - 1 + info->explicit_group] =
1401        XkbInternAtom(NULL, name.str, False);
1402
1403    return True;
1404}
1405
1406static int
1407HandleSymbolsVar(VarDef * stmt, XkbDescPtr xkb, SymbolsInfo * info)
1408{
1409    ExprResult elem, field, tmp;
1410    ExprDef *arrayNdx;
1411
1412    if (ExprResolveLhs(stmt->name, &elem, &field, &arrayNdx) == 0)
1413        return 0;               /* internal error, already reported */
1414    if (elem.str && (uStrCaseCmp(elem.str, "key") == 0))
1415    {
1416        return SetSymbolsField(&info->dflt, xkb, field.str, arrayNdx,
1417                               stmt->value, info);
1418    }
1419    else if ((elem.str == NULL) && ((uStrCaseCmp(field.str, "name") == 0) ||
1420                                    (uStrCaseCmp(field.str, "groupname") ==
1421                                     0)))
1422    {
1423        return SetGroupName(info, arrayNdx, stmt->value);
1424    }
1425    else if ((elem.str == NULL)
1426             && ((uStrCaseCmp(field.str, "groupswrap") == 0)
1427                 || (uStrCaseCmp(field.str, "wrapgroups") == 0)))
1428    {
1429        if (!ExprResolveBoolean(stmt->value, &tmp, NULL, NULL))
1430        {
1431            ERROR("Illegal setting for global groupsWrap\n");
1432            ACTION("Non-boolean value ignored\n");
1433            return False;
1434        }
1435        if (tmp.uval)
1436            info->groupInfo = XkbWrapIntoRange;
1437        else
1438            info->groupInfo = XkbClampIntoRange;
1439        return True;
1440    }
1441    else if ((elem.str == NULL)
1442             && ((uStrCaseCmp(field.str, "groupsclamp") == 0)
1443                 || (uStrCaseCmp(field.str, "clampgroups") == 0)))
1444    {
1445        if (!ExprResolveBoolean(stmt->value, &tmp, NULL, NULL))
1446        {
1447            ERROR("Illegal setting for global groupsClamp\n");
1448            ACTION("Non-boolean value ignored\n");
1449            return False;
1450        }
1451        if (tmp.uval)
1452            info->groupInfo = XkbClampIntoRange;
1453        else
1454            info->groupInfo = XkbWrapIntoRange;
1455        return True;
1456    }
1457    else if ((elem.str == NULL)
1458             && ((uStrCaseCmp(field.str, "groupsredirect") == 0)
1459                 || (uStrCaseCmp(field.str, "redirectgroups") == 0)))
1460    {
1461        if (!ExprResolveInteger(stmt->value, &tmp,
1462                                SimpleLookup, (XPointer) groupNames))
1463        {
1464            ERROR("Illegal group index for global groupsRedirect\n");
1465            ACTION("Definition with non-integer group ignored\n");
1466            return False;
1467        }
1468        if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups))
1469        {
1470            ERROR1
1471                ("Out-of-range (1..%d) group for global groupsRedirect\n",
1472                 XkbNumKbdGroups);
1473            ACTION1("Ignoring illegal group %d\n", tmp.uval);
1474            return False;
1475        }
1476        info->groupInfo = XkbSetGroupInfo(0, XkbRedirectIntoRange, tmp.uval);
1477        return True;
1478    }
1479    else if ((elem.str == NULL) && (uStrCaseCmp(field.str, "allownone") == 0))
1480    {
1481        return SetAllowNone(&info->dflt, arrayNdx, stmt->value);
1482    }
1483    return SetActionField(xkb, elem.str, field.str, arrayNdx, stmt->value,
1484                          &info->action);
1485}
1486
1487static Bool
1488HandleSymbolsBody(VarDef * def,
1489                  XkbDescPtr xkb, KeyInfo * key, SymbolsInfo * info)
1490{
1491    Bool ok = True;
1492    ExprResult tmp, field;
1493    ExprDef *arrayNdx;
1494
1495    for (; def != NULL; def = (VarDef *) def->common.next)
1496    {
1497        if ((def->name) && (def->name->type == ExprFieldRef))
1498        {
1499            ok = HandleSymbolsVar(def, xkb, info);
1500            continue;
1501        }
1502        else
1503        {
1504            if (def->name == NULL)
1505            {
1506                if ((def->value == NULL)
1507                    || (def->value->op == ExprKeysymList))
1508                    field.str = "symbols";
1509                else
1510                    field.str = "actions";
1511                arrayNdx = NULL;
1512            }
1513            else
1514            {
1515                ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx);
1516            }
1517            if (ok)
1518                ok = SetSymbolsField(key, xkb, field.str, arrayNdx,
1519                                     def->value, info);
1520        }
1521    }
1522    return ok;
1523}
1524
1525static Bool
1526SetExplicitGroup(SymbolsInfo * info, KeyInfo * key)
1527{
1528    unsigned group = info->explicit_group;
1529
1530    if (group == 0)
1531        return True;
1532
1533    if ((key->typesDefined | key->symsDefined | key->actsDefined) & ~1)
1534    {
1535        int i;
1536        WARN1("For the map %s an explicit group specified\n", info->name);
1537        WARN1("but key %s has more than one group defined\n",
1538              longText(key->name, XkbMessage));
1539        ACTION("All groups except first one will be ignored\n");
1540        for (i = 1; i < XkbNumKbdGroups; i++)
1541        {
1542            key->numLevels[i] = 0;
1543            if (key->syms[i] != NULL)
1544                uFree(key->syms[i]);
1545            key->syms[i] = (KeySym *) NULL;
1546            if (key->acts[i] != NULL)
1547                uFree(key->acts[i]);
1548            key->acts[i] = (XkbAction *) NULL;
1549            key->types[i] = (Atom) 0;
1550        }
1551    }
1552    key->typesDefined = key->symsDefined = key->actsDefined = 1 << group;
1553
1554    key->numLevels[group] = key->numLevels[0];
1555    key->numLevels[0] = 0;
1556    key->syms[group] = key->syms[0];
1557    key->syms[0] = (KeySym *) NULL;
1558    key->acts[group] = key->acts[0];
1559    key->acts[0] = (XkbAction *) NULL;
1560    key->types[group] = key->types[0];
1561    key->types[0] = (Atom) 0;
1562    return True;
1563}
1564
1565static int
1566HandleSymbolsDef(SymbolsDef * stmt,
1567                 XkbDescPtr xkb, unsigned merge, SymbolsInfo * info)
1568{
1569    KeyInfo key;
1570
1571    InitKeyInfo(&key);
1572    CopyKeyInfo(&info->dflt, &key, False);
1573    key.defs.merge = stmt->merge;
1574    key.name = KeyNameToLong(stmt->keyName);
1575    if (!HandleSymbolsBody((VarDef *) stmt->symbols, xkb, &key, info))
1576    {
1577        info->errorCount++;
1578        return False;
1579    }
1580
1581    if (!SetExplicitGroup(info, &key))
1582    {
1583        info->errorCount++;
1584        return False;
1585    }
1586
1587    if (!AddKeySymbols(info, &key, xkb))
1588    {
1589        info->errorCount++;
1590        return False;
1591    }
1592    return True;
1593}
1594
1595static Bool
1596HandleModMapDef(ModMapDef * def,
1597                XkbDescPtr xkb, unsigned merge, SymbolsInfo * info)
1598{
1599    ExprDef *key;
1600    ModMapEntry tmp;
1601    ExprResult rtrn;
1602    Bool ok;
1603
1604    if (!LookupModIndex(NULL, None, def->modifier, TypeInt, &rtrn))
1605    {
1606        ERROR("Illegal modifier map definition\n");
1607        ACTION1("Ignoring map for non-modifier \"%s\"\n",
1608                XkbAtomText(NULL, def->modifier, XkbMessage));
1609        return False;
1610    }
1611    ok = True;
1612    tmp.modifier = rtrn.uval;
1613    for (key = def->keys; key != NULL; key = (ExprDef *) key->common.next)
1614    {
1615        if ((key->op == ExprValue) && (key->type == TypeKeyName))
1616        {
1617            tmp.haveSymbol = False;
1618            tmp.u.keyName = KeyNameToLong(key->value.keyName);
1619        }
1620        else if (ExprResolveKeySym(key, &rtrn, NULL, NULL))
1621        {
1622            tmp.haveSymbol = True;
1623            tmp.u.keySym = rtrn.uval;
1624        }
1625        else
1626        {
1627            ERROR("Modmap entries may contain only key names or keysyms\n");
1628            ACTION1("Illegal definition for %s modifier ignored\n",
1629                    XkbModIndexText(tmp.modifier, XkbMessage));
1630            continue;
1631        }
1632
1633        ok = AddModMapEntry(info, &tmp) && ok;
1634    }
1635    return ok;
1636}
1637
1638static void
1639HandleSymbolsFile(XkbFile * file,
1640                  XkbDescPtr xkb, unsigned merge, SymbolsInfo * info)
1641{
1642    ParseCommon *stmt;
1643
1644    info->name = uStringDup(file->name);
1645    stmt = file->defs;
1646    while (stmt)
1647    {
1648        switch (stmt->stmtType)
1649        {
1650        case StmtInclude:
1651            if (!HandleIncludeSymbols((IncludeStmt *) stmt, xkb, info,
1652                                      HandleSymbolsFile))
1653                info->errorCount++;
1654            break;
1655        case StmtSymbolsDef:
1656            if (!HandleSymbolsDef((SymbolsDef *) stmt, xkb, merge, info))
1657                info->errorCount++;
1658            break;
1659        case StmtVarDef:
1660            if (!HandleSymbolsVar((VarDef *) stmt, xkb, info))
1661                info->errorCount++;
1662            break;
1663        case StmtVModDef:
1664            if (!HandleVModDef((VModDef *) stmt, merge, &info->vmods))
1665                info->errorCount++;
1666            break;
1667        case StmtInterpDef:
1668            ERROR("Interpretation files may not include other types\n");
1669            ACTION("Ignoring definition of symbol interpretation\n");
1670            info->errorCount++;
1671            break;
1672        case StmtKeycodeDef:
1673            ERROR("Interpretation files may not include other types\n");
1674            ACTION("Ignoring definition of key name\n");
1675            info->errorCount++;
1676            break;
1677        case StmtModMapDef:
1678            if (!HandleModMapDef((ModMapDef *) stmt, xkb, merge, info))
1679                info->errorCount++;
1680            break;
1681        default:
1682            WSGO1("Unexpected statement type %d in HandleSymbolsFile\n",
1683                  stmt->stmtType);
1684            break;
1685        }
1686        stmt = stmt->next;
1687        if (info->errorCount > 10)
1688        {
1689#ifdef NOISY
1690            ERROR("Too many errors\n");
1691#endif
1692            ACTION1("Abandoning symbols file \"%s\"\n", file->topName);
1693            break;
1694        }
1695    }
1696    return;
1697}
1698
1699static Bool
1700FindKeyForSymbol(XkbDescPtr xkb, KeySym sym, unsigned int *kc_rtrn)
1701{
1702    register int i, j;
1703    register Bool gotOne;
1704
1705    j = 0;
1706    do
1707    {
1708        gotOne = False;
1709        for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++)
1710        {
1711            if (j < (int) XkbKeyNumSyms(xkb, i))
1712            {
1713                gotOne = True;
1714                if (XkbKeySym(xkb, i, j) == sym)
1715                {
1716                    *kc_rtrn = i;
1717                    return True;
1718                }
1719            }
1720        }
1721        j++;
1722    }
1723    while (gotOne);
1724    return False;
1725}
1726
1727/**
1728 * Find the given name in the xkb->map->types and return its index.
1729 *
1730 * @param name The atom to search for.
1731 * @param type_rtrn Set to the index of the name if found.
1732 *
1733 * @return True if found, False otherwise.
1734 */
1735static Bool
1736FindNamedType(XkbDescPtr xkb, Atom name, unsigned *type_rtrn)
1737{
1738    register unsigned n;
1739
1740    if (xkb && xkb->map && xkb->map->types)
1741    {
1742        for (n = 0; n < xkb->map->num_types; n++)
1743        {
1744            if (xkb->map->types[n].name == (Atom) name)
1745            {
1746                *type_rtrn = n;
1747                return True;
1748            }
1749        }
1750    }
1751    return False;
1752}
1753
1754static Bool
1755KSIsLower(KeySym ks)
1756{
1757    KeySym lower, upper;
1758    XConvertCase(ks, &lower, &upper);
1759
1760    if (lower == upper)
1761        return False;
1762    return (ks == lower ? True : False);
1763}
1764
1765static Bool
1766KSIsUpper(KeySym ks)
1767{
1768    KeySym lower, upper;
1769    XConvertCase(ks, &lower, &upper);
1770
1771    if (lower == upper)
1772        return False;
1773    return (ks == upper ? True : False);
1774}
1775
1776/**
1777 * Assign a type to the given sym and return the Atom for the type assigned.
1778 *
1779 * Simple recipe:
1780 * - ONE_LEVEL for width 0/1
1781 * - ALPHABETIC for 2 shift levels, with lower/upercase
1782 * - KEYPAD for keypad keys.
1783 * - TWO_LEVEL for other 2 shift level keys.
1784 * and the same for four level keys.
1785 *
1786 * @param width Number of sysms in syms.
1787 * @param syms The keysyms for the given key (must be size width).
1788 * @param typeNameRtrn Set to the Atom of the type name.
1789 *
1790 * @returns True if a type could be found, False otherwise.
1791 */
1792static Bool
1793FindAutomaticType(int width, KeySym * syms, Atom * typeNameRtrn,
1794                  Bool * autoType)
1795{
1796    *autoType = False;
1797    if ((width == 1) || (width == 0))
1798    {
1799        *typeNameRtrn = XkbInternAtom(NULL, "ONE_LEVEL", False);
1800        *autoType = True;
1801    }
1802    else if (width == 2)
1803    {
1804        if (syms && KSIsLower(syms[0]) && KSIsUpper(syms[1]))
1805        {
1806            *typeNameRtrn = XkbInternAtom(NULL, "ALPHABETIC", False);
1807        }
1808        else if (syms && (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1])))
1809        {
1810            *typeNameRtrn = XkbInternAtom(NULL, "KEYPAD", False);
1811            *autoType = True;
1812        }
1813        else
1814        {
1815            *typeNameRtrn = XkbInternAtom(NULL, "TWO_LEVEL", False);
1816            *autoType = True;
1817        }
1818    }
1819    else if (width <= 4)
1820    {
1821        if (syms && KSIsLower(syms[0]) && KSIsUpper(syms[1]))
1822            if (KSIsLower(syms[2]) && KSIsUpper(syms[3]))
1823                *typeNameRtrn =
1824                    XkbInternAtom(NULL, "FOUR_LEVEL_ALPHABETIC", False);
1825            else
1826                *typeNameRtrn = XkbInternAtom(NULL,
1827                                              "FOUR_LEVEL_SEMIALPHABETIC",
1828                                              False);
1829
1830        else if (syms && (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1])))
1831            *typeNameRtrn = XkbInternAtom(NULL, "FOUR_LEVEL_KEYPAD", False);
1832        else
1833            *typeNameRtrn = XkbInternAtom(NULL, "FOUR_LEVEL", False);
1834        /* XXX: why not set autoType here? */
1835    }
1836    return ((width >= 0) && (width <= 4));
1837}
1838
1839/**
1840 * Ensure the given KeyInfo is in a coherent state, i.e. no gaps between the
1841 * groups, and reduce to one group if all groups are identical anyway.
1842 */
1843static void
1844PrepareKeyDef(KeyInfo * key)
1845{
1846    int i, j, width, defined, lastGroup;
1847    Bool identical;
1848
1849    defined = key->symsDefined | key->actsDefined | key->typesDefined;
1850    /* get highest group number */
1851    for (i = XkbNumKbdGroups - 1; i >= 0; i--)
1852    {
1853        if (defined & (1 << i))
1854            break;
1855    }
1856    lastGroup = i;
1857
1858    if (lastGroup == 0)
1859        return;
1860
1861    /* If there are empty groups between non-empty ones fill them with data */
1862    /* from the first group. */
1863    /* We can make a wrong assumption here. But leaving gaps is worse. */
1864    for (i = lastGroup; i > 0; i--)
1865    {
1866        if (defined & (1 << i))
1867            continue;
1868        width = key->numLevels[0];
1869        if (key->typesDefined & 1)
1870        {
1871            for (j = 0; j < width; j++)
1872            {
1873                key->types[i] = key->types[0];
1874            }
1875            key->typesDefined |= 1 << i;
1876        }
1877        if ((key->actsDefined & 1) && key->acts[0])
1878        {
1879            key->acts[i] = uTypedCalloc(width, XkbAction);
1880            if (key->acts[i] == NULL)
1881                continue;
1882            memcpy((void *) key->acts[i], (void *) key->acts[0],
1883                   width * sizeof(XkbAction));
1884            key->actsDefined |= 1 << i;
1885        }
1886        if ((key->symsDefined & 1) && key->syms[0])
1887        {
1888            key->syms[i] = uTypedCalloc(width, KeySym);
1889            if (key->syms[i] == NULL)
1890                continue;
1891            memcpy((void *) key->syms[i], (void *) key->syms[0],
1892                   width * sizeof(KeySym));
1893            key->symsDefined |= 1 << i;
1894        }
1895        if (defined & 1)
1896        {
1897            key->numLevels[i] = key->numLevels[0];
1898        }
1899    }
1900    /* If all groups are completely identical remove them all */
1901    /* exept the first one. */
1902    identical = True;
1903    for (i = lastGroup; i > 0; i--)
1904    {
1905        if ((key->numLevels[i] != key->numLevels[0]) ||
1906            (key->types[i] != key->types[0]))
1907        {
1908            identical = False;
1909            break;
1910        }
1911        if ((key->syms[i] != key->syms[0]) &&
1912            (key->syms[i] == NULL || key->syms[0] == NULL ||
1913             memcmp((void *) key->syms[i], (void *) key->syms[0],
1914                    sizeof(KeySym) * key->numLevels[0])))
1915        {
1916            identical = False;
1917            break;
1918        }
1919        if ((key->acts[i] != key->acts[0]) &&
1920            (key->acts[i] == NULL || key->acts[0] == NULL ||
1921             memcmp((void *) key->acts[i], (void *) key->acts[0],
1922                    sizeof(XkbAction) * key->numLevels[0])))
1923        {
1924            identical = False;
1925            break;
1926        }
1927    }
1928    if (identical)
1929    {
1930        for (i = lastGroup; i > 0; i--)
1931        {
1932            key->numLevels[i] = 0;
1933            if (key->syms[i] != NULL)
1934                uFree(key->syms[i]);
1935            key->syms[i] = (KeySym *) NULL;
1936            if (key->acts[i] != NULL)
1937                uFree(key->acts[i]);
1938            key->acts[i] = (XkbAction *) NULL;
1939            key->types[i] = (Atom) 0;
1940        }
1941        key->symsDefined &= 1;
1942        key->actsDefined &= 1;
1943        key->typesDefined &= 1;
1944    }
1945    return;
1946}
1947
1948/**
1949 * Copy the KeyInfo into result.
1950 *
1951 * This function recurses.
1952 */
1953static Bool
1954CopySymbolsDef(XkbFileInfo * result, KeyInfo * key, int start_from)
1955{
1956    register int i;
1957    unsigned okc, kc, width, tmp, nGroups;
1958    XkbKeyTypePtr type;
1959    Bool haveActions, autoType, useAlias;
1960    KeySym *outSyms;
1961    XkbAction *outActs;
1962    XkbDescPtr xkb;
1963    unsigned types[XkbNumKbdGroups];
1964
1965    xkb = result->xkb;
1966    useAlias = (start_from == 0);
1967
1968    /* get the keycode for the key. */
1969    if (!FindNamedKey(xkb, key->name, &kc, useAlias, CreateKeyNames(xkb),
1970                      start_from))
1971    {
1972        if ((start_from == 0) && (warningLevel >= 5))
1973        {
1974            WARN2("Key %s not found in %s keycodes\n",
1975                  longText(key->name, XkbMessage),
1976                  XkbAtomText(NULL, xkb->names->keycodes, XkbMessage));
1977            ACTION("Symbols ignored\n");
1978        }
1979        return False;
1980    }
1981
1982    haveActions = False;
1983    for (i = width = nGroups = 0; i < XkbNumKbdGroups; i++)
1984    {
1985        if (((i + 1) > nGroups)
1986            && (((key->symsDefined | key->actsDefined) & (1 << i))
1987                || (key->typesDefined) & (1 << i)))
1988            nGroups = i + 1;
1989        if (key->acts[i])
1990            haveActions = True;
1991        autoType = False;
1992        /* Assign the type to the key, if it is missing. */
1993        if (key->types[i] == None)
1994        {
1995            if (key->dfltType != None)
1996                key->types[i] = key->dfltType;
1997            else if (FindAutomaticType(key->numLevels[i], key->syms[i],
1998                                       &key->types[i], &autoType))
1999            {
2000            }
2001            else
2002            {
2003                if (warningLevel >= 5)
2004                {
2005                    WARN1("No automatic type for %d symbols\n",
2006                          (unsigned int) key->numLevels[i]);
2007                    ACTION3("Using %s for the %s key (keycode %d)\n",
2008                            XkbAtomText(NULL, key->types[i],
2009                                        XkbMessage),
2010                            longText(key->name, XkbMessage), kc);
2011                }
2012            }
2013        }
2014        if (FindNamedType(xkb, key->types[i], &types[i]))
2015        {
2016            if (!autoType || key->numLevels[i] > 2)
2017                xkb->server->explicit[kc] |= (1 << i);
2018        }
2019        else
2020        {
2021            if (warningLevel >= 3)
2022            {
2023                WARN1("Type \"%s\" is not defined\n",
2024                      XkbAtomText(NULL, key->types[i], XkbMessage));
2025                ACTION2("Using TWO_LEVEL for the %s key (keycode %d)\n",
2026                        longText(key->name, XkbMessage), kc);
2027            }
2028            types[i] = XkbTwoLevelIndex;
2029        }
2030        /* if the type specifies less syms than the key has, shrink the key */
2031        type = &xkb->map->types[types[i]];
2032        if (type->num_levels < key->numLevels[i])
2033        {
2034            if (warningLevel > 5)
2035            {
2036                WARN4
2037                    ("Type \"%s\" has %d levels, but %s has %d symbols\n",
2038                     XkbAtomText(NULL, type->name, XkbMessage),
2039                     (unsigned int) type->num_levels,
2040                     longText(key->name, XkbMessage),
2041                     (unsigned int) key->numLevels[i]);
2042                ACTION("Ignoring extra symbols\n");
2043            }
2044            key->numLevels[i] = type->num_levels;
2045        }
2046        if (key->numLevels[i] > width)
2047            width = key->numLevels[i];
2048        if (type->num_levels > width)
2049            width = type->num_levels;
2050    }
2051
2052    /* width is now the largest width found */
2053
2054    i = width * nGroups;
2055    outSyms = XkbResizeKeySyms(xkb, kc, i);
2056    if (outSyms == NULL)
2057    {
2058        WSGO2("Could not enlarge symbols for %s (keycode %d)\n",
2059              longText(key->name, XkbMessage), kc);
2060        return False;
2061    }
2062    if (haveActions)
2063    {
2064        outActs = XkbResizeKeyActions(xkb, kc, i);
2065        if (outActs == NULL)
2066        {
2067            WSGO2("Could not enlarge actions for %s (key %d)\n",
2068                  longText(key->name, XkbMessage), kc);
2069            return False;
2070        }
2071        xkb->server->explicit[kc] |= XkbExplicitInterpretMask;
2072    }
2073    else
2074        outActs = NULL;
2075    if (key->defs.defined & _Key_GroupInfo)
2076        i = key->groupInfo;
2077    else
2078        i = xkb->map->key_sym_map[kc].group_info;
2079
2080    xkb->map->key_sym_map[kc].group_info = XkbSetNumGroups(i, nGroups);
2081    xkb->map->key_sym_map[kc].width = width;
2082    for (i = 0; i < nGroups; i++)
2083    {
2084        /* assign kt_index[i] to the index of the type in map->types.
2085         * kt_index[i] may have been set by a previous run (if we have two
2086         * layouts specified). Let's not overwrite it with the ONE_LEVEL
2087         * default group if we dont even have keys for this group anyway.
2088         *
2089         * FIXME: There should be a better fix for this.
2090         */
2091        if (key->numLevels[i])
2092            xkb->map->key_sym_map[kc].kt_index[i] = types[i];
2093        if (key->syms[i] != NULL)
2094        {
2095            /* fill key to "width" symbols*/
2096            for (tmp = 0; tmp < width; tmp++)
2097            {
2098                if (tmp < key->numLevels[i])
2099                    outSyms[tmp] = key->syms[i][tmp];
2100                else
2101                    outSyms[tmp] = NoSymbol;
2102                if ((outActs != NULL) && (key->acts[i] != NULL))
2103                {
2104                    if (tmp < key->numLevels[i])
2105                        outActs[tmp] = key->acts[i][tmp];
2106                    else
2107                        outActs[tmp].type = XkbSA_NoAction;
2108                }
2109            }
2110        }
2111        outSyms += width;
2112        if (outActs)
2113            outActs += width;
2114    }
2115    switch (key->behavior.type & XkbKB_OpMask)
2116    {
2117    case XkbKB_Default:
2118        break;
2119    case XkbKB_Overlay1:
2120    case XkbKB_Overlay2:
2121        /* find key by name! */
2122        if (!FindNamedKey(xkb, key->nameForOverlayKey, &okc, True,
2123                          CreateKeyNames(xkb), 0))
2124        {
2125            if (warningLevel >= 1)
2126            {
2127                WARN2("Key %s not found in %s keycodes\n",
2128                      longText(key->nameForOverlayKey, XkbMessage),
2129                      XkbAtomText(NULL, xkb->names->keycodes, XkbMessage));
2130                ACTION1("Not treating %s as an overlay key \n",
2131                        longText(key->name, XkbMessage));
2132            }
2133            break;
2134        }
2135        key->behavior.data = okc;
2136    default:
2137        xkb->server->behaviors[kc] = key->behavior;
2138        xkb->server->explicit[kc] |= XkbExplicitBehaviorMask;
2139        break;
2140    }
2141    if (key->defs.defined & _Key_VModMap)
2142    {
2143        xkb->server->vmodmap[kc] = key->vmodmap;
2144        xkb->server->explicit[kc] |= XkbExplicitVModMapMask;
2145    }
2146    if (key->repeat != RepeatUndefined)
2147    {
2148        if (key->repeat == RepeatYes)
2149            xkb->ctrls->per_key_repeat[kc / 8] |= (1 << (kc % 8));
2150        else
2151            xkb->ctrls->per_key_repeat[kc / 8] &= ~(1 << (kc % 8));
2152        xkb->server->explicit[kc] |= XkbExplicitAutoRepeatMask;
2153    }
2154
2155    /* do the same thing for the next key */
2156    CopySymbolsDef(result, key, kc + 1);
2157    return True;
2158}
2159
2160static Bool
2161CopyModMapDef(XkbFileInfo * result, ModMapEntry * entry)
2162{
2163    unsigned kc;
2164    XkbDescPtr xkb;
2165
2166    xkb = result->xkb;
2167    if ((!entry->haveSymbol)
2168        &&
2169        (!FindNamedKey
2170         (xkb, entry->u.keyName, &kc, True, CreateKeyNames(xkb), 0)))
2171    {
2172        if (warningLevel >= 5)
2173        {
2174            WARN2("Key %s not found in %s keycodes\n",
2175                  longText(entry->u.keyName, XkbMessage),
2176                  XkbAtomText(NULL, xkb->names->keycodes, XkbMessage));
2177            ACTION1("Modifier map entry for %s not updated\n",
2178                    XkbModIndexText(entry->modifier, XkbMessage));
2179        }
2180        return False;
2181    }
2182    else if (entry->haveSymbol
2183             && (!FindKeyForSymbol(xkb, entry->u.keySym, &kc)))
2184    {
2185        if (warningLevel > 5)
2186        {
2187            WARN2("Key \"%s\" not found in %s symbol map\n",
2188                  XkbKeysymText(entry->u.keySym, XkbMessage),
2189                  XkbAtomText(NULL, xkb->names->symbols, XkbMessage));
2190            ACTION1("Modifier map entry for %s not updated\n",
2191                    XkbModIndexText(entry->modifier, XkbMessage));
2192        }
2193        return False;
2194    }
2195    xkb->map->modmap[kc] |= (1 << entry->modifier);
2196    return True;
2197}
2198
2199/**
2200 * Handle the xkb_symbols section of an xkb file.
2201 *
2202 * @param file The parsed xkb_symbols section of the xkb file.
2203 * @param result Handle to the data to store the result in.
2204 * @param merge Merge strategy (e.g. MergeOverride).
2205 */
2206Bool
2207CompileSymbols(XkbFile * file, XkbFileInfo * result, unsigned merge)
2208{
2209    register int i;
2210    SymbolsInfo info;
2211    XkbDescPtr xkb;
2212
2213    xkb = result->xkb;
2214    InitSymbolsInfo(&info, xkb);
2215    info.dflt.defs.fileID = file->id;
2216    info.dflt.defs.merge = merge;
2217    HandleSymbolsFile(file, xkb, merge, &info);
2218
2219    if (info.nKeys == 0)
2220        return True;
2221    if (info.errorCount == 0)
2222    {
2223        KeyInfo *key;
2224
2225        /* alloc memory in the xkb struct */
2226        if (XkbAllocNames(xkb, XkbSymbolsNameMask | XkbGroupNamesMask, 0, 0)
2227            != Success)
2228        {
2229            WSGO("Can not allocate names in CompileSymbols\n");
2230            ACTION("Symbols not added\n");
2231            return False;
2232        }
2233        if (XkbAllocClientMap(xkb, XkbKeySymsMask | XkbModifierMapMask, 0)
2234            != Success)
2235        {
2236            WSGO("Could not allocate client map in CompileSymbols\n");
2237            ACTION("Symbols not added\n");
2238            return False;
2239        }
2240        if (XkbAllocServerMap(xkb, XkbAllServerInfoMask, 32) != Success)
2241        {
2242            WSGO("Could not allocate server map in CompileSymbols\n");
2243            ACTION("Symbols not added\n");
2244            return False;
2245        }
2246        if (XkbAllocControls(xkb, XkbPerKeyRepeatMask) != Success)
2247        {
2248            WSGO("Could not allocate controls in CompileSymbols\n");
2249            ACTION("Symbols not added\n");
2250            return False;
2251        }
2252
2253        /* now copy info into xkb. */
2254        xkb->names->symbols = XkbInternAtom(xkb->dpy, info.name, False);
2255        if (info.aliases)
2256            ApplyAliases(xkb, False, &info.aliases);
2257        for (i = 0; i < XkbNumKbdGroups; i++)
2258        {
2259            if (info.groupNames[i] != None)
2260                xkb->names->groups[i] = info.groupNames[i];
2261        }
2262        /* sanitize keys */
2263        for (key = info.keys, i = 0; i < info.nKeys; i++, key++)
2264        {
2265            PrepareKeyDef(key);
2266        }
2267        /* copy! */
2268        for (key = info.keys, i = 0; i < info.nKeys; i++, key++)
2269        {
2270            if (!CopySymbolsDef(result, key, 0))
2271                info.errorCount++;
2272        }
2273        if (warningLevel > 3)
2274        {
2275            for (i = xkb->min_key_code; i <= xkb->max_key_code; i++)
2276            {
2277                if (xkb->names->keys[i].name[0] == '\0')
2278                    continue;
2279                if (XkbKeyNumGroups(xkb, i) < 1)
2280                {
2281                    char buf[5];
2282                    memcpy(buf, xkb->names->keys[i].name, 4);
2283                    buf[4] = '\0';
2284                    WARN2
2285                        ("No symbols defined for <%s> (keycode %d)\n",
2286                         buf, i);
2287                }
2288            }
2289        }
2290        if (info.modMap)
2291        {
2292            ModMapEntry *mm, *next;
2293            for (mm = info.modMap; mm != NULL; mm = next)
2294            {
2295                if (!CopyModMapDef(result, mm))
2296                    info.errorCount++;
2297                next = (ModMapEntry *) mm->defs.next;
2298            }
2299        }
2300        return True;
2301    }
2302    return False;
2303}
2304