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