486 lines
14 KiB
C
486 lines
14 KiB
C
|
/* $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;
|
||
|
}
|