symbols: don't use CommonInfo in KeyInfo
[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 "alias.h"
28 #include "keycodes.h"
29
30 static void
31 HandleCollision(AliasInfo * old, AliasInfo * new)
32 {
33     if (strncmp(new->real, old->real, XkbKeyNameLength) == 0) {
34         if (((new->def.file_id == old->def.file_id) && (warningLevel > 0)) ||
35             (warningLevel > 9)) {
36             WARN("Alias of %s for %s declared more than once\n",
37                  XkbcKeyNameText(new->alias), XkbcKeyNameText(new->real));
38             ACTION("First definition ignored\n");
39         }
40     }
41     else {
42         char *use, *ignore;
43         if (new->def.merge == MERGE_AUGMENT) {
44             use = old->real;
45             ignore = new->real;
46         }
47         else {
48             use = new->real;
49             ignore = old->real;
50         }
51         if (((old->def.file_id == new->def.file_id) && (warningLevel > 0)) ||
52             (warningLevel > 9)) {
53             WARN("Multiple definitions for alias %s\n",
54                  XkbcKeyNameText(old->alias));
55             ACTION("Using %s, ignoring %s\n",
56                    XkbcKeyNameText(use), XkbcKeyNameText(ignore));
57         }
58         if (use != old->real)
59             memcpy(old->real, use, XkbKeyNameLength);
60     }
61     old->def.file_id = new->def.file_id;
62     old->def.merge = new->def.merge;
63 }
64
65 static void
66 InitAliasInfo(AliasInfo * info,
67               enum merge_mode merge, unsigned file_id, char *alias,
68               char *real)
69 {
70     memset(info, 0, sizeof(AliasInfo));
71     info->def.merge = merge;
72     info->def.file_id = file_id;
73     strncpy(info->alias, alias, XkbKeyNameLength);
74     strncpy(info->real, real, XkbKeyNameLength);
75 }
76
77 int
78 HandleAliasDef(KeyAliasDef * def,
79                enum merge_mode merge, unsigned file_id, AliasInfo ** info_in)
80 {
81     AliasInfo *info;
82
83     for (info = *info_in; info != NULL; info =
84              (AliasInfo *) info->def.next) {
85         if (strncmp(info->alias, def->alias, XkbKeyNameLength) == 0) {
86             AliasInfo new;
87             InitAliasInfo(&new, merge, file_id, def->alias, def->real);
88             HandleCollision(info, &new);
89             return true;
90         }
91     }
92     info = uTypedCalloc(1, AliasInfo);
93     if (info == NULL) {
94         WSGO("Allocation failure in HandleAliasDef\n");
95         return false;
96     }
97     info->def.file_id = file_id;
98     info->def.merge = merge;
99     info->def.next = (CommonInfo *) *info_in;
100     memcpy(info->alias, def->alias, XkbKeyNameLength);
101     memcpy(info->real, def->real, XkbKeyNameLength);
102     *info_in = AddCommonInfo(&(*info_in)->def, &info->def);
103     return true;
104 }
105
106 void
107 ClearAliases(AliasInfo ** info_in)
108 {
109     if ((info_in) && (*info_in))
110         ClearCommonInfo(&(*info_in)->def);
111 }
112
113 bool
114 MergeAliases(AliasInfo ** into, AliasInfo ** merge,
115              enum merge_mode how_merge)
116 {
117     AliasInfo *tmp;
118     KeyAliasDef def;
119
120     if ((*merge) == NULL)
121         return true;
122     if ((*into) == NULL) {
123         *into = *merge;
124         *merge = NULL;
125         return true;
126     }
127     memset(&def, 0, sizeof(KeyAliasDef));
128     for (tmp = *merge; tmp != NULL; tmp = (AliasInfo *) tmp->def.next) {
129         if (how_merge == MERGE_DEFAULT)
130             def.merge = tmp->def.merge;
131         else
132             def.merge = how_merge;
133         memcpy(def.alias, tmp->alias, XkbKeyNameLength);
134         memcpy(def.real, tmp->real, XkbKeyNameLength);
135         if (!HandleAliasDef(&def, def.merge, tmp->def.file_id, into))
136             return false;
137     }
138     return true;
139 }
140
141 int
142 ApplyAliases(struct xkb_keymap *keymap, AliasInfo ** info_in)
143 {
144     int i;
145     struct xkb_key *key;
146     struct xkb_key_alias *old, *a;
147     AliasInfo *info;
148     int nNew, nOld;
149
150     nOld = darray_size(keymap->key_aliases);
151     old = &darray_item(keymap->key_aliases, 0);
152
153     for (nNew = 0, info = *info_in; info;
154          info = (AliasInfo *)info->def.next) {
155         unsigned long lname;
156
157         lname = KeyNameToLong(info->real);
158         key = FindNamedKey(keymap, lname, false, CreateKeyNames(keymap), 0);
159         if (!key) {
160             if (warningLevel > 4) {
161                 WARN("Attempt to alias %s to non-existent key %s\n",
162                      XkbcKeyNameText(info->alias), XkbcKeyNameText(info->real));
163                 ACTION("Ignored\n");
164             }
165             info->alias[0] = '\0';
166             continue;
167         }
168
169         lname = KeyNameToLong(info->alias);
170         key = FindNamedKey(keymap, lname, false, false, 0);
171         if (key) {
172             if (warningLevel > 4) {
173                 WARN("Attempt to create alias with the name of a real key\n");
174                 ACTION("Alias \"%s = %s\" ignored\n",
175                        XkbcKeyNameText(info->alias),
176                        XkbcKeyNameText(info->real));
177             }
178             info->alias[0] = '\0';
179             continue;
180         }
181
182         nNew++;
183
184         if (!old)
185             continue;
186
187         for (i = 0, a = old; i < nOld; i++, a++) {
188             AliasInfo old_info;
189
190             if (strncmp(a->alias, info->alias, XkbKeyNameLength) != 0)
191                 continue;
192
193             InitAliasInfo(&old_info, MERGE_AUGMENT, 0, a->alias, a->real);
194             HandleCollision(&old_info, info);
195             memcpy(old_info.real, a->real, XkbKeyNameLength);
196             info->alias[0] = '\0';
197             nNew--;
198             break;
199         }
200     }
201
202     if (nNew == 0)
203         goto out;
204
205     darray_resize0(keymap->key_aliases, nOld + nNew);
206
207     a = &darray_item(keymap->key_aliases, nOld);
208     for (info = *info_in; info; info = (AliasInfo *)info->def.next) {
209         if (info->alias[0] != '\0') {
210             strncpy(a->alias, info->alias, XkbKeyNameLength);
211             strncpy(a->real, info->real, XkbKeyNameLength);
212             a++;
213         }
214     }
215
216 out:
217     ClearCommonInfo(&(*info_in)->def);
218     *info_in = NULL;
219     return true;
220 }