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