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), stmt->map, stmt->file);
107 else if ((rtrn->common.next != NULL) && (warningLevel > 5))
109 WARN1("No map in include statement, but \"%s\" contains several\n",
111 ACTION1("Using first defined map, \"%s\"\n", rtrn->name);
113 setScanState(oldFile, oldLine);
114 if (mapToUse->type != file_type)
116 ERROR2("Include file wrong type (expected %s, got %s)\n",
117 XkbConfigText(file_type), XkbConfigText(mapToUse->type));
118 ACTION1("Include file \"%s\" ignored\n", stmt->file);
121 /* FIXME: we have to check recursive includes here (or somewhere) */
123 mapToUse->compiled = True;
124 *file_rtrn = mapToUse;
125 *merge_rtrn = stmt->merge;
129 /***====================================================================***/
132 ReportNotArray(const char *type, const char *field, const char *name)
134 ERROR2("The %s %s field is not an array\n", type, field);
135 ACTION1("Ignoring illegal assignment in %s\n", name);
140 ReportShouldBeArray(const char *type, const char *field, char *name)
142 ERROR2("Missing subscript for %s %s\n", type, field);
143 ACTION1("Ignoring illegal assignment in %s\n", name);
148 ReportBadType(const char *type, const char *field,
149 const char *name, const char *wanted)
151 ERROR3("The %s %s field must be a %s\n", type, field, wanted);
152 ACTION1("Ignoring illegal assignment in %s\n", name);
157 ReportBadIndexType(char *type, char *field, char *name, char *wanted)
159 ERROR3("Index for the %s %s field must be a %s\n", type, field, wanted);
160 ACTION1("Ignoring assignment to illegal field in %s\n", name);
165 ReportBadField(const char *type, const char *field, const char *name)
167 ERROR3("Unknown %s field %s in %s\n", type, field, name);
168 ACTION1("Ignoring assignment to unknown field in %s\n", name);
173 ReportMultipleDefs(char *type, char *field, char *name)
175 WARN3("Multiple definitions of %s in %s \"%s\"\n", field, type, name);
176 ACTION("Using last definition\n");
180 /***====================================================================***/
183 UseNewField(unsigned field,
184 CommonInfo * oldDefs, CommonInfo * newDefs, unsigned *pCollide)
189 if (oldDefs->defined & field)
191 if (newDefs->defined & field)
193 if (((oldDefs->fileID == newDefs->fileID)
194 && (warningLevel > 0)) || (warningLevel > 9))
198 if (newDefs->merge != MergeAugment)
202 else if (newDefs->defined & field)
208 MergeNewField(unsigned field,
209 CommonInfo * oldDefs, CommonInfo * newDefs, unsigned *pCollide)
211 if ((oldDefs->defined & field) && (newDefs->defined & field))
213 if (((oldDefs->fileID == newDefs->fileID) && (warningLevel > 0)) ||
218 if (newDefs->merge == MergeAugment)
225 ClearCommonInfo(CommonInfo * cmn)
229 CommonInfo *this, *next;
230 for (this = cmn; this != NULL; this = next)
240 AddCommonInfo(CommonInfo * old, CommonInfo * new)
245 while (old && old->next)
253 return (char *) first;
258 /***====================================================================***/
260 typedef struct _KeyNameDesc
268 static KeyNameDesc dfltKeys[] = {
269 {XK_Escape, NoSymbol, "ESC\0"},
270 {XK_quoteleft, XK_asciitilde, "TLDE"},
271 {XK_1, XK_exclam, "AE01"},
272 {XK_2, XK_at, "AE02"},
273 {XK_3, XK_numbersign, "AE03"},
274 {XK_4, XK_dollar, "AE04"},
275 {XK_5, XK_percent, "AE05"},
276 {XK_6, XK_asciicircum, "AE06"},
277 {XK_7, XK_ampersand, "AE07"},
278 {XK_8, XK_asterisk, "AE08"},
279 {XK_9, XK_parenleft, "AE09"},
280 {XK_0, XK_parenright, "AE10"},
281 {XK_minus, XK_underscore, "AE11"},
282 {XK_equal, XK_plus, "AE12"},
283 {XK_BackSpace, NoSymbol, "BKSP"},
284 {XK_Tab, NoSymbol, "TAB\0"},
285 {XK_q, XK_Q, "AD01"},
286 {XK_w, XK_W, "AD02"},
287 {XK_e, XK_E, "AD03"},
288 {XK_r, XK_R, "AD04"},
289 {XK_t, XK_T, "AD05"},
290 {XK_y, XK_Y, "AD06"},
291 {XK_u, XK_U, "AD07"},
292 {XK_i, XK_I, "AD08"},
293 {XK_o, XK_O, "AD09"},
294 {XK_p, XK_P, "AD10"},
295 {XK_bracketleft, XK_braceleft, "AD11"},
296 {XK_bracketright, XK_braceright, "AD12"},
297 {XK_Return, NoSymbol, "RTRN"},
298 {XK_Caps_Lock, NoSymbol, "CAPS"},
299 {XK_a, XK_A, "AC01"},
300 {XK_s, XK_S, "AC02"},
301 {XK_d, XK_D, "AC03"},
302 {XK_f, XK_F, "AC04"},
303 {XK_g, XK_G, "AC05"},
304 {XK_h, XK_H, "AC06"},
305 {XK_j, XK_J, "AC07"},
306 {XK_k, XK_K, "AC08"},
307 {XK_l, XK_L, "AC09"},
308 {XK_semicolon, XK_colon, "AC10"},
309 {XK_quoteright, XK_quotedbl, "AC11"},
310 {XK_Shift_L, NoSymbol, "LFSH"},
311 {XK_z, XK_Z, "AB01"},
312 {XK_x, XK_X, "AB02"},
313 {XK_c, XK_C, "AB03"},
314 {XK_v, XK_V, "AB04"},
315 {XK_b, XK_B, "AB05"},
316 {XK_n, XK_N, "AB06"},
317 {XK_m, XK_M, "AB07"},
318 {XK_comma, XK_less, "AB08"},
319 {XK_period, XK_greater, "AB09"},
320 {XK_slash, XK_question, "AB10"},
321 {XK_backslash, XK_bar, "BKSL"},
322 {XK_Control_L, NoSymbol, "LCTL"},
323 {XK_space, NoSymbol, "SPCE"},
324 {XK_Shift_R, NoSymbol, "RTSH"},
325 {XK_Alt_L, NoSymbol, "LALT"},
326 {XK_space, NoSymbol, "SPCE"},
327 {XK_Control_R, NoSymbol, "RCTL"},
328 {XK_Alt_R, NoSymbol, "RALT"},
329 {XK_F1, NoSymbol, "FK01"},
330 {XK_F2, NoSymbol, "FK02"},
331 {XK_F3, NoSymbol, "FK03"},
332 {XK_F4, NoSymbol, "FK04"},
333 {XK_F5, NoSymbol, "FK05"},
334 {XK_F6, NoSymbol, "FK06"},
335 {XK_F7, NoSymbol, "FK07"},
336 {XK_F8, NoSymbol, "FK08"},
337 {XK_F9, NoSymbol, "FK09"},
338 {XK_F10, NoSymbol, "FK10"},
339 {XK_F11, NoSymbol, "FK11"},
340 {XK_F12, NoSymbol, "FK12"},
341 {XK_Print, NoSymbol, "PRSC"},
342 {XK_Scroll_Lock, NoSymbol, "SCLK"},
343 {XK_Pause, NoSymbol, "PAUS"},
344 {XK_Insert, NoSymbol, "INS\0"},
345 {XK_Home, NoSymbol, "HOME"},
346 {XK_Prior, NoSymbol, "PGUP"},
347 {XK_Delete, NoSymbol, "DELE"},
348 {XK_End, NoSymbol, "END"},
349 {XK_Next, NoSymbol, "PGDN"},
350 {XK_Up, NoSymbol, "UP\0\0"},
351 {XK_Left, NoSymbol, "LEFT"},
352 {XK_Down, NoSymbol, "DOWN"},
353 {XK_Right, NoSymbol, "RGHT"},
354 {XK_Num_Lock, NoSymbol, "NMLK"},
355 {XK_KP_Divide, NoSymbol, "KPDV"},
356 {XK_KP_Multiply, NoSymbol, "KPMU"},
357 {XK_KP_Subtract, NoSymbol, "KPSU"},
358 {NoSymbol, XK_KP_7, "KP7\0"},
359 {NoSymbol, XK_KP_8, "KP8\0"},
360 {NoSymbol, XK_KP_9, "KP9\0"},
361 {XK_KP_Add, NoSymbol, "KPAD"},
362 {NoSymbol, XK_KP_4, "KP4\0"},
363 {NoSymbol, XK_KP_5, "KP5\0"},
364 {NoSymbol, XK_KP_6, "KP6\0"},
365 {NoSymbol, XK_KP_1, "KP1\0"},
366 {NoSymbol, XK_KP_2, "KP2\0"},
367 {NoSymbol, XK_KP_3, "KP3\0"},
368 {XK_KP_Enter, NoSymbol, "KPEN"},
369 {NoSymbol, XK_KP_0, "KP0\0"},
370 {XK_KP_Delete, NoSymbol, "KPDL"},
371 {XK_less, XK_greater, "LSGT"},
372 {XK_KP_Separator, NoSymbol, "KPCO"},
373 {XK_Find, NoSymbol, "FIND"},
374 {NoSymbol, NoSymbol, "\0\0\0\0"}
378 ComputeKbdDefaults(XkbcDescPtr xkb)
381 register int i, tmp, nUnknown;
385 if ((xkb->names == NULL) || (xkb->names->keys == NULL))
387 if ((rtrn = XkbAllocNames(xkb, XkbKeyNamesMask, 0, 0)) != Success)
390 for (name = dfltKeys; (name->name[0] != '\0'); name++)
395 for (i = xkb->min_key_code; i <= xkb->max_key_code; i++)
397 tmp = XkbKeyNumSyms(xkb, i);
398 if ((xkb->names->keys[i].name[0] == '\0') && (tmp > 0))
400 tmp = XkbKeyGroupsWidth(xkb, i);
401 syms = XkbKeySymsPtr(xkb, i);
402 for (name = dfltKeys; (name->name[0] != '\0'); name++)
405 if (((name->level1 != syms[0])
406 && (name->level1 != NoSymbol))
407 || ((name->level2 != NoSymbol) && (tmp < 2))
408 || ((name->level2 != syms[1])
409 && (name->level2 != NoSymbol)))
417 memcpy(xkb->names->keys[i].name, name->name,
423 if (warningLevel > 2)
426 ("Several keys match pattern for %s\n",
427 XkbKeyNameText(name->name, XkbMessage));
428 ACTION2("Using <U%03d> for key %d\n",
431 sprintf(xkb->names->keys[i].name, "U%03d",
437 if (xkb->names->keys[i].name[0] == '\0')
439 if (warningLevel > 2)
441 WARN1("Key %d does not match any defaults\n", i);
442 ACTION1("Using name <U%03d>\n", nUnknown);
443 sprintf(xkb->names->keys[i].name, "U%03d", nUnknown++);
452 * Find the key with the given name and return its keycode in kc_rtrn.
454 * @param name The 4-letter name of the key as a long.
455 * @param kc_rtrn Set to the keycode if the key was found, otherwise 0.
456 * @param use_aliases True if the key aliases should be searched too.
457 * @param create If True and the key is not found, it is added to the
458 * xkb->names at the first free keycode.
459 * @param start_from Keycode to start searching from.
461 * @return True if found, False otherwise.
464 FindNamedKey(XkbcDescPtr xkb,
466 unsigned int *kc_rtrn,
467 Bool use_aliases, Bool create, int start_from)
471 if (start_from < xkb->min_key_code)
473 start_from = xkb->min_key_code;
475 else if (start_from > xkb->max_key_code)
480 *kc_rtrn = 0; /* some callers rely on this */
481 if (xkb && xkb->names && xkb->names->keys)
483 for (n = start_from; n <= xkb->max_key_code; n++)
486 tmp = KeyNameToLong(xkb->names->keys[n].name);
495 unsigned long new_name;
496 if (FindKeyNameForAlias(xkb, name, &new_name))
497 return FindNamedKey(xkb, new_name, kc_rtrn, False, create, 0);
502 if ((!xkb->names) || (!xkb->names->keys))
504 if (xkb->min_key_code < XkbMinLegalKeyCode)
506 xkb->min_key_code = XkbMinLegalKeyCode;
507 xkb->max_key_code = XkbMaxLegalKeyCode;
509 if (XkbAllocNames(xkb, XkbKeyNamesMask, 0, 0) != Success)
511 if (warningLevel > 0)
513 WARN("Couldn't allocate key names in FindNamedKey\n");
514 ACTION1("Key \"%s\" not automatically created\n",
515 longText(name, XkbMessage));
520 /* Find first unused keycode and store our key here */
521 for (n = xkb->min_key_code; n <= xkb->max_key_code; n++)
523 if (xkb->names->keys[n].name[0] == '\0')
525 char buf[XkbKeyNameLength + 1];
526 LongToKeyName(name, buf);
527 memcpy(xkb->names->keys[n].name, buf, XkbKeyNameLength);
537 FindKeyNameForAlias(XkbcDescPtr xkb, unsigned long lname,
538 unsigned long *real_name)
541 char name[XkbKeyNameLength + 1];
543 if (xkb && xkb->geom && xkb->geom->key_aliases)
546 a = xkb->geom->key_aliases;
547 LongToKeyName(lname, name);
548 name[XkbKeyNameLength] = '\0';
549 for (i = 0; i < xkb->geom->num_key_aliases; i++, a++)
551 if (strncmp(name, a->alias, XkbKeyNameLength) == 0)
553 *real_name = KeyNameToLong(a->real);
558 if (xkb && xkb->names && xkb->names->key_aliases)
561 a = xkb->names->key_aliases;
562 LongToKeyName(lname, name);
563 name[XkbKeyNameLength] = '\0';
564 for (i = 0; i < xkb->names->num_key_aliases; i++, a++)
566 if (strncmp(name, a->alias, XkbKeyNameLength) == 0)
568 *real_name = KeyNameToLong(a->real);
577 XkbConfigText(unsigned config)
580 case XkmSemanticsFile:
586 case XkmGeometryFile:
587 case XkmGeometryIndex:
591 case XkmCompatMapIndex:
593 case XkmSymbolsIndex:
595 case XkmIndicatorsIndex:
597 case XkmKeyNamesIndex:
599 case XkmVirtualModsIndex:
600 return "VirtualMods";
606 static char *actionTypeNames[XkbSA_NumActions]= {
608 "SetMods", "LatchMods", "LockMods",
609 "SetGroup", "LatchGroup", "LockGroup",
611 "PtrBtn", "LockPtrBtn",
614 "Terminate", "SwitchScreen",
615 "SetControls", "LockControls",
618 "DeviceBtn", "LockDeviceBtn"
622 XkbActionTypeText(unsigned type)
625 if (type <= XkbSA_LastAction)
626 return actionTypeNames[type];