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