xkbcomp: Use xkbcommon allocation functions
[platform/upstream/libxkbcommon.git] / src / 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/XKBgeomcommon.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                   XkbcKeyNameText(new->alias), XkbcKeyNameText(new->real));
44             ACTION("First definition ignored\n");
45         }
46     }
47     else
48     {
49         char *use, *ignore;
50         if (new->def.merge == MergeAugment)
51         {
52             use = old->real;
53             ignore = new->real;
54         }
55         else
56         {
57             use = new->real;
58             ignore = old->real;
59         }
60         if (((old->def.fileID == new->def.fileID) && (warningLevel > 0)) ||
61             (warningLevel > 9))
62         {
63             WARN1("Multiple definitions for alias %s\n",
64                   XkbcKeyNameText(old->alias));
65             ACTION2("Using %s, ignoring %s\n",
66                     XkbcKeyNameText(use), XkbcKeyNameText(ignore));
67         }
68         if (use != old->real)
69             memcpy(old->real, use, XkbKeyNameLength);
70     }
71     old->def.fileID = new->def.fileID;
72     old->def.merge = new->def.merge;
73     return;
74 }
75
76 static void
77 InitAliasInfo(AliasInfo * info,
78               unsigned merge, unsigned file_id, char *alias, char *real)
79 {
80     bzero(info, sizeof(AliasInfo));
81     info->def.merge = merge;
82     info->def.fileID = file_id;
83     strncpy(info->alias, alias, XkbKeyNameLength);
84     strncpy(info->real, real, XkbKeyNameLength);
85     return;
86 }
87
88 int
89 HandleAliasDef(KeyAliasDef * def,
90                unsigned merge, unsigned file_id, AliasInfo ** info_in)
91 {
92     AliasInfo *info;
93
94     for (info = *info_in; info != NULL; info = (AliasInfo *) info->def.next)
95     {
96         if (strncmp(info->alias, def->alias, XkbKeyNameLength) == 0)
97         {
98             AliasInfo new;
99             InitAliasInfo(&new, merge, file_id, def->alias, def->real);
100             HandleCollision(info, &new);
101             return True;
102         }
103     }
104     info = uTypedCalloc(1, AliasInfo);
105     if (info == NULL)
106     {
107         WSGO("Allocation failure in HandleAliasDef\n");
108         return False;
109     }
110     info->def.fileID = file_id;
111     info->def.merge = merge;
112     info->def.next = (CommonInfo *) * info_in;
113     memcpy(info->alias, def->alias, XkbKeyNameLength);
114     memcpy(info->real, def->real, XkbKeyNameLength);
115     *info_in = (AliasInfo *) AddCommonInfo(&(*info_in)->def, &info->def);
116     return True;
117 }
118
119 void
120 ClearAliases(AliasInfo ** info_in)
121 {
122     if ((info_in) && (*info_in))
123         ClearCommonInfo(&(*info_in)->def);
124     return;
125 }
126
127 Bool
128 MergeAliases(AliasInfo ** into, AliasInfo ** merge, unsigned how_merge)
129 {
130     AliasInfo *tmp;
131     KeyAliasDef def;
132
133     if ((*merge) == NULL)
134         return True;
135     if ((*into) == NULL)
136     {
137         *into = *merge;
138         *merge = NULL;
139         return True;
140     }
141     bzero((char *) &def, sizeof(KeyAliasDef));
142     for (tmp = *merge; tmp != NULL; tmp = (AliasInfo *) tmp->def.next)
143     {
144         if (how_merge == MergeDefault)
145             def.merge = tmp->def.merge;
146         else
147             def.merge = how_merge;
148         memcpy(def.alias, tmp->alias, XkbKeyNameLength);
149         memcpy(def.real, tmp->real, XkbKeyNameLength);
150         if (!HandleAliasDef(&def, def.merge, tmp->def.fileID, into))
151             return False;
152     }
153     return True;
154 }
155
156 int
157 ApplyAliases(XkbcDescPtr xkb, Bool toGeom, AliasInfo ** info_in)
158 {
159     register int i;
160     XkbKeyAliasPtr old, a;
161     AliasInfo *info;
162     int nNew, nOld;
163     int status;
164
165     if (*info_in == NULL)
166         return True;
167     if (toGeom)
168     {
169         nOld = (xkb->geom ? xkb->geom->num_key_aliases : 0);
170         old = (xkb->geom ? xkb->geom->key_aliases : NULL);
171     }
172     else
173     {
174         nOld = (xkb->names ? xkb->names->num_key_aliases : 0);
175         old = (xkb->names ? xkb->names->key_aliases : NULL);
176     }
177     for (nNew = 0, info = *info_in; info != NULL;
178          info = (AliasInfo *) info->def.next)
179     {
180         unsigned long lname;
181         unsigned int kc;
182
183         lname = KeyNameToLong(info->real);
184         if (!FindNamedKey(xkb, lname, &kc, False, CreateKeyNames(xkb), 0))
185         {
186             if (warningLevel > 4)
187             {
188                 WARN2("Attempt to alias %s to non-existent key %s\n",
189                       XkbcKeyNameText(info->alias), XkbcKeyNameText(info->real));
190                 ACTION("Ignored\n");
191             }
192             info->alias[0] = '\0';
193             continue;
194         }
195         lname = KeyNameToLong(info->alias);
196         if (FindNamedKey(xkb, lname, &kc, False, False, 0))
197         {
198             if (warningLevel > 4)
199             {
200                 WARN("Attempt to create alias with the name of a real key\n");
201                 ACTION2("Alias \"%s = %s\" ignored\n",
202                         XkbcKeyNameText(info->alias),
203                         XkbcKeyNameText(info->real));
204             }
205             info->alias[0] = '\0';
206             continue;
207         }
208         nNew++;
209         if (old)
210         {
211             for (i = 0, a = old; i < nOld; i++, a++)
212             {
213                 if (strncmp(a->alias, info->alias, XkbKeyNameLength) == 0)
214                 {
215                     AliasInfo old;
216                     InitAliasInfo(&old, MergeAugment, 0, a->alias, a->real);
217                     HandleCollision(&old, info);
218                     memcpy(old.real, a->real, XkbKeyNameLength);
219                     info->alias[0] = '\0';
220                     nNew--;
221                     break;
222                 }
223             }
224         }
225     }
226     if (nNew == 0)
227     {
228         ClearCommonInfo(&(*info_in)->def);
229         *info_in = NULL;
230         return True;
231     }
232     status = Success;
233     if (toGeom)
234     {
235         if (!xkb->geom)
236         {
237             XkbGeometrySizesRec sizes;
238             bzero((char *) &sizes, sizeof(XkbGeometrySizesRec));
239             sizes.which = XkbGeomKeyAliasesMask;
240             sizes.num_key_aliases = nOld + nNew;
241             status = XkbcAllocGeometry(xkb, &sizes);
242         }
243         else
244         {
245             status = XkbcAllocGeomKeyAliases(xkb->geom, nOld + nNew);
246         }
247         if (xkb->geom)
248             old = xkb->geom->key_aliases;
249     }
250     else
251     {
252         status = XkbcAllocNames(xkb, XkbKeyAliasesMask, 0, nOld + nNew);
253         if (xkb->names)
254             old = xkb->names->key_aliases;
255     }
256     if (status != Success)
257     {
258         WSGO("Allocation failure in ApplyAliases\n");
259         return False;
260     }
261     if (toGeom)
262         a = &xkb->geom->key_aliases[nOld];
263     else
264         a = &xkb->names->key_aliases[nOld];
265     for (info = *info_in; info != NULL; info = (AliasInfo *) info->def.next)
266     {
267         if (info->alias[0] != '\0')
268         {
269             strncpy(a->alias, info->alias, XkbKeyNameLength);
270             strncpy(a->real, info->real, XkbKeyNameLength);
271             a++;
272         }
273     }
274 #ifdef DEBUG
275     if ((a - old) != (nOld + nNew))
276     {
277         WSGO2("Expected %d aliases total but created %d\n", nOld + nNew,
278               a - old);
279     }
280 #endif
281     if (toGeom)
282         xkb->geom->num_key_aliases += nNew;
283     ClearCommonInfo(&(*info_in)->def);
284     *info_in = NULL;
285     return True;
286 }