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/XKBgeomcommon.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 (char *) first;
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(XkbcDescPtr xkb)
383 register int i, tmp, nUnknown;
387 if ((xkb->names == NULL) || (xkb->names->keys == NULL))
389 if ((rtrn = XkbAllocNames(xkb, XkbKeyNamesMask, 0, 0)) != Success)
392 for (name = dfltKeys; (name->name[0] != '\0'); name++)
397 for (i = xkb->min_key_code; i <= xkb->max_key_code; i++)
399 tmp = XkbKeyNumSyms(xkb, i);
400 if ((xkb->names->keys[i].name[0] == '\0') && (tmp > 0))
402 tmp = XkbKeyGroupsWidth(xkb, i);
403 syms = XkbKeySymsPtr(xkb, i);
404 for (name = dfltKeys; (name->name[0] != '\0'); name++)
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)))
419 memcpy(xkb->names->keys[i].name, name->name,
425 if (warningLevel > 2)
428 ("Several keys match pattern for %s\n",
429 XkbKeyNameText(name->name, XkbMessage));
430 ACTION2("Using <U%03d> for key %d\n",
433 sprintf(xkb->names->keys[i].name, "U%03d",
439 if (xkb->names->keys[i].name[0] == '\0')
441 if (warningLevel > 2)
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++);
454 * Find the key with the given name and return its keycode in kc_rtrn.
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.
463 * @return True if found, False otherwise.
466 FindNamedKey(XkbcDescPtr xkb,
468 unsigned int *kc_rtrn,
469 Bool use_aliases, Bool create, int start_from)
473 if (start_from < xkb->min_key_code)
475 start_from = xkb->min_key_code;
477 else if (start_from > xkb->max_key_code)
482 *kc_rtrn = 0; /* some callers rely on this */
483 if (xkb && xkb->names && xkb->names->keys)
485 for (n = start_from; n <= xkb->max_key_code; n++)
488 tmp = KeyNameToLong(xkb->names->keys[n].name);
497 unsigned long new_name;
498 if (FindKeyNameForAlias(xkb, name, &new_name))
499 return FindNamedKey(xkb, new_name, kc_rtrn, False, create, 0);
504 if ((!xkb->names) || (!xkb->names->keys))
506 if (xkb->min_key_code < XkbMinLegalKeyCode)
508 xkb->min_key_code = XkbMinLegalKeyCode;
509 xkb->max_key_code = XkbMaxLegalKeyCode;
511 if (XkbAllocNames(xkb, XkbKeyNamesMask, 0, 0) != Success)
513 if (warningLevel > 0)
515 WARN("Couldn't allocate key names in FindNamedKey\n");
516 ACTION1("Key \"%s\" not automatically created\n",
517 longText(name, XkbMessage));
522 /* Find first unused keycode and store our key here */
523 for (n = xkb->min_key_code; n <= xkb->max_key_code; n++)
525 if (xkb->names->keys[n].name[0] == '\0')
527 char buf[XkbKeyNameLength + 1];
528 LongToKeyName(name, buf);
529 memcpy(xkb->names->keys[n].name, buf, XkbKeyNameLength);
539 FindKeyNameForAlias(XkbcDescPtr xkb, unsigned long lname,
540 unsigned long *real_name)
543 char name[XkbKeyNameLength + 1];
545 if (xkb && xkb->geom && xkb->geom->key_aliases)
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++)
553 if (strncmp(name, a->alias, XkbKeyNameLength) == 0)
555 *real_name = KeyNameToLong(a->real);
560 if (xkb && xkb->names && xkb->names->key_aliases)
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++)
568 if (strncmp(name, a->alias, XkbKeyNameLength) == 0)
570 *real_name = KeyNameToLong(a->real);
579 XkbConfigText(unsigned config, unsigned format)
582 case XkmSemanticsFile:
588 case XkmGeometryFile:
589 case XkmGeometryIndex:
593 case XkmCompatMapIndex:
595 case XkmSymbolsIndex:
597 case XkmIndicatorsIndex:
599 case XkmKeyNamesIndex:
601 case XkmVirtualModsIndex:
602 return "VirtualMods";
608 static char *actionTypeNames[XkbSA_NumActions]= {
610 "SetMods", "LatchMods", "LockMods",
611 "SetGroup", "LatchGroup", "LockGroup",
613 "PtrBtn", "LockPtrBtn",
616 "Terminate", "SwitchScreen",
617 "SetControls", "LockControls",
620 "DeviceBtn", "LockDeviceBtn"
624 XkbActionTypeText(unsigned type, unsigned format)
627 if (type <= XkbSA_LastAction)
628 return actionTypeNames[type];