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