aboutsummaryrefslogtreecommitdiff
path: root/xkbcomp/indicators.c
diff options
context:
space:
mode:
Diffstat (limited to 'xkbcomp/indicators.c')
-rw-r--r--xkbcomp/indicators.c485
1 files changed, 485 insertions, 0 deletions
diff --git a/xkbcomp/indicators.c b/xkbcomp/indicators.c
new file mode 100644
index 000000000..3061f3e27
--- /dev/null
+++ b/xkbcomp/indicators.c
@@ -0,0 +1,485 @@
+/* $Xorg: indicators.c,v 1.3 2000/08/17 19:54:31 cpqbld Exp $ */
+/************************************************************
+ Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+/* $XFree86: xc/programs/xkbcomp/indicators.c,v 1.4 2001/01/17 23:45:43 dawes Exp $ */
+
+#include "xkbcomp.h"
+#include "misc.h"
+#include "tokens.h"
+#include "expr.h"
+#include "vmod.h"
+#include "indicators.h"
+#include "action.h"
+#include "compat.h"
+
+/***====================================================================***/
+
+#define ReportIndicatorBadType(d,l,f,w) \
+ ReportBadType("indicator map",(f),\
+ XkbAtomText((d),(l)->name,XkbMessage),(w))
+#define ReportIndicatorNotArray(d,l,f) \
+ ReportNotArray("indicator map",(f),\
+ XkbAtomText((d),(l)->name,XkbMessage))
+
+/***====================================================================***/
+
+void
+ClearIndicatorMapInfo(Display *dpy,LEDInfo *info)
+{
+ info->name= XkbInternAtom(dpy,"default",False);
+ info->indicator= _LED_NotBound;
+ info->flags= info->which_mods= info->real_mods= 0;
+ info->vmods= 0;
+ info->which_groups= info->groups= 0;
+ info->ctrls= 0;
+ return;
+}
+
+LEDInfo *
+AddIndicatorMap(LEDInfo *oldLEDs,LEDInfo *new)
+{
+LEDInfo *old,*last;
+unsigned collide;
+
+ last= NULL;
+ for (old=oldLEDs;old!=NULL;old=(LEDInfo *)old->defs.next) {
+ if (old->name==new->name) {
+ if ((old->real_mods==new->real_mods)&&
+ (old->vmods==new->vmods)&&
+ (old->groups==new->groups)&&
+ (old->ctrls==new->ctrls)&&
+ (old->which_mods==new->which_mods)&&
+ (old->which_groups==new->which_groups)) {
+ old->defs.defined|= new->defs.defined;
+ return oldLEDs;
+ }
+ if (new->defs.merge==MergeReplace) {
+ CommonInfo *next= old->defs.next;
+ if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))||
+ (warningLevel>9)) {
+ WARN1("Map for indicator %s redefined\n",
+ XkbAtomText(NULL,old->name,XkbMessage));
+ ACTION("Earlier definition ignored\n");
+ }
+ *old= *new;
+ old->defs.next= next;
+ return oldLEDs;
+ }
+ collide= 0;
+ if (UseNewField(_LED_Index,&old->defs,&new->defs,&collide)) {
+ old->indicator= new->indicator;
+ old->defs.defined|= _LED_Index;
+ }
+ if (UseNewField(_LED_Mods,&old->defs,&new->defs,&collide)) {
+ old->which_mods= new->which_mods;
+ old->real_mods= new->real_mods;
+ old->vmods= new->vmods;
+ old->defs.defined|= _LED_Mods;
+ }
+ if (UseNewField(_LED_Groups,&old->defs,&new->defs,&collide)) {
+ old->which_groups= new->which_groups;
+ old->groups= new->groups;
+ old->defs.defined|= _LED_Groups;
+ }
+ if (UseNewField(_LED_Ctrls,&old->defs,&new->defs,&collide)) {
+ old->ctrls= new->ctrls;
+ old->defs.defined|= _LED_Ctrls;
+ }
+ if (UseNewField(_LED_Explicit,&old->defs,&new->defs,&collide)) {
+ old->flags&= ~XkbIM_NoExplicit;
+ old->flags|= (new->flags&XkbIM_NoExplicit);
+ old->defs.defined|= _LED_Explicit;
+ }
+ if (UseNewField(_LED_Automatic,&old->defs,&new->defs,&collide)) {
+ old->flags&= ~XkbIM_NoAutomatic;
+ old->flags|= (new->flags&XkbIM_NoAutomatic);
+ old->defs.defined|= _LED_Automatic;
+ }
+ if (UseNewField(_LED_DrivesKbd,&old->defs,&new->defs,&collide)) {
+ old->flags&= ~XkbIM_LEDDrivesKB;
+ old->flags|= (new->flags&XkbIM_LEDDrivesKB);
+ old->defs.defined|= _LED_DrivesKbd;
+ }
+ if (collide) {
+ WARN1("Map for indicator %s redefined\n",
+ XkbAtomText(NULL,old->name,XkbMessage));
+ ACTION1("Using %s definition for duplicate fields\n",
+ (new->defs.merge==MergeAugment?"first":"last"));
+ }
+ return oldLEDs;
+ }
+ if (old->defs.next==NULL)
+ last= old;
+ }
+ /* new definition */
+ old= uTypedAlloc(LEDInfo);
+ if (!old) {
+ WSGO("Couldn't allocate indicator map\n");
+ ACTION1("Map for indicator %s not compiled\n",
+ XkbAtomText(NULL,new->name,XkbMessage));
+ return False;
+ }
+ *old= *new;
+ old->defs.next= NULL;
+ if (last) {
+ last->defs.next= &old->defs;
+ return oldLEDs;
+ }
+ return old;
+}
+
+LookupEntry modComponentNames[] = {
+ { "base", XkbIM_UseBase },
+ { "latched", XkbIM_UseLatched },
+ { "locked", XkbIM_UseLocked },
+ { "effective", XkbIM_UseEffective },
+ { "compat", XkbIM_UseCompat },
+ { "any", XkbIM_UseAnyMods },
+ { "none", 0 },
+ { NULL, 0 }
+};
+LookupEntry groupComponentNames[] = {
+ { "base", XkbIM_UseBase },
+ { "latched", XkbIM_UseLatched },
+ { "locked", XkbIM_UseLocked },
+ { "effective", XkbIM_UseEffective },
+ { "any", XkbIM_UseAnyGroup },
+ { "none", 0 },
+ { NULL, 0 }
+};
+
+int
+SetIndicatorMapField( LEDInfo * led,
+ XkbDescPtr xkb,
+ char * field,
+ ExprDef * arrayNdx,
+ ExprDef * value)
+{
+ExprResult rtrn;
+Bool ok;
+
+ ok= True;
+ if ((uStrCaseCmp(field,"modifiers")==0)||(uStrCaseCmp(field,"mods")==0)) {
+ if (arrayNdx!=NULL)
+ return ReportIndicatorNotArray(xkb->dpy,led,field);
+ if (!ExprResolveModMask(value,&rtrn,LookupVModMask,(XPointer)xkb))
+ return ReportIndicatorBadType(xkb->dpy,led,field,"modifier mask");
+ led->real_mods= rtrn.uval&0xff;
+ led->vmods= (rtrn.uval>>8)&0xff;
+ led->defs.defined|= _LED_Mods;
+ }
+ else if (uStrCaseCmp(field,"groups")==0) {
+ if (arrayNdx!=NULL)
+ return ReportIndicatorNotArray(xkb->dpy,led,field);
+ if (!ExprResolveMask(value,&rtrn,SimpleLookup,(XPointer)groupNames))
+ return ReportIndicatorBadType(xkb->dpy,led,field,"group mask");
+ led->groups= rtrn.uval;
+ led->defs.defined|= _LED_Groups;
+ }
+ else if ((uStrCaseCmp(field,"controls")==0)||
+ (uStrCaseCmp(field,"ctrls")==0)) {
+ if (arrayNdx!=NULL)
+ return ReportIndicatorNotArray(xkb->dpy,led,field);
+ if (!ExprResolveMask(value,&rtrn,SimpleLookup,(XPointer)ctrlNames))
+ return ReportIndicatorBadType(xkb->dpy,led,field,"controls mask");
+ led->ctrls= rtrn.uval;
+ led->defs.defined|= _LED_Ctrls;
+ }
+ else if (uStrCaseCmp(field,"allowexplicit")==0) {
+ if (arrayNdx!=NULL)
+ return ReportIndicatorNotArray(xkb->dpy,led,field);
+ if (!ExprResolveBoolean(value,&rtrn,NULL,NULL))
+ return ReportIndicatorBadType(xkb->dpy,led,field,"boolean");
+ if (rtrn.uval) led->flags&= ~XkbIM_NoExplicit;
+ else led->flags|= XkbIM_NoExplicit;
+ led->defs.defined|= _LED_Explicit;
+ }
+ else if ((uStrCaseCmp(field,"whichmodstate")==0)||
+ (uStrCaseCmp(field,"whichmodifierstate")==0)) {
+ if (arrayNdx!=NULL)
+ return ReportIndicatorNotArray(xkb->dpy,led,field);
+ if (!ExprResolveMask(value,&rtrn,SimpleLookup,
+ (XPointer)modComponentNames)) {
+ return ReportIndicatorBadType(xkb->dpy,led,field,
+ "mask of modifier state components");
+ }
+ led->which_mods= rtrn.uval;
+ }
+ else if (uStrCaseCmp(field,"whichgroupstate")==0) {
+ if (arrayNdx!=NULL)
+ return ReportIndicatorNotArray(xkb->dpy,led,field);
+ if (!ExprResolveMask(value,&rtrn,SimpleLookup,
+ (XPointer)groupComponentNames)){
+ return ReportIndicatorBadType(xkb->dpy,led,field,
+ "mask of group state components");
+ }
+ led->which_groups= rtrn.uval;
+ }
+ else if ((uStrCaseCmp(field,"driveskbd")==0)||
+ (uStrCaseCmp(field,"driveskeyboard")==0)||
+ (uStrCaseCmp(field,"leddriveskbd")==0)||
+ (uStrCaseCmp(field,"leddriveskeyboard")==0)||
+ (uStrCaseCmp(field,"indicatordriveskbd")==0)||
+ (uStrCaseCmp(field,"indicatordriveskeyboard")==0)) {
+ if (arrayNdx!=NULL)
+ return ReportIndicatorNotArray(xkb->dpy,led,field);
+ if (!ExprResolveBoolean(value,&rtrn,NULL,NULL))
+ return ReportIndicatorBadType(xkb->dpy,led,field,"boolean");
+ if (rtrn.uval) led->flags|= XkbIM_LEDDrivesKB;
+ else led->flags&= ~XkbIM_LEDDrivesKB;
+ led->defs.defined|= _LED_DrivesKbd;
+ }
+ else if (uStrCaseCmp(field,"index")==0) {
+ if (arrayNdx!=NULL)
+ return ReportIndicatorNotArray(xkb->dpy,led,field);
+ if (!ExprResolveInteger(value,&rtrn,NULL,NULL))
+ return ReportIndicatorBadType(xkb->dpy,led,field,"indicator index");
+ if ((rtrn.uval<1)||(rtrn.uval>32)) {
+ ERROR2("Illegal indicator index %d (range 1..%d)\n",rtrn.uval,
+ XkbNumIndicators);
+ ACTION1("Index definition for %s indicator ignored\n",
+ XkbAtomText(NULL,led->name,XkbMessage));
+ return False;
+ }
+ led->indicator= rtrn.uval;
+ led->defs.defined|= _LED_Index;
+ }
+ else {
+ ERROR2("Unknown field %s in map for %s indicator\n",field,
+ XkbAtomText(NULL,led->name,XkbMessage));
+ ACTION("Definition ignored\n");
+ ok= False;
+ }
+ return ok;
+}
+
+LEDInfo *
+HandleIndicatorMapDef( IndicatorMapDef * def,
+ XkbDescPtr xkb,
+ LEDInfo * dflt,
+ LEDInfo * oldLEDs,
+ unsigned merge)
+{
+LEDInfo led,*rtrn;
+VarDef * var;
+Bool ok;
+
+ if (def->merge!=MergeDefault)
+ merge= def->merge;
+
+ led= *dflt;
+ led.defs.merge= merge;
+ led.name= def->name;
+
+ ok= True;
+ for (var= def->body;var!=NULL;var= (VarDef *)var->common.next) {
+ ExprResult elem,field;
+ ExprDef * arrayNdx;
+ if (!ExprResolveLhs(var->name,&elem,&field,&arrayNdx)) {
+ ok= False;
+ continue;
+ }
+ if (elem.str!=NULL) {
+ ERROR1("Cannot set defaults for \"%s\" element in indicator map\n",
+ elem.str);
+ ACTION2("Assignment to %s.%s ignored\n",elem.str,field.str);
+ ok= False;
+ }
+ else {
+ ok=SetIndicatorMapField(&led,xkb,field.str,arrayNdx,var->value)&&ok;
+ }
+ }
+ if (ok) {
+ rtrn= AddIndicatorMap(oldLEDs,&led);
+ return rtrn;
+ }
+ return NULL;
+}
+
+Bool
+CopyIndicatorMapDefs(XkbFileInfo *result,LEDInfo *leds,LEDInfo **unboundRtrn)
+{
+LEDInfo * led,*next;
+LEDInfo * unbound,*last;
+XkbDescPtr xkb;
+
+ xkb= result->xkb;
+ if (XkbAllocNames(xkb,XkbIndicatorNamesMask,0,0)!=Success) {
+ WSGO("Couldn't allocate names\n");
+ ACTION("Indicator names may be incorrect\n");
+ }
+ if (XkbAllocIndicatorMaps(xkb)!=Success) {
+ WSGO("Can't allocate indicator maps\n");
+ ACTION("Indicator map definitions may be lost\n");
+ return False;
+ }
+ last= unbound= (unboundRtrn?*unboundRtrn:NULL);
+ while ((last!=NULL) && (last->defs.next!=NULL)) {
+ last= (LEDInfo *)last->defs.next;
+ }
+ for (led=leds;led!=NULL;led=next) {
+ next= (LEDInfo *)led->defs.next;
+ if ((led->groups!=0)&&(led->which_groups==0))
+ led->which_groups= XkbIM_UseEffective;
+ if ((led->which_mods==0)&&((led->real_mods)||(led->vmods)))
+ led->which_mods= XkbIM_UseEffective;
+ if ((led->indicator==_LED_NotBound)||(!xkb->indicators)) {
+ if (unboundRtrn!=NULL) {
+ led->defs.next= NULL;
+ if (last!=NULL) last->defs.next= (CommonInfo *)led;
+ else unbound= led;
+ last= led;
+ }
+ else uFree(led);
+ }
+ else {
+ register XkbIndicatorMapPtr im;
+ im= &xkb->indicators->maps[led->indicator-1];
+ im->flags= led->flags;
+ im->which_groups= led->which_groups;
+ im->groups= led->groups;
+ im->which_mods= led->which_mods;
+ im->mods.mask= led->real_mods;
+ im->mods.real_mods= led->real_mods;
+ im->mods.vmods= led->vmods;
+ im->ctrls= led->ctrls;
+ if (xkb->names!=NULL)
+ xkb->names->indicators[led->indicator-1]= led->name;
+ uFree(led);
+ }
+ }
+ if (unboundRtrn!=NULL) {
+ *unboundRtrn= unbound;
+ }
+ return True;
+}
+
+Bool
+BindIndicators( XkbFileInfo * result,
+ Bool force,
+ LEDInfo * unbound,
+ LEDInfo ** unboundRtrn)
+{
+XkbDescPtr xkb;
+register int i;
+register LEDInfo *led,*next,*last;
+
+ xkb= result->xkb;
+ if (xkb->names!=NULL) {
+ for (led=unbound;led!=NULL;led= (LEDInfo *)led->defs.next) {
+ if (led->indicator==_LED_NotBound) {
+ for (i=0;i<XkbNumIndicators;i++) {
+ if (xkb->names->indicators[i]==led->name) {
+ led->indicator= i+1;
+ break;
+ }
+ }
+ }
+ }
+ if (force) {
+ for (led=unbound;led!=NULL;led= (LEDInfo *)led->defs.next) {
+ if (led->indicator==_LED_NotBound) {
+ for (i=0;i<XkbNumIndicators;i++) {
+ if (xkb->names->indicators[i]==None) {
+ xkb->names->indicators[i]= led->name;
+ led->indicator= i+1;
+ xkb->indicators->phys_indicators&= ~(1<<i);
+ break;
+ }
+ }
+ if (led->indicator==_LED_NotBound) {
+ ERROR("No unnamed indicators found\n");
+ ACTION1("Virtual indicator map \"%s\" not bound\n",
+ XkbAtomGetString(xkb->dpy,led->name));
+ continue;
+ }
+ }
+ }
+ }
+ }
+ for (last=NULL,led=unbound;led!=NULL;led= next) {
+ next= (LEDInfo *)led->defs.next;
+ if (led->indicator==_LED_NotBound) {
+ if (force) {
+ unbound= next;
+ uFree(led);
+ }
+ else {
+ if (last)
+ last->defs.next= &led->defs;
+ else unbound= led;
+ last= led;
+ }
+ }
+ else {
+ if ((xkb->names!=NULL)&&
+ (xkb->names->indicators[led->indicator-1]!=led->name)) {
+ Atom old= xkb->names->indicators[led->indicator-1];
+ ERROR1("Multiple names bound to indicator %d\n",(unsigned int)led->indicator);
+ ACTION2("Using %s, ignoring %s\n",
+ XkbAtomGetString(xkb->dpy,old),
+ XkbAtomGetString(xkb->dpy,led->name));
+ led->indicator= _LED_NotBound;
+ if (force) {
+ uFree(led);
+ unbound= next;
+ }
+ else {
+ if (last)
+ last->defs.next= &led->defs;
+ else unbound= led;
+ last= led;
+ }
+ }
+ else {
+ XkbIndicatorMapPtr map;
+ map= &xkb->indicators->maps[led->indicator-1];
+ map->flags= led->flags;
+ map->which_groups= led->which_groups;
+ map->groups= led->groups;
+ map->which_mods= led->which_mods;
+ map->mods.mask= led->real_mods;
+ map->mods.real_mods= led->real_mods;
+ map->mods.vmods= led->vmods;
+ map->ctrls= led->ctrls;
+ if (last) last->defs.next= &next->defs;
+ else unbound= next;
+ led->defs.next= NULL;
+ uFree(led);
+ }
+ }
+ }
+ if (unboundRtrn) {
+ *unboundRtrn= unbound;
+ }
+ else if (unbound) {
+ for (led=unbound;led!=NULL;led=next) {
+ next= (LEDInfo *)led->defs.next;
+ uFree(led);
+ }
+ }
+ return True;
+}