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