b26c9fa800dca8d991ec3a138aa08b542670cd75
[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 "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/XKBgeomcommon.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 char *
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 char *
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 (char *) first;
256     }
257     return (char *) 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(XkbcDescPtr xkb)
381 {
382     Status rtrn;
383     register int i, tmp, nUnknown;
384     KeyNameDesc *name;
385     KeySym *syms;
386
387     if ((xkb->names == NULL) || (xkb->names->keys == NULL))
388     {
389         if ((rtrn = XkbAllocNames(xkb, XkbKeyNamesMask, 0, 0)) != Success)
390             return rtrn;
391     }
392     for (name = dfltKeys; (name->name[0] != '\0'); name++)
393     {
394         name->used = False;
395     }
396     nUnknown = 0;
397     for (i = xkb->min_key_code; i <= xkb->max_key_code; i++)
398     {
399         tmp = XkbKeyNumSyms(xkb, i);
400         if ((xkb->names->keys[i].name[0] == '\0') && (tmp > 0))
401         {
402             tmp = XkbKeyGroupsWidth(xkb, i);
403             syms = XkbKeySymsPtr(xkb, i);
404             for (name = dfltKeys; (name->name[0] != '\0'); name++)
405             {
406                 Bool match = True;
407                 if (((name->level1 != syms[0])
408                      && (name->level1 != NoSymbol))
409                     || ((name->level2 != NoSymbol) && (tmp < 2))
410                     || ((name->level2 != syms[1])
411                         && (name->level2 != NoSymbol)))
412                 {
413                     match = False;
414                 }
415                 if (match)
416                 {
417                     if (!name->used)
418                     {
419                         memcpy(xkb->names->keys[i].name, name->name,
420                                XkbKeyNameLength);
421                         name->used = True;
422                     }
423                     else
424                     {
425                         if (warningLevel > 2)
426                         {
427                             WARN1
428                                 ("Several keys match pattern for %s\n",
429                                  XkbKeyNameText(name->name, XkbMessage));
430                             ACTION2("Using <U%03d> for key %d\n",
431                                     nUnknown, i);
432                         }
433                         sprintf(xkb->names->keys[i].name, "U%03d",
434                                 nUnknown++);
435                     }
436                     break;
437                 }
438             }
439             if (xkb->names->keys[i].name[0] == '\0')
440             {
441                 if (warningLevel > 2)
442                 {
443                     WARN1("Key %d does not match any defaults\n", i);
444                     ACTION1("Using name <U%03d>\n", nUnknown);
445                     sprintf(xkb->names->keys[i].name, "U%03d", nUnknown++);
446                 }
447             }
448         }
449     }
450     return Success;
451 }
452
453 /**
454  * Find the key with the given name and return its keycode in kc_rtrn.
455  *
456  * @param name The 4-letter name of the key as a long.
457  * @param kc_rtrn Set to the keycode if the key was found, otherwise 0.
458  * @param use_aliases True if the key aliases should be searched too.
459  * @param create If True and the key is not found, it is added to the
460  *        xkb->names at the first free keycode.
461  * @param start_from Keycode to start searching from.
462  *
463  * @return True if found, False otherwise.
464  */
465 Bool
466 FindNamedKey(XkbcDescPtr xkb,
467              unsigned long name,
468              unsigned int *kc_rtrn,
469              Bool use_aliases, Bool create, int start_from)
470 {
471     register unsigned n;
472
473     if (start_from < xkb->min_key_code)
474     {
475         start_from = xkb->min_key_code;
476     }
477     else if (start_from > xkb->max_key_code)
478     {
479         return False;
480     }
481
482     *kc_rtrn = 0;               /* some callers rely on this */
483     if (xkb && xkb->names && xkb->names->keys)
484     {
485         for (n = start_from; n <= xkb->max_key_code; n++)
486         {
487             unsigned long tmp;
488             tmp = KeyNameToLong(xkb->names->keys[n].name);
489             if (tmp == name)
490             {
491                 *kc_rtrn = n;
492                 return True;
493             }
494         }
495         if (use_aliases)
496         {
497             unsigned long new_name;
498             if (FindKeyNameForAlias(xkb, name, &new_name))
499                 return FindNamedKey(xkb, new_name, kc_rtrn, False, create, 0);
500         }
501     }
502     if (create)
503     {
504         if ((!xkb->names) || (!xkb->names->keys))
505         {
506             if (xkb->min_key_code < XkbMinLegalKeyCode)
507             {
508                 xkb->min_key_code = XkbMinLegalKeyCode;
509                 xkb->max_key_code = XkbMaxLegalKeyCode;
510             }
511             if (XkbAllocNames(xkb, XkbKeyNamesMask, 0, 0) != Success)
512             {
513                 if (warningLevel > 0)
514                 {
515                     WARN("Couldn't allocate key names in FindNamedKey\n");
516                     ACTION1("Key \"%s\" not automatically created\n",
517                             longText(name, XkbMessage));
518                 }
519                 return False;
520             }
521         }
522         /* Find first unused keycode and store our key here */
523         for (n = xkb->min_key_code; n <= xkb->max_key_code; n++)
524         {
525             if (xkb->names->keys[n].name[0] == '\0')
526             {
527                 char buf[XkbKeyNameLength + 1];
528                 LongToKeyName(name, buf);
529                 memcpy(xkb->names->keys[n].name, buf, XkbKeyNameLength);
530                 *kc_rtrn = n;
531                 return True;
532             }
533         }
534     }
535     return False;
536 }
537
538 Bool
539 FindKeyNameForAlias(XkbcDescPtr xkb, unsigned long lname,
540                     unsigned long *real_name)
541 {
542     register int i;
543     char name[XkbKeyNameLength + 1];
544
545     if (xkb && xkb->geom && xkb->geom->key_aliases)
546     {
547         XkbKeyAliasPtr a;
548         a = xkb->geom->key_aliases;
549         LongToKeyName(lname, name);
550         name[XkbKeyNameLength] = '\0';
551         for (i = 0; i < xkb->geom->num_key_aliases; i++, a++)
552         {
553             if (strncmp(name, a->alias, XkbKeyNameLength) == 0)
554             {
555                 *real_name = KeyNameToLong(a->real);
556                 return True;
557             }
558         }
559     }
560     if (xkb && xkb->names && xkb->names->key_aliases)
561     {
562         XkbKeyAliasPtr a;
563         a = xkb->names->key_aliases;
564         LongToKeyName(lname, name);
565         name[XkbKeyNameLength] = '\0';
566         for (i = 0; i < xkb->names->num_key_aliases; i++, a++)
567         {
568             if (strncmp(name, a->alias, XkbKeyNameLength) == 0)
569             {
570                 *real_name = KeyNameToLong(a->real);
571                 return True;
572             }
573         }
574     }
575     return False;
576 }
577
578 char *
579 XkbConfigText(unsigned config, unsigned format)
580 {
581     switch (config) {
582     case XkmSemanticsFile:
583         return "Semantics";
584     case XkmLayoutFile:
585         return "Layout";
586     case XkmKeymapFile:
587         return "Keymap";
588     case XkmGeometryFile:
589     case XkmGeometryIndex:
590         return "Geometry";
591     case XkmTypesIndex:
592         return "Types";
593     case XkmCompatMapIndex:
594         return "CompatMap";
595     case XkmSymbolsIndex:
596         return "Symbols";
597     case XkmIndicatorsIndex:
598         return "Indicators";
599     case XkmKeyNamesIndex:
600         return "KeyNames";
601     case XkmVirtualModsIndex:
602         return "VirtualMods";
603     default:
604         return "unknown";
605     }
606 }
607
608 static char *actionTypeNames[XkbSA_NumActions]= {
609     "NoAction",
610     "SetMods",      "LatchMods",    "LockMods",
611     "SetGroup",     "LatchGroup",   "LockGroup",
612     "MovePtr",
613     "PtrBtn",       "LockPtrBtn",
614     "SetPtrDflt",
615     "ISOLock",
616     "Terminate",    "SwitchScreen",
617     "SetControls",  "LockControls",
618     "ActionMessage",
619     "RedirectKey",
620     "DeviceBtn",    "LockDeviceBtn"
621 };
622
623 char *
624 XkbActionTypeText(unsigned type, unsigned format)
625 {
626
627     if (type <= XkbSA_LastAction)
628         return actionTypeNames[type];
629     return "Private";
630 }