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