1f46a6179Smrg/************************************************************ 2f46a6179Smrg Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 3f46a6179Smrg 4f46a6179Smrg Permission to use, copy, modify, and distribute this 5f46a6179Smrg software and its documentation for any purpose and without 6f46a6179Smrg fee is hereby granted, provided that the above copyright 7f46a6179Smrg notice appear in all copies and that both that copyright 8f46a6179Smrg notice and this permission notice appear in supporting 9bfe6082cSmrg documentation, and that the name of Silicon Graphics not be 10bfe6082cSmrg used in advertising or publicity pertaining to distribution 11f46a6179Smrg of the software without specific prior written permission. 12bfe6082cSmrg Silicon Graphics makes no representation about the suitability 13f46a6179Smrg of this software for any purpose. It is provided "as is" 14f46a6179Smrg without any express or implied warranty. 15bfe6082cSmrg 16bfe6082cSmrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17bfe6082cSmrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18f46a6179Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19bfe6082cSmrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20bfe6082cSmrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21bfe6082cSmrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22f46a6179Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23f46a6179Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE. 24f46a6179Smrg 25f46a6179Smrg ********************************************************/ 26f46a6179Smrg 27f46a6179Smrg#include "xkbcomp.h" 28f46a6179Smrg#include "xkbpath.h" 29f46a6179Smrg#include "tokens.h" 30f46a6179Smrg#include "keycodes.h" 31f46a6179Smrg#include "misc.h" 32f46a6179Smrg#include <X11/keysym.h> 33f46a6179Smrg#include "parseutils.h" 34f46a6179Smrg 35f46a6179Smrg#include <X11/extensions/XKBgeom.h> 36f46a6179Smrg 37f46a6179Smrg/***====================================================================***/ 38f46a6179Smrg 3934345a63Smrg/** 4034345a63Smrg * Open the file given in the include statement and parse it's content. 4134345a63Smrg * If the statement defines a specific map to use, this map is returned in 4234345a63Smrg * file_rtrn. Otherwise, the default map is returned. 4334345a63Smrg * 4434345a63Smrg * @param stmt The include statement, specifying the file name to look for. 4534345a63Smrg * @param file_type Type of file (XkmKeyNamesIdx, etc.) 4634345a63Smrg * @param file_rtrn Returns the key map to be used. 4734345a63Smrg * @param merge_rtrn Always returns stmt->merge. 4834345a63Smrg * 4934345a63Smrg * @return True on success or False otherwise. 5034345a63Smrg */ 51f46a6179SmrgBool 5234345a63SmrgProcessIncludeFile(IncludeStmt * stmt, 5334345a63Smrg unsigned file_type, 5434345a63Smrg XkbFile ** file_rtrn, unsigned *merge_rtrn) 55f46a6179Smrg{ 5634345a63Smrg XkbFile *rtrn, *mapToUse; 5734345a63Smrg char oldFile[1024] = {0}; 5834345a63Smrg int oldLine = lineNum; 5934345a63Smrg 6034345a63Smrg rtrn = XkbFindFileInCache(stmt->file, file_type, &stmt->path); 6134345a63Smrg if (rtrn == NULL) 6234345a63Smrg { 6334345a63Smrg /* file not in cache, open it, parse it and store it in cache for next 6434345a63Smrg time. */ 656930ead5Smrg FILE *file = XkbFindFileInPath(stmt->file, file_type, &stmt->path); 6634345a63Smrg if (file == NULL) 6734345a63Smrg { 68bfe6082cSmrg ERROR("Can't find file \"%s\" for %s include\n", stmt->file, 6934345a63Smrg XkbDirectoryForInclude(file_type)); 7034345a63Smrg ACTION("Exiting\n"); 7134345a63Smrg return False; 7234345a63Smrg } 7334345a63Smrg strcpy(oldFile, scanFile); 7434345a63Smrg oldLine = lineNum; 7534345a63Smrg setScanState(stmt->file, 1); 766930ead5Smrg#ifdef DEBUG 7734345a63Smrg if (debugFlags & 2) 78bfe6082cSmrg INFO("About to parse include file %s\n", stmt->file); 796930ead5Smrg#endif 8034345a63Smrg /* parse the file */ 8134345a63Smrg if ((XKBParseFile(file, &rtrn) == 0) || (rtrn == NULL)) 8234345a63Smrg { 8334345a63Smrg setScanState(oldFile, oldLine); 84bfe6082cSmrg ERROR("Error interpreting include file \"%s\"\n", stmt->file); 8534345a63Smrg ACTION("Exiting\n"); 8634345a63Smrg fclose(file); 8734345a63Smrg return False; 8834345a63Smrg } 8934345a63Smrg fclose(file); 9034345a63Smrg XkbAddFileToCache(stmt->file, file_type, stmt->path, rtrn); 91f46a6179Smrg } 92f757b1e9Smrg 93f757b1e9Smrg /* 94f757b1e9Smrg * A single file may contain several maps. Here's how we choose the map: 95f757b1e9Smrg * - If a specific map was requested, look for it exclusively. 96f757b1e9Smrg * - Otherwise, if the file only contains a single map, return it. 97f757b1e9Smrg * - Otherwise, if the file has maps tagged as default, return the 98f757b1e9Smrg * first one. 99f757b1e9Smrg * - If all fails, return the first map in the file. 100f757b1e9Smrg */ 10134345a63Smrg mapToUse = rtrn; 10234345a63Smrg if (stmt->map != NULL) 10334345a63Smrg { 10434345a63Smrg while ((mapToUse) && ((!uStringEqual(mapToUse->name, stmt->map)) || 10534345a63Smrg (mapToUse->type != file_type))) 10634345a63Smrg { 10734345a63Smrg mapToUse = (XkbFile *) mapToUse->common.next; 10834345a63Smrg } 10934345a63Smrg if (!mapToUse) 11034345a63Smrg { 111bfe6082cSmrg ERROR("No %s named \"%s\" in the include file \"%s\"\n", 11234345a63Smrg XkbConfigText(file_type, XkbMessage), stmt->map, 11334345a63Smrg stmt->file); 11434345a63Smrg ACTION("Exiting\n"); 11534345a63Smrg return False; 11634345a63Smrg } 117f46a6179Smrg } 118f757b1e9Smrg else if (rtrn->common.next != NULL) 11934345a63Smrg { 120f757b1e9Smrg while ((mapToUse) && !(mapToUse->flags & XkbLC_Default)) 121f757b1e9Smrg { 122f757b1e9Smrg mapToUse = (XkbFile *) mapToUse->common.next; 123f757b1e9Smrg } 124f757b1e9Smrg if (!mapToUse) 125f757b1e9Smrg { 126f757b1e9Smrg if (warningLevel > 5) 127f757b1e9Smrg { 128bfe6082cSmrg WARN("No map in include statement, but \"%s\" contains several without a default map\n", 129f757b1e9Smrg stmt->file); 130bfe6082cSmrg ACTION("Using first defined map, \"%s\"\n", rtrn->name); 131f757b1e9Smrg } 132f757b1e9Smrg mapToUse = rtrn; 133f757b1e9Smrg } 134f46a6179Smrg } 135f757b1e9Smrg 13634345a63Smrg setScanState(oldFile, oldLine); 13734345a63Smrg if (mapToUse->type != file_type) 13834345a63Smrg { 139bfe6082cSmrg ERROR("Include file wrong type (expected %s, got %s)\n", 14034345a63Smrg XkbConfigText(file_type, XkbMessage), 14134345a63Smrg XkbConfigText(mapToUse->type, XkbMessage)); 142bfe6082cSmrg ACTION("Include file \"%s\" ignored\n", stmt->file); 14334345a63Smrg return False; 144f46a6179Smrg } 145f46a6179Smrg /* FIXME: we have to check recursive includes here (or somewhere) */ 146f46a6179Smrg 14734345a63Smrg mapToUse->compiled = True; 14834345a63Smrg *file_rtrn = mapToUse; 14934345a63Smrg *merge_rtrn = stmt->merge; 150f46a6179Smrg return True; 151f46a6179Smrg} 152f46a6179Smrg 153f46a6179Smrg/***====================================================================***/ 154f46a6179Smrg 155f46a6179Smrgint 156f46a6179SmrgReportNotArray(const char *type, const char *field, const char *name) 157f46a6179Smrg{ 158bfe6082cSmrg ERROR("The %s %s field is not an array\n", type, field); 159bfe6082cSmrg ACTION("Ignoring illegal assignment in %s\n", name); 160f46a6179Smrg return False; 161f46a6179Smrg} 162f46a6179Smrg 163f46a6179Smrgint 164f46a6179SmrgReportShouldBeArray(const char *type, const char *field, char *name) 165f46a6179Smrg{ 166bfe6082cSmrg ERROR("Missing subscript for %s %s\n", type, field); 167bfe6082cSmrg ACTION("Ignoring illegal assignment in %s\n", name); 168f46a6179Smrg return False; 169f46a6179Smrg} 170f46a6179Smrg 171f46a6179Smrgint 172f46a6179SmrgReportBadType(const char *type, const char *field, 173f46a6179Smrg const char *name, const char *wanted) 174f46a6179Smrg{ 175bfe6082cSmrg ERROR("The %s %s field must be a %s\n", type, field, wanted); 176bfe6082cSmrg ACTION("Ignoring illegal assignment in %s\n", name); 177f46a6179Smrg return False; 178f46a6179Smrg} 179f46a6179Smrg 1806930ead5Smrg#if 0 181f46a6179Smrgint 18234345a63SmrgReportBadIndexType(char *type, char *field, char *name, char *wanted) 183f46a6179Smrg{ 184bfe6082cSmrg ERROR("Index for the %s %s field must be a %s\n", type, field, wanted); 185bfe6082cSmrg ACTION("Ignoring assignment to illegal field in %s\n", name); 186f46a6179Smrg return False; 187f46a6179Smrg} 1886930ead5Smrg#endif 189f46a6179Smrg 190f46a6179Smrgint 191f46a6179SmrgReportBadField(const char *type, const char *field, const char *name) 192f46a6179Smrg{ 193bfe6082cSmrg ERROR("Unknown %s field %s in %s\n", type, field, name); 194bfe6082cSmrg ACTION("Ignoring assignment to unknown field in %s\n", name); 195f46a6179Smrg return False; 196f46a6179Smrg} 197f46a6179Smrg 1986930ead5Smrg#if 0 199f46a6179Smrgint 20034345a63SmrgReportMultipleDefs(char *type, char *field, char *name) 201f46a6179Smrg{ 202bfe6082cSmrg WARN("Multiple definitions of %s in %s \"%s\"\n", field, type, name); 203f46a6179Smrg ACTION("Using last definition\n"); 204f46a6179Smrg return False; 205f46a6179Smrg} 2066930ead5Smrg#endif 207f46a6179Smrg 208f46a6179Smrg/***====================================================================***/ 209f46a6179Smrg 21034345a63SmrgBool 2116930ead5SmrgUseNewField(unsigned field, const CommonInfo *oldDefs, 2126930ead5Smrg const CommonInfo *newDefs, unsigned *pCollide) 213f46a6179Smrg{ 21434345a63Smrg Bool useNew; 21534345a63Smrg 21634345a63Smrg useNew = False; 21734345a63Smrg if (oldDefs->defined & field) 21834345a63Smrg { 21934345a63Smrg if (newDefs->defined & field) 22034345a63Smrg { 22134345a63Smrg if (((oldDefs->fileID == newDefs->fileID) 22234345a63Smrg && (warningLevel > 0)) || (warningLevel > 9)) 22334345a63Smrg { 22434345a63Smrg *pCollide |= field; 22534345a63Smrg } 22634345a63Smrg if (newDefs->merge != MergeAugment) 22734345a63Smrg useNew = True; 22834345a63Smrg } 229f46a6179Smrg } 23034345a63Smrg else if (newDefs->defined & field) 23134345a63Smrg useNew = True; 232f46a6179Smrg return useNew; 233f46a6179Smrg} 234f46a6179Smrg 2356930ead5Smrg#if 0 2366930ead5Smrgstatic Bool 2376930ead5SmrgMergeNewField(unsigned field, const CommonInfo *oldDefs, 2386930ead5Smrg const CommonInfo *newDefs, unsigned *pCollide) 239f46a6179Smrg{ 24034345a63Smrg if ((oldDefs->defined & field) && (newDefs->defined & field)) 24134345a63Smrg { 24234345a63Smrg if (((oldDefs->fileID == newDefs->fileID) && (warningLevel > 0)) || 24334345a63Smrg (warningLevel > 9)) 24434345a63Smrg { 24534345a63Smrg *pCollide |= field; 24634345a63Smrg } 24734345a63Smrg if (newDefs->merge == MergeAugment) 24834345a63Smrg return True; 249f46a6179Smrg } 250f46a6179Smrg return False; 251f46a6179Smrg} 2526930ead5Smrg#endif 253f46a6179Smrg 254f46a6179SmrgXPointer 25534345a63SmrgClearCommonInfo(CommonInfo * cmn) 256f46a6179Smrg{ 25734345a63Smrg if (cmn != NULL) 25834345a63Smrg { 25934345a63Smrg CommonInfo *this, *next; 26034345a63Smrg for (this = cmn; this != NULL; this = next) 26134345a63Smrg { 26234345a63Smrg next = this->next; 2636930ead5Smrg free(this); 26434345a63Smrg } 265f46a6179Smrg } 266f46a6179Smrg return NULL; 267f46a6179Smrg} 268f46a6179Smrg 269f46a6179SmrgXPointer 27034345a63SmrgAddCommonInfo(CommonInfo * old, CommonInfo * new) 271f46a6179Smrg{ 27234345a63Smrg CommonInfo *first; 273f46a6179Smrg 27434345a63Smrg first = old; 27534345a63Smrg while (old && old->next) 27634345a63Smrg { 27734345a63Smrg old = old->next; 278f46a6179Smrg } 27934345a63Smrg new->next = NULL; 28034345a63Smrg if (old) 28134345a63Smrg { 28234345a63Smrg old->next = new; 28334345a63Smrg return (XPointer) first; 284f46a6179Smrg } 28534345a63Smrg return (XPointer) new; 286f46a6179Smrg} 287f46a6179Smrg 288f46a6179Smrg/***====================================================================***/ 289f46a6179Smrg 29034345a63Smrgtypedef struct _KeyNameDesc 29134345a63Smrg{ 29234345a63Smrg KeySym level1; 29334345a63Smrg KeySym level2; 29434345a63Smrg char name[5]; 29534345a63Smrg Bool used; 296f46a6179Smrg} KeyNameDesc; 297f46a6179Smrg 29834345a63Smrgstatic KeyNameDesc dfltKeys[] = { 2996930ead5Smrg {XK_Escape, NoSymbol, "ESC\0", 0}, 3006930ead5Smrg {XK_quoteleft, XK_asciitilde, "TLDE", 0}, 3016930ead5Smrg {XK_1, XK_exclam, "AE01", 0}, 3026930ead5Smrg {XK_2, XK_at, "AE02", 0}, 3036930ead5Smrg {XK_3, XK_numbersign, "AE03", 0}, 3046930ead5Smrg {XK_4, XK_dollar, "AE04", 0}, 3056930ead5Smrg {XK_5, XK_percent, "AE05", 0}, 3066930ead5Smrg {XK_6, XK_asciicircum, "AE06", 0}, 3076930ead5Smrg {XK_7, XK_ampersand, "AE07", 0}, 3086930ead5Smrg {XK_8, XK_asterisk, "AE08", 0}, 3096930ead5Smrg {XK_9, XK_parenleft, "AE09", 0}, 3106930ead5Smrg {XK_0, XK_parenright, "AE10", 0}, 3116930ead5Smrg {XK_minus, XK_underscore, "AE11", 0}, 3126930ead5Smrg {XK_equal, XK_plus, "AE12", 0}, 3136930ead5Smrg {XK_BackSpace, NoSymbol, "BKSP", 0}, 3146930ead5Smrg {XK_Tab, NoSymbol, "TAB\0", 0}, 3156930ead5Smrg {XK_q, XK_Q, "AD01", 0}, 3166930ead5Smrg {XK_w, XK_W, "AD02", 0}, 3176930ead5Smrg {XK_e, XK_E, "AD03", 0}, 3186930ead5Smrg {XK_r, XK_R, "AD04", 0}, 3196930ead5Smrg {XK_t, XK_T, "AD05", 0}, 3206930ead5Smrg {XK_y, XK_Y, "AD06", 0}, 3216930ead5Smrg {XK_u, XK_U, "AD07", 0}, 3226930ead5Smrg {XK_i, XK_I, "AD08", 0}, 3236930ead5Smrg {XK_o, XK_O, "AD09", 0}, 3246930ead5Smrg {XK_p, XK_P, "AD10", 0}, 3256930ead5Smrg {XK_bracketleft, XK_braceleft, "AD11", 0}, 3266930ead5Smrg {XK_bracketright, XK_braceright, "AD12", 0}, 3276930ead5Smrg {XK_Return, NoSymbol, "RTRN", 0}, 3286930ead5Smrg {XK_Caps_Lock, NoSymbol, "CAPS", 0}, 3296930ead5Smrg {XK_a, XK_A, "AC01", 0}, 3306930ead5Smrg {XK_s, XK_S, "AC02", 0}, 3316930ead5Smrg {XK_d, XK_D, "AC03", 0}, 3326930ead5Smrg {XK_f, XK_F, "AC04", 0}, 3336930ead5Smrg {XK_g, XK_G, "AC05", 0}, 3346930ead5Smrg {XK_h, XK_H, "AC06", 0}, 3356930ead5Smrg {XK_j, XK_J, "AC07", 0}, 3366930ead5Smrg {XK_k, XK_K, "AC08", 0}, 3376930ead5Smrg {XK_l, XK_L, "AC09", 0}, 3386930ead5Smrg {XK_semicolon, XK_colon, "AC10", 0}, 3396930ead5Smrg {XK_quoteright, XK_quotedbl, "AC11", 0}, 3406930ead5Smrg {XK_Shift_L, NoSymbol, "LFSH", 0}, 3416930ead5Smrg {XK_z, XK_Z, "AB01", 0}, 3426930ead5Smrg {XK_x, XK_X, "AB02", 0}, 3436930ead5Smrg {XK_c, XK_C, "AB03", 0}, 3446930ead5Smrg {XK_v, XK_V, "AB04", 0}, 3456930ead5Smrg {XK_b, XK_B, "AB05", 0}, 3466930ead5Smrg {XK_n, XK_N, "AB06", 0}, 3476930ead5Smrg {XK_m, XK_M, "AB07", 0}, 3486930ead5Smrg {XK_comma, XK_less, "AB08", 0}, 3496930ead5Smrg {XK_period, XK_greater, "AB09", 0}, 3506930ead5Smrg {XK_slash, XK_question, "AB10", 0}, 3516930ead5Smrg {XK_backslash, XK_bar, "BKSL", 0}, 3526930ead5Smrg {XK_Control_L, NoSymbol, "LCTL", 0}, 3536930ead5Smrg {XK_space, NoSymbol, "SPCE", 0}, 3546930ead5Smrg {XK_Shift_R, NoSymbol, "RTSH", 0}, 3556930ead5Smrg {XK_Alt_L, NoSymbol, "LALT", 0}, 3566930ead5Smrg {XK_space, NoSymbol, "SPCE", 0}, 3576930ead5Smrg {XK_Control_R, NoSymbol, "RCTL", 0}, 3586930ead5Smrg {XK_Alt_R, NoSymbol, "RALT", 0}, 3596930ead5Smrg {XK_F1, NoSymbol, "FK01", 0}, 3606930ead5Smrg {XK_F2, NoSymbol, "FK02", 0}, 3616930ead5Smrg {XK_F3, NoSymbol, "FK03", 0}, 3626930ead5Smrg {XK_F4, NoSymbol, "FK04", 0}, 3636930ead5Smrg {XK_F5, NoSymbol, "FK05", 0}, 3646930ead5Smrg {XK_F6, NoSymbol, "FK06", 0}, 3656930ead5Smrg {XK_F7, NoSymbol, "FK07", 0}, 3666930ead5Smrg {XK_F8, NoSymbol, "FK08", 0}, 3676930ead5Smrg {XK_F9, NoSymbol, "FK09", 0}, 3686930ead5Smrg {XK_F10, NoSymbol, "FK10", 0}, 3696930ead5Smrg {XK_F11, NoSymbol, "FK11", 0}, 3706930ead5Smrg {XK_F12, NoSymbol, "FK12", 0}, 3716930ead5Smrg {XK_Print, NoSymbol, "PRSC", 0}, 3726930ead5Smrg {XK_Scroll_Lock, NoSymbol, "SCLK", 0}, 3736930ead5Smrg {XK_Pause, NoSymbol, "PAUS", 0}, 3746930ead5Smrg {XK_Insert, NoSymbol, "INS\0", 0}, 3756930ead5Smrg {XK_Home, NoSymbol, "HOME", 0}, 3766930ead5Smrg {XK_Prior, NoSymbol, "PGUP", 0}, 3776930ead5Smrg {XK_Delete, NoSymbol, "DELE", 0}, 3786930ead5Smrg {XK_End, NoSymbol, "END", 0}, 3796930ead5Smrg {XK_Next, NoSymbol, "PGDN", 0}, 3806930ead5Smrg {XK_Up, NoSymbol, "UP\0\0", 0}, 3816930ead5Smrg {XK_Left, NoSymbol, "LEFT", 0}, 3826930ead5Smrg {XK_Down, NoSymbol, "DOWN", 0}, 3836930ead5Smrg {XK_Right, NoSymbol, "RGHT", 0}, 3846930ead5Smrg {XK_Num_Lock, NoSymbol, "NMLK", 0}, 3856930ead5Smrg {XK_KP_Divide, NoSymbol, "KPDV", 0}, 3866930ead5Smrg {XK_KP_Multiply, NoSymbol, "KPMU", 0}, 3876930ead5Smrg {XK_KP_Subtract, NoSymbol, "KPSU", 0}, 3886930ead5Smrg {NoSymbol, XK_KP_7, "KP7\0", 0}, 3896930ead5Smrg {NoSymbol, XK_KP_8, "KP8\0", 0}, 3906930ead5Smrg {NoSymbol, XK_KP_9, "KP9\0", 0}, 3916930ead5Smrg {XK_KP_Add, NoSymbol, "KPAD", 0}, 3926930ead5Smrg {NoSymbol, XK_KP_4, "KP4\0", 0}, 3936930ead5Smrg {NoSymbol, XK_KP_5, "KP5\0", 0}, 3946930ead5Smrg {NoSymbol, XK_KP_6, "KP6\0", 0}, 3956930ead5Smrg {NoSymbol, XK_KP_1, "KP1\0", 0}, 3966930ead5Smrg {NoSymbol, XK_KP_2, "KP2\0", 0}, 3976930ead5Smrg {NoSymbol, XK_KP_3, "KP3\0", 0}, 3986930ead5Smrg {XK_KP_Enter, NoSymbol, "KPEN", 0}, 3996930ead5Smrg {NoSymbol, XK_KP_0, "KP0\0", 0}, 4006930ead5Smrg {XK_KP_Delete, NoSymbol, "KPDL", 0}, 4016930ead5Smrg {XK_less, XK_greater, "LSGT", 0}, 4026930ead5Smrg {XK_KP_Separator, NoSymbol, "KPCO", 0}, 4036930ead5Smrg {XK_Find, NoSymbol, "FIND", 0}, 4046930ead5Smrg {NoSymbol, NoSymbol, "\0\0\0\0", 0} 405f46a6179Smrg}; 406f46a6179Smrg 407f46a6179SmrgStatus 408f46a6179SmrgComputeKbdDefaults(XkbDescPtr xkb) 409f46a6179Smrg{ 4106930ead5Smrg int nUnknown; 41134345a63Smrg 41234345a63Smrg if ((xkb->names == NULL) || (xkb->names->keys == NULL)) 41334345a63Smrg { 4146930ead5Smrg Status rtrn; 41534345a63Smrg if ((rtrn = XkbAllocNames(xkb, XkbKeyNamesMask, 0, 0)) != Success) 41634345a63Smrg return rtrn; 417f46a6179Smrg } 4186930ead5Smrg for (KeyNameDesc *name = dfltKeys; (name->name[0] != '\0'); name++) 41934345a63Smrg { 42034345a63Smrg name->used = False; 421f46a6179Smrg } 42234345a63Smrg nUnknown = 0; 4236930ead5Smrg for (int i = xkb->min_key_code; i <= xkb->max_key_code; i++) 42434345a63Smrg { 4256930ead5Smrg int tmp = XkbKeyNumSyms(xkb, i); 42634345a63Smrg if ((xkb->names->keys[i].name[0] == '\0') && (tmp > 0)) 42734345a63Smrg { 4286930ead5Smrg KeySym *syms; 4296930ead5Smrg 43034345a63Smrg tmp = XkbKeyGroupsWidth(xkb, i); 43134345a63Smrg syms = XkbKeySymsPtr(xkb, i); 4326930ead5Smrg for (KeyNameDesc *name = dfltKeys; (name->name[0] != '\0'); name++) 43334345a63Smrg { 43434345a63Smrg Bool match = True; 43534345a63Smrg if (((name->level1 != syms[0]) 43634345a63Smrg && (name->level1 != NoSymbol)) 43734345a63Smrg || ((name->level2 != NoSymbol) && (tmp < 2)) 43834345a63Smrg || ((name->level2 != syms[1]) 43934345a63Smrg && (name->level2 != NoSymbol))) 44034345a63Smrg { 44134345a63Smrg match = False; 44234345a63Smrg } 44334345a63Smrg if (match) 44434345a63Smrg { 44534345a63Smrg if (!name->used) 44634345a63Smrg { 44734345a63Smrg memcpy(xkb->names->keys[i].name, name->name, 44834345a63Smrg XkbKeyNameLength); 44934345a63Smrg name->used = True; 45034345a63Smrg } 45134345a63Smrg else 45234345a63Smrg { 4536930ead5Smrg char tmpname[XkbKeyNameLength + 1]; 4546930ead5Smrg 45534345a63Smrg if (warningLevel > 2) 45634345a63Smrg { 457bfe6082cSmrg WARN 45834345a63Smrg ("Several keys match pattern for %s\n", 45934345a63Smrg XkbKeyNameText(name->name, XkbMessage)); 460bfe6082cSmrg ACTION("Using <U%03d> for key %d\n", 46134345a63Smrg nUnknown, i); 46234345a63Smrg } 46334345a63Smrg snprintf(tmpname, sizeof(tmpname), "U%03d", 46434345a63Smrg nUnknown++); 46534345a63Smrg memcpy(xkb->names->keys[i].name, tmpname, 46634345a63Smrg XkbKeyNameLength); 46734345a63Smrg } 46834345a63Smrg break; 46934345a63Smrg } 47034345a63Smrg } 47134345a63Smrg if (xkb->names->keys[i].name[0] == '\0') 47234345a63Smrg { 47334345a63Smrg if (warningLevel > 2) 47434345a63Smrg { 4756930ead5Smrg char tmpname[XkbKeyNameLength + 1]; 4766930ead5Smrg 477bfe6082cSmrg WARN("Key %d does not match any defaults\n", i); 478bfe6082cSmrg ACTION("Using name <U%03d>\n", nUnknown); 47934345a63Smrg snprintf(tmpname, sizeof(tmpname), "U%03d", nUnknown++); 48034345a63Smrg memcpy(xkb->names->keys[i].name, tmpname, 48134345a63Smrg XkbKeyNameLength); 48234345a63Smrg } 48334345a63Smrg } 48434345a63Smrg } 485f46a6179Smrg } 486f46a6179Smrg return Success; 487f46a6179Smrg} 488f46a6179Smrg 48934345a63Smrg/** 49034345a63Smrg * Find the key with the given name and return its keycode in kc_rtrn. 49134345a63Smrg * 49234345a63Smrg * @param name The 4-letter name of the key as a long. 49334345a63Smrg * @param kc_rtrn Set to the keycode if the key was found, otherwise 0. 49434345a63Smrg * @param use_aliases True if the key aliases should be searched too. 49534345a63Smrg * @param create If True and the key is not found, it is added to the 49634345a63Smrg * xkb->names at the first free keycode. 49734345a63Smrg * @param start_from Keycode to start searching from. 49834345a63Smrg * 49934345a63Smrg * @return True if found, False otherwise. 50034345a63Smrg */ 501f46a6179SmrgBool 50234345a63SmrgFindNamedKey(XkbDescPtr xkb, 50334345a63Smrg unsigned long name, 50434345a63Smrg unsigned int *kc_rtrn, 50534345a63Smrg Bool use_aliases, Bool create, int start_from) 506f46a6179Smrg{ 50734345a63Smrg if (start_from < xkb->min_key_code) 50834345a63Smrg { 50934345a63Smrg start_from = xkb->min_key_code; 510f46a6179Smrg } 51134345a63Smrg else if (start_from > xkb->max_key_code) 51234345a63Smrg { 51334345a63Smrg return False; 514f46a6179Smrg } 515f46a6179Smrg 51634345a63Smrg *kc_rtrn = 0; /* some callers rely on this */ 51734345a63Smrg if (xkb && xkb->names && xkb->names->keys) 51834345a63Smrg { 5196930ead5Smrg for (unsigned n = start_from; n <= xkb->max_key_code; n++) 52034345a63Smrg { 52134345a63Smrg unsigned long tmp; 52234345a63Smrg tmp = KeyNameToLong(xkb->names->keys[n].name); 52334345a63Smrg if (tmp == name) 52434345a63Smrg { 52534345a63Smrg *kc_rtrn = n; 52634345a63Smrg return True; 52734345a63Smrg } 52834345a63Smrg } 52934345a63Smrg if (use_aliases) 53034345a63Smrg { 53134345a63Smrg unsigned long new_name; 53234345a63Smrg if (FindKeyNameForAlias(xkb, name, &new_name)) 53334345a63Smrg return FindNamedKey(xkb, new_name, kc_rtrn, False, create, 0); 53434345a63Smrg } 535f46a6179Smrg } 53634345a63Smrg if (create) 53734345a63Smrg { 53834345a63Smrg if ((!xkb->names) || (!xkb->names->keys)) 53934345a63Smrg { 54034345a63Smrg if (xkb->min_key_code < XkbMinLegalKeyCode) 54134345a63Smrg { 54234345a63Smrg xkb->min_key_code = XkbMinLegalKeyCode; 54334345a63Smrg xkb->max_key_code = XkbMaxLegalKeyCode; 54434345a63Smrg } 54534345a63Smrg if (XkbAllocNames(xkb, XkbKeyNamesMask, 0, 0) != Success) 54634345a63Smrg { 54734345a63Smrg if (warningLevel > 0) 54834345a63Smrg { 54934345a63Smrg WARN("Couldn't allocate key names in FindNamedKey\n"); 550bfe6082cSmrg ACTION("Key \"%s\" not automatically created\n", 55134345a63Smrg longText(name, XkbMessage)); 55234345a63Smrg } 55334345a63Smrg return False; 55434345a63Smrg } 55534345a63Smrg } 55634345a63Smrg /* Find first unused keycode and store our key here */ 5576930ead5Smrg for (unsigned n = xkb->min_key_code; n <= xkb->max_key_code; n++) 55834345a63Smrg { 55934345a63Smrg if (xkb->names->keys[n].name[0] == '\0') 56034345a63Smrg { 56134345a63Smrg char buf[XkbKeyNameLength + 1]; 56234345a63Smrg LongToKeyName(name, buf); 56334345a63Smrg memcpy(xkb->names->keys[n].name, buf, XkbKeyNameLength); 56434345a63Smrg *kc_rtrn = n; 56534345a63Smrg return True; 56634345a63Smrg } 56734345a63Smrg } 568f46a6179Smrg } 569f46a6179Smrg return False; 570f46a6179Smrg} 571f46a6179Smrg 572f46a6179SmrgBool 57334345a63SmrgFindKeyNameForAlias(XkbDescPtr xkb, unsigned long lname, 57434345a63Smrg unsigned long *real_name) 575f46a6179Smrg{ 57634345a63Smrg char name[XkbKeyNameLength + 1]; 57734345a63Smrg 57834345a63Smrg if (xkb && xkb->geom && xkb->geom->key_aliases) 57934345a63Smrg { 58034345a63Smrg XkbKeyAliasPtr a; 58134345a63Smrg a = xkb->geom->key_aliases; 58234345a63Smrg LongToKeyName(lname, name); 58334345a63Smrg name[XkbKeyNameLength] = '\0'; 5846930ead5Smrg for (int i = 0; i < xkb->geom->num_key_aliases; i++, a++) 58534345a63Smrg { 58634345a63Smrg if (strncmp(name, a->alias, XkbKeyNameLength) == 0) 58734345a63Smrg { 58834345a63Smrg *real_name = KeyNameToLong(a->real); 58934345a63Smrg return True; 59034345a63Smrg } 59134345a63Smrg } 592f46a6179Smrg } 59334345a63Smrg if (xkb && xkb->names && xkb->names->key_aliases) 59434345a63Smrg { 59534345a63Smrg XkbKeyAliasPtr a; 59634345a63Smrg a = xkb->names->key_aliases; 59734345a63Smrg LongToKeyName(lname, name); 59834345a63Smrg name[XkbKeyNameLength] = '\0'; 5996930ead5Smrg for (int i = 0; i < xkb->names->num_key_aliases; i++, a++) 60034345a63Smrg { 60134345a63Smrg if (strncmp(name, a->alias, XkbKeyNameLength) == 0) 60234345a63Smrg { 60334345a63Smrg *real_name = KeyNameToLong(a->real); 60434345a63Smrg return True; 60534345a63Smrg } 60634345a63Smrg } 607f46a6179Smrg } 608f46a6179Smrg return False; 609f46a6179Smrg} 610