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