aboutsummaryrefslogtreecommitdiff
path: root/xkbcomp/alias.c
diff options
context:
space:
mode:
Diffstat (limited to 'xkbcomp/alias.c')
-rw-r--r--xkbcomp/alias.c261
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;
+}