diff options
Diffstat (limited to 'compat.c')
-rw-r--r-- | compat.c | 913 |
1 files changed, 913 insertions, 0 deletions
diff --git a/compat.c b/compat.c new file mode 100644 index 0000000..2b44523 --- /dev/null +++ b/compat.c @@ -0,0 +1,913 @@ +/* $Xorg: compat.c,v 1.3 2000/08/17 19:54:30 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. + + ********************************************************/ + +#include <X11/Xos.h> +#include "xkbcomp.h" +#include "tokens.h" +#include "expr.h" +#include "vmod.h" +#include "misc.h" +#include "indicators.h" +#include "action.h" + +typedef struct _SymInterpInfo { + CommonInfo defs; + XkbSymInterpretRec interp; +} SymInterpInfo; + +#define _SI_VirtualMod (1<<0) +#define _SI_Action (1<<1) +#define _SI_AutoRepeat (1<<2) +#define _SI_LockingKey (1<<3) +#define _SI_LevelOneOnly (1<<4) + +typedef struct _GroupCompatInfo { + unsigned char fileID; + unsigned char merge; + unsigned char real_mods; + unsigned short vmods; +} GroupCompatInfo; + +typedef struct _CompatInfo { + char * name; + unsigned fileID; + int errorCount; + int nInterps; + SymInterpInfo * interps; + SymInterpInfo dflt; + LEDInfo ledDflt; + GroupCompatInfo groupCompat[XkbNumKbdGroups]; + LEDInfo * leds; + VModInfo vmods; + ActionInfo * act; + XkbDescPtr xkb; +} CompatInfo; + +/***====================================================================***/ + +#define ReportSINotArray(si,f,i) \ + ReportNotArray("symbol interpretation",(f),siText((si),(i))) +#define ReportSIBadType(si,f,w,i) \ + ReportBadType("symbol interpretation",(f),siText((si),(i)),(w)) + +/***====================================================================***/ + +static char * +#if NeedFunctionPrototypes +siText(SymInterpInfo * si,CompatInfo * info) +#else +siText(si,info) + SymInterpInfo * si; + CompatInfo * info; +#endif +{ +static char buf[128]; + + if (si==&info->dflt) { + sprintf(buf,"default"); + } + else { + sprintf(buf,"%s+%s(%s)",XkbKeysymText(si->interp.sym,XkbMessage), + XkbSIMatchText(si->interp.match,XkbMessage), + XkbModMaskText(si->interp.mods,XkbMessage)); + } + return buf; +} + +static void +#if NeedFunctionPrototypes +InitCompatInfo(CompatInfo *info,XkbDescPtr xkb) +#else +InitCompatInfo(info,xkb) + CompatInfo * info; + XkbDescPtr xkb; +#endif +{ +register int i; + + info->xkb= xkb; + info->name= NULL; + info->fileID= 0; + info->errorCount= 0; + info->nInterps= 0; + info->interps= NULL; + info->act= NULL; + info->dflt.defs.fileID= info->fileID; + info->dflt.defs.defined= 0; + info->dflt.defs.merge= MergeOverride; + info->dflt.interp.flags= 0; + info->dflt.interp.virtual_mod= XkbNoModifier; + info->dflt.interp.act.type= XkbSA_NoAction; + for (i=0;i<XkbAnyActionDataSize;i++) { + info->dflt.interp.act.data[i]= 0; + } + ClearIndicatorMapInfo(xkb->dpy,&info->ledDflt); + info->ledDflt.defs.fileID= info->fileID; + info->ledDflt.defs.defined= 0; + info->ledDflt.defs.merge= MergeOverride; + bzero((char *)&info->groupCompat[0],XkbNumKbdGroups*sizeof(GroupCompatInfo)); + info->leds= NULL; + InitVModInfo(&info->vmods,xkb); + return; +} + +static void +#if NeedFunctionPrototypes +ClearCompatInfo(CompatInfo *info,XkbDescPtr xkb) +#else +ClearCompatInfo(info,xkb) + CompatInfo * info; + XkbDescPtr xkb; +#endif +{ +register int i; + + if (info->name!=NULL) + uFree(info->name); + info->name= NULL; + info->dflt.defs.defined= 0; + info->dflt.defs.merge= MergeAugment; + info->dflt.interp.flags= 0; + info->dflt.interp.virtual_mod= XkbNoModifier; + info->dflt.interp.act.type= XkbSA_NoAction; + for (i=0;i<XkbAnyActionDataSize;i++) { + info->dflt.interp.act.data[i]= 0; + } + ClearIndicatorMapInfo(xkb->dpy,&info->ledDflt); + info->nInterps= 0; + info->interps= (SymInterpInfo *)ClearCommonInfo(&info->interps->defs); + bzero((char *)&info->groupCompat[0],XkbNumKbdGroups*sizeof(GroupCompatInfo)); + info->leds= (LEDInfo *)ClearCommonInfo(&info->leds->defs); + /* 3/30/94 (ef) -- XXX! Should free action info here */ + ClearVModInfo(&info->vmods,xkb); + return; +} + +static SymInterpInfo * +#if NeedFunctionPrototypes +NextInterp(CompatInfo *info) +#else +NextInterp(info) + CompatInfo * info; +#endif +{ +SymInterpInfo * si; + + si= uTypedAlloc(SymInterpInfo); + if (si) { + bzero((char *)si,sizeof(SymInterpInfo)); + info->interps= (SymInterpInfo *)AddCommonInfo(&info->interps->defs, + (CommonInfo *)si); + info->nInterps++; + } + return si; +} + +static SymInterpInfo * +#if NeedFunctionPrototypes +FindMatchingInterp(CompatInfo *info,SymInterpInfo *new) +#else +FindMatchingInterp(info,new) + CompatInfo * info; + SymInterpInfo * new; +#endif +{ +SymInterpInfo * old; + + for (old= info->interps;old!=NULL;old=(SymInterpInfo *)old->defs.next) { + if ((old->interp.sym==new->interp.sym)&& + (old->interp.mods==new->interp.mods)&& + (old->interp.match==new->interp.match)) { + return old; + } + } + return NULL; +} + +static Bool +#if NeedFunctionPrototypes +AddInterp(CompatInfo *info,SymInterpInfo *new) +#else +AddInterp(info,new) + CompatInfo * info; + SymInterpInfo * new; +#endif +{ +unsigned collide; +SymInterpInfo * old; + + collide= 0; + old= FindMatchingInterp(info,new); + if (old!=NULL) { + if (new->defs.merge==MergeReplace) { + SymInterpInfo *next= (SymInterpInfo *)old->defs.next; + if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))|| + (warningLevel>9)) { + WARN1("Multiple definitions for \"%s\"\n",siText(new,info)); + ACTION("Earlier interpretation ignored\n"); + } + *old= *new; + old->defs.next= &next->defs; + return True; + } + if (UseNewField(_SI_VirtualMod,&old->defs,&new->defs,&collide)) { + old->interp.virtual_mod= new->interp.virtual_mod; + old->defs.defined|= _SI_VirtualMod; + } + if (UseNewField(_SI_Action,&old->defs,&new->defs,&collide)) { + old->interp.act= new->interp.act; + old->defs.defined|= _SI_Action; + } + if (UseNewField(_SI_AutoRepeat,&old->defs,&new->defs,&collide)) { + old->interp.flags&= ~XkbSI_AutoRepeat; + old->interp.flags|= (new->interp.flags&XkbSI_AutoRepeat); + old->defs.defined|= _SI_AutoRepeat; + } + if (UseNewField(_SI_LockingKey,&old->defs,&new->defs,&collide)) { + old->interp.flags&= ~XkbSI_LockingKey; + old->interp.flags|= (new->interp.flags&XkbSI_LockingKey); + old->defs.defined|= _SI_LockingKey; + } + if (UseNewField(_SI_LevelOneOnly,&old->defs,&new->defs,&collide)) { + old->interp.match&= ~XkbSI_LevelOneOnly; + old->interp.match|= (new->interp.match&XkbSI_LevelOneOnly); + old->defs.defined|= _SI_LevelOneOnly; + } + if (collide) { + WARN1("Multiple interpretations of \"%s\"\n",siText(new,info)); + ACTION1("Using %s definition for duplicate fields\n", + (new->defs.merge!=MergeAugment?"last":"first")); + } + return True; + } + old= new; + if ((new= NextInterp(info))==NULL) + return False; + *new= *old; + new->defs.next= NULL; + return True; +} + +static Bool +#if NeedFunctionPrototypes +AddGroupCompat(CompatInfo *info,unsigned group,GroupCompatInfo *newGC) +#else +AddGroupCompat(info,group,newGC) + CompatInfo * info; + unsigned group; + GroupCompatInfo * newGC; +#endif +{ +GroupCompatInfo * gc; +unsigned merge; + + merge= newGC->merge; + gc= &info->groupCompat[group]; + if ((gc->fileID<1)|| + ((gc->real_mods==newGC->real_mods)&&(gc->vmods==newGC->vmods))) { + *gc= *newGC; + return True; + } + if (((gc->fileID==newGC->fileID)&&(warningLevel>0))||(warningLevel>9)) { + WARN1("Compat map for group %d redefined\n",group+1); + ACTION1("Using %s definition\n",(merge==MergeAugment?"old":"new")); + } + if (merge!=MergeAugment) + *gc= *newGC; + return True; +} + +/***====================================================================***/ + +static Bool +#if NeedFunctionPrototypes +ResolveStateAndPredicate( ExprDef * expr, + unsigned * pred_rtrn, + unsigned * mods_rtrn, + CompatInfo * info) +#else +ResolveStateAndPredicate(expr,pred_rtrn,mods_rtrn,info) + ExprDef * expr; + unsigned * pred_rtrn; + unsigned * mods_rtrn; + CompatInfo * info; +#endif +{ +ExprResult result; + + if (expr==NULL) { + *pred_rtrn= XkbSI_AnyOfOrNone; + *mods_rtrn= ~0; + return True; + } + + *pred_rtrn= XkbSI_Exactly; + if (expr->op==ExprActionDecl) { + char *pred_txt= XkbAtomText(NULL,expr->value.action.name,XkbMessage); + if (uStrCaseCmp(pred_txt,"noneof")==0) + *pred_rtrn= XkbSI_NoneOf; + else if (uStrCaseCmp(pred_txt,"anyofornone")==0) + *pred_rtrn= XkbSI_AnyOfOrNone; + else if (uStrCaseCmp(pred_txt,"anyof")==0) + *pred_rtrn= XkbSI_AnyOf; + else if (uStrCaseCmp(pred_txt,"allof")==0) + *pred_rtrn= XkbSI_AllOf; + else if (uStrCaseCmp(pred_txt,"exactly")==0) + *pred_rtrn= XkbSI_Exactly; + else { + ERROR1("Illegal modifier predicate \"%s\"\n",pred_txt); + ACTION("Ignored\n"); + return False; + } + expr= expr->value.action.args; + } + else if (expr->op==ExprIdent) { + char *pred_txt= XkbAtomText(NULL,expr->value.str,XkbMessage); + if ((pred_txt)&&(uStrCaseCmp(pred_txt,"any")==0)) { + *pred_rtrn= XkbSI_AnyOf; + *mods_rtrn= 0xff; + return True; + } + } + + if (ExprResolveModMask(expr,&result,NULL,NULL)) { + *mods_rtrn= result.uval; + return True; + } + return False; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +MergeIncludedCompatMaps( CompatInfo * into, + CompatInfo * from, + unsigned merge) +#else +MergeIncludedCompatMaps(into,from,merge) + CompatInfo * into; + CompatInfo * from; + unsigned merge; +#endif +{ +SymInterpInfo * si; +LEDInfo * led,*rtrn,*next; +GroupCompatInfo * gcm; +register int i; + + if (from->errorCount>0) { + into->errorCount+= from->errorCount; + return; + } + if (into->name==NULL) { + into->name= from->name; + from->name= NULL; + } + for (si=from->interps;si;si=(SymInterpInfo *)si->defs.next) { + if (merge!=MergeDefault) + si->defs.merge= merge; + if (!AddInterp(into,si)) + into->errorCount++; + } + for (i=0,gcm=&from->groupCompat[0];i<XkbNumKbdGroups;i++,gcm++) { + if (merge!=MergeDefault) + gcm->merge= merge; + if (!AddGroupCompat(into,i,gcm)) + into->errorCount++; + } + for (led=from->leds;led!=NULL;led=next) { + next= (LEDInfo *)led->defs.next; + if (merge!=MergeDefault) + led->defs.merge= merge; + rtrn= AddIndicatorMap(into->leds,led); + if (rtrn!=NULL) + into->leds= rtrn; + else into->errorCount++; + } + return; +} + +typedef void (*FileHandler)( +#if NeedFunctionPrototypes + XkbFile * /* rtrn */, + XkbDescPtr /* xkb */, + unsigned /* merge */, + CompatInfo * /* info */ +#endif +); + +static Bool +#if NeedFunctionPrototypes +HandleIncludeCompatMap( IncludeStmt * stmt, + XkbDescPtr xkb, + CompatInfo * info, + FileHandler hndlr) +#else +HandleIncludeCompatMap(stmt,xkb,info,hndlr) + IncludeStmt * stmt; + XkbDescPtr xkb; + CompatInfo * info; + FileHandler hndlr; +#endif +{ +unsigned newMerge; +XkbFile * rtrn; +CompatInfo included; +Bool haveSelf; + + haveSelf= False; + if ((stmt->file==NULL)&&(stmt->map==NULL)) { + haveSelf= True; + included= *info; + bzero(info,sizeof(CompatInfo)); + } + else if (ProcessIncludeFile(stmt,XkmCompatMapIndex,&rtrn,&newMerge)) { + InitCompatInfo(&included,xkb); + included.fileID= rtrn->id; + included.dflt= info->dflt; + included.dflt.defs.fileID= rtrn->id; + included.dflt.defs.merge= newMerge; + included.ledDflt.defs.fileID= rtrn->id; + included.ledDflt.defs.merge= newMerge; + included.act= info->act; + (*hndlr)(rtrn,xkb,MergeOverride,&included); + if (stmt->stmt!=NULL) { + if (included.name!=NULL) + uFree(included.name); + included.name= stmt->stmt; + stmt->stmt= NULL; + } + } + else { + info->errorCount+= 10; + return False; + } + if ((stmt->next!=NULL)&&(included.errorCount<1)) { + IncludeStmt * next; + unsigned op; + CompatInfo next_incl; + + for (next=stmt->next;next!=NULL;next=next->next) { + if ((next->file==NULL)&&(next->map==NULL)) { + haveSelf= True; + MergeIncludedCompatMaps(&included,info,next->merge); + ClearCompatInfo(info,xkb); + } + else if (ProcessIncludeFile(next,XkmCompatMapIndex,&rtrn,&op)) { + InitCompatInfo(&next_incl,xkb); + next_incl.fileID= rtrn->id; + next_incl.dflt= info->dflt; + next_incl.dflt.defs.fileID= rtrn->id; + next_incl.dflt.defs.merge= op; + next_incl.ledDflt.defs.fileID= rtrn->id; + next_incl.ledDflt.defs.merge= op; + next_incl.act= info->act; + (*hndlr)(rtrn,xkb,MergeOverride,&next_incl); + MergeIncludedCompatMaps(&included,&next_incl,op); + ClearCompatInfo(&next_incl,xkb); + } + else { + info->errorCount+= 10; + return False; + } + } + } + if (haveSelf) + *info= included; + else { + MergeIncludedCompatMaps(info,&included,newMerge); + ClearCompatInfo(&included,xkb); + } + return (info->errorCount==0); +} + +static LookupEntry useModMapValues[] = { + { "levelone", 1 }, + { "level1", 1 }, + { "anylevel", 0 }, + { "any", 0 }, + { NULL, 0 } +}; + +static int +#if NeedFunctionPrototypes +SetInterpField( SymInterpInfo * si, + XkbDescPtr xkb, + char * field, + ExprDef * arrayNdx, + ExprDef * value, + CompatInfo * info) +#else +SetInterpField(si,xkb,field,arrayNdx,value,info) + SymInterpInfo * si; + XkbDescPtr xkb; + char * field; + ExprDef * arrayNdx; + ExprDef * value; + CompatInfo * info; +#endif +{ +int ok= 1; +ExprResult tmp; + + if (uStrCaseCmp(field,"action")==0) { + if (arrayNdx!=NULL) + return ReportSINotArray(si,field,info); + ok= HandleActionDef(value,xkb,&si->interp.act,si->defs.merge,info->act); + if (ok) + si->defs.defined|= _SI_Action; + } + else if ((uStrCaseCmp(field,"virtualmodifier")==0)|| + (uStrCaseCmp(field,"virtualmod")==0)) { + if (arrayNdx!=NULL) + return ReportSINotArray(si,field,info); + ok= ResolveVirtualModifier(value,&tmp,&info->vmods); + if (ok) { + si->interp.virtual_mod= tmp.uval; + si->defs.defined|= _SI_VirtualMod; + } + else return ReportSIBadType(si,field,"virtual modifier",info); + } + else if (uStrCaseCmp(field,"repeat")==0) { + if (arrayNdx!=NULL) + return ReportSINotArray(si,field,info); + ok= ExprResolveBoolean(value,&tmp,NULL,NULL); + if (ok) { + if (tmp.uval) si->interp.flags|= XkbSI_AutoRepeat; + else si->interp.flags&= ~XkbSI_AutoRepeat; + si->defs.defined|= _SI_AutoRepeat; + } + else return ReportSIBadType(si,field,"boolean",info); + } + else if (uStrCaseCmp(field,"locking")==0) { + if (arrayNdx!=NULL) + return ReportSINotArray(si,field,info); + ok= ExprResolveBoolean(value,&tmp,NULL,NULL); + if (ok) { + if (tmp.uval) si->interp.flags|= XkbSI_LockingKey; + else si->interp.flags&= ~XkbSI_LockingKey; + si->defs.defined|= _SI_LockingKey; + } + else return ReportSIBadType(si,field,"boolean",info); + } + else if ((uStrCaseCmp(field,"usemodmap")==0)|| + (uStrCaseCmp(field,"usemodmapmods")==0)) { + if (arrayNdx!=NULL) + return ReportSINotArray(si,field,info); + ok= ExprResolveEnum(value,&tmp,useModMapValues); + if (ok) { + if (tmp.uval) si->interp.match|= XkbSI_LevelOneOnly; + else si->interp.match&= ~XkbSI_LevelOneOnly; + si->defs.defined|= _SI_LevelOneOnly; + } + else return ReportSIBadType(si,field,"level specification",info); + } + else { + ok= ReportBadField("symbol interpretation",field,siText(si,info)); + } + return ok; +} + +LookupEntry groupNames[]= { + { "group1", 0x01 }, + { "group2", 0x02 }, + { "group3", 0x04 }, + { "group4", 0x08 }, + { "group5", 0x10 }, + { "group6", 0x20 }, + { "group7", 0x40 }, + { "group8", 0x80 }, + { "none", 0x00 }, + { "all", 0xff }, + { NULL, 0 } +}; + +static int +#if NeedFunctionPrototypes +HandleInterpVar(VarDef *stmt,XkbDescPtr xkb,CompatInfo *info) +#else +HandleInterpVar(stmt,xkb,info) + VarDef * stmt; + XkbDescPtr xkb; + CompatInfo * info; +#endif +{ +ExprResult elem,field; +ExprDef * ndx; + + if (ExprResolveLhs(stmt->name,&elem,&field,&ndx)==0) + return 0; /* internal error, already reported */ + if (elem.str&&(uStrCaseCmp(elem.str,"interpret")==0)) + return SetInterpField(&info->dflt,xkb,field.str,ndx,stmt->value,info); + if (elem.str&&(uStrCaseCmp(elem.str,"indicator")==0)) { + return SetIndicatorMapField(&info->ledDflt,xkb,field.str,ndx, + stmt->value); + } + return SetActionField(xkb,elem.str,field.str,ndx,stmt->value,&info->act); +} + +static int +#if NeedFunctionPrototypes +HandleInterpBody(VarDef *def,XkbDescPtr xkb,SymInterpInfo *si,CompatInfo *info) +#else +HandleInterpBody(def,xkb,si,info) + VarDef * def; + XkbDescPtr xkb; + SymInterpInfo * si; + CompatInfo * info; +#endif +{ +int ok= 1; +ExprResult tmp,field; +ExprDef * arrayNdx; + + for (;def!=NULL;def= (VarDef *)def->common.next) { + if ((def->name)&&(def->name->type==ExprFieldRef)) { + ok= HandleInterpVar(def,xkb,info); + continue; + } + ok= ExprResolveLhs(def->name,&tmp,&field,&arrayNdx); + if (ok) + ok= SetInterpField(si,xkb,field.str,arrayNdx,def->value,info); + } + return ok; +} + +static int +#if NeedFunctionPrototypes +HandleInterpDef(InterpDef *def,XkbDescPtr xkb,unsigned merge,CompatInfo *info) +#else +HandleInterpDef(def,xkb,merge,info) + InterpDef * def; + XkbDescPtr xkb; + unsigned merge; + CompatInfo * info; +#endif +{ +unsigned pred,mods; +SymInterpInfo si; + + if (!ResolveStateAndPredicate(def->match,&pred,&mods,info)) { + ERROR("Couldn't determine matching modifiers\n"); + ACTION("Symbol interpretation ignored\n"); + return False; + } + if (def->merge!=MergeDefault) + merge= def->merge; + + si= info->dflt; + si.defs.merge= merge; + si.interp.sym= def->sym; + si.interp.match= (si.interp.match&(~XkbSI_OpMask))|(pred&XkbSI_OpMask); + si.interp.mods= mods; + if (!HandleInterpBody(def->def,xkb,&si,info)) { + info->errorCount++; + return False; + } + + if (!AddInterp(info,&si)) { + info->errorCount++; + return False; + } + return True; +} + +static int +#if NeedFunctionPrototypes +HandleGroupCompatDef( GroupCompatDef * def, + XkbDescPtr xkb, + unsigned merge, + CompatInfo * info) +#else +HandleGroupCompatDef(def,xkb,merge,info) + GroupCompatDef * def; + XkbDescPtr xkb; + unsigned merge; + CompatInfo * info; +#endif +{ +ExprResult val; +GroupCompatInfo tmp; + + if (def->merge!=MergeDefault) + merge= def->merge; + if (!XkbIsLegalGroup(def->group-1)) { + ERROR1("Keyboard group must be in the range 1..%d\n",XkbNumKbdGroups+1); + ACTION1("Compatibility map for illegal group %d ignored\n",def->group); + return False; + } + tmp.fileID= info->fileID; + tmp.merge= merge; + if (!ExprResolveModMask(def->def,&val,LookupVModMask,(XPointer)xkb)) { + ERROR("Expected a modifier mask in group compatibility definition\n"); + ACTION1("Ignoring illegal compatibility map for group %d\n",def->group); + return False; + } + tmp.real_mods= val.uval&0xff; + tmp.vmods= (val.uval>>8)&0xffff; + return AddGroupCompat(info,def->group-1,&tmp); +} + +static void +#if NeedFunctionPrototypes +HandleCompatMapFile( XkbFile * file, + XkbDescPtr xkb, + unsigned merge, + CompatInfo * info) +#else +HandleCompatMapFile(file,xkb,merge,info) + XkbFile *file; + XkbDescPtr xkb; + unsigned merge; + CompatInfo *info; +#endif +{ +ParseCommon *stmt; + + if (merge==MergeDefault) + merge= MergeAugment; + info->name= uStringDup(file->name); + stmt= file->defs; + while (stmt) { + switch (stmt->stmtType) { + case StmtInclude: + if (!HandleIncludeCompatMap((IncludeStmt *)stmt,xkb,info, + HandleCompatMapFile)) + info->errorCount++; + break; + case StmtInterpDef: + if (!HandleInterpDef((InterpDef *)stmt,xkb,merge,info)) + info->errorCount++; + break; + case StmtGroupCompatDef: + if (!HandleGroupCompatDef((GroupCompatDef*)stmt,xkb,merge,info)) + info->errorCount++; + break; + case StmtIndicatorMapDef: + { + LEDInfo *rtrn; + rtrn= HandleIndicatorMapDef((IndicatorMapDef *)stmt,xkb, + &info->ledDflt,info->leds, + merge); + if (rtrn!=NULL) + info->leds= rtrn; + else info->errorCount++; + } + break; + case StmtVarDef: + if (!HandleInterpVar((VarDef *)stmt,xkb,info)) + info->errorCount++; + break; + case StmtVModDef: + if (!HandleVModDef((VModDef *)stmt,merge,&info->vmods)) + info->errorCount++; + break; + case StmtKeycodeDef: + ERROR("Interpretation files may not include other types\n"); + ACTION("Ignoring definition of key name\n"); + info->errorCount++; + break; + default: + WSGO1("Unexpected statement type %d in HandleCompatMapFile\n", + stmt->stmtType); + break; + } + stmt= stmt->next; + if (info->errorCount>10) { +#ifdef NOISY + ERROR("Too many errors\n"); +#endif + ACTION1("Abandoning compatibility map \"%s\"\n",file->topName); + break; + } + } + return; +} + +static void +#if NeedFunctionPrototypes +CopyInterps( CompatInfo * info, + XkbCompatMapPtr compat, + Bool needSymbol, + unsigned pred) +#else +CopyInterps(info,compat,needSymbol,pred) + CompatInfo * info; + XkbCompatMapPtr compat; + Bool needSymbol; + unsigned pred; +#endif +{ +SymInterpInfo * si; + + for (si=info->interps;si;si=(SymInterpInfo *)si->defs.next) { + if (((si->interp.match&XkbSI_OpMask)!=pred)|| + (needSymbol&&(si->interp.sym==NoSymbol))|| + ((!needSymbol)&&(si->interp.sym!=NoSymbol))) + continue; + if (compat->num_si>=compat->size_si) { + WSGO("No room to merge symbol interpretations\n"); + ACTION("Symbol interpretations lost\n"); + return; + } + compat->sym_interpret[compat->num_si++]= si->interp; + } + return; +} + +Bool +#if NeedFunctionPrototypes +CompileCompatMap( XkbFile * file, + XkbFileInfo * result, + unsigned merge, + LEDInfo ** unboundLEDs) +#else +CompileCompatMap(file,result,merge,unboundLEDs) + XkbFile * file; + XkbFileInfo * result; + unsigned merge; + LEDInfo ** unboundLEDs; +#endif +{ +int i; +CompatInfo info; +XkbDescPtr xkb; +GroupCompatInfo * gcm; + + xkb= result->xkb; + InitCompatInfo(&info,xkb); + info.dflt.defs.merge= merge; + info.ledDflt.defs.merge= merge; + HandleCompatMapFile(file,xkb,merge,&info); + + if (info.errorCount==0) { + int size; + if (XkbAllocCompatMap(xkb,XkbAllCompatMask,info.nInterps)!=Success) { + WSGO("Couldn't allocate compatibility map\n"); + ACTION("Exiting\n"); + return False; + } + if (info.name!=NULL) { + if (XkbAllocNames(xkb,XkbCompatNameMask,0,0)==Success) + xkb->names->compat= XkbInternAtom(xkb->dpy,info.name,False); + else { + WSGO("Couldn't allocate space for compat name\n"); + ACTION2("Name \"%s\" (from %s) NOT assigned\n",scanFile, + info.name); + } + } + size= info.nInterps*sizeof(XkbSymInterpretRec); + if (size>0) { + CopyInterps(&info,xkb->compat,True,XkbSI_Exactly); + CopyInterps(&info,xkb->compat,True,XkbSI_AllOf|XkbSI_NoneOf); + CopyInterps(&info,xkb->compat,True,XkbSI_AnyOf); + CopyInterps(&info,xkb->compat,True,XkbSI_AnyOfOrNone); + CopyInterps(&info,xkb->compat,False,XkbSI_Exactly); + CopyInterps(&info,xkb->compat,False,XkbSI_AllOf|XkbSI_NoneOf); + CopyInterps(&info,xkb->compat,False,XkbSI_AnyOf); + CopyInterps(&info,xkb->compat,False,XkbSI_AnyOfOrNone); + } + for (i=0,gcm=&info.groupCompat[0];i<XkbNumKbdGroups;i++,gcm++) { + if ((gcm->fileID!=0)||(gcm->real_mods!=0)||(gcm->vmods!=0)) { + xkb->compat->groups[i].mask= gcm->real_mods; + xkb->compat->groups[i].real_mods= gcm->real_mods; + xkb->compat->groups[i].vmods= gcm->vmods; + } + } + if (info.leds!=NULL) { + if (!CopyIndicatorMapDefs(result,info.leds,unboundLEDs)) + info.errorCount++; + info.leds= NULL; + } + ClearCompatInfo(&info,xkb); + return True; + } + if (info.interps!=NULL) + uFree(info.interps); + return False; +} |