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