xkbcomp should not try to build into a pure wayland platform.
[platform/upstream/xkbcomp.git] / 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 "xkbpath.h"
29 #include "tokens.h"
30 #include "keycodes.h"
31 #include "misc.h"
32 #include <X11/keysym.h>
33 #include "parseutils.h"
34
35 #include <X11/extensions/XKBgeom.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             ERROR2("Can't find file \"%s\" for %s include\n", stmt->file,
70                    XkbDirectoryForInclude(file_type));
71             ACTION("Exiting\n");
72             return False;
73         }
74         strcpy(oldFile, scanFile);
75         oldLine = lineNum;
76         setScanState(stmt->file, 1);
77         if (debugFlags & 2)
78             INFO1("About to parse include file %s\n", stmt->file);
79         /* parse the file */
80         if ((XKBParseFile(file, &rtrn) == 0) || (rtrn == NULL))
81         {
82             setScanState(oldFile, oldLine);
83             ERROR1("Error interpreting include file \"%s\"\n", stmt->file);
84             ACTION("Exiting\n");
85             fclose(file);
86             return False;
87         }
88         fclose(file);
89         XkbAddFileToCache(stmt->file, file_type, stmt->path, rtrn);
90     }
91     mapToUse = rtrn;
92     if (stmt->map != NULL)
93     {
94         while ((mapToUse) && ((!uStringEqual(mapToUse->name, stmt->map)) ||
95                               (mapToUse->type != file_type)))
96         {
97             mapToUse = (XkbFile *) mapToUse->common.next;
98         }
99         if (!mapToUse)
100         {
101             ERROR3("No %s named \"%s\" in the include file \"%s\"\n",
102                    XkbConfigText(file_type, XkbMessage), stmt->map,
103                    stmt->file);
104             ACTION("Exiting\n");
105             return False;
106         }
107     }
108     else if ((rtrn->common.next != NULL) && (warningLevel > 5))
109     {
110         WARN1("No map in include statement, but \"%s\" contains several\n",
111               stmt->file);
112         ACTION1("Using first defined map, \"%s\"\n", rtrn->name);
113     }
114     setScanState(oldFile, oldLine);
115     if (mapToUse->type != file_type)
116     {
117         ERROR2("Include file wrong type (expected %s, got %s)\n",
118                XkbConfigText(file_type, XkbMessage),
119                XkbConfigText(mapToUse->type, XkbMessage));
120         ACTION1("Include file \"%s\" ignored\n", stmt->file);
121         return False;
122     }
123     /* FIXME: we have to check recursive includes here (or somewhere) */
124
125     mapToUse->compiled = True;
126     *file_rtrn = mapToUse;
127     *merge_rtrn = stmt->merge;
128     return True;
129 }
130
131 /***====================================================================***/
132
133 int
134 ReportNotArray(const char *type, const char *field, const char *name)
135 {
136     ERROR2("The %s %s field is not an array\n", type, field);
137     ACTION1("Ignoring illegal assignment in %s\n", name);
138     return False;
139 }
140
141 int
142 ReportShouldBeArray(const char *type, const char *field, char *name)
143 {
144     ERROR2("Missing subscript for %s %s\n", type, field);
145     ACTION1("Ignoring illegal assignment in %s\n", name);
146     return False;
147 }
148
149 int
150 ReportBadType(const char *type, const char *field,
151               const char *name, const char *wanted)
152 {
153     ERROR3("The %s %s field must be a %s\n", type, field, wanted);
154     ACTION1("Ignoring illegal assignment in %s\n", name);
155     return False;
156 }
157
158 int
159 ReportBadIndexType(char *type, char *field, char *name, char *wanted)
160 {
161     ERROR3("Index for the %s %s field must be a %s\n", type, field, wanted);
162     ACTION1("Ignoring assignment to illegal field in %s\n", name);
163     return False;
164 }
165
166 int
167 ReportBadField(const char *type, const char *field, const char *name)
168 {
169     ERROR3("Unknown %s field %s in %s\n", type, field, name);
170     ACTION1("Ignoring assignment to unknown field in %s\n", name);
171     return False;
172 }
173
174 int
175 ReportMultipleDefs(char *type, char *field, char *name)
176 {
177     WARN3("Multiple definitions of %s in %s \"%s\"\n", field, type, name);
178     ACTION("Using last definition\n");
179     return False;
180 }
181
182 /***====================================================================***/
183
184 Bool
185 UseNewField(unsigned field,
186             CommonInfo * oldDefs, CommonInfo * newDefs, unsigned *pCollide)
187 {
188     Bool useNew;
189
190     useNew = False;
191     if (oldDefs->defined & field)
192     {
193         if (newDefs->defined & field)
194         {
195             if (((oldDefs->fileID == newDefs->fileID)
196                  && (warningLevel > 0)) || (warningLevel > 9))
197             {
198                 *pCollide |= field;
199             }
200             if (newDefs->merge != MergeAugment)
201                 useNew = True;
202         }
203     }
204     else if (newDefs->defined & field)
205         useNew = True;
206     return useNew;
207 }
208
209 Bool
210 MergeNewField(unsigned field,
211               CommonInfo * oldDefs, CommonInfo * newDefs, unsigned *pCollide)
212 {
213     if ((oldDefs->defined & field) && (newDefs->defined & field))
214     {
215         if (((oldDefs->fileID == newDefs->fileID) && (warningLevel > 0)) ||
216             (warningLevel > 9))
217         {
218             *pCollide |= field;
219         }
220         if (newDefs->merge == MergeAugment)
221             return True;
222     }
223     return False;
224 }
225
226 XPointer
227 ClearCommonInfo(CommonInfo * cmn)
228 {
229     if (cmn != NULL)
230     {
231         CommonInfo *this, *next;
232         for (this = cmn; this != NULL; this = next)
233         {
234             next = this->next;
235             uFree(this);
236         }
237     }
238     return NULL;
239 }
240
241 XPointer
242 AddCommonInfo(CommonInfo * old, CommonInfo * new)
243 {
244     CommonInfo *first;
245
246     first = old;
247     while (old && old->next)
248     {
249         old = old->next;
250     }
251     new->next = NULL;
252     if (old)
253     {
254         old->next = new;
255         return (XPointer) first;
256     }
257     return (XPointer) new;
258 }
259
260 /***====================================================================***/
261
262 typedef struct _KeyNameDesc
263 {
264     KeySym level1;
265     KeySym level2;
266     char name[5];
267     Bool used;
268 } KeyNameDesc;
269
270 static KeyNameDesc dfltKeys[] = {
271     {XK_Escape, NoSymbol, "ESC\0"},
272     {XK_quoteleft, XK_asciitilde, "TLDE"},
273     {XK_1, XK_exclam, "AE01"},
274     {XK_2, XK_at, "AE02"},
275     {XK_3, XK_numbersign, "AE03"},
276     {XK_4, XK_dollar, "AE04"},
277     {XK_5, XK_percent, "AE05"},
278     {XK_6, XK_asciicircum, "AE06"},
279     {XK_7, XK_ampersand, "AE07"},
280     {XK_8, XK_asterisk, "AE08"},
281     {XK_9, XK_parenleft, "AE09"},
282     {XK_0, XK_parenright, "AE10"},
283     {XK_minus, XK_underscore, "AE11"},
284     {XK_equal, XK_plus, "AE12"},
285     {XK_BackSpace, NoSymbol, "BKSP"},
286     {XK_Tab, NoSymbol, "TAB\0"},
287     {XK_q, XK_Q, "AD01"},
288     {XK_w, XK_W, "AD02"},
289     {XK_e, XK_E, "AD03"},
290     {XK_r, XK_R, "AD04"},
291     {XK_t, XK_T, "AD05"},
292     {XK_y, XK_Y, "AD06"},
293     {XK_u, XK_U, "AD07"},
294     {XK_i, XK_I, "AD08"},
295     {XK_o, XK_O, "AD09"},
296     {XK_p, XK_P, "AD10"},
297     {XK_bracketleft, XK_braceleft, "AD11"},
298     {XK_bracketright, XK_braceright, "AD12"},
299     {XK_Return, NoSymbol, "RTRN"},
300     {XK_Caps_Lock, NoSymbol, "CAPS"},
301     {XK_a, XK_A, "AC01"},
302     {XK_s, XK_S, "AC02"},
303     {XK_d, XK_D, "AC03"},
304     {XK_f, XK_F, "AC04"},
305     {XK_g, XK_G, "AC05"},
306     {XK_h, XK_H, "AC06"},
307     {XK_j, XK_J, "AC07"},
308     {XK_k, XK_K, "AC08"},
309     {XK_l, XK_L, "AC09"},
310     {XK_semicolon, XK_colon, "AC10"},
311     {XK_quoteright, XK_quotedbl, "AC11"},
312     {XK_Shift_L, NoSymbol, "LFSH"},
313     {XK_z, XK_Z, "AB01"},
314     {XK_x, XK_X, "AB02"},
315     {XK_c, XK_C, "AB03"},
316     {XK_v, XK_V, "AB04"},
317     {XK_b, XK_B, "AB05"},
318     {XK_n, XK_N, "AB06"},
319     {XK_m, XK_M, "AB07"},
320     {XK_comma, XK_less, "AB08"},
321     {XK_period, XK_greater, "AB09"},
322     {XK_slash, XK_question, "AB10"},
323     {XK_backslash, XK_bar, "BKSL"},
324     {XK_Control_L, NoSymbol, "LCTL"},
325     {XK_space, NoSymbol, "SPCE"},
326     {XK_Shift_R, NoSymbol, "RTSH"},
327     {XK_Alt_L, NoSymbol, "LALT"},
328     {XK_space, NoSymbol, "SPCE"},
329     {XK_Control_R, NoSymbol, "RCTL"},
330     {XK_Alt_R, NoSymbol, "RALT"},
331     {XK_F1, NoSymbol, "FK01"},
332     {XK_F2, NoSymbol, "FK02"},
333     {XK_F3, NoSymbol, "FK03"},
334     {XK_F4, NoSymbol, "FK04"},
335     {XK_F5, NoSymbol, "FK05"},
336     {XK_F6, NoSymbol, "FK06"},
337     {XK_F7, NoSymbol, "FK07"},
338     {XK_F8, NoSymbol, "FK08"},
339     {XK_F9, NoSymbol, "FK09"},
340     {XK_F10, NoSymbol, "FK10"},
341     {XK_F11, NoSymbol, "FK11"},
342     {XK_F12, NoSymbol, "FK12"},
343     {XK_Print, NoSymbol, "PRSC"},
344     {XK_Scroll_Lock, NoSymbol, "SCLK"},
345     {XK_Pause, NoSymbol, "PAUS"},
346     {XK_Insert, NoSymbol, "INS\0"},
347     {XK_Home, NoSymbol, "HOME"},
348     {XK_Prior, NoSymbol, "PGUP"},
349     {XK_Delete, NoSymbol, "DELE"},
350     {XK_End, NoSymbol, "END"},
351     {XK_Next, NoSymbol, "PGDN"},
352     {XK_Up, NoSymbol, "UP\0\0"},
353     {XK_Left, NoSymbol, "LEFT"},
354     {XK_Down, NoSymbol, "DOWN"},
355     {XK_Right, NoSymbol, "RGHT"},
356     {XK_Num_Lock, NoSymbol, "NMLK"},
357     {XK_KP_Divide, NoSymbol, "KPDV"},
358     {XK_KP_Multiply, NoSymbol, "KPMU"},
359     {XK_KP_Subtract, NoSymbol, "KPSU"},
360     {NoSymbol, XK_KP_7, "KP7\0"},
361     {NoSymbol, XK_KP_8, "KP8\0"},
362     {NoSymbol, XK_KP_9, "KP9\0"},
363     {XK_KP_Add, NoSymbol, "KPAD"},
364     {NoSymbol, XK_KP_4, "KP4\0"},
365     {NoSymbol, XK_KP_5, "KP5\0"},
366     {NoSymbol, XK_KP_6, "KP6\0"},
367     {NoSymbol, XK_KP_1, "KP1\0"},
368     {NoSymbol, XK_KP_2, "KP2\0"},
369     {NoSymbol, XK_KP_3, "KP3\0"},
370     {XK_KP_Enter, NoSymbol, "KPEN"},
371     {NoSymbol, XK_KP_0, "KP0\0"},
372     {XK_KP_Delete, NoSymbol, "KPDL"},
373     {XK_less, XK_greater, "LSGT"},
374     {XK_KP_Separator, NoSymbol, "KPCO"},
375     {XK_Find, NoSymbol, "FIND"},
376     {NoSymbol, NoSymbol, "\0\0\0\0"}
377 };
378
379 Status
380 ComputeKbdDefaults(XkbDescPtr xkb)
381 {
382     Status rtrn;
383     register int i, tmp, nUnknown;
384     KeyNameDesc *name;
385     KeySym *syms;
386     char tmpname[XkbKeyNameLength + 1];
387
388     if ((xkb->names == NULL) || (xkb->names->keys == NULL))
389     {
390         if ((rtrn = XkbAllocNames(xkb, XkbKeyNamesMask, 0, 0)) != Success)
391             return rtrn;
392     }
393     for (name = dfltKeys; (name->name[0] != '\0'); name++)
394     {
395         name->used = False;
396     }
397     nUnknown = 0;
398     for (i = xkb->min_key_code; i <= xkb->max_key_code; i++)
399     {
400         tmp = XkbKeyNumSyms(xkb, i);
401         if ((xkb->names->keys[i].name[0] == '\0') && (tmp > 0))
402         {
403             tmp = XkbKeyGroupsWidth(xkb, i);
404             syms = XkbKeySymsPtr(xkb, i);
405             for (name = dfltKeys; (name->name[0] != '\0'); name++)
406             {
407                 Bool match = True;
408                 if (((name->level1 != syms[0])
409                      && (name->level1 != NoSymbol))
410                     || ((name->level2 != NoSymbol) && (tmp < 2))
411                     || ((name->level2 != syms[1])
412                         && (name->level2 != NoSymbol)))
413                 {
414                     match = False;
415                 }
416                 if (match)
417                 {
418                     if (!name->used)
419                     {
420                         memcpy(xkb->names->keys[i].name, name->name,
421                                XkbKeyNameLength);
422                         name->used = True;
423                     }
424                     else
425                     {
426                         if (warningLevel > 2)
427                         {
428                             WARN1
429                                 ("Several keys match pattern for %s\n",
430                                  XkbKeyNameText(name->name, XkbMessage));
431                             ACTION2("Using <U%03d> for key %d\n",
432                                     nUnknown, i);
433                         }
434                         snprintf(tmpname, sizeof(tmpname), "U%03d",
435                                  nUnknown++);
436                         memcpy(xkb->names->keys[i].name, tmpname,
437                                XkbKeyNameLength);
438                     }
439                     break;
440                 }
441             }
442             if (xkb->names->keys[i].name[0] == '\0')
443             {
444                 if (warningLevel > 2)
445                 {
446                     WARN1("Key %d does not match any defaults\n", i);
447                     ACTION1("Using name <U%03d>\n", nUnknown);
448                     snprintf(tmpname, sizeof(tmpname), "U%03d", nUnknown++);
449                     memcpy(xkb->names->keys[i].name, tmpname,
450                            XkbKeyNameLength);
451                 }
452             }
453         }
454     }
455     return Success;
456 }
457
458 /**
459  * Find the key with the given name and return its keycode in kc_rtrn.
460  *
461  * @param name The 4-letter name of the key as a long.
462  * @param kc_rtrn Set to the keycode if the key was found, otherwise 0.
463  * @param use_aliases True if the key aliases should be searched too.
464  * @param create If True and the key is not found, it is added to the
465  *        xkb->names at the first free keycode.
466  * @param start_from Keycode to start searching from.
467  *
468  * @return True if found, False otherwise.
469  */
470 Bool
471 FindNamedKey(XkbDescPtr xkb,
472              unsigned long name,
473              unsigned int *kc_rtrn,
474              Bool use_aliases, Bool create, int start_from)
475 {
476     register unsigned n;
477
478     if (start_from < xkb->min_key_code)
479     {
480         start_from = xkb->min_key_code;
481     }
482     else if (start_from > xkb->max_key_code)
483     {
484         return False;
485     }
486
487     *kc_rtrn = 0;               /* some callers rely on this */
488     if (xkb && xkb->names && xkb->names->keys)
489     {
490         for (n = start_from; n <= xkb->max_key_code; n++)
491         {
492             unsigned long tmp;
493             tmp = KeyNameToLong(xkb->names->keys[n].name);
494             if (tmp == name)
495             {
496                 *kc_rtrn = n;
497                 return True;
498             }
499         }
500         if (use_aliases)
501         {
502             unsigned long new_name;
503             if (FindKeyNameForAlias(xkb, name, &new_name))
504                 return FindNamedKey(xkb, new_name, kc_rtrn, False, create, 0);
505         }
506     }
507     if (create)
508     {
509         if ((!xkb->names) || (!xkb->names->keys))
510         {
511             if (xkb->min_key_code < XkbMinLegalKeyCode)
512             {
513                 xkb->min_key_code = XkbMinLegalKeyCode;
514                 xkb->max_key_code = XkbMaxLegalKeyCode;
515             }
516             if (XkbAllocNames(xkb, XkbKeyNamesMask, 0, 0) != Success)
517             {
518                 if (warningLevel > 0)
519                 {
520                     WARN("Couldn't allocate key names in FindNamedKey\n");
521                     ACTION1("Key \"%s\" not automatically created\n",
522                             longText(name, XkbMessage));
523                 }
524                 return False;
525             }
526         }
527         /* Find first unused keycode and store our key here */
528         for (n = xkb->min_key_code; n <= xkb->max_key_code; n++)
529         {
530             if (xkb->names->keys[n].name[0] == '\0')
531             {
532                 char buf[XkbKeyNameLength + 1];
533                 LongToKeyName(name, buf);
534                 memcpy(xkb->names->keys[n].name, buf, XkbKeyNameLength);
535                 *kc_rtrn = n;
536                 return True;
537             }
538         }
539     }
540     return False;
541 }
542
543 Bool
544 FindKeyNameForAlias(XkbDescPtr xkb, unsigned long lname,
545                     unsigned long *real_name)
546 {
547     register int i;
548     char name[XkbKeyNameLength + 1];
549
550     if (xkb && xkb->geom && xkb->geom->key_aliases)
551     {
552         XkbKeyAliasPtr a;
553         a = xkb->geom->key_aliases;
554         LongToKeyName(lname, name);
555         name[XkbKeyNameLength] = '\0';
556         for (i = 0; i < xkb->geom->num_key_aliases; i++, a++)
557         {
558             if (strncmp(name, a->alias, XkbKeyNameLength) == 0)
559             {
560                 *real_name = KeyNameToLong(a->real);
561                 return True;
562             }
563         }
564     }
565     if (xkb && xkb->names && xkb->names->key_aliases)
566     {
567         XkbKeyAliasPtr a;
568         a = xkb->names->key_aliases;
569         LongToKeyName(lname, name);
570         name[XkbKeyNameLength] = '\0';
571         for (i = 0; i < xkb->names->num_key_aliases; i++, a++)
572         {
573             if (strncmp(name, a->alias, XkbKeyNameLength) == 0)
574             {
575                 *real_name = KeyNameToLong(a->real);
576                 return True;
577             }
578         }
579     }
580     return False;
581 }