8802283fb18ceba26252a54cd4a845b79af6e7cf
[platform/upstream/libxkbcommon.git] / src / xkbcomp / misc.c
1 /************************************************************
2  Copyright (c) 1994 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-priv.h"
28 #include "parseutils.h"
29 #include "keycodes.h"
30
31 /***====================================================================***/
32
33 /**
34  * Open the file given in the include statement and parse it's content.
35  * If the statement defines a specific map to use, this map is returned in
36  * file_rtrn. Otherwise, the default map is returned.
37  *
38  * @param ctx The ctx containing include paths
39  * @param stmt The include statement, specifying the file name to look for.
40  * @param file_type Type of file (XkmKeyNamesIdx, etc.)
41  * @param file_rtrn Returns the key map to be used.
42  * @param merge_rtrn Always returns stmt->merge.
43  *
44  * @return true on success or false otherwise.
45  */
46 bool
47 ProcessIncludeFile(struct xkb_ctx *ctx,
48                    IncludeStmt * stmt,
49                    unsigned file_type,
50                    XkbFile ** file_rtrn, unsigned *merge_rtrn)
51 {
52     FILE *file;
53     XkbFile *rtrn, *mapToUse, *next;
54
55     file = XkbFindFileInPath(ctx, stmt->file, file_type, &stmt->path);
56     if (file == NULL)
57     {
58         ERROR("Can't find file \"%s\" for %s include\n", stmt->file,
59                 XkbDirectoryForInclude(file_type));
60         return false;
61     }
62
63
64     if (!XKBParseFile(ctx, file, stmt->file, &rtrn))
65     {
66         ERROR("Error interpreting include file \"%s\"\n", stmt->file);
67         fclose(file);
68         return false;
69     }
70     fclose(file);
71
72     mapToUse = rtrn;
73     if (stmt->map != NULL)
74     {
75         while (mapToUse)
76         {
77             next = (XkbFile *)mapToUse->common.next;
78             mapToUse->common.next = NULL;
79             if (strcmp(mapToUse->name, stmt->map) == 0 &&
80                 mapToUse->type == file_type)
81             {
82                     FreeXKBFile(next);
83                     break;
84             }
85             else
86             {
87                 FreeXKBFile(mapToUse);
88             }
89             mapToUse = next;
90         }
91         if (!mapToUse)
92         {
93             ERROR("No %s named \"%s\" in the include file \"%s\"\n",
94                    XkbcConfigText(file_type), stmt->map, stmt->file);
95             return false;
96         }
97     }
98     else if ((rtrn->common.next != NULL) && (warningLevel > 5))
99     {
100         WARN("No map in include statement, but \"%s\" contains several\n",
101               stmt->file);
102         ACTION("Using first defined map, \"%s\"\n", rtrn->name);
103     }
104     if (mapToUse->type != file_type)
105     {
106         ERROR("Include file wrong type (expected %s, got %s)\n",
107                XkbcConfigText(file_type), XkbcConfigText(mapToUse->type));
108         ACTION("Include file \"%s\" ignored\n", stmt->file);
109         return false;
110     }
111     /* FIXME: we have to check recursive includes here (or somewhere) */
112
113     *file_rtrn = mapToUse;
114     *merge_rtrn = stmt->merge;
115     return true;
116 }
117
118 /***====================================================================***/
119
120 int
121 ReportNotArray(const char *type, const char *field, const char *name)
122 {
123     ERROR("The %s %s field is not an array\n", type, field);
124     ACTION("Ignoring illegal assignment in %s\n", name);
125     return false;
126 }
127
128 int
129 ReportShouldBeArray(const char *type, const char *field, const char *name)
130 {
131     ERROR("Missing subscript for %s %s\n", type, field);
132     ACTION("Ignoring illegal assignment in %s\n", name);
133     return false;
134 }
135
136 int
137 ReportBadType(const char *type, const char *field,
138               const char *name, const char *wanted)
139 {
140     ERROR("The %s %s field must be a %s\n", type, field, wanted);
141     ACTION("Ignoring illegal assignment in %s\n", name);
142     return false;
143 }
144
145 int
146 ReportBadField(const char *type, const char *field, const char *name)
147 {
148     ERROR("Unknown %s field %s in %s\n", type, field, name);
149     ACTION("Ignoring assignment to unknown field in %s\n", name);
150     return false;
151 }
152
153 /***====================================================================***/
154
155 bool
156 UseNewField(unsigned field,
157             CommonInfo * oldDefs, CommonInfo * newDefs, unsigned *pCollide)
158 {
159     bool useNew;
160
161     useNew = false;
162     if (oldDefs->defined & field)
163     {
164         if (newDefs->defined & field)
165         {
166             if (((oldDefs->fileID == newDefs->fileID)
167                  && (warningLevel > 0)) || (warningLevel > 9))
168             {
169                 *pCollide |= field;
170             }
171             if (newDefs->merge != MergeAugment)
172                 useNew = true;
173         }
174     }
175     else if (newDefs->defined & field)
176         useNew = true;
177     return useNew;
178 }
179
180 char *
181 ClearCommonInfo(CommonInfo * cmn)
182 {
183     if (cmn != NULL)
184     {
185         CommonInfo *this, *next;
186         for (this = cmn; this != NULL; this = next)
187         {
188             next = this->next;
189             free(this);
190         }
191     }
192     return NULL;
193 }
194
195 char *
196 AddCommonInfo(CommonInfo * old, CommonInfo * new)
197 {
198     CommonInfo *first;
199
200     first = old;
201     while (old && old->next)
202     {
203         old = old->next;
204     }
205     new->next = NULL;
206     if (old)
207     {
208         old->next = new;
209         return (char *) first;
210     }
211     return (char *) new;
212 }
213
214 /***====================================================================***/
215
216 /**
217  * Find the key with the given name and return its keycode in kc_rtrn.
218  *
219  * @param keymap The keymap to search in.
220  * @param name The 4-letter name of the key as a long.
221  * @param kc_rtrn Set to the keycode if the key was found, otherwise 0.
222  * @param use_aliases true if the key aliases should be searched too.
223  * @param create If true and the key is not found, it is added to the
224  *        keymap->names at the first free keycode.
225  * @param start_from Keycode to start searching from.
226  *
227  * @return true if found, false otherwise.
228  */
229 bool
230 FindNamedKey(struct xkb_keymap *keymap, unsigned long name,
231              xkb_keycode_t *kc_rtrn, bool use_aliases, bool create,
232              xkb_keycode_t start_from)
233 {
234     unsigned n;
235
236     if (start_from < keymap->min_key_code)
237     {
238         start_from = keymap->min_key_code;
239     }
240     else if (start_from > keymap->max_key_code)
241     {
242         return false;
243     }
244
245     *kc_rtrn = 0;               /* some callers rely on this */
246     if (keymap && keymap->names && keymap->names->keys)
247     {
248         for (n = start_from; n <= keymap->max_key_code; n++)
249         {
250             unsigned long tmp;
251             tmp = KeyNameToLong(keymap->names->keys[n].name);
252             if (tmp == name)
253             {
254                 *kc_rtrn = n;
255                 return true;
256             }
257         }
258         if (use_aliases)
259         {
260             unsigned long new_name;
261             if (FindKeyNameForAlias(keymap, name, &new_name))
262                 return FindNamedKey(keymap, new_name, kc_rtrn, false,
263                                     create, 0);
264         }
265     }
266     if (create)
267     {
268         if ((!keymap->names) || (!keymap->names->keys))
269         {
270             if (XkbcAllocNames(keymap, XkbKeyNamesMask, 0) != Success)
271             {
272                 if (warningLevel > 0)
273                 {
274                     WARN("Couldn't allocate key names in FindNamedKey\n");
275                     ACTION("Key \"%s\" not automatically created\n",
276                             longText(name));
277                 }
278                 return false;
279             }
280         }
281         /* Find first unused keycode and store our key here */
282         for (n = keymap->min_key_code; n <= keymap->max_key_code; n++)
283         {
284             if (keymap->names->keys[n].name[0] == '\0')
285             {
286                 char buf[XkbKeyNameLength + 1];
287                 LongToKeyName(name, buf);
288                 memcpy(keymap->names->keys[n].name, buf, XkbKeyNameLength);
289                 *kc_rtrn = n;
290                 return true;
291             }
292         }
293     }
294     return false;
295 }
296
297 bool
298 FindKeyNameForAlias(struct xkb_keymap *keymap, unsigned long lname,
299                     unsigned long *real_name)
300 {
301     unsigned int i;
302     char name[XkbKeyNameLength + 1];
303
304     if (keymap && keymap->names && keymap->names->key_aliases)
305     {
306         struct xkb_key_alias * a;
307         a = keymap->names->key_aliases;
308         LongToKeyName(lname, name);
309         name[XkbKeyNameLength] = '\0';
310         for (i = 0; i < keymap->names->num_key_aliases; i++, a++)
311         {
312             if (strncmp(name, a->alias, XkbKeyNameLength) == 0)
313             {
314                 *real_name = KeyNameToLong(a->real);
315                 return true;
316             }
317         }
318     }
319     return false;
320 }