1 /************************************************************
2 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
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.
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.
25 ********************************************************/
32 #include <X11/keysym.h>
33 #include "parseutils.h"
35 #include <X11/extensions/XKBgeom.h>
37 /***====================================================================***/
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.
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.
49 * @return True on success or False otherwise.
52 ProcessIncludeFile(IncludeStmt * stmt,
54 XkbFile ** file_rtrn, unsigned *merge_rtrn)
57 XkbFile *rtrn, *mapToUse;
58 char oldFile[1024] = {0};
59 int oldLine = lineNum;
61 rtrn = XkbFindFileInCache(stmt->file, file_type, &stmt->path);
64 /* file not in cache, open it, parse it and store it in cache for next
66 file = XkbFindFileInPath(stmt->file, file_type, &stmt->path);
69 ERROR2("Can't find file \"%s\" for %s include\n", stmt->file,
70 XkbDirectoryForInclude(file_type));
74 strcpy(oldFile, scanFile);
76 setScanState(stmt->file, 1);
78 INFO1("About to parse include file %s\n", stmt->file);
80 if ((XKBParseFile(file, &rtrn) == 0) || (rtrn == NULL))
82 setScanState(oldFile, oldLine);
83 ERROR1("Error interpreting include file \"%s\"\n", stmt->file);
89 XkbAddFileToCache(stmt->file, file_type, stmt->path, rtrn);
92 if (stmt->map != NULL)
94 while ((mapToUse) && ((!uStringEqual(mapToUse->name, stmt->map)) ||
95 (mapToUse->type != file_type)))
97 mapToUse = (XkbFile *) mapToUse->common.next;
101 ERROR3("No %s named \"%s\" in the include file \"%s\"\n",
102 XkbConfigText(file_type, XkbMessage), stmt->map,
108 else if ((rtrn->common.next != NULL) && (warningLevel > 5))
110 WARN1("No map in include statement, but \"%s\" contains several\n",
112 ACTION1("Using first defined map, \"%s\"\n", rtrn->name);
114 setScanState(oldFile, oldLine);
115 if (mapToUse->type != file_type)
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);
123 /* FIXME: we have to check recursive includes here (or somewhere) */
125 mapToUse->compiled = True;
126 *file_rtrn = mapToUse;
127 *merge_rtrn = stmt->merge;
131 /***====================================================================***/
134 ReportNotArray(const char *type, const char *field, const char *name)
136 ERROR2("The %s %s field is not an array\n", type, field);
137 ACTION1("Ignoring illegal assignment in %s\n", name);
142 ReportShouldBeArray(const char *type, const char *field, char *name)
144 ERROR2("Missing subscript for %s %s\n", type, field);
145 ACTION1("Ignoring illegal assignment in %s\n", name);
150 ReportBadType(const char *type, const char *field,
151 const char *name, const char *wanted)
153 ERROR3("The %s %s field must be a %s\n", type, field, wanted);
154 ACTION1("Ignoring illegal assignment in %s\n", name);
159 ReportBadIndexType(char *type, char *field, char *name, char *wanted)
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);
167 ReportBadField(const char *type, const char *field, const char *name)
169 ERROR3("Unknown %s field %s in %s\n", type, field, name);
170 ACTION1("Ignoring assignment to unknown field in %s\n", name);
175 ReportMultipleDefs(char *type, char *field, char *name)
177 WARN3("Multiple definitions of %s in %s \"%s\"\n", field, type, name);
178 ACTION("Using last definition\n");
182 /***====================================================================***/
185 UseNewField(unsigned field,
186 CommonInfo * oldDefs, CommonInfo * newDefs, unsigned *pCollide)
191 if (oldDefs->defined & field)
193 if (newDefs->defined & field)
195 if (((oldDefs->fileID == newDefs->fileID)
196 && (warningLevel > 0)) || (warningLevel > 9))
200 if (newDefs->merge != MergeAugment)
204 else if (newDefs->defined & field)
210 MergeNewField(unsigned field,
211 CommonInfo * oldDefs, CommonInfo * newDefs, unsigned *pCollide)
213 if ((oldDefs->defined & field) && (newDefs->defined & field))
215 if (((oldDefs->fileID == newDefs->fileID) && (warningLevel > 0)) ||
220 if (newDefs->merge == MergeAugment)
227 ClearCommonInfo(CommonInfo * cmn)
231 CommonInfo *this, *next;
232 for (this = cmn; this != NULL; this = next)
242 AddCommonInfo(CommonInfo * old, CommonInfo * new)
247 while (old && old->next)
255 return (XPointer) first;
257 return (XPointer) new;
260 /***====================================================================***/
262 typedef struct _KeyNameDesc
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"}
380 ComputeKbdDefaults(XkbDescPtr xkb)
383 register int i, tmp, nUnknown;
386 char tmpname[XkbKeyNameLength + 1];
388 if ((xkb->names == NULL) || (xkb->names->keys == NULL))
390 if ((rtrn = XkbAllocNames(xkb, XkbKeyNamesMask, 0, 0)) != Success)
393 for (name = dfltKeys; (name->name[0] != '\0'); name++)
398 for (i = xkb->min_key_code; i <= xkb->max_key_code; i++)
400 tmp = XkbKeyNumSyms(xkb, i);
401 if ((xkb->names->keys[i].name[0] == '\0') && (tmp > 0))
403 tmp = XkbKeyGroupsWidth(xkb, i);
404 syms = XkbKeySymsPtr(xkb, i);
405 for (name = dfltKeys; (name->name[0] != '\0'); name++)
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)))
420 memcpy(xkb->names->keys[i].name, name->name,
426 if (warningLevel > 2)
429 ("Several keys match pattern for %s\n",
430 XkbKeyNameText(name->name, XkbMessage));
431 ACTION2("Using <U%03d> for key %d\n",
434 snprintf(tmpname, sizeof(tmpname), "U%03d",
436 memcpy(xkb->names->keys[i].name, tmpname,
442 if (xkb->names->keys[i].name[0] == '\0')
444 if (warningLevel > 2)
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,
459 * Find the key with the given name and return its keycode in kc_rtrn.
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.
468 * @return True if found, False otherwise.
471 FindNamedKey(XkbDescPtr xkb,
473 unsigned int *kc_rtrn,
474 Bool use_aliases, Bool create, int start_from)
478 if (start_from < xkb->min_key_code)
480 start_from = xkb->min_key_code;
482 else if (start_from > xkb->max_key_code)
487 *kc_rtrn = 0; /* some callers rely on this */
488 if (xkb && xkb->names && xkb->names->keys)
490 for (n = start_from; n <= xkb->max_key_code; n++)
493 tmp = KeyNameToLong(xkb->names->keys[n].name);
502 unsigned long new_name;
503 if (FindKeyNameForAlias(xkb, name, &new_name))
504 return FindNamedKey(xkb, new_name, kc_rtrn, False, create, 0);
509 if ((!xkb->names) || (!xkb->names->keys))
511 if (xkb->min_key_code < XkbMinLegalKeyCode)
513 xkb->min_key_code = XkbMinLegalKeyCode;
514 xkb->max_key_code = XkbMaxLegalKeyCode;
516 if (XkbAllocNames(xkb, XkbKeyNamesMask, 0, 0) != Success)
518 if (warningLevel > 0)
520 WARN("Couldn't allocate key names in FindNamedKey\n");
521 ACTION1("Key \"%s\" not automatically created\n",
522 longText(name, XkbMessage));
527 /* Find first unused keycode and store our key here */
528 for (n = xkb->min_key_code; n <= xkb->max_key_code; n++)
530 if (xkb->names->keys[n].name[0] == '\0')
532 char buf[XkbKeyNameLength + 1];
533 LongToKeyName(name, buf);
534 memcpy(xkb->names->keys[n].name, buf, XkbKeyNameLength);
544 FindKeyNameForAlias(XkbDescPtr xkb, unsigned long lname,
545 unsigned long *real_name)
548 char name[XkbKeyNameLength + 1];
550 if (xkb && xkb->geom && xkb->geom->key_aliases)
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++)
558 if (strncmp(name, a->alias, XkbKeyNameLength) == 0)
560 *real_name = KeyNameToLong(a->real);
565 if (xkb && xkb->names && xkb->names->key_aliases)
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++)
573 if (strncmp(name, a->alias, XkbKeyNameLength) == 0)
575 *real_name = KeyNameToLong(a->real);