alias.c revision f46a6179
1f46a6179Smrg/* $Xorg: alias.c,v 1.3 2000/08/17 19:54:30 cpqbld Exp $ */
2f46a6179Smrg/************************************************************
3f46a6179Smrg Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
4f46a6179Smrg
5f46a6179Smrg Permission to use, copy, modify, and distribute this
6f46a6179Smrg software and its documentation for any purpose and without
7f46a6179Smrg fee is hereby granted, provided that the above copyright
8f46a6179Smrg notice appear in all copies and that both that copyright
9f46a6179Smrg notice and this permission notice appear in supporting
10f46a6179Smrg documentation, and that the name of Silicon Graphics not be
11f46a6179Smrg used in advertising or publicity pertaining to distribution
12f46a6179Smrg of the software without specific prior written permission.
13f46a6179Smrg Silicon Graphics makes no representation about the suitability
14f46a6179Smrg of this software for any purpose. It is provided "as is"
15f46a6179Smrg without any express or implied warranty.
16f46a6179Smrg
17f46a6179Smrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
18f46a6179Smrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19f46a6179Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
20f46a6179Smrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
21f46a6179Smrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
22f46a6179Smrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
23f46a6179Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
24f46a6179Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE.
25f46a6179Smrg
26f46a6179Smrg ********************************************************/
27f46a6179Smrg/* $XFree86$ */
28f46a6179Smrg
29f46a6179Smrg#include "xkbcomp.h"
30f46a6179Smrg#include "misc.h"
31f46a6179Smrg#include "alias.h"
32f46a6179Smrg#include "keycodes.h"
33f46a6179Smrg
34f46a6179Smrg#include <X11/extensions/XKBgeom.h>
35f46a6179Smrg
36f46a6179Smrgstatic void
37f46a6179SmrgHandleCollision(AliasInfo *old,AliasInfo *new)
38f46a6179Smrg{
39f46a6179Smrg    if (strncmp(new->real,old->real,XkbKeyNameLength)==0) {
40f46a6179Smrg	if (((new->def.fileID==old->def.fileID)&&(warningLevel>0))||
41f46a6179Smrg							(warningLevel>9)) {
42f46a6179Smrg	    WARN2("Alias of %s for %s declared more than once\n",
43f46a6179Smrg					XkbKeyNameText(new->alias,XkbMessage),
44f46a6179Smrg					XkbKeyNameText(new->real,XkbMessage));
45f46a6179Smrg	    ACTION("First definition ignored\n");
46f46a6179Smrg	}
47f46a6179Smrg    }
48f46a6179Smrg    else {
49f46a6179Smrg	char *use,*ignore;
50f46a6179Smrg	if (new->def.merge==MergeAugment) {
51f46a6179Smrg	    use= old->real;
52f46a6179Smrg	    ignore= new->real;
53f46a6179Smrg	}
54f46a6179Smrg	else {
55f46a6179Smrg	    use= new->real;
56f46a6179Smrg	    ignore= old->real;
57f46a6179Smrg	}
58f46a6179Smrg	if (((old->def.fileID==new->def.fileID)&&(warningLevel>0))||
59f46a6179Smrg							(warningLevel>9)){
60f46a6179Smrg	    WARN1("Multiple definitions for alias %s\n",
61f46a6179Smrg					XkbKeyNameText(old->alias,XkbMessage));
62f46a6179Smrg	    ACTION2("Using %s, ignoring %s\n", XkbKeyNameText(use,XkbMessage),
63f46a6179Smrg					XkbKeyNameText(ignore,XkbMessage));
64f46a6179Smrg	}
65f46a6179Smrg	if (use!=old->real)
66f46a6179Smrg	    memcpy(old->real,use,XkbKeyNameLength);
67f46a6179Smrg    }
68f46a6179Smrg    old->def.fileID= new->def.fileID;
69f46a6179Smrg    old->def.merge= new->def.merge;
70f46a6179Smrg    return;
71f46a6179Smrg}
72f46a6179Smrg
73f46a6179Smrgstatic void
74f46a6179SmrgInitAliasInfo(	AliasInfo *	info,
75f46a6179Smrg		unsigned	merge,
76f46a6179Smrg		unsigned	file_id,
77f46a6179Smrg		char *		alias,
78f46a6179Smrg		char *		real)
79f46a6179Smrg{
80f46a6179Smrg    bzero(info,sizeof(AliasInfo));
81f46a6179Smrg    info->def.merge= merge;
82f46a6179Smrg    info->def.fileID= file_id;
83f46a6179Smrg    strncpy(info->alias,alias,XkbKeyNameLength);
84f46a6179Smrg    strncpy(info->real,real,XkbKeyNameLength);
85f46a6179Smrg    return;
86f46a6179Smrg}
87f46a6179Smrg
88f46a6179Smrgint
89f46a6179SmrgHandleAliasDef(	KeyAliasDef *	def,
90f46a6179Smrg		unsigned 	merge,
91f46a6179Smrg		unsigned 	file_id,
92f46a6179Smrg		AliasInfo **	info_in)
93f46a6179Smrg{
94f46a6179SmrgAliasInfo *	info;
95f46a6179Smrg
96f46a6179Smrg    for (info= *info_in;info!=NULL;info= (AliasInfo *)info->def.next) {
97f46a6179Smrg	if (strncmp(info->alias,def->alias,XkbKeyNameLength)==0) {
98f46a6179Smrg	    AliasInfo new;
99f46a6179Smrg	    InitAliasInfo(&new,merge,file_id,def->alias,def->real);
100f46a6179Smrg	    HandleCollision(info,&new);
101f46a6179Smrg	    return True;
102f46a6179Smrg	}
103f46a6179Smrg    }
104f46a6179Smrg    info= uTypedCalloc(1,AliasInfo);
105f46a6179Smrg    if (info==NULL) {
106f46a6179Smrg	WSGO("Allocation failure in HandleAliasDef\n");
107f46a6179Smrg	return False;
108f46a6179Smrg    }
109f46a6179Smrg    info->def.fileID= file_id;
110f46a6179Smrg    info->def.merge= merge;
111f46a6179Smrg    info->def.next= (CommonInfo *)*info_in;
112f46a6179Smrg    memcpy(info->alias,def->alias,XkbKeyNameLength);
113f46a6179Smrg    memcpy(info->real,def->real,XkbKeyNameLength);
114f46a6179Smrg    *info_in= (AliasInfo *)AddCommonInfo(&(*info_in)->def,&info->def);
115f46a6179Smrg    return True;
116f46a6179Smrg}
117f46a6179Smrg
118f46a6179Smrgvoid
119f46a6179SmrgClearAliases(AliasInfo **info_in)
120f46a6179Smrg{
121f46a6179Smrg    if ((info_in)&&(*info_in))
122f46a6179Smrg	ClearCommonInfo(&(*info_in)->def);
123f46a6179Smrg    return;
124f46a6179Smrg}
125f46a6179Smrg
126f46a6179SmrgBool
127f46a6179SmrgMergeAliases(AliasInfo **into,AliasInfo **merge,unsigned how_merge)
128f46a6179Smrg{
129f46a6179SmrgAliasInfo *	tmp;
130f46a6179SmrgKeyAliasDef 	def;
131f46a6179Smrg
132f46a6179Smrg    if ((*merge)==NULL)
133f46a6179Smrg	return True;
134f46a6179Smrg    if ((*into)==NULL) {
135f46a6179Smrg	*into= *merge;
136f46a6179Smrg	*merge= NULL;
137f46a6179Smrg	return True;
138f46a6179Smrg    }
139f46a6179Smrg    bzero((char *)&def,sizeof(KeyAliasDef));
140f46a6179Smrg    for (tmp= *merge;tmp!=NULL;tmp= (AliasInfo *)tmp->def.next) {
141f46a6179Smrg	if (how_merge==MergeDefault)
142f46a6179Smrg	     def.merge= tmp->def.merge;
143f46a6179Smrg	else def.merge= how_merge;
144f46a6179Smrg	memcpy(def.alias,tmp->alias,XkbKeyNameLength);
145f46a6179Smrg	memcpy(def.real,tmp->real,XkbKeyNameLength);
146f46a6179Smrg	if (!HandleAliasDef(&def,def.merge,tmp->def.fileID,into))
147f46a6179Smrg	    return False;
148f46a6179Smrg    }
149f46a6179Smrg    return True;
150f46a6179Smrg}
151f46a6179Smrg
152f46a6179Smrgint
153f46a6179SmrgApplyAliases(XkbDescPtr	xkb,Bool toGeom,AliasInfo **info_in)
154f46a6179Smrg{
155f46a6179Smrgregister int 	i;
156f46a6179SmrgXkbKeyAliasPtr	old,a;
157f46a6179SmrgAliasInfo *	info;
158f46a6179Smrgint		nNew,nOld;
159f46a6179SmrgStatus		status;
160f46a6179Smrg
161f46a6179Smrg    if (*info_in==NULL)
162f46a6179Smrg	return True;
163f46a6179Smrg    if (toGeom) {
164f46a6179Smrg	nOld= (xkb->geom?xkb->geom->num_key_aliases:0);
165f46a6179Smrg	old= (xkb->geom?xkb->geom->key_aliases:NULL);
166f46a6179Smrg    }
167f46a6179Smrg    else {
168f46a6179Smrg	nOld= (xkb->names?xkb->names->num_key_aliases:0);
169f46a6179Smrg	old= (xkb->names?xkb->names->key_aliases:NULL);
170f46a6179Smrg    }
171f46a6179Smrg    for (nNew=0,info= *info_in;info!=NULL;info= (AliasInfo *)info->def.next) {
172f46a6179Smrg	unsigned long lname;
173f46a6179Smrg	unsigned int kc;
174f46a6179Smrg
175f46a6179Smrg	lname= KeyNameToLong(info->real);
176f46a6179Smrg	if (!FindNamedKey(xkb,lname,&kc,False,CreateKeyNames(xkb),0)) {
177f46a6179Smrg	    if (warningLevel>4) {
178f46a6179Smrg		WARN2("Attempt to alias %s to non-existent key %s\n",
179f46a6179Smrg					XkbKeyNameText(info->alias,XkbMessage),
180f46a6179Smrg					XkbKeyNameText(info->real,XkbMessage));
181f46a6179Smrg		ACTION("Ignored\n");
182f46a6179Smrg	    }
183f46a6179Smrg	    info->alias[0]= '\0';
184f46a6179Smrg	    continue;
185f46a6179Smrg	}
186f46a6179Smrg	lname= KeyNameToLong(info->alias);
187f46a6179Smrg	if (FindNamedKey(xkb,lname,&kc,False,False,0)) {
188f46a6179Smrg	    if (warningLevel>4) {
189f46a6179Smrg		WARN("Attempt to create alias with the name of a real key\n");
190f46a6179Smrg		ACTION2("Alias \"%s = %s\" ignored\n",
191f46a6179Smrg					XkbKeyNameText(info->alias,XkbMessage),
192f46a6179Smrg					XkbKeyNameText(info->real,XkbMessage));
193f46a6179Smrg	    }
194f46a6179Smrg	    info->alias[0]= '\0';
195f46a6179Smrg	    continue;
196f46a6179Smrg	}
197f46a6179Smrg	nNew++;
198f46a6179Smrg	if ( old ) {
199f46a6179Smrg	    for (i=0,a=old;i<nOld;i++,a++) {
200f46a6179Smrg		if (strncmp(a->alias,info->alias,XkbKeyNameLength)==0) {
201f46a6179Smrg		    AliasInfo old;
202f46a6179Smrg		    InitAliasInfo(&old,MergeAugment,0,a->alias,a->real);
203f46a6179Smrg		    HandleCollision(&old,info);
204f46a6179Smrg		    memcpy(old.real,a->real,XkbKeyNameLength);
205f46a6179Smrg		    info->alias[0]= '\0';
206f46a6179Smrg		    nNew--;
207f46a6179Smrg		    break;
208f46a6179Smrg		}
209f46a6179Smrg	    }
210f46a6179Smrg	}
211f46a6179Smrg    }
212f46a6179Smrg    if (nNew==0) {
213f46a6179Smrg	ClearCommonInfo(&(*info_in)->def);
214f46a6179Smrg	*info_in= NULL;
215f46a6179Smrg	return True;
216f46a6179Smrg    }
217f46a6179Smrg    status= Success;
218f46a6179Smrg    if (toGeom) {
219f46a6179Smrg	if (!xkb->geom) {
220f46a6179Smrg	    XkbGeometrySizesRec	sizes;
221f46a6179Smrg	    bzero((char *)&sizes,sizeof(XkbGeometrySizesRec));
222f46a6179Smrg	    sizes.which= XkbGeomKeyAliasesMask;
223f46a6179Smrg	    sizes.num_key_aliases= nOld+nNew;
224f46a6179Smrg	    status= XkbAllocGeometry(xkb,&sizes);
225f46a6179Smrg	}
226f46a6179Smrg	else {
227f46a6179Smrg	    status= XkbAllocGeomKeyAliases(xkb->geom,nOld+nNew);
228f46a6179Smrg	}
229f46a6179Smrg	if (xkb->geom)
230f46a6179Smrg	    old= xkb->geom->key_aliases;
231f46a6179Smrg    }
232f46a6179Smrg    else {
233f46a6179Smrg	status= XkbAllocNames(xkb,XkbKeyAliasesMask,0,nOld+nNew);
234f46a6179Smrg	if (xkb->names)
235f46a6179Smrg	    old= xkb->names->key_aliases;
236f46a6179Smrg    }
237f46a6179Smrg    if (status!=Success) {
238f46a6179Smrg	WSGO("Allocation failure in ApplyAliases\n");
239f46a6179Smrg	return False;
240f46a6179Smrg    }
241f46a6179Smrg    if (toGeom)
242f46a6179Smrg	 a= &xkb->geom->key_aliases[nOld];
243f46a6179Smrg    else a= &xkb->names->key_aliases[nOld];
244f46a6179Smrg    for (info= *info_in;info!=NULL;info= (AliasInfo *)info->def.next) {
245f46a6179Smrg	if (info->alias[0]!='\0') {
246f46a6179Smrg	    strncpy(a->alias,info->alias,XkbKeyNameLength);
247f46a6179Smrg	    strncpy(a->real,info->real,XkbKeyNameLength);
248f46a6179Smrg	    a++;
249f46a6179Smrg	}
250f46a6179Smrg    }
251f46a6179Smrg#ifdef DEBUG
252f46a6179Smrg    if ((a-old)!=(nOld+nNew)) {
253f46a6179Smrg	WSGO2("Expected %d aliases total but created %d\n",nOld+nNew,a-old);
254f46a6179Smrg    }
255f46a6179Smrg#endif
256f46a6179Smrg    if (toGeom)
257f46a6179Smrg	xkb->geom->num_key_aliases+= nNew;
258f46a6179Smrg    ClearCommonInfo(&(*info_in)->def);
259f46a6179Smrg    *info_in= NULL;
260f46a6179Smrg    return True;
261f46a6179Smrg}
262