diff options
Diffstat (limited to 'xkbcomp/alias.c')
-rw-r--r-- | xkbcomp/alias.c | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/xkbcomp/alias.c b/xkbcomp/alias.c new file mode 100644 index 000000000..f228b0d66 --- /dev/null +++ b/xkbcomp/alias.c @@ -0,0 +1,261 @@ +/* $Xorg: alias.c,v 1.3 2000/08/17 19:54:30 cpqbld Exp $ */ +/************************************************************ + Copyright (c) 1995 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$ */ + +#include "xkbcomp.h" +#include "misc.h" +#include "alias.h" +#include "keycodes.h" + +#include <X11/extensions/XKBgeom.h> + +static void +HandleCollision(AliasInfo *old,AliasInfo *new) +{ + if (strncmp(new->real,old->real,XkbKeyNameLength)==0) { + if (((new->def.fileID==old->def.fileID)&&(warningLevel>0))|| + (warningLevel>9)) { + WARN2("Alias of %s for %s declared more than once\n", + XkbKeyNameText(new->alias,XkbMessage), + XkbKeyNameText(new->real,XkbMessage)); + ACTION("First definition ignored\n"); + } + } + else { + char *use,*ignore; + if (new->def.merge==MergeAugment) { + use= old->real; + ignore= new->real; + } + else { + use= new->real; + ignore= old->real; + } + if (((old->def.fileID==new->def.fileID)&&(warningLevel>0))|| + (warningLevel>9)){ + WARN1("Multiple definitions for alias %s\n", + XkbKeyNameText(old->alias,XkbMessage)); + ACTION2("Using %s, ignoring %s\n", XkbKeyNameText(use,XkbMessage), + XkbKeyNameText(ignore,XkbMessage)); + } + if (use!=old->real) + memcpy(old->real,use,XkbKeyNameLength); + } + old->def.fileID= new->def.fileID; + old->def.merge= new->def.merge; + return; +} + +static void +InitAliasInfo( AliasInfo * info, + unsigned merge, + unsigned file_id, + char * alias, + char * real) +{ + bzero(info,sizeof(AliasInfo)); + info->def.merge= merge; + info->def.fileID= file_id; + strncpy(info->alias,alias,XkbKeyNameLength); + strncpy(info->real,real,XkbKeyNameLength); + return; +} + +int +HandleAliasDef( KeyAliasDef * def, + unsigned merge, + unsigned file_id, + AliasInfo ** info_in) +{ +AliasInfo * info; + + for (info= *info_in;info!=NULL;info= (AliasInfo *)info->def.next) { + if (strncmp(info->alias,def->alias,XkbKeyNameLength)==0) { + AliasInfo new; + InitAliasInfo(&new,merge,file_id,def->alias,def->real); + HandleCollision(info,&new); + return True; + } + } + info= uTypedCalloc(1,AliasInfo); + if (info==NULL) { + WSGO("Allocation failure in HandleAliasDef\n"); + return False; + } + info->def.fileID= file_id; + info->def.merge= merge; + info->def.next= (CommonInfo *)*info_in; + memcpy(info->alias,def->alias,XkbKeyNameLength); + memcpy(info->real,def->real,XkbKeyNameLength); + *info_in= (AliasInfo *)AddCommonInfo(&(*info_in)->def,&info->def); + return True; +} + +void +ClearAliases(AliasInfo **info_in) +{ + if ((info_in)&&(*info_in)) + ClearCommonInfo(&(*info_in)->def); + return; +} + +Bool +MergeAliases(AliasInfo **into,AliasInfo **merge,unsigned how_merge) +{ +AliasInfo * tmp; +KeyAliasDef def; + + if ((*merge)==NULL) + return True; + if ((*into)==NULL) { + *into= *merge; + *merge= NULL; + return True; + } + bzero((char *)&def,sizeof(KeyAliasDef)); + for (tmp= *merge;tmp!=NULL;tmp= (AliasInfo *)tmp->def.next) { + if (how_merge==MergeDefault) + def.merge= tmp->def.merge; + else def.merge= how_merge; + memcpy(def.alias,tmp->alias,XkbKeyNameLength); + memcpy(def.real,tmp->real,XkbKeyNameLength); + if (!HandleAliasDef(&def,def.merge,tmp->def.fileID,into)) + return False; + } + return True; +} + +int +ApplyAliases(XkbDescPtr xkb,Bool toGeom,AliasInfo **info_in) +{ +register int i; +XkbKeyAliasPtr old,a; +AliasInfo * info; +int nNew,nOld; +Status status; + + if (*info_in==NULL) + return True; + if (toGeom) { + nOld= (xkb->geom?xkb->geom->num_key_aliases:0); + old= (xkb->geom?xkb->geom->key_aliases:NULL); + } + else { + nOld= (xkb->names?xkb->names->num_key_aliases:0); + old= (xkb->names?xkb->names->key_aliases:NULL); + } + for (nNew=0,info= *info_in;info!=NULL;info= (AliasInfo *)info->def.next) { + unsigned long lname; + unsigned int kc; + + lname= KeyNameToLong(info->real); + if (!FindNamedKey(xkb,lname,&kc,False,CreateKeyNames(xkb),0)) { + if (warningLevel>4) { + WARN2("Attempt to alias %s to non-existent key %s\n", + XkbKeyNameText(info->alias,XkbMessage), + XkbKeyNameText(info->real,XkbMessage)); + ACTION("Ignored\n"); + } + info->alias[0]= '\0'; + continue; + } + lname= KeyNameToLong(info->alias); + if (FindNamedKey(xkb,lname,&kc,False,False,0)) { + if (warningLevel>4) { + WARN("Attempt to create alias with the name of a real key\n"); + ACTION2("Alias \"%s = %s\" ignored\n", + XkbKeyNameText(info->alias,XkbMessage), + XkbKeyNameText(info->real,XkbMessage)); + } + info->alias[0]= '\0'; + continue; + } + nNew++; + if ( old ) { + for (i=0,a=old;i<nOld;i++,a++) { + if (strncmp(a->alias,info->alias,XkbKeyNameLength)==0) { + AliasInfo old; + InitAliasInfo(&old,MergeAugment,0,a->alias,a->real); + HandleCollision(&old,info); + memcpy(old.real,a->real,XkbKeyNameLength); + info->alias[0]= '\0'; + nNew--; + break; + } + } + } + } + if (nNew==0) { + ClearCommonInfo(&(*info_in)->def); + *info_in= NULL; + return True; + } + status= Success; + if (toGeom) { + if (!xkb->geom) { + XkbGeometrySizesRec sizes; + bzero((char *)&sizes,sizeof(XkbGeometrySizesRec)); + sizes.which= XkbGeomKeyAliasesMask; + sizes.num_key_aliases= nOld+nNew; + status= XkbAllocGeometry(xkb,&sizes); + } + else { + status= XkbAllocGeomKeyAliases(xkb->geom,nOld+nNew); + } + if (xkb->geom) + old= xkb->geom->key_aliases; + } + else { + status= XkbAllocNames(xkb,XkbKeyAliasesMask,0,nOld+nNew); + if (xkb->names) + old= xkb->names->key_aliases; + } + if (status!=Success) { + WSGO("Allocation failure in ApplyAliases\n"); + return False; + } + if (toGeom) + a= &xkb->geom->key_aliases[nOld]; + else a= &xkb->names->key_aliases[nOld]; + for (info= *info_in;info!=NULL;info= (AliasInfo *)info->def.next) { + if (info->alias[0]!='\0') { + strncpy(a->alias,info->alias,XkbKeyNameLength); + strncpy(a->real,info->real,XkbKeyNameLength); + a++; + } + } +#ifdef DEBUG + if ((a-old)!=(nOld+nNew)) { + WSGO2("Expected %d aliases total but created %d\n",nOld+nNew,a-old); + } +#endif + if (toGeom) + xkb->geom->num_key_aliases+= nNew; + ClearCommonInfo(&(*info_in)->def); + *info_in= NULL; + return True; +} |