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