indicators.c revision a57d84fe
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 *
6034345a63SmrgAddIndicatorMap(LEDInfo * oldLEDs, LEDInfo * new)
61f46a6179Smrg{
6234345a63Smrg    LEDInfo *old, *last;
6334345a63Smrg    unsigned collide;
64f46a6179Smrg
6534345a63Smrg    last = NULL;
6634345a63Smrg    for (old = oldLEDs; old != NULL; old = (LEDInfo *) old->defs.next)
6734345a63Smrg    {
6834345a63Smrg        if (old->name == new->name)
6934345a63Smrg        {
7034345a63Smrg            if ((old->real_mods == new->real_mods) &&
7134345a63Smrg                (old->vmods == new->vmods) &&
7234345a63Smrg                (old->groups == new->groups) &&
7334345a63Smrg                (old->ctrls == new->ctrls) &&
7434345a63Smrg                (old->which_mods == new->which_mods) &&
7534345a63Smrg                (old->which_groups == new->which_groups))
7634345a63Smrg            {
7734345a63Smrg                old->defs.defined |= new->defs.defined;
7834345a63Smrg                return oldLEDs;
7934345a63Smrg            }
8034345a63Smrg            if (new->defs.merge == MergeReplace)
8134345a63Smrg            {
8234345a63Smrg                CommonInfo *next = old->defs.next;
8334345a63Smrg                if (((old->defs.fileID == new->defs.fileID)
8434345a63Smrg                     && (warningLevel > 0)) || (warningLevel > 9))
8534345a63Smrg                {
86bfe6082cSmrg                    WARN("Map for indicator %s redefined\n",
8734345a63Smrg                          XkbAtomText(NULL, old->name, XkbMessage));
8834345a63Smrg                    ACTION("Earlier definition ignored\n");
8934345a63Smrg                }
9034345a63Smrg                *old = *new;
9134345a63Smrg                old->defs.next = next;
9234345a63Smrg                return oldLEDs;
9334345a63Smrg            }
9434345a63Smrg            collide = 0;
9534345a63Smrg            if (UseNewField(_LED_Index, &old->defs, &new->defs, &collide))
9634345a63Smrg            {
9734345a63Smrg                old->indicator = new->indicator;
9834345a63Smrg                old->defs.defined |= _LED_Index;
9934345a63Smrg            }
10034345a63Smrg            if (UseNewField(_LED_Mods, &old->defs, &new->defs, &collide))
10134345a63Smrg            {
10234345a63Smrg                old->which_mods = new->which_mods;
10334345a63Smrg                old->real_mods = new->real_mods;
10434345a63Smrg                old->vmods = new->vmods;
10534345a63Smrg                old->defs.defined |= _LED_Mods;
10634345a63Smrg            }
10734345a63Smrg            if (UseNewField(_LED_Groups, &old->defs, &new->defs, &collide))
10834345a63Smrg            {
10934345a63Smrg                old->which_groups = new->which_groups;
11034345a63Smrg                old->groups = new->groups;
11134345a63Smrg                old->defs.defined |= _LED_Groups;
11234345a63Smrg            }
11334345a63Smrg            if (UseNewField(_LED_Ctrls, &old->defs, &new->defs, &collide))
11434345a63Smrg            {
11534345a63Smrg                old->ctrls = new->ctrls;
11634345a63Smrg                old->defs.defined |= _LED_Ctrls;
11734345a63Smrg            }
11834345a63Smrg            if (UseNewField(_LED_Explicit, &old->defs, &new->defs, &collide))
11934345a63Smrg            {
12034345a63Smrg                old->flags &= ~XkbIM_NoExplicit;
12134345a63Smrg                old->flags |= (new->flags & XkbIM_NoExplicit);
12234345a63Smrg                old->defs.defined |= _LED_Explicit;
12334345a63Smrg            }
12434345a63Smrg            if (UseNewField(_LED_Automatic, &old->defs, &new->defs, &collide))
12534345a63Smrg            {
12634345a63Smrg                old->flags &= ~XkbIM_NoAutomatic;
12734345a63Smrg                old->flags |= (new->flags & XkbIM_NoAutomatic);
12834345a63Smrg                old->defs.defined |= _LED_Automatic;
12934345a63Smrg            }
13034345a63Smrg            if (UseNewField(_LED_DrivesKbd, &old->defs, &new->defs, &collide))
13134345a63Smrg            {
13234345a63Smrg                old->flags &= ~XkbIM_LEDDrivesKB;
13334345a63Smrg                old->flags |= (new->flags & XkbIM_LEDDrivesKB);
13434345a63Smrg                old->defs.defined |= _LED_DrivesKbd;
13534345a63Smrg            }
136a57d84feSmrg            if (collide && (warningLevel > 0))
13734345a63Smrg            {
138bfe6082cSmrg                WARN("Map for indicator %s redefined\n",
13934345a63Smrg                      XkbAtomText(NULL, old->name, XkbMessage));
140bfe6082cSmrg                ACTION("Using %s definition for duplicate fields\n",
14134345a63Smrg                        (new->defs.merge == MergeAugment ? "first" : "last"));
14234345a63Smrg            }
14334345a63Smrg            return oldLEDs;
14434345a63Smrg        }
14534345a63Smrg        if (old->defs.next == NULL)
14634345a63Smrg            last = old;
147f46a6179Smrg    }
148f46a6179Smrg    /* new definition */
14934345a63Smrg    old = uTypedAlloc(LEDInfo);
15034345a63Smrg    if (!old)
15134345a63Smrg    {
15234345a63Smrg        WSGO("Couldn't allocate indicator map\n");
153bfe6082cSmrg        ACTION("Map for indicator %s not compiled\n",
15434345a63Smrg                XkbAtomText(NULL, new->name, XkbMessage));
15534345a63Smrg        return NULL;
156f46a6179Smrg    }
15734345a63Smrg    *old = *new;
15834345a63Smrg    old->defs.next = NULL;
15934345a63Smrg    if (last)
16034345a63Smrg    {
16134345a63Smrg        last->defs.next = &old->defs;
16234345a63Smrg        return oldLEDs;
163f46a6179Smrg    }
164f46a6179Smrg    return old;
165f46a6179Smrg}
166f46a6179Smrg
16734345a63Smrgstatic LookupEntry modComponentNames[] = {
16834345a63Smrg    {"base", XkbIM_UseBase}
16934345a63Smrg    ,
17034345a63Smrg    {"latched", XkbIM_UseLatched}
17134345a63Smrg    ,
17234345a63Smrg    {"locked", XkbIM_UseLocked}
17334345a63Smrg    ,
17434345a63Smrg    {"effective", XkbIM_UseEffective}
17534345a63Smrg    ,
17634345a63Smrg    {"compat", XkbIM_UseCompat}
17734345a63Smrg    ,
17834345a63Smrg    {"any", XkbIM_UseAnyMods}
17934345a63Smrg    ,
18034345a63Smrg    {"none", 0}
18134345a63Smrg    ,
18234345a63Smrg    {NULL, 0}
183f46a6179Smrg};
18434345a63Smrgstatic LookupEntry groupComponentNames[] = {
18534345a63Smrg    {"base", XkbIM_UseBase}
18634345a63Smrg    ,
18734345a63Smrg    {"latched", XkbIM_UseLatched}
18834345a63Smrg    ,
18934345a63Smrg    {"locked", XkbIM_UseLocked}
19034345a63Smrg    ,
19134345a63Smrg    {"effective", XkbIM_UseEffective}
19234345a63Smrg    ,
19334345a63Smrg    {"any", XkbIM_UseAnyGroup}
19434345a63Smrg    ,
19534345a63Smrg    {"none", 0}
19634345a63Smrg    ,
19734345a63Smrg    {NULL, 0}
198f46a6179Smrg};
199f46a6179Smrg
200f46a6179Smrgint
20134345a63SmrgSetIndicatorMapField(LEDInfo * led,
20234345a63Smrg                     XkbDescPtr xkb,
203c82dfdfbSmrg                     const char *field, ExprDef *arrayNdx, 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 *
32634345a63SmrgHandleIndicatorMapDef(IndicatorMapDef * def,
32734345a63Smrg                      XkbDescPtr xkb,
32834345a63Smrg                      LEDInfo * dflt, LEDInfo * oldLEDs, unsigned merge)
329f46a6179Smrg{
33034345a63Smrg    LEDInfo led, *rtrn;
33134345a63Smrg    VarDef *var;
33234345a63Smrg    Bool ok;
333f46a6179Smrg
33434345a63Smrg    if (def->merge != MergeDefault)
33534345a63Smrg        merge = def->merge;
336f46a6179Smrg
33734345a63Smrg    led = *dflt;
33834345a63Smrg    led.defs.merge = merge;
33934345a63Smrg    led.name = def->name;
34034345a63Smrg
34134345a63Smrg    ok = True;
34234345a63Smrg    for (var = def->body; var != NULL; var = (VarDef *) var->common.next)
34334345a63Smrg    {
34434345a63Smrg        ExprResult elem, field;
34534345a63Smrg        ExprDef *arrayNdx;
34634345a63Smrg        if (!ExprResolveLhs(var->name, &elem, &field, &arrayNdx))
34734345a63Smrg        {
34834345a63Smrg            ok = False;
34934345a63Smrg            continue;
35034345a63Smrg        }
35134345a63Smrg        if (elem.str != NULL)
35234345a63Smrg        {
353bfe6082cSmrg            ERROR
35434345a63Smrg                ("Cannot set defaults for \"%s\" element in indicator map\n",
35534345a63Smrg                 elem.str);
356bfe6082cSmrg            ACTION("Assignment to %s.%s ignored\n", elem.str, field.str);
35734345a63Smrg            ok = False;
35834345a63Smrg        }
35934345a63Smrg        else
36034345a63Smrg        {
36134345a63Smrg            ok = SetIndicatorMapField(&led, xkb, field.str, arrayNdx,
36234345a63Smrg                                      var->value) && ok;
36334345a63Smrg        }
364f46a6179Smrg    }
36534345a63Smrg    if (ok)
36634345a63Smrg    {
36734345a63Smrg        rtrn = AddIndicatorMap(oldLEDs, &led);
36834345a63Smrg        return rtrn;
369f46a6179Smrg    }
370f46a6179Smrg    return NULL;
371f46a6179Smrg}
372f46a6179Smrg
37334345a63SmrgBool
37434345a63SmrgCopyIndicatorMapDefs(XkbFileInfo * result, LEDInfo * leds,
37534345a63Smrg                     LEDInfo ** unboundRtrn)
376f46a6179Smrg{
37734345a63Smrg    LEDInfo *led, *next;
37834345a63Smrg    LEDInfo *unbound, *last;
37934345a63Smrg    XkbDescPtr xkb;
380f46a6179Smrg
38134345a63Smrg    xkb = result->xkb;
38234345a63Smrg    if (XkbAllocNames(xkb, XkbIndicatorNamesMask, 0, 0) != Success)
38334345a63Smrg    {
38434345a63Smrg        WSGO("Couldn't allocate names\n");
38534345a63Smrg        ACTION("Indicator names may be incorrect\n");
386f46a6179Smrg    }
38734345a63Smrg    if (XkbAllocIndicatorMaps(xkb) != Success)
38834345a63Smrg    {
38934345a63Smrg        WSGO("Can't allocate indicator maps\n");
39034345a63Smrg        ACTION("Indicator map definitions may be lost\n");
39134345a63Smrg        return False;
392f46a6179Smrg    }
39334345a63Smrg    last = unbound = (unboundRtrn ? *unboundRtrn : NULL);
39434345a63Smrg    while ((last != NULL) && (last->defs.next != NULL))
39534345a63Smrg    {
39634345a63Smrg        last = (LEDInfo *) last->defs.next;
397f46a6179Smrg    }
39834345a63Smrg    for (led = leds; led != NULL; led = next)
39934345a63Smrg    {
40034345a63Smrg        next = (LEDInfo *) led->defs.next;
40134345a63Smrg        if ((led->groups != 0) && (led->which_groups == 0))
40234345a63Smrg            led->which_groups = XkbIM_UseEffective;
40334345a63Smrg        if ((led->which_mods == 0) && ((led->real_mods) || (led->vmods)))
40434345a63Smrg            led->which_mods = XkbIM_UseEffective;
40534345a63Smrg        if ((led->indicator == _LED_NotBound) || (!xkb->indicators))
40634345a63Smrg        {
40734345a63Smrg            if (unboundRtrn != NULL)
40834345a63Smrg            {
40934345a63Smrg                led->defs.next = NULL;
41034345a63Smrg                if (last != NULL)
41134345a63Smrg                    last->defs.next = (CommonInfo *) led;
41234345a63Smrg                else
41334345a63Smrg                    unbound = led;
41434345a63Smrg                last = led;
41534345a63Smrg            }
41634345a63Smrg            else
41734345a63Smrg                uFree(led);
41834345a63Smrg        }
41934345a63Smrg        else
42034345a63Smrg        {
42134345a63Smrg            register XkbIndicatorMapPtr im;
42234345a63Smrg            im = &xkb->indicators->maps[led->indicator - 1];
42334345a63Smrg            im->flags = led->flags;
42434345a63Smrg            im->which_groups = led->which_groups;
42534345a63Smrg            im->groups = led->groups;
42634345a63Smrg            im->which_mods = led->which_mods;
42734345a63Smrg            im->mods.mask = led->real_mods;
42834345a63Smrg            im->mods.real_mods = led->real_mods;
42934345a63Smrg            im->mods.vmods = led->vmods;
43034345a63Smrg            im->ctrls = led->ctrls;
43134345a63Smrg            if (xkb->names != NULL)
43234345a63Smrg                xkb->names->indicators[led->indicator - 1] = led->name;
43334345a63Smrg            uFree(led);
43434345a63Smrg        }
435f46a6179Smrg    }
43634345a63Smrg    if (unboundRtrn != NULL)
43734345a63Smrg    {
43834345a63Smrg        *unboundRtrn = unbound;
439f46a6179Smrg    }
440f46a6179Smrg    return True;
441f46a6179Smrg}
442f46a6179Smrg
443f46a6179SmrgBool
44434345a63SmrgBindIndicators(XkbFileInfo * result,
44534345a63Smrg               Bool force, LEDInfo * unbound, LEDInfo ** unboundRtrn)
446f46a6179Smrg{
44734345a63Smrg    XkbDescPtr xkb;
44834345a63Smrg    register int i;
44934345a63Smrg    register LEDInfo *led, *next, *last;
450f46a6179Smrg
45134345a63Smrg    xkb = result->xkb;
45234345a63Smrg    if (xkb->names != NULL)
45334345a63Smrg    {
45434345a63Smrg        for (led = unbound; led != NULL; led = (LEDInfo *) led->defs.next)
45534345a63Smrg        {
45634345a63Smrg            if (led->indicator == _LED_NotBound)
45734345a63Smrg            {
45834345a63Smrg                for (i = 0; i < XkbNumIndicators; i++)
45934345a63Smrg                {
46034345a63Smrg                    if (xkb->names->indicators[i] == led->name)
46134345a63Smrg                    {
46234345a63Smrg                        led->indicator = i + 1;
46334345a63Smrg                        break;
46434345a63Smrg                    }
46534345a63Smrg                }
46634345a63Smrg            }
46734345a63Smrg        }
46834345a63Smrg        if (force)
46934345a63Smrg        {
47034345a63Smrg            for (led = unbound; led != NULL; led = (LEDInfo *) led->defs.next)
47134345a63Smrg            {
47234345a63Smrg                if (led->indicator == _LED_NotBound)
47334345a63Smrg                {
47434345a63Smrg                    for (i = 0; i < XkbNumIndicators; i++)
47534345a63Smrg                    {
47634345a63Smrg                        if (xkb->names->indicators[i] == None)
47734345a63Smrg                        {
47834345a63Smrg                            xkb->names->indicators[i] = led->name;
47934345a63Smrg                            led->indicator = i + 1;
48034345a63Smrg                            xkb->indicators->phys_indicators &= ~(1 << i);
48134345a63Smrg                            break;
48234345a63Smrg                        }
48334345a63Smrg                    }
48434345a63Smrg                    if (led->indicator == _LED_NotBound)
48534345a63Smrg                    {
48634345a63Smrg                        ERROR("No unnamed indicators found\n");
487bfe6082cSmrg                        ACTION
48834345a63Smrg                            ("Virtual indicator map \"%s\" not bound\n",
48934345a63Smrg                             XkbAtomGetString(xkb->dpy, led->name));
49034345a63Smrg                        continue;
49134345a63Smrg                    }
49234345a63Smrg                }
49334345a63Smrg            }
49434345a63Smrg        }
495f46a6179Smrg    }
49634345a63Smrg    for (last = NULL, led = unbound; led != NULL; led = next)
49734345a63Smrg    {
49834345a63Smrg        next = (LEDInfo *) led->defs.next;
49934345a63Smrg        if (led->indicator == _LED_NotBound)
50034345a63Smrg        {
50134345a63Smrg            if (force)
50234345a63Smrg            {
50334345a63Smrg                unbound = next;
50434345a63Smrg                uFree(led);
50534345a63Smrg            }
50634345a63Smrg            else
50734345a63Smrg            {
50834345a63Smrg                if (last)
50934345a63Smrg                    last->defs.next = &led->defs;
51034345a63Smrg                else
51134345a63Smrg                    unbound = led;
51234345a63Smrg                last = led;
51334345a63Smrg            }
51434345a63Smrg        }
51534345a63Smrg        else
51634345a63Smrg        {
51734345a63Smrg            if ((xkb->names != NULL) &&
51834345a63Smrg                (xkb->names->indicators[led->indicator - 1] != led->name))
51934345a63Smrg            {
52034345a63Smrg                Atom old = xkb->names->indicators[led->indicator - 1];
521bfe6082cSmrg                ERROR("Multiple names bound to indicator %d\n",
52234345a63Smrg                       (unsigned int) led->indicator);
523bfe6082cSmrg                ACTION("Using %s, ignoring %s\n",
52434345a63Smrg                        XkbAtomGetString(xkb->dpy, old),
52534345a63Smrg                        XkbAtomGetString(xkb->dpy, led->name));
52634345a63Smrg                led->indicator = _LED_NotBound;
52734345a63Smrg                if (force)
52834345a63Smrg                {
52934345a63Smrg                    uFree(led);
53034345a63Smrg                    unbound = next;
53134345a63Smrg                }
53234345a63Smrg                else
53334345a63Smrg                {
53434345a63Smrg                    if (last)
53534345a63Smrg                        last->defs.next = &led->defs;
53634345a63Smrg                    else
53734345a63Smrg                        unbound = led;
53834345a63Smrg                    last = led;
53934345a63Smrg                }
54034345a63Smrg            }
54134345a63Smrg            else
54234345a63Smrg            {
54334345a63Smrg                XkbIndicatorMapPtr map;
54434345a63Smrg                map = &xkb->indicators->maps[led->indicator - 1];
54534345a63Smrg                map->flags = led->flags;
54634345a63Smrg                map->which_groups = led->which_groups;
54734345a63Smrg                map->groups = led->groups;
54834345a63Smrg                map->which_mods = led->which_mods;
54934345a63Smrg                map->mods.mask = led->real_mods;
55034345a63Smrg                map->mods.real_mods = led->real_mods;
55134345a63Smrg                map->mods.vmods = led->vmods;
55234345a63Smrg                map->ctrls = led->ctrls;
55334345a63Smrg                if (last)
55434345a63Smrg                    last->defs.next = &next->defs;
55534345a63Smrg                else
55634345a63Smrg                    unbound = next;
55734345a63Smrg                led->defs.next = NULL;
55834345a63Smrg                uFree(led);
55934345a63Smrg            }
56034345a63Smrg        }
561f46a6179Smrg    }
56234345a63Smrg    if (unboundRtrn)
56334345a63Smrg    {
56434345a63Smrg        *unboundRtrn = unbound;
565f46a6179Smrg    }
56634345a63Smrg    else if (unbound)
56734345a63Smrg    {
56834345a63Smrg        for (led = unbound; led != NULL; led = next)
56934345a63Smrg        {
57034345a63Smrg            next = (LEDInfo *) led->defs.next;
57134345a63Smrg            uFree(led);
57234345a63Smrg        }
573f46a6179Smrg    }
574f46a6179Smrg    return True;
575f46a6179Smrg}
576