indicators.c revision 6930ead5
1f46a6179Smrg/************************************************************
2f46a6179Smrg Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3f46a6179Smrg
4f46a6179Smrg Permission to use, copy, modify, and distribute this
5f46a6179Smrg software and its documentation for any purpose and without
6f46a6179Smrg fee is hereby granted, provided that the above copyright
7f46a6179Smrg notice appear in all copies and that both that copyright
8f46a6179Smrg notice and this permission notice appear in supporting
9bfe6082cSmrg documentation, and that the name of Silicon Graphics not be
10bfe6082cSmrg used in advertising or publicity pertaining to distribution
11f46a6179Smrg of the software without specific prior written permission.
12bfe6082cSmrg Silicon Graphics makes no representation about the suitability
13f46a6179Smrg of this software for any purpose. It is provided "as is"
14f46a6179Smrg without any express or implied warranty.
15bfe6082cSmrg
16bfe6082cSmrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17bfe6082cSmrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18f46a6179Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19bfe6082cSmrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20bfe6082cSmrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21bfe6082cSmrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22f46a6179Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23f46a6179Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE.
24f46a6179Smrg
25f46a6179Smrg ********************************************************/
26f46a6179Smrg
27f46a6179Smrg#include "xkbcomp.h"
28f46a6179Smrg#include "misc.h"
29f46a6179Smrg#include "tokens.h"
30f46a6179Smrg#include "expr.h"
31f46a6179Smrg#include "vmod.h"
32f46a6179Smrg#include "indicators.h"
33f46a6179Smrg#include "action.h"
34f46a6179Smrg#include "compat.h"
35f46a6179Smrg
36f46a6179Smrg/***====================================================================***/
37f46a6179Smrg
38f46a6179Smrg#define	ReportIndicatorBadType(d,l,f,w)	\
39f46a6179Smrg		ReportBadType("indicator map",(f),\
40f46a6179Smrg		      	XkbAtomText((d),(l)->name,XkbMessage),(w))
41f46a6179Smrg#define	ReportIndicatorNotArray(d,l,f)	\
42f46a6179Smrg		ReportNotArray("indicator map",(f),\
43f46a6179Smrg			XkbAtomText((d),(l)->name,XkbMessage))
44f46a6179Smrg
45f46a6179Smrg/***====================================================================***/
46f46a6179Smrg
47f46a6179Smrgvoid
4834345a63SmrgClearIndicatorMapInfo(Display * dpy, LEDInfo * info)
49f46a6179Smrg{
5034345a63Smrg    info->name = XkbInternAtom(dpy, "default", False);
5134345a63Smrg    info->indicator = _LED_NotBound;
5234345a63Smrg    info->flags = info->which_mods = info->real_mods = 0;
5334345a63Smrg    info->vmods = 0;
5434345a63Smrg    info->which_groups = info->groups = 0;
5534345a63Smrg    info->ctrls = 0;
56f46a6179Smrg    return;
57f46a6179Smrg}
58f46a6179Smrg
59f46a6179SmrgLEDInfo *
606930ead5SmrgAddIndicatorMap(LEDInfo *oldLEDs, const LEDInfo *new)
61f46a6179Smrg{
6234345a63Smrg    LEDInfo *old, *last;
63f46a6179Smrg
6434345a63Smrg    last = NULL;
6534345a63Smrg    for (old = oldLEDs; old != NULL; old = (LEDInfo *) old->defs.next)
6634345a63Smrg    {
6734345a63Smrg        if (old->name == new->name)
6834345a63Smrg        {
696930ead5Smrg            unsigned collide;
706930ead5Smrg
7134345a63Smrg            if ((old->real_mods == new->real_mods) &&
7234345a63Smrg                (old->vmods == new->vmods) &&
7334345a63Smrg                (old->groups == new->groups) &&
7434345a63Smrg                (old->ctrls == new->ctrls) &&
7534345a63Smrg                (old->which_mods == new->which_mods) &&
7634345a63Smrg                (old->which_groups == new->which_groups))
7734345a63Smrg            {
7834345a63Smrg                old->defs.defined |= new->defs.defined;
7934345a63Smrg                return oldLEDs;
8034345a63Smrg            }
8134345a63Smrg            if (new->defs.merge == MergeReplace)
8234345a63Smrg            {
8334345a63Smrg                CommonInfo *next = old->defs.next;
8434345a63Smrg                if (((old->defs.fileID == new->defs.fileID)
8534345a63Smrg                     && (warningLevel > 0)) || (warningLevel > 9))
8634345a63Smrg                {
87bfe6082cSmrg                    WARN("Map for indicator %s redefined\n",
8834345a63Smrg                          XkbAtomText(NULL, old->name, XkbMessage));
8934345a63Smrg                    ACTION("Earlier definition ignored\n");
9034345a63Smrg                }
9134345a63Smrg                *old = *new;
9234345a63Smrg                old->defs.next = next;
9334345a63Smrg                return oldLEDs;
9434345a63Smrg            }
9534345a63Smrg            collide = 0;
9634345a63Smrg            if (UseNewField(_LED_Index, &old->defs, &new->defs, &collide))
9734345a63Smrg            {
9834345a63Smrg                old->indicator = new->indicator;
9934345a63Smrg                old->defs.defined |= _LED_Index;
10034345a63Smrg            }
10134345a63Smrg            if (UseNewField(_LED_Mods, &old->defs, &new->defs, &collide))
10234345a63Smrg            {
10334345a63Smrg                old->which_mods = new->which_mods;
10434345a63Smrg                old->real_mods = new->real_mods;
10534345a63Smrg                old->vmods = new->vmods;
10634345a63Smrg                old->defs.defined |= _LED_Mods;
10734345a63Smrg            }
10834345a63Smrg            if (UseNewField(_LED_Groups, &old->defs, &new->defs, &collide))
10934345a63Smrg            {
11034345a63Smrg                old->which_groups = new->which_groups;
11134345a63Smrg                old->groups = new->groups;
11234345a63Smrg                old->defs.defined |= _LED_Groups;
11334345a63Smrg            }
11434345a63Smrg            if (UseNewField(_LED_Ctrls, &old->defs, &new->defs, &collide))
11534345a63Smrg            {
11634345a63Smrg                old->ctrls = new->ctrls;
11734345a63Smrg                old->defs.defined |= _LED_Ctrls;
11834345a63Smrg            }
11934345a63Smrg            if (UseNewField(_LED_Explicit, &old->defs, &new->defs, &collide))
12034345a63Smrg            {
12134345a63Smrg                old->flags &= ~XkbIM_NoExplicit;
12234345a63Smrg                old->flags |= (new->flags & XkbIM_NoExplicit);
12334345a63Smrg                old->defs.defined |= _LED_Explicit;
12434345a63Smrg            }
12534345a63Smrg            if (UseNewField(_LED_Automatic, &old->defs, &new->defs, &collide))
12634345a63Smrg            {
12734345a63Smrg                old->flags &= ~XkbIM_NoAutomatic;
12834345a63Smrg                old->flags |= (new->flags & XkbIM_NoAutomatic);
12934345a63Smrg                old->defs.defined |= _LED_Automatic;
13034345a63Smrg            }
13134345a63Smrg            if (UseNewField(_LED_DrivesKbd, &old->defs, &new->defs, &collide))
13234345a63Smrg            {
13334345a63Smrg                old->flags &= ~XkbIM_LEDDrivesKB;
13434345a63Smrg                old->flags |= (new->flags & XkbIM_LEDDrivesKB);
13534345a63Smrg                old->defs.defined |= _LED_DrivesKbd;
13634345a63Smrg            }
137a57d84feSmrg            if (collide && (warningLevel > 0))
13834345a63Smrg            {
139bfe6082cSmrg                WARN("Map for indicator %s redefined\n",
14034345a63Smrg                      XkbAtomText(NULL, old->name, XkbMessage));
141bfe6082cSmrg                ACTION("Using %s definition for duplicate fields\n",
14234345a63Smrg                        (new->defs.merge == MergeAugment ? "first" : "last"));
14334345a63Smrg            }
14434345a63Smrg            return oldLEDs;
14534345a63Smrg        }
14634345a63Smrg        if (old->defs.next == NULL)
14734345a63Smrg            last = old;
148f46a6179Smrg    }
149f46a6179Smrg    /* new definition */
1506930ead5Smrg    old = malloc(sizeof(LEDInfo));
15134345a63Smrg    if (!old)
15234345a63Smrg    {
15334345a63Smrg        WSGO("Couldn't allocate indicator map\n");
154bfe6082cSmrg        ACTION("Map for indicator %s not compiled\n",
15534345a63Smrg                XkbAtomText(NULL, new->name, XkbMessage));
15634345a63Smrg        return NULL;
157f46a6179Smrg    }
15834345a63Smrg    *old = *new;
15934345a63Smrg    old->defs.next = NULL;
16034345a63Smrg    if (last)
16134345a63Smrg    {
16234345a63Smrg        last->defs.next = &old->defs;
16334345a63Smrg        return oldLEDs;
164f46a6179Smrg    }
165f46a6179Smrg    return old;
166f46a6179Smrg}
167f46a6179Smrg
16834345a63Smrgstatic LookupEntry modComponentNames[] = {
16934345a63Smrg    {"base", XkbIM_UseBase}
17034345a63Smrg    ,
17134345a63Smrg    {"latched", XkbIM_UseLatched}
17234345a63Smrg    ,
17334345a63Smrg    {"locked", XkbIM_UseLocked}
17434345a63Smrg    ,
17534345a63Smrg    {"effective", XkbIM_UseEffective}
17634345a63Smrg    ,
17734345a63Smrg    {"compat", XkbIM_UseCompat}
17834345a63Smrg    ,
17934345a63Smrg    {"any", XkbIM_UseAnyMods}
18034345a63Smrg    ,
18134345a63Smrg    {"none", 0}
18234345a63Smrg    ,
18334345a63Smrg    {NULL, 0}
184f46a6179Smrg};
18534345a63Smrgstatic LookupEntry groupComponentNames[] = {
18634345a63Smrg    {"base", XkbIM_UseBase}
18734345a63Smrg    ,
18834345a63Smrg    {"latched", XkbIM_UseLatched}
18934345a63Smrg    ,
19034345a63Smrg    {"locked", XkbIM_UseLocked}
19134345a63Smrg    ,
19234345a63Smrg    {"effective", XkbIM_UseEffective}
19334345a63Smrg    ,
19434345a63Smrg    {"any", XkbIM_UseAnyGroup}
19534345a63Smrg    ,
19634345a63Smrg    {"none", 0}
19734345a63Smrg    ,
19834345a63Smrg    {NULL, 0}
199f46a6179Smrg};
200f46a6179Smrg
201f46a6179Smrgint
2026930ead5SmrgSetIndicatorMapField(LEDInfo *led, XkbDescPtr xkb, const char *field,
2036930ead5Smrg                     const ExprDef *arrayNdx, const ExprDef *value)
204f46a6179Smrg{
20534345a63Smrg    ExprResult rtrn;
20634345a63Smrg    Bool ok;
207f46a6179Smrg
20834345a63Smrg    ok = True;
20934345a63Smrg    if ((uStrCaseCmp(field, "modifiers") == 0)
21034345a63Smrg        || (uStrCaseCmp(field, "mods") == 0))
21134345a63Smrg    {
21234345a63Smrg        if (arrayNdx != NULL)
21334345a63Smrg            return ReportIndicatorNotArray(xkb->dpy, led, field);
21434345a63Smrg        if (!ExprResolveModMask(value, &rtrn, LookupVModMask, (XPointer) xkb))
21534345a63Smrg            return ReportIndicatorBadType(xkb->dpy, led, field,
21634345a63Smrg                                          "modifier mask");
21734345a63Smrg        led->real_mods = rtrn.uval & 0xff;
21834345a63Smrg        led->vmods = (rtrn.uval >> 8) & 0xff;
21934345a63Smrg        led->defs.defined |= _LED_Mods;
220f46a6179Smrg    }
22134345a63Smrg    else if (uStrCaseCmp(field, "groups") == 0)
22234345a63Smrg    {
22334345a63Smrg        if (arrayNdx != NULL)
22434345a63Smrg            return ReportIndicatorNotArray(xkb->dpy, led, field);
22534345a63Smrg        if (!ExprResolveMask
22634345a63Smrg            (value, &rtrn, SimpleLookup, (XPointer) groupNames))
22734345a63Smrg            return ReportIndicatorBadType(xkb->dpy, led, field, "group mask");
22834345a63Smrg        led->groups = rtrn.uval;
22934345a63Smrg        led->defs.defined |= _LED_Groups;
230f46a6179Smrg    }
23134345a63Smrg    else if ((uStrCaseCmp(field, "controls") == 0) ||
23234345a63Smrg             (uStrCaseCmp(field, "ctrls") == 0))
23334345a63Smrg    {
23434345a63Smrg        if (arrayNdx != NULL)
23534345a63Smrg            return ReportIndicatorNotArray(xkb->dpy, led, field);
23634345a63Smrg        if (!ExprResolveMask
23734345a63Smrg            (value, &rtrn, SimpleLookup, (XPointer) ctrlNames))
23834345a63Smrg            return ReportIndicatorBadType(xkb->dpy, led, field,
23934345a63Smrg                                          "controls mask");
24034345a63Smrg        led->ctrls = rtrn.uval;
24134345a63Smrg        led->defs.defined |= _LED_Ctrls;
242f46a6179Smrg    }
24334345a63Smrg    else if (uStrCaseCmp(field, "allowexplicit") == 0)
24434345a63Smrg    {
24534345a63Smrg        if (arrayNdx != NULL)
24634345a63Smrg            return ReportIndicatorNotArray(xkb->dpy, led, field);
24734345a63Smrg        if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
24834345a63Smrg            return ReportIndicatorBadType(xkb->dpy, led, field, "boolean");
24934345a63Smrg        if (rtrn.uval)
25034345a63Smrg            led->flags &= ~XkbIM_NoExplicit;
25134345a63Smrg        else
25234345a63Smrg            led->flags |= XkbIM_NoExplicit;
25334345a63Smrg        led->defs.defined |= _LED_Explicit;
254f46a6179Smrg    }
25534345a63Smrg    else if ((uStrCaseCmp(field, "whichmodstate") == 0) ||
25634345a63Smrg             (uStrCaseCmp(field, "whichmodifierstate") == 0))
25734345a63Smrg    {
25834345a63Smrg        if (arrayNdx != NULL)
25934345a63Smrg            return ReportIndicatorNotArray(xkb->dpy, led, field);
26034345a63Smrg        if (!ExprResolveMask(value, &rtrn, SimpleLookup,
26134345a63Smrg                             (XPointer) modComponentNames))
26234345a63Smrg        {
26334345a63Smrg            return ReportIndicatorBadType(xkb->dpy, led, field,
26434345a63Smrg                                          "mask of modifier state components");
26534345a63Smrg        }
26634345a63Smrg        led->which_mods = rtrn.uval;
267f46a6179Smrg    }
26834345a63Smrg    else if (uStrCaseCmp(field, "whichgroupstate") == 0)
26934345a63Smrg    {
27034345a63Smrg        if (arrayNdx != NULL)
27134345a63Smrg            return ReportIndicatorNotArray(xkb->dpy, led, field);
27234345a63Smrg        if (!ExprResolveMask(value, &rtrn, SimpleLookup,
27334345a63Smrg                             (XPointer) groupComponentNames))
27434345a63Smrg        {
27534345a63Smrg            return ReportIndicatorBadType(xkb->dpy, led, field,
27634345a63Smrg                                          "mask of group state components");
27734345a63Smrg        }
27834345a63Smrg        led->which_groups = rtrn.uval;
279f46a6179Smrg    }
28034345a63Smrg    else if ((uStrCaseCmp(field, "driveskbd") == 0) ||
28134345a63Smrg             (uStrCaseCmp(field, "driveskeyboard") == 0) ||
28234345a63Smrg             (uStrCaseCmp(field, "leddriveskbd") == 0) ||
28334345a63Smrg             (uStrCaseCmp(field, "leddriveskeyboard") == 0) ||
28434345a63Smrg             (uStrCaseCmp(field, "indicatordriveskbd") == 0) ||
28534345a63Smrg             (uStrCaseCmp(field, "indicatordriveskeyboard") == 0))
28634345a63Smrg    {
28734345a63Smrg        if (arrayNdx != NULL)
28834345a63Smrg            return ReportIndicatorNotArray(xkb->dpy, led, field);
28934345a63Smrg        if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
29034345a63Smrg            return ReportIndicatorBadType(xkb->dpy, led, field, "boolean");
29134345a63Smrg        if (rtrn.uval)
29234345a63Smrg            led->flags |= XkbIM_LEDDrivesKB;
29334345a63Smrg        else
29434345a63Smrg            led->flags &= ~XkbIM_LEDDrivesKB;
29534345a63Smrg        led->defs.defined |= _LED_DrivesKbd;
296f46a6179Smrg    }
29734345a63Smrg    else if (uStrCaseCmp(field, "index") == 0)
29834345a63Smrg    {
29934345a63Smrg        if (arrayNdx != NULL)
30034345a63Smrg            return ReportIndicatorNotArray(xkb->dpy, led, field);
30134345a63Smrg        if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
30234345a63Smrg            return ReportIndicatorBadType(xkb->dpy, led, field,
30334345a63Smrg                                          "indicator index");
30434345a63Smrg        if ((rtrn.uval < 1) || (rtrn.uval > 32))
30534345a63Smrg        {
306bfe6082cSmrg            ERROR("Illegal indicator index %d (range 1..%d)\n",
30734345a63Smrg                   rtrn.uval, XkbNumIndicators);
308bfe6082cSmrg            ACTION("Index definition for %s indicator ignored\n",
30934345a63Smrg                    XkbAtomText(NULL, led->name, XkbMessage));
31034345a63Smrg            return False;
31134345a63Smrg        }
31234345a63Smrg        led->indicator = rtrn.uval;
31334345a63Smrg        led->defs.defined |= _LED_Index;
31434345a63Smrg    }
31534345a63Smrg    else
31634345a63Smrg    {
317bfe6082cSmrg        ERROR("Unknown field %s in map for %s indicator\n", field,
31834345a63Smrg               XkbAtomText(NULL, led->name, XkbMessage));
31934345a63Smrg        ACTION("Definition ignored\n");
32034345a63Smrg        ok = False;
321f46a6179Smrg    }
322f46a6179Smrg    return ok;
323f46a6179Smrg}
324f46a6179Smrg
325f46a6179SmrgLEDInfo *
3266930ead5SmrgHandleIndicatorMapDef(IndicatorMapDef *def, XkbDescPtr xkb,
3276930ead5Smrg                      const LEDInfo *dflt, LEDInfo *oldLEDs, unsigned merge)
328f46a6179Smrg{
3296930ead5Smrg    LEDInfo led;
33034345a63Smrg    Bool ok;
331f46a6179Smrg
33234345a63Smrg    if (def->merge != MergeDefault)
33334345a63Smrg        merge = def->merge;
334f46a6179Smrg
33534345a63Smrg    led = *dflt;
33634345a63Smrg    led.defs.merge = merge;
33734345a63Smrg    led.name = def->name;
33834345a63Smrg
33934345a63Smrg    ok = True;
3406930ead5Smrg    for (VarDef *var = def->body; var != NULL;
3416930ead5Smrg         var = (VarDef *) var->common.next)
34234345a63Smrg    {
34334345a63Smrg        ExprResult elem, field;
34434345a63Smrg        ExprDef *arrayNdx;
34534345a63Smrg        if (!ExprResolveLhs(var->name, &elem, &field, &arrayNdx))
34634345a63Smrg        {
34734345a63Smrg            ok = False;
34834345a63Smrg            continue;
34934345a63Smrg        }
35034345a63Smrg        if (elem.str != NULL)
35134345a63Smrg        {
352bfe6082cSmrg            ERROR
35334345a63Smrg                ("Cannot set defaults for \"%s\" element in indicator map\n",
35434345a63Smrg                 elem.str);
355bfe6082cSmrg            ACTION("Assignment to %s.%s ignored\n", elem.str, field.str);
35634345a63Smrg            ok = False;
35734345a63Smrg        }
35834345a63Smrg        else
35934345a63Smrg        {
36034345a63Smrg            ok = SetIndicatorMapField(&led, xkb, field.str, arrayNdx,
36134345a63Smrg                                      var->value) && ok;
36234345a63Smrg        }
363f46a6179Smrg    }
36434345a63Smrg    if (ok)
36534345a63Smrg    {
3666930ead5Smrg        LEDInfo *rtrn = AddIndicatorMap(oldLEDs, &led);
36734345a63Smrg        return rtrn;
368f46a6179Smrg    }
369f46a6179Smrg    return NULL;
370f46a6179Smrg}
371f46a6179Smrg
37234345a63SmrgBool
37334345a63SmrgCopyIndicatorMapDefs(XkbFileInfo * result, LEDInfo * leds,
37434345a63Smrg                     LEDInfo ** unboundRtrn)
375f46a6179Smrg{
37634345a63Smrg    LEDInfo *led, *next;
37734345a63Smrg    LEDInfo *unbound, *last;
37834345a63Smrg    XkbDescPtr xkb;
379f46a6179Smrg
38034345a63Smrg    xkb = result->xkb;
38134345a63Smrg    if (XkbAllocNames(xkb, XkbIndicatorNamesMask, 0, 0) != Success)
38234345a63Smrg    {
38334345a63Smrg        WSGO("Couldn't allocate names\n");
38434345a63Smrg        ACTION("Indicator names may be incorrect\n");
385f46a6179Smrg    }
38634345a63Smrg    if (XkbAllocIndicatorMaps(xkb) != Success)
38734345a63Smrg    {
38834345a63Smrg        WSGO("Can't allocate indicator maps\n");
38934345a63Smrg        ACTION("Indicator map definitions may be lost\n");
39034345a63Smrg        return False;
391f46a6179Smrg    }
39234345a63Smrg    last = unbound = (unboundRtrn ? *unboundRtrn : NULL);
39334345a63Smrg    while ((last != NULL) && (last->defs.next != NULL))
39434345a63Smrg    {
39534345a63Smrg        last = (LEDInfo *) last->defs.next;
396f46a6179Smrg    }
39734345a63Smrg    for (led = leds; led != NULL; led = next)
39834345a63Smrg    {
39934345a63Smrg        next = (LEDInfo *) led->defs.next;
40034345a63Smrg        if ((led->groups != 0) && (led->which_groups == 0))
40134345a63Smrg            led->which_groups = XkbIM_UseEffective;
40234345a63Smrg        if ((led->which_mods == 0) && ((led->real_mods) || (led->vmods)))
40334345a63Smrg            led->which_mods = XkbIM_UseEffective;
40434345a63Smrg        if ((led->indicator == _LED_NotBound) || (!xkb->indicators))
40534345a63Smrg        {
40634345a63Smrg            if (unboundRtrn != NULL)
40734345a63Smrg            {
40834345a63Smrg                led->defs.next = NULL;
40934345a63Smrg                if (last != NULL)
41034345a63Smrg                    last->defs.next = (CommonInfo *) led;
41134345a63Smrg                else
41234345a63Smrg                    unbound = led;
41334345a63Smrg                last = led;
41434345a63Smrg            }
41534345a63Smrg            else
4166930ead5Smrg                free(led);
41734345a63Smrg        }
41834345a63Smrg        else
41934345a63Smrg        {
4206930ead5Smrg            XkbIndicatorMapPtr im;
42134345a63Smrg            im = &xkb->indicators->maps[led->indicator - 1];
42234345a63Smrg            im->flags = led->flags;
42334345a63Smrg            im->which_groups = led->which_groups;
42434345a63Smrg            im->groups = led->groups;
42534345a63Smrg            im->which_mods = led->which_mods;
42634345a63Smrg            im->mods.mask = led->real_mods;
42734345a63Smrg            im->mods.real_mods = led->real_mods;
42834345a63Smrg            im->mods.vmods = led->vmods;
42934345a63Smrg            im->ctrls = led->ctrls;
43034345a63Smrg            if (xkb->names != NULL)
43134345a63Smrg                xkb->names->indicators[led->indicator - 1] = led->name;
4326930ead5Smrg            free(led);
43334345a63Smrg        }
434f46a6179Smrg    }
43534345a63Smrg    if (unboundRtrn != NULL)
43634345a63Smrg    {
43734345a63Smrg        *unboundRtrn = unbound;
438f46a6179Smrg    }
439f46a6179Smrg    return True;
440f46a6179Smrg}
441f46a6179Smrg
442f46a6179SmrgBool
44334345a63SmrgBindIndicators(XkbFileInfo * result,
44434345a63Smrg               Bool force, LEDInfo * unbound, LEDInfo ** unboundRtrn)
445f46a6179Smrg{
44634345a63Smrg    XkbDescPtr xkb;
4476930ead5Smrg    LEDInfo *led, *next, *last;
448f46a6179Smrg
44934345a63Smrg    xkb = result->xkb;
45034345a63Smrg    if (xkb->names != NULL)
45134345a63Smrg    {
45234345a63Smrg        for (led = unbound; led != NULL; led = (LEDInfo *) led->defs.next)
45334345a63Smrg        {
45434345a63Smrg            if (led->indicator == _LED_NotBound)
45534345a63Smrg            {
4566930ead5Smrg                for (int i = 0; i < XkbNumIndicators; i++)
45734345a63Smrg                {
45834345a63Smrg                    if (xkb->names->indicators[i] == led->name)
45934345a63Smrg                    {
46034345a63Smrg                        led->indicator = i + 1;
46134345a63Smrg                        break;
46234345a63Smrg                    }
46334345a63Smrg                }
46434345a63Smrg            }
46534345a63Smrg        }
46634345a63Smrg        if (force)
46734345a63Smrg        {
46834345a63Smrg            for (led = unbound; led != NULL; led = (LEDInfo *) led->defs.next)
46934345a63Smrg            {
47034345a63Smrg                if (led->indicator == _LED_NotBound)
47134345a63Smrg                {
4726930ead5Smrg                    for (int i = 0; i < XkbNumIndicators; i++)
47334345a63Smrg                    {
47434345a63Smrg                        if (xkb->names->indicators[i] == None)
47534345a63Smrg                        {
47634345a63Smrg                            xkb->names->indicators[i] = led->name;
47734345a63Smrg                            led->indicator = i + 1;
47834345a63Smrg                            xkb->indicators->phys_indicators &= ~(1 << i);
47934345a63Smrg                            break;
48034345a63Smrg                        }
48134345a63Smrg                    }
48234345a63Smrg                    if (led->indicator == _LED_NotBound)
48334345a63Smrg                    {
48434345a63Smrg                        ERROR("No unnamed indicators found\n");
485bfe6082cSmrg                        ACTION
48634345a63Smrg                            ("Virtual indicator map \"%s\" not bound\n",
48734345a63Smrg                             XkbAtomGetString(xkb->dpy, led->name));
48834345a63Smrg                        continue;
48934345a63Smrg                    }
49034345a63Smrg                }
49134345a63Smrg            }
49234345a63Smrg        }
493f46a6179Smrg    }
49434345a63Smrg    for (last = NULL, led = unbound; led != NULL; led = next)
49534345a63Smrg    {
49634345a63Smrg        next = (LEDInfo *) led->defs.next;
49734345a63Smrg        if (led->indicator == _LED_NotBound)
49834345a63Smrg        {
49934345a63Smrg            if (force)
50034345a63Smrg            {
50134345a63Smrg                unbound = next;
5026930ead5Smrg                free(led);
50334345a63Smrg            }
50434345a63Smrg            else
50534345a63Smrg            {
50634345a63Smrg                if (last)
50734345a63Smrg                    last->defs.next = &led->defs;
50834345a63Smrg                else
50934345a63Smrg                    unbound = led;
51034345a63Smrg                last = led;
51134345a63Smrg            }
51234345a63Smrg        }
51334345a63Smrg        else
51434345a63Smrg        {
51534345a63Smrg            if ((xkb->names != NULL) &&
51634345a63Smrg                (xkb->names->indicators[led->indicator - 1] != led->name))
51734345a63Smrg            {
51834345a63Smrg                Atom old = xkb->names->indicators[led->indicator - 1];
519bfe6082cSmrg                ERROR("Multiple names bound to indicator %d\n",
52034345a63Smrg                       (unsigned int) led->indicator);
521bfe6082cSmrg                ACTION("Using %s, ignoring %s\n",
52234345a63Smrg                        XkbAtomGetString(xkb->dpy, old),
52334345a63Smrg                        XkbAtomGetString(xkb->dpy, led->name));
52434345a63Smrg                led->indicator = _LED_NotBound;
52534345a63Smrg                if (force)
52634345a63Smrg                {
5276930ead5Smrg                    free(led);
52834345a63Smrg                    unbound = next;
52934345a63Smrg                }
53034345a63Smrg                else
53134345a63Smrg                {
53234345a63Smrg                    if (last)
53334345a63Smrg                        last->defs.next = &led->defs;
53434345a63Smrg                    else
53534345a63Smrg                        unbound = led;
53634345a63Smrg                    last = led;
53734345a63Smrg                }
53834345a63Smrg            }
53934345a63Smrg            else
54034345a63Smrg            {
54134345a63Smrg                XkbIndicatorMapPtr map;
54234345a63Smrg                map = &xkb->indicators->maps[led->indicator - 1];
54334345a63Smrg                map->flags = led->flags;
54434345a63Smrg                map->which_groups = led->which_groups;
54534345a63Smrg                map->groups = led->groups;
54634345a63Smrg                map->which_mods = led->which_mods;
54734345a63Smrg                map->mods.mask = led->real_mods;
54834345a63Smrg                map->mods.real_mods = led->real_mods;
54934345a63Smrg                map->mods.vmods = led->vmods;
55034345a63Smrg                map->ctrls = led->ctrls;
55134345a63Smrg                if (last)
55234345a63Smrg                    last->defs.next = &next->defs;
55334345a63Smrg                else
55434345a63Smrg                    unbound = next;
55534345a63Smrg                led->defs.next = NULL;
5566930ead5Smrg                free(led);
55734345a63Smrg            }
55834345a63Smrg        }
559f46a6179Smrg    }
56034345a63Smrg    if (unboundRtrn)
56134345a63Smrg    {
56234345a63Smrg        *unboundRtrn = unbound;
563f46a6179Smrg    }
56434345a63Smrg    else if (unbound)
56534345a63Smrg    {
56634345a63Smrg        for (led = unbound; led != NULL; led = next)
56734345a63Smrg        {
56834345a63Smrg            next = (LEDInfo *) led->defs.next;
5696930ead5Smrg            free(led);
57034345a63Smrg        }
571f46a6179Smrg    }
572f46a6179Smrg    return True;
573f46a6179Smrg}
574