indicators.c revision f46a6179
1f46a6179Smrg/* $Xorg: indicators.c,v 1.3 2000/08/17 19:54:31 cpqbld Exp $ */
2f46a6179Smrg/************************************************************
3f46a6179Smrg Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
4f46a6179Smrg
5f46a6179Smrg Permission to use, copy, modify, and distribute this
6f46a6179Smrg software and its documentation for any purpose and without
7f46a6179Smrg fee is hereby granted, provided that the above copyright
8f46a6179Smrg notice appear in all copies and that both that copyright
9f46a6179Smrg notice and this permission notice appear in supporting
10f46a6179Smrg documentation, and that the name of Silicon Graphics not be
11f46a6179Smrg used in advertising or publicity pertaining to distribution
12f46a6179Smrg of the software without specific prior written permission.
13f46a6179Smrg Silicon Graphics makes no representation about the suitability
14f46a6179Smrg of this software for any purpose. It is provided "as is"
15f46a6179Smrg without any express or implied warranty.
16f46a6179Smrg
17f46a6179Smrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
18f46a6179Smrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19f46a6179Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
20f46a6179Smrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
21f46a6179Smrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
22f46a6179Smrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
23f46a6179Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
24f46a6179Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE.
25f46a6179Smrg
26f46a6179Smrg ********************************************************/
27f46a6179Smrg/* $XFree86: xc/programs/xkbcomp/indicators.c,v 1.4 2001/01/17 23:45:43 dawes Exp $ */
28f46a6179Smrg
29f46a6179Smrg#include "xkbcomp.h"
30f46a6179Smrg#include "misc.h"
31f46a6179Smrg#include "tokens.h"
32f46a6179Smrg#include "expr.h"
33f46a6179Smrg#include "vmod.h"
34f46a6179Smrg#include "indicators.h"
35f46a6179Smrg#include "action.h"
36f46a6179Smrg#include "compat.h"
37f46a6179Smrg
38f46a6179Smrg/***====================================================================***/
39f46a6179Smrg
40f46a6179Smrg#define	ReportIndicatorBadType(d,l,f,w)	\
41f46a6179Smrg		ReportBadType("indicator map",(f),\
42f46a6179Smrg		      	XkbAtomText((d),(l)->name,XkbMessage),(w))
43f46a6179Smrg#define	ReportIndicatorNotArray(d,l,f)	\
44f46a6179Smrg		ReportNotArray("indicator map",(f),\
45f46a6179Smrg			XkbAtomText((d),(l)->name,XkbMessage))
46f46a6179Smrg
47f46a6179Smrg/***====================================================================***/
48f46a6179Smrg
49f46a6179Smrgvoid
50f46a6179SmrgClearIndicatorMapInfo(Display *dpy,LEDInfo *info)
51f46a6179Smrg{
52f46a6179Smrg    info->name= 	XkbInternAtom(dpy,"default",False);
53f46a6179Smrg    info->indicator=	_LED_NotBound;
54f46a6179Smrg    info->flags= info->which_mods= info->real_mods= 0;
55f46a6179Smrg    info->vmods= 0;
56f46a6179Smrg    info->which_groups= info->groups= 0;
57f46a6179Smrg    info->ctrls= 0;
58f46a6179Smrg    return;
59f46a6179Smrg}
60f46a6179Smrg
61f46a6179SmrgLEDInfo *
62f46a6179SmrgAddIndicatorMap(LEDInfo *oldLEDs,LEDInfo *new)
63f46a6179Smrg{
64f46a6179SmrgLEDInfo *old,*last;
65f46a6179Smrgunsigned collide;
66f46a6179Smrg
67f46a6179Smrg    last= NULL;
68f46a6179Smrg    for (old=oldLEDs;old!=NULL;old=(LEDInfo *)old->defs.next) {
69f46a6179Smrg	if (old->name==new->name) {
70f46a6179Smrg	    if ((old->real_mods==new->real_mods)&&
71f46a6179Smrg		(old->vmods==new->vmods)&&
72f46a6179Smrg		(old->groups==new->groups)&&
73f46a6179Smrg		(old->ctrls==new->ctrls)&&
74f46a6179Smrg		(old->which_mods==new->which_mods)&&
75f46a6179Smrg		(old->which_groups==new->which_groups)) {
76f46a6179Smrg		old->defs.defined|= new->defs.defined;
77f46a6179Smrg		return oldLEDs;
78f46a6179Smrg	    }
79f46a6179Smrg	    if (new->defs.merge==MergeReplace) {
80f46a6179Smrg		CommonInfo *next= old->defs.next;
81f46a6179Smrg		if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))||
82f46a6179Smrg		   					   (warningLevel>9)) {
83f46a6179Smrg		    WARN1("Map for indicator %s redefined\n",
84f46a6179Smrg				  XkbAtomText(NULL,old->name,XkbMessage));
85f46a6179Smrg		    ACTION("Earlier definition ignored\n");
86f46a6179Smrg		}
87f46a6179Smrg		*old= *new;
88f46a6179Smrg		old->defs.next= next;
89f46a6179Smrg		return oldLEDs;
90f46a6179Smrg	    }
91f46a6179Smrg	    collide= 0;
92f46a6179Smrg	    if (UseNewField(_LED_Index,&old->defs,&new->defs,&collide)) {
93f46a6179Smrg		old->indicator= new->indicator;
94f46a6179Smrg		old->defs.defined|= _LED_Index;
95f46a6179Smrg	    }
96f46a6179Smrg	    if (UseNewField(_LED_Mods,&old->defs,&new->defs,&collide)) {
97f46a6179Smrg		old->which_mods= new->which_mods;
98f46a6179Smrg		old->real_mods= new->real_mods;
99f46a6179Smrg		old->vmods= new->vmods;
100f46a6179Smrg		old->defs.defined|= _LED_Mods;
101f46a6179Smrg	    }
102f46a6179Smrg	    if (UseNewField(_LED_Groups,&old->defs,&new->defs,&collide)) {
103f46a6179Smrg		old->which_groups= new->which_groups;
104f46a6179Smrg		old->groups= new->groups;
105f46a6179Smrg		old->defs.defined|= _LED_Groups;
106f46a6179Smrg	    }
107f46a6179Smrg	    if (UseNewField(_LED_Ctrls,&old->defs,&new->defs,&collide)) {
108f46a6179Smrg		old->ctrls= new->ctrls;
109f46a6179Smrg		old->defs.defined|= _LED_Ctrls;
110f46a6179Smrg	    }
111f46a6179Smrg	    if (UseNewField(_LED_Explicit,&old->defs,&new->defs,&collide)) {
112f46a6179Smrg		old->flags&= ~XkbIM_NoExplicit;
113f46a6179Smrg		old->flags|= (new->flags&XkbIM_NoExplicit);
114f46a6179Smrg		old->defs.defined|= _LED_Explicit;
115f46a6179Smrg	    }
116f46a6179Smrg	    if (UseNewField(_LED_Automatic,&old->defs,&new->defs,&collide)) {
117f46a6179Smrg		old->flags&= ~XkbIM_NoAutomatic;
118f46a6179Smrg		old->flags|= (new->flags&XkbIM_NoAutomatic);
119f46a6179Smrg		old->defs.defined|= _LED_Automatic;
120f46a6179Smrg	    }
121f46a6179Smrg	    if (UseNewField(_LED_DrivesKbd,&old->defs,&new->defs,&collide)) {
122f46a6179Smrg		old->flags&= ~XkbIM_LEDDrivesKB;
123f46a6179Smrg		old->flags|= (new->flags&XkbIM_LEDDrivesKB);
124f46a6179Smrg		old->defs.defined|= _LED_DrivesKbd;
125f46a6179Smrg	    }
126f46a6179Smrg	    if (collide) {
127f46a6179Smrg		WARN1("Map for indicator %s redefined\n",
128f46a6179Smrg				XkbAtomText(NULL,old->name,XkbMessage));
129f46a6179Smrg		ACTION1("Using %s definition for duplicate fields\n",
130f46a6179Smrg				(new->defs.merge==MergeAugment?"first":"last"));
131f46a6179Smrg	    }
132f46a6179Smrg	    return oldLEDs;
133f46a6179Smrg	}
134f46a6179Smrg	if (old->defs.next==NULL)
135f46a6179Smrg	    last= old;
136f46a6179Smrg    }
137f46a6179Smrg    /* new definition */
138f46a6179Smrg    old= uTypedAlloc(LEDInfo);
139f46a6179Smrg    if (!old) {
140f46a6179Smrg	WSGO("Couldn't allocate indicator map\n");
141f46a6179Smrg	ACTION1("Map for indicator %s not compiled\n",
142f46a6179Smrg				XkbAtomText(NULL,new->name,XkbMessage));
143f46a6179Smrg	return False;
144f46a6179Smrg    }
145f46a6179Smrg    *old= *new;
146f46a6179Smrg    old->defs.next= NULL;
147f46a6179Smrg    if (last) {
148f46a6179Smrg	last->defs.next= &old->defs;
149f46a6179Smrg	return oldLEDs;
150f46a6179Smrg    }
151f46a6179Smrg    return old;
152f46a6179Smrg}
153f46a6179Smrg
154f46a6179SmrgLookupEntry	modComponentNames[] = {
155f46a6179Smrg	{	"base",		XkbIM_UseBase		},
156f46a6179Smrg	{	"latched",	XkbIM_UseLatched	},
157f46a6179Smrg	{	"locked",	XkbIM_UseLocked		},
158f46a6179Smrg	{	"effective",	XkbIM_UseEffective	},
159f46a6179Smrg	{	"compat",	XkbIM_UseCompat		},
160f46a6179Smrg	{	"any",		XkbIM_UseAnyMods	},
161f46a6179Smrg	{	"none",		0			},
162f46a6179Smrg	{	NULL,		0			}
163f46a6179Smrg};
164f46a6179SmrgLookupEntry	groupComponentNames[] = {
165f46a6179Smrg	{	"base",		XkbIM_UseBase		},
166f46a6179Smrg	{	"latched",	XkbIM_UseLatched	},
167f46a6179Smrg	{	"locked",	XkbIM_UseLocked		},
168f46a6179Smrg	{	"effective",	XkbIM_UseEffective	},
169f46a6179Smrg	{	"any",		XkbIM_UseAnyGroup	},
170f46a6179Smrg	{	"none",		0			},
171f46a6179Smrg	{	NULL,		0			}
172f46a6179Smrg};
173f46a6179Smrg
174f46a6179Smrgint
175f46a6179SmrgSetIndicatorMapField(	LEDInfo *	led,
176f46a6179Smrg			XkbDescPtr 	xkb,
177f46a6179Smrg			char *		field,
178f46a6179Smrg			ExprDef *	arrayNdx,
179f46a6179Smrg			ExprDef *	value)
180f46a6179Smrg{
181f46a6179SmrgExprResult	rtrn;
182f46a6179SmrgBool		ok;
183f46a6179Smrg
184f46a6179Smrg    ok= True;
185f46a6179Smrg    if ((uStrCaseCmp(field,"modifiers")==0)||(uStrCaseCmp(field,"mods")==0)) {
186f46a6179Smrg	if (arrayNdx!=NULL)
187f46a6179Smrg	    return ReportIndicatorNotArray(xkb->dpy,led,field);
188f46a6179Smrg	if (!ExprResolveModMask(value,&rtrn,LookupVModMask,(XPointer)xkb))
189f46a6179Smrg	    return ReportIndicatorBadType(xkb->dpy,led,field,"modifier mask");
190f46a6179Smrg	led->real_mods= rtrn.uval&0xff;
191f46a6179Smrg	led->vmods= (rtrn.uval>>8)&0xff;
192f46a6179Smrg	led->defs.defined|= _LED_Mods;
193f46a6179Smrg    }
194f46a6179Smrg    else if (uStrCaseCmp(field,"groups")==0) {
195f46a6179Smrg	if (arrayNdx!=NULL)
196f46a6179Smrg	    return ReportIndicatorNotArray(xkb->dpy,led,field);
197f46a6179Smrg	if (!ExprResolveMask(value,&rtrn,SimpleLookup,(XPointer)groupNames))
198f46a6179Smrg	    return ReportIndicatorBadType(xkb->dpy,led,field,"group mask");
199f46a6179Smrg	led->groups= rtrn.uval;
200f46a6179Smrg	led->defs.defined|= _LED_Groups;
201f46a6179Smrg    }
202f46a6179Smrg    else if ((uStrCaseCmp(field,"controls")==0)||
203f46a6179Smrg	     (uStrCaseCmp(field,"ctrls")==0)) {
204f46a6179Smrg	if (arrayNdx!=NULL)
205f46a6179Smrg	    return ReportIndicatorNotArray(xkb->dpy,led,field);
206f46a6179Smrg	if (!ExprResolveMask(value,&rtrn,SimpleLookup,(XPointer)ctrlNames))
207f46a6179Smrg	    return ReportIndicatorBadType(xkb->dpy,led,field,"controls mask");
208f46a6179Smrg	led->ctrls= rtrn.uval;
209f46a6179Smrg	led->defs.defined|= _LED_Ctrls;
210f46a6179Smrg    }
211f46a6179Smrg    else if (uStrCaseCmp(field,"allowexplicit")==0) {
212f46a6179Smrg	if (arrayNdx!=NULL)
213f46a6179Smrg	    return ReportIndicatorNotArray(xkb->dpy,led,field);
214f46a6179Smrg	if (!ExprResolveBoolean(value,&rtrn,NULL,NULL))
215f46a6179Smrg	    return ReportIndicatorBadType(xkb->dpy,led,field,"boolean");
216f46a6179Smrg	if (rtrn.uval)	led->flags&= ~XkbIM_NoExplicit;
217f46a6179Smrg	else		led->flags|=  XkbIM_NoExplicit;
218f46a6179Smrg	led->defs.defined|= _LED_Explicit;
219f46a6179Smrg    }
220f46a6179Smrg    else if ((uStrCaseCmp(field,"whichmodstate")==0)||
221f46a6179Smrg	     (uStrCaseCmp(field,"whichmodifierstate")==0)) {
222f46a6179Smrg	if (arrayNdx!=NULL)
223f46a6179Smrg	    return ReportIndicatorNotArray(xkb->dpy,led,field);
224f46a6179Smrg	if (!ExprResolveMask(value,&rtrn,SimpleLookup,
225f46a6179Smrg						(XPointer)modComponentNames)) {
226f46a6179Smrg	    return ReportIndicatorBadType(xkb->dpy,led,field,
227f46a6179Smrg    					"mask of modifier state components");
228f46a6179Smrg	}
229f46a6179Smrg	led->which_mods= rtrn.uval;
230f46a6179Smrg    }
231f46a6179Smrg    else if (uStrCaseCmp(field,"whichgroupstate")==0) {
232f46a6179Smrg	if (arrayNdx!=NULL)
233f46a6179Smrg	    return ReportIndicatorNotArray(xkb->dpy,led,field);
234f46a6179Smrg	if (!ExprResolveMask(value,&rtrn,SimpleLookup,
235f46a6179Smrg						(XPointer)groupComponentNames)){
236f46a6179Smrg	    return ReportIndicatorBadType(xkb->dpy,led,field,
237f46a6179Smrg					"mask of group state components");
238f46a6179Smrg	}
239f46a6179Smrg	led->which_groups= rtrn.uval;
240f46a6179Smrg    }
241f46a6179Smrg    else if ((uStrCaseCmp(field,"driveskbd")==0)||
242f46a6179Smrg	     (uStrCaseCmp(field,"driveskeyboard")==0)||
243f46a6179Smrg	     (uStrCaseCmp(field,"leddriveskbd")==0)||
244f46a6179Smrg	     (uStrCaseCmp(field,"leddriveskeyboard")==0)||
245f46a6179Smrg	     (uStrCaseCmp(field,"indicatordriveskbd")==0)||
246f46a6179Smrg	     (uStrCaseCmp(field,"indicatordriveskeyboard")==0)) {
247f46a6179Smrg	if (arrayNdx!=NULL)
248f46a6179Smrg	    return ReportIndicatorNotArray(xkb->dpy,led,field);
249f46a6179Smrg	if (!ExprResolveBoolean(value,&rtrn,NULL,NULL))
250f46a6179Smrg	    return ReportIndicatorBadType(xkb->dpy,led,field,"boolean");
251f46a6179Smrg	if (rtrn.uval)	led->flags|=  XkbIM_LEDDrivesKB;
252f46a6179Smrg	else		led->flags&= ~XkbIM_LEDDrivesKB;
253f46a6179Smrg	led->defs.defined|= _LED_DrivesKbd;
254f46a6179Smrg    }
255f46a6179Smrg    else if (uStrCaseCmp(field,"index")==0) {
256f46a6179Smrg	if (arrayNdx!=NULL)
257f46a6179Smrg	    return ReportIndicatorNotArray(xkb->dpy,led,field);
258f46a6179Smrg	if (!ExprResolveInteger(value,&rtrn,NULL,NULL))
259f46a6179Smrg	    return ReportIndicatorBadType(xkb->dpy,led,field,"indicator index");
260f46a6179Smrg	if ((rtrn.uval<1)||(rtrn.uval>32)) {
261f46a6179Smrg	    ERROR2("Illegal indicator index %d (range 1..%d)\n",rtrn.uval,
262f46a6179Smrg							XkbNumIndicators);
263f46a6179Smrg	    ACTION1("Index definition for %s indicator ignored\n",
264f46a6179Smrg				XkbAtomText(NULL,led->name,XkbMessage));
265f46a6179Smrg	    return False;
266f46a6179Smrg	}
267f46a6179Smrg	led->indicator= rtrn.uval;
268f46a6179Smrg	led->defs.defined|= _LED_Index;
269f46a6179Smrg    }
270f46a6179Smrg    else {
271f46a6179Smrg	ERROR2("Unknown field %s in map for %s indicator\n",field,
272f46a6179Smrg				XkbAtomText(NULL,led->name,XkbMessage));
273f46a6179Smrg	ACTION("Definition ignored\n");
274f46a6179Smrg	ok= False;
275f46a6179Smrg    }
276f46a6179Smrg    return ok;
277f46a6179Smrg}
278f46a6179Smrg
279f46a6179SmrgLEDInfo *
280f46a6179SmrgHandleIndicatorMapDef(	IndicatorMapDef *	def,
281f46a6179Smrg			XkbDescPtr		xkb,
282f46a6179Smrg			LEDInfo *		dflt,
283f46a6179Smrg			LEDInfo *		oldLEDs,
284f46a6179Smrg			unsigned 		merge)
285f46a6179Smrg{
286f46a6179SmrgLEDInfo			led,*rtrn;
287f46a6179SmrgVarDef *		var;
288f46a6179SmrgBool			ok;
289f46a6179Smrg
290f46a6179Smrg    if (def->merge!=MergeDefault)
291f46a6179Smrg	merge= def->merge;
292f46a6179Smrg
293f46a6179Smrg    led= *dflt;
294f46a6179Smrg    led.defs.merge= merge;
295f46a6179Smrg    led.name= def->name;
296f46a6179Smrg
297f46a6179Smrg    ok= True;
298f46a6179Smrg    for (var= def->body;var!=NULL;var= (VarDef *)var->common.next) {
299f46a6179Smrg	ExprResult	elem,field;
300f46a6179Smrg	ExprDef *	arrayNdx;
301f46a6179Smrg	if (!ExprResolveLhs(var->name,&elem,&field,&arrayNdx)) {
302f46a6179Smrg	    ok= False;
303f46a6179Smrg	    continue;
304f46a6179Smrg	}
305f46a6179Smrg	if (elem.str!=NULL) {
306f46a6179Smrg	    ERROR1("Cannot set defaults for \"%s\" element in indicator map\n",
307f46a6179Smrg								elem.str);
308f46a6179Smrg	    ACTION2("Assignment to %s.%s ignored\n",elem.str,field.str);
309f46a6179Smrg	    ok= False;
310f46a6179Smrg	}
311f46a6179Smrg	else {
312f46a6179Smrg	    ok=SetIndicatorMapField(&led,xkb,field.str,arrayNdx,var->value)&&ok;
313f46a6179Smrg	}
314f46a6179Smrg    }
315f46a6179Smrg    if (ok) {
316f46a6179Smrg	rtrn= AddIndicatorMap(oldLEDs,&led);
317f46a6179Smrg	return rtrn;
318f46a6179Smrg    }
319f46a6179Smrg    return NULL;
320f46a6179Smrg}
321f46a6179Smrg
322f46a6179SmrgBool
323f46a6179SmrgCopyIndicatorMapDefs(XkbFileInfo *result,LEDInfo *leds,LEDInfo **unboundRtrn)
324f46a6179Smrg{
325f46a6179SmrgLEDInfo *		led,*next;
326f46a6179SmrgLEDInfo *		unbound,*last;
327f46a6179SmrgXkbDescPtr		xkb;
328f46a6179Smrg
329f46a6179Smrg    xkb= result->xkb;
330f46a6179Smrg    if (XkbAllocNames(xkb,XkbIndicatorNamesMask,0,0)!=Success) {
331f46a6179Smrg	WSGO("Couldn't allocate names\n");
332f46a6179Smrg	ACTION("Indicator names may be incorrect\n");
333f46a6179Smrg    }
334f46a6179Smrg    if (XkbAllocIndicatorMaps(xkb)!=Success) {
335f46a6179Smrg	WSGO("Can't allocate indicator maps\n");
336f46a6179Smrg	ACTION("Indicator map definitions may be lost\n");
337f46a6179Smrg	return False;
338f46a6179Smrg    }
339f46a6179Smrg    last= unbound= (unboundRtrn?*unboundRtrn:NULL);
340f46a6179Smrg    while ((last!=NULL) && (last->defs.next!=NULL)) {
341f46a6179Smrg	last= (LEDInfo *)last->defs.next;
342f46a6179Smrg    }
343f46a6179Smrg    for (led=leds;led!=NULL;led=next) {
344f46a6179Smrg	next= (LEDInfo *)led->defs.next;
345f46a6179Smrg	if ((led->groups!=0)&&(led->which_groups==0))
346f46a6179Smrg	    led->which_groups= XkbIM_UseEffective;
347f46a6179Smrg	if ((led->which_mods==0)&&((led->real_mods)||(led->vmods)))
348f46a6179Smrg	    led->which_mods= XkbIM_UseEffective;
349f46a6179Smrg	if ((led->indicator==_LED_NotBound)||(!xkb->indicators)) {
350f46a6179Smrg	    if (unboundRtrn!=NULL) {
351f46a6179Smrg		led->defs.next= NULL;
352f46a6179Smrg		if (last!=NULL) 	last->defs.next= (CommonInfo *)led;
353f46a6179Smrg		else			unbound= led;
354f46a6179Smrg		last= led;
355f46a6179Smrg	    }
356f46a6179Smrg	    else uFree(led);
357f46a6179Smrg	}
358f46a6179Smrg	else {
359f46a6179Smrg	    register XkbIndicatorMapPtr im;
360f46a6179Smrg	    im= &xkb->indicators->maps[led->indicator-1];
361f46a6179Smrg	    im->flags= led->flags;
362f46a6179Smrg	    im->which_groups= led->which_groups;
363f46a6179Smrg	    im->groups= led->groups;
364f46a6179Smrg	    im->which_mods= led->which_mods;
365f46a6179Smrg	    im->mods.mask= led->real_mods;
366f46a6179Smrg	    im->mods.real_mods= led->real_mods;
367f46a6179Smrg	    im->mods.vmods= led->vmods;
368f46a6179Smrg	    im->ctrls= led->ctrls;
369f46a6179Smrg	    if (xkb->names!=NULL)
370f46a6179Smrg		xkb->names->indicators[led->indicator-1]= led->name;
371f46a6179Smrg	    uFree(led);
372f46a6179Smrg	}
373f46a6179Smrg    }
374f46a6179Smrg    if (unboundRtrn!=NULL) {
375f46a6179Smrg	*unboundRtrn= unbound;
376f46a6179Smrg    }
377f46a6179Smrg    return True;
378f46a6179Smrg}
379f46a6179Smrg
380f46a6179SmrgBool
381f46a6179SmrgBindIndicators(	XkbFileInfo *	result,
382f46a6179Smrg		Bool		force,
383f46a6179Smrg		LEDInfo *	unbound,
384f46a6179Smrg		LEDInfo **	unboundRtrn)
385f46a6179Smrg{
386f46a6179SmrgXkbDescPtr		xkb;
387f46a6179Smrgregister int 		i;
388f46a6179Smrgregister LEDInfo	 *led,*next,*last;
389f46a6179Smrg
390f46a6179Smrg    xkb= result->xkb;
391f46a6179Smrg    if (xkb->names!=NULL) {
392f46a6179Smrg	for (led=unbound;led!=NULL;led= (LEDInfo *)led->defs.next) {
393f46a6179Smrg	    if (led->indicator==_LED_NotBound) {
394f46a6179Smrg		for (i=0;i<XkbNumIndicators;i++) {
395f46a6179Smrg		    if (xkb->names->indicators[i]==led->name) {
396f46a6179Smrg			led->indicator= i+1;
397f46a6179Smrg			break;
398f46a6179Smrg		    }
399f46a6179Smrg		}
400f46a6179Smrg	    }
401f46a6179Smrg	}
402f46a6179Smrg	if (force) {
403f46a6179Smrg	    for (led=unbound;led!=NULL;led= (LEDInfo *)led->defs.next) {
404f46a6179Smrg		if (led->indicator==_LED_NotBound) {
405f46a6179Smrg		    for (i=0;i<XkbNumIndicators;i++) {
406f46a6179Smrg			if (xkb->names->indicators[i]==None) {
407f46a6179Smrg			    xkb->names->indicators[i]= led->name;
408f46a6179Smrg			    led->indicator= i+1;
409f46a6179Smrg			    xkb->indicators->phys_indicators&= ~(1<<i);
410f46a6179Smrg			    break;
411f46a6179Smrg			}
412f46a6179Smrg		    }
413f46a6179Smrg		    if (led->indicator==_LED_NotBound) {
414f46a6179Smrg			ERROR("No unnamed indicators found\n");
415f46a6179Smrg			ACTION1("Virtual indicator map \"%s\" not bound\n",
416f46a6179Smrg				XkbAtomGetString(xkb->dpy,led->name));
417f46a6179Smrg			continue;
418f46a6179Smrg		    }
419f46a6179Smrg		}
420f46a6179Smrg	    }
421f46a6179Smrg	}
422f46a6179Smrg    }
423f46a6179Smrg    for (last=NULL,led=unbound;led!=NULL;led= next) {
424f46a6179Smrg	next= (LEDInfo *)led->defs.next;
425f46a6179Smrg	if (led->indicator==_LED_NotBound) {
426f46a6179Smrg	    if (force) {
427f46a6179Smrg		unbound= next;
428f46a6179Smrg		uFree(led);
429f46a6179Smrg	    }
430f46a6179Smrg	    else {
431f46a6179Smrg		if (last)
432f46a6179Smrg		     last->defs.next= &led->defs;
433f46a6179Smrg		else unbound= led;
434f46a6179Smrg		last= led;
435f46a6179Smrg	    }
436f46a6179Smrg	}
437f46a6179Smrg	else {
438f46a6179Smrg	    if ((xkb->names!=NULL)&&
439f46a6179Smrg		(xkb->names->indicators[led->indicator-1]!=led->name)) {
440f46a6179Smrg		Atom old= xkb->names->indicators[led->indicator-1];
441f46a6179Smrg		ERROR1("Multiple names bound to indicator %d\n",(unsigned int)led->indicator);
442f46a6179Smrg		ACTION2("Using %s, ignoring %s\n",
443f46a6179Smrg				XkbAtomGetString(xkb->dpy,old),
444f46a6179Smrg				XkbAtomGetString(xkb->dpy,led->name));
445f46a6179Smrg		led->indicator= _LED_NotBound;
446f46a6179Smrg		if (force) {
447f46a6179Smrg		    uFree(led);
448f46a6179Smrg		    unbound= next;
449f46a6179Smrg		}
450f46a6179Smrg		else {
451f46a6179Smrg		    if (last)
452f46a6179Smrg			 last->defs.next= &led->defs;
453f46a6179Smrg		    else unbound= led;
454f46a6179Smrg		    last= led;
455f46a6179Smrg		}
456f46a6179Smrg	    }
457f46a6179Smrg	    else {
458f46a6179Smrg		XkbIndicatorMapPtr map;
459f46a6179Smrg		map= &xkb->indicators->maps[led->indicator-1];
460f46a6179Smrg		map->flags= led->flags;
461f46a6179Smrg		map->which_groups= led->which_groups;
462f46a6179Smrg		map->groups= led->groups;
463f46a6179Smrg		map->which_mods= led->which_mods;
464f46a6179Smrg		map->mods.mask= led->real_mods;
465f46a6179Smrg		map->mods.real_mods= led->real_mods;
466f46a6179Smrg		map->mods.vmods= led->vmods;
467f46a6179Smrg		map->ctrls= led->ctrls;
468f46a6179Smrg		if (last)	last->defs.next= &next->defs;
469f46a6179Smrg		else		unbound= next;
470f46a6179Smrg		led->defs.next= NULL;
471f46a6179Smrg		uFree(led);
472f46a6179Smrg	    }
473f46a6179Smrg	}
474f46a6179Smrg    }
475f46a6179Smrg    if (unboundRtrn) {
476f46a6179Smrg	*unboundRtrn= unbound;
477f46a6179Smrg    }
478f46a6179Smrg    else if (unbound) {
479f46a6179Smrg	for (led=unbound;led!=NULL;led=next) {
480f46a6179Smrg	    next= (LEDInfo *)led->defs.next;
481f46a6179Smrg	    uFree(led);
482f46a6179Smrg	}
483f46a6179Smrg    }
484f46a6179Smrg    return True;
485f46a6179Smrg}
486