Remove all non-public API from XKBcommon.h header
[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 #include <X11/extensions/XKBgeomcommon.h>
36
37 static void
38 HandleCollision(AliasInfo * old, AliasInfo * new)
39 {
40     if (strncmp(new->real, old->real, XkbKeyNameLength) == 0)
41     {
42         if (((new->def.fileID == old->def.fileID) && (warningLevel > 0)) ||
43             (warningLevel > 9))
44         {
45             WARN("Alias of %s for %s declared more than once\n",
46                   XkbcKeyNameText(new->alias), XkbcKeyNameText(new->real));
47             ACTION("First definition ignored\n");
48         }
49     }
50     else
51     {
52         char *use, *ignore;
53         if (new->def.merge == MergeAugment)
54         {
55             use = old->real;
56             ignore = new->real;
57         }
58         else
59         {
60             use = new->real;
61             ignore = old->real;
62         }
63         if (((old->def.fileID == new->def.fileID) && (warningLevel > 0)) ||
64             (warningLevel > 9))
65         {
66             WARN("Multiple definitions for alias %s\n",
67                   XkbcKeyNameText(old->alias));
68             ACTION("Using %s, ignoring %s\n",
69                     XkbcKeyNameText(use), XkbcKeyNameText(ignore));
70         }
71         if (use != old->real)
72             memcpy(old->real, use, XkbKeyNameLength);
73     }
74     old->def.fileID = new->def.fileID;
75     old->def.merge = new->def.merge;
76     return;
77 }
78
79 static void
80 InitAliasInfo(AliasInfo * info,
81               unsigned merge, unsigned file_id, char *alias, char *real)
82 {
83     bzero(info, sizeof(AliasInfo));
84     info->def.merge = merge;
85     info->def.fileID = file_id;
86     strncpy(info->alias, alias, XkbKeyNameLength);
87     strncpy(info->real, real, XkbKeyNameLength);
88     return;
89 }
90
91 int
92 HandleAliasDef(KeyAliasDef * def,
93                unsigned merge, unsigned file_id, AliasInfo ** info_in)
94 {
95     AliasInfo *info;
96
97     for (info = *info_in; info != NULL; info = (AliasInfo *) info->def.next)
98     {
99         if (strncmp(info->alias, def->alias, XkbKeyNameLength) == 0)
100         {
101             AliasInfo new;
102             InitAliasInfo(&new, merge, file_id, def->alias, def->real);
103             HandleCollision(info, &new);
104             return True;
105         }
106     }
107     info = uTypedCalloc(1, AliasInfo);
108     if (info == NULL)
109     {
110         WSGO("Allocation failure in HandleAliasDef\n");
111         return False;
112     }
113     info->def.fileID = file_id;
114     info->def.merge = merge;
115     info->def.next = (CommonInfo *) * info_in;
116     memcpy(info->alias, def->alias, XkbKeyNameLength);
117     memcpy(info->real, def->real, XkbKeyNameLength);
118     *info_in = (AliasInfo *) AddCommonInfo(&(*info_in)->def, &info->def);
119     return True;
120 }
121
122 void
123 ClearAliases(AliasInfo ** info_in)
124 {
125     if ((info_in) && (*info_in))
126         ClearCommonInfo(&(*info_in)->def);
127     return;
128 }
129
130 Bool
131 MergeAliases(AliasInfo ** into, AliasInfo ** merge, unsigned how_merge)
132 {
133     AliasInfo *tmp;
134     KeyAliasDef def;
135
136     if ((*merge) == NULL)
137         return True;
138     if ((*into) == NULL)
139     {
140         *into = *merge;
141         *merge = NULL;
142         return True;
143     }
144     bzero((char *) &def, sizeof(KeyAliasDef));
145     for (tmp = *merge; tmp != NULL; tmp = (AliasInfo *) tmp->def.next)
146     {
147         if (how_merge == MergeDefault)
148             def.merge = tmp->def.merge;
149         else
150             def.merge = how_merge;
151         memcpy(def.alias, tmp->alias, XkbKeyNameLength);
152         memcpy(def.real, tmp->real, XkbKeyNameLength);
153         if (!HandleAliasDef(&def, def.merge, tmp->def.fileID, into))
154             return False;
155     }
156     return True;
157 }
158
159 int
160 ApplyAliases(XkbcDescPtr xkb, Bool toGeom, AliasInfo ** info_in)
161 {
162     register int i;
163     XkbKeyAliasPtr old, a;
164     AliasInfo *info;
165     int nNew, nOld;
166     int status;
167
168     if (*info_in == NULL)
169         return True;
170     if (toGeom)
171     {
172         nOld = (xkb->geom ? xkb->geom->num_key_aliases : 0);
173         old = (xkb->geom ? xkb->geom->key_aliases : NULL);
174     }
175     else
176     {
177         nOld = (xkb->names ? xkb->names->num_key_aliases : 0);
178         old = (xkb->names ? xkb->names->key_aliases : NULL);
179     }
180     for (nNew = 0, info = *info_in; info != NULL;
181          info = (AliasInfo *) info->def.next)
182     {
183         unsigned long lname;
184         unsigned int kc;
185
186         lname = KeyNameToLong(info->real);
187         if (!FindNamedKey(xkb, lname, &kc, False, CreateKeyNames(xkb), 0))
188         {
189             if (warningLevel > 4)
190             {
191                 WARN("Attempt to alias %s to non-existent key %s\n",
192                       XkbcKeyNameText(info->alias), XkbcKeyNameText(info->real));
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                 ACTION("Alias \"%s = %s\" ignored\n",
205                         XkbcKeyNameText(info->alias),
206                         XkbcKeyNameText(info->real));
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 = XkbcAllocGeometry(xkb, &sizes);
245         }
246         else
247         {
248             status = XkbcAllocGeomKeyAliases(xkb->geom, nOld + nNew);
249         }
250         if (xkb->geom)
251             old = xkb->geom->key_aliases;
252     }
253     else
254     {
255         status = XkbcAllocNames(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         WSGO("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 }