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