misc.c revision bfe6082c
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 FILE *file; 5734345a63Smrg XkbFile *rtrn, *mapToUse; 5834345a63Smrg char oldFile[1024] = {0}; 5934345a63Smrg int oldLine = lineNum; 6034345a63Smrg 6134345a63Smrg rtrn = XkbFindFileInCache(stmt->file, file_type, &stmt->path); 6234345a63Smrg if (rtrn == NULL) 6334345a63Smrg { 6434345a63Smrg /* file not in cache, open it, parse it and store it in cache for next 6534345a63Smrg time. */ 6634345a63Smrg file = XkbFindFileInPath(stmt->file, file_type, &stmt->path); 6734345a63Smrg if (file == NULL) 6834345a63Smrg { 69bfe6082cSmrg ERROR("Can't find file \"%s\" for %s include\n", stmt->file, 7034345a63Smrg XkbDirectoryForInclude(file_type)); 7134345a63Smrg ACTION("Exiting\n"); 7234345a63Smrg return False; 7334345a63Smrg } 7434345a63Smrg strcpy(oldFile, scanFile); 7534345a63Smrg oldLine = lineNum; 7634345a63Smrg setScanState(stmt->file, 1); 7734345a63Smrg if (debugFlags & 2) 78bfe6082cSmrg INFO("About to parse include file %s\n", stmt->file); 7934345a63Smrg /* parse the file */ 8034345a63Smrg if ((XKBParseFile(file, &rtrn) == 0) || (rtrn == NULL)) 8134345a63Smrg { 8234345a63Smrg setScanState(oldFile, oldLine); 83bfe6082cSmrg ERROR("Error interpreting include file \"%s\"\n", stmt->file); 8434345a63Smrg ACTION("Exiting\n"); 8534345a63Smrg fclose(file); 8634345a63Smrg return False; 8734345a63Smrg } 8834345a63Smrg fclose(file); 8934345a63Smrg XkbAddFileToCache(stmt->file, file_type, stmt->path, rtrn); 90f46a6179Smrg } 91f757b1e9Smrg 92f757b1e9Smrg /* 93f757b1e9Smrg * A single file may contain several maps. Here's how we choose the map: 94f757b1e9Smrg * - If a specific map was requested, look for it exclusively. 95f757b1e9Smrg * - Otherwise, if the file only contains a single map, return it. 96f757b1e9Smrg * - Otherwise, if the file has maps tagged as default, return the 97f757b1e9Smrg * first one. 98f757b1e9Smrg * - If all fails, return the first map in the file. 99f757b1e9Smrg */ 10034345a63Smrg mapToUse = rtrn; 10134345a63Smrg if (stmt->map != NULL) 10234345a63Smrg { 10334345a63Smrg while ((mapToUse) && ((!uStringEqual(mapToUse->name, stmt->map)) || 10434345a63Smrg (mapToUse->type != file_type))) 10534345a63Smrg { 10634345a63Smrg mapToUse = (XkbFile *) mapToUse->common.next; 10734345a63Smrg } 10834345a63Smrg if (!mapToUse) 10934345a63Smrg { 110bfe6082cSmrg ERROR("No %s named \"%s\" in the include file \"%s\"\n", 11134345a63Smrg XkbConfigText(file_type, XkbMessage), stmt->map, 11234345a63Smrg stmt->file); 11334345a63Smrg ACTION("Exiting\n"); 11434345a63Smrg return False; 11534345a63Smrg } 116f46a6179Smrg } 117f757b1e9Smrg else if (rtrn->common.next != NULL) 11834345a63Smrg { 119f757b1e9Smrg while ((mapToUse) && !(mapToUse->flags & XkbLC_Default)) 120f757b1e9Smrg { 121f757b1e9Smrg mapToUse = (XkbFile *) mapToUse->common.next; 122f757b1e9Smrg } 123f757b1e9Smrg if (!mapToUse) 124f757b1e9Smrg { 125f757b1e9Smrg if (warningLevel > 5) 126f757b1e9Smrg { 127bfe6082cSmrg WARN("No map in include statement, but \"%s\" contains several without a default map\n", 128f757b1e9Smrg stmt->file); 129bfe6082cSmrg ACTION("Using first defined map, \"%s\"\n", rtrn->name); 130f757b1e9Smrg } 131f757b1e9Smrg mapToUse = rtrn; 132f757b1e9Smrg } 133f46a6179Smrg } 134f757b1e9Smrg 13534345a63Smrg setScanState(oldFile, oldLine); 13634345a63Smrg if (mapToUse->type != file_type) 13734345a63Smrg { 138bfe6082cSmrg ERROR("Include file wrong type (expected %s, got %s)\n", 13934345a63Smrg XkbConfigText(file_type, XkbMessage), 14034345a63Smrg XkbConfigText(mapToUse->type, XkbMessage)); 141bfe6082cSmrg ACTION("Include file \"%s\" ignored\n", stmt->file); 14234345a63Smrg return False; 143f46a6179Smrg } 144f46a6179Smrg /* FIXME: we have to check recursive includes here (or somewhere) */ 145f46a6179Smrg 14634345a63Smrg mapToUse->compiled = True; 14734345a63Smrg *file_rtrn = mapToUse; 14834345a63Smrg *merge_rtrn = stmt->merge; 149f46a6179Smrg return True; 150f46a6179Smrg} 151f46a6179Smrg 152f46a6179Smrg/***====================================================================***/ 153f46a6179Smrg 154f46a6179Smrgint 155f46a6179SmrgReportNotArray(const char *type, const char *field, const char *name) 156f46a6179Smrg{ 157bfe6082cSmrg ERROR("The %s %s field is not an array\n", type, field); 158bfe6082cSmrg ACTION("Ignoring illegal assignment in %s\n", name); 159f46a6179Smrg return False; 160f46a6179Smrg} 161f46a6179Smrg 162f46a6179Smrgint 163f46a6179SmrgReportShouldBeArray(const char *type, const char *field, char *name) 164f46a6179Smrg{ 165bfe6082cSmrg ERROR("Missing subscript for %s %s\n", type, field); 166bfe6082cSmrg ACTION("Ignoring illegal assignment in %s\n", name); 167f46a6179Smrg return False; 168f46a6179Smrg} 169f46a6179Smrg 170f46a6179Smrgint 171f46a6179SmrgReportBadType(const char *type, const char *field, 172f46a6179Smrg const char *name, const char *wanted) 173f46a6179Smrg{ 174bfe6082cSmrg ERROR("The %s %s field must be a %s\n", type, field, wanted); 175bfe6082cSmrg ACTION("Ignoring illegal assignment in %s\n", name); 176f46a6179Smrg return False; 177f46a6179Smrg} 178f46a6179Smrg 179f46a6179Smrgint 18034345a63SmrgReportBadIndexType(char *type, char *field, char *name, char *wanted) 181f46a6179Smrg{ 182bfe6082cSmrg ERROR("Index for the %s %s field must be a %s\n", type, field, wanted); 183bfe6082cSmrg ACTION("Ignoring assignment to illegal field in %s\n", name); 184f46a6179Smrg return False; 185f46a6179Smrg} 186f46a6179Smrg 187f46a6179Smrgint 188f46a6179SmrgReportBadField(const char *type, const char *field, const char *name) 189f46a6179Smrg{ 190bfe6082cSmrg ERROR("Unknown %s field %s in %s\n", type, field, name); 191bfe6082cSmrg ACTION("Ignoring assignment to unknown field in %s\n", name); 192f46a6179Smrg return False; 193f46a6179Smrg} 194f46a6179Smrg 195f46a6179Smrgint 19634345a63SmrgReportMultipleDefs(char *type, char *field, char *name) 197f46a6179Smrg{ 198bfe6082cSmrg WARN("Multiple definitions of %s in %s \"%s\"\n", field, type, name); 199f46a6179Smrg ACTION("Using last definition\n"); 200f46a6179Smrg return False; 201f46a6179Smrg} 202f46a6179Smrg 203f46a6179Smrg/***====================================================================***/ 204f46a6179Smrg 20534345a63SmrgBool 20634345a63SmrgUseNewField(unsigned field, 20734345a63Smrg CommonInfo * oldDefs, CommonInfo * newDefs, unsigned *pCollide) 208f46a6179Smrg{ 20934345a63Smrg Bool useNew; 21034345a63Smrg 21134345a63Smrg useNew = False; 21234345a63Smrg if (oldDefs->defined & field) 21334345a63Smrg { 21434345a63Smrg if (newDefs->defined & field) 21534345a63Smrg { 21634345a63Smrg if (((oldDefs->fileID == newDefs->fileID) 21734345a63Smrg && (warningLevel > 0)) || (warningLevel > 9)) 21834345a63Smrg { 21934345a63Smrg *pCollide |= field; 22034345a63Smrg } 22134345a63Smrg if (newDefs->merge != MergeAugment) 22234345a63Smrg useNew = True; 22334345a63Smrg } 224f46a6179Smrg } 22534345a63Smrg else if (newDefs->defined & field) 22634345a63Smrg useNew = True; 227f46a6179Smrg return useNew; 228f46a6179Smrg} 229f46a6179Smrg 23034345a63SmrgBool 23134345a63SmrgMergeNewField(unsigned field, 23234345a63Smrg CommonInfo * oldDefs, CommonInfo * newDefs, unsigned *pCollide) 233f46a6179Smrg{ 23434345a63Smrg if ((oldDefs->defined & field) && (newDefs->defined & field)) 23534345a63Smrg { 23634345a63Smrg if (((oldDefs->fileID == newDefs->fileID) && (warningLevel > 0)) || 23734345a63Smrg (warningLevel > 9)) 23834345a63Smrg { 23934345a63Smrg *pCollide |= field; 24034345a63Smrg } 24134345a63Smrg if (newDefs->merge == MergeAugment) 24234345a63Smrg return True; 243f46a6179Smrg } 244f46a6179Smrg return False; 245f46a6179Smrg} 246f46a6179Smrg 247f46a6179SmrgXPointer 24834345a63SmrgClearCommonInfo(CommonInfo * cmn) 249f46a6179Smrg{ 25034345a63Smrg if (cmn != NULL) 25134345a63Smrg { 25234345a63Smrg CommonInfo *this, *next; 25334345a63Smrg for (this = cmn; this != NULL; this = next) 25434345a63Smrg { 25534345a63Smrg next = this->next; 25634345a63Smrg uFree(this); 25734345a63Smrg } 258f46a6179Smrg } 259f46a6179Smrg return NULL; 260f46a6179Smrg} 261f46a6179Smrg 262f46a6179SmrgXPointer 26334345a63SmrgAddCommonInfo(CommonInfo * old, CommonInfo * new) 264f46a6179Smrg{ 26534345a63Smrg CommonInfo *first; 266f46a6179Smrg 26734345a63Smrg first = old; 26834345a63Smrg while (old && old->next) 26934345a63Smrg { 27034345a63Smrg old = old->next; 271f46a6179Smrg } 27234345a63Smrg new->next = NULL; 27334345a63Smrg if (old) 27434345a63Smrg { 27534345a63Smrg old->next = new; 27634345a63Smrg return (XPointer) first; 277f46a6179Smrg } 27834345a63Smrg return (XPointer) new; 279f46a6179Smrg} 280f46a6179Smrg 281f46a6179Smrg/***====================================================================***/ 282f46a6179Smrg 28334345a63Smrgtypedef struct _KeyNameDesc 28434345a63Smrg{ 28534345a63Smrg KeySym level1; 28634345a63Smrg KeySym level2; 28734345a63Smrg char name[5]; 28834345a63Smrg Bool used; 289f46a6179Smrg} KeyNameDesc; 290f46a6179Smrg 29134345a63Smrgstatic KeyNameDesc dfltKeys[] = { 29234345a63Smrg {XK_Escape, NoSymbol, "ESC\0"}, 29334345a63Smrg {XK_quoteleft, XK_asciitilde, "TLDE"}, 29434345a63Smrg {XK_1, XK_exclam, "AE01"}, 29534345a63Smrg {XK_2, XK_at, "AE02"}, 29634345a63Smrg {XK_3, XK_numbersign, "AE03"}, 29734345a63Smrg {XK_4, XK_dollar, "AE04"}, 29834345a63Smrg {XK_5, XK_percent, "AE05"}, 29934345a63Smrg {XK_6, XK_asciicircum, "AE06"}, 30034345a63Smrg {XK_7, XK_ampersand, "AE07"}, 30134345a63Smrg {XK_8, XK_asterisk, "AE08"}, 30234345a63Smrg {XK_9, XK_parenleft, "AE09"}, 30334345a63Smrg {XK_0, XK_parenright, "AE10"}, 30434345a63Smrg {XK_minus, XK_underscore, "AE11"}, 30534345a63Smrg {XK_equal, XK_plus, "AE12"}, 30634345a63Smrg {XK_BackSpace, NoSymbol, "BKSP"}, 30734345a63Smrg {XK_Tab, NoSymbol, "TAB\0"}, 30834345a63Smrg {XK_q, XK_Q, "AD01"}, 30934345a63Smrg {XK_w, XK_W, "AD02"}, 31034345a63Smrg {XK_e, XK_E, "AD03"}, 31134345a63Smrg {XK_r, XK_R, "AD04"}, 31234345a63Smrg {XK_t, XK_T, "AD05"}, 31334345a63Smrg {XK_y, XK_Y, "AD06"}, 31434345a63Smrg {XK_u, XK_U, "AD07"}, 31534345a63Smrg {XK_i, XK_I, "AD08"}, 31634345a63Smrg {XK_o, XK_O, "AD09"}, 31734345a63Smrg {XK_p, XK_P, "AD10"}, 31834345a63Smrg {XK_bracketleft, XK_braceleft, "AD11"}, 31934345a63Smrg {XK_bracketright, XK_braceright, "AD12"}, 32034345a63Smrg {XK_Return, NoSymbol, "RTRN"}, 32134345a63Smrg {XK_Caps_Lock, NoSymbol, "CAPS"}, 32234345a63Smrg {XK_a, XK_A, "AC01"}, 32334345a63Smrg {XK_s, XK_S, "AC02"}, 32434345a63Smrg {XK_d, XK_D, "AC03"}, 32534345a63Smrg {XK_f, XK_F, "AC04"}, 32634345a63Smrg {XK_g, XK_G, "AC05"}, 32734345a63Smrg {XK_h, XK_H, "AC06"}, 32834345a63Smrg {XK_j, XK_J, "AC07"}, 32934345a63Smrg {XK_k, XK_K, "AC08"}, 33034345a63Smrg {XK_l, XK_L, "AC09"}, 33134345a63Smrg {XK_semicolon, XK_colon, "AC10"}, 33234345a63Smrg {XK_quoteright, XK_quotedbl, "AC11"}, 33334345a63Smrg {XK_Shift_L, NoSymbol, "LFSH"}, 33434345a63Smrg {XK_z, XK_Z, "AB01"}, 33534345a63Smrg {XK_x, XK_X, "AB02"}, 33634345a63Smrg {XK_c, XK_C, "AB03"}, 33734345a63Smrg {XK_v, XK_V, "AB04"}, 33834345a63Smrg {XK_b, XK_B, "AB05"}, 33934345a63Smrg {XK_n, XK_N, "AB06"}, 34034345a63Smrg {XK_m, XK_M, "AB07"}, 34134345a63Smrg {XK_comma, XK_less, "AB08"}, 34234345a63Smrg {XK_period, XK_greater, "AB09"}, 34334345a63Smrg {XK_slash, XK_question, "AB10"}, 34434345a63Smrg {XK_backslash, XK_bar, "BKSL"}, 34534345a63Smrg {XK_Control_L, NoSymbol, "LCTL"}, 34634345a63Smrg {XK_space, NoSymbol, "SPCE"}, 34734345a63Smrg {XK_Shift_R, NoSymbol, "RTSH"}, 34834345a63Smrg {XK_Alt_L, NoSymbol, "LALT"}, 34934345a63Smrg {XK_space, NoSymbol, "SPCE"}, 35034345a63Smrg {XK_Control_R, NoSymbol, "RCTL"}, 35134345a63Smrg {XK_Alt_R, NoSymbol, "RALT"}, 35234345a63Smrg {XK_F1, NoSymbol, "FK01"}, 35334345a63Smrg {XK_F2, NoSymbol, "FK02"}, 35434345a63Smrg {XK_F3, NoSymbol, "FK03"}, 35534345a63Smrg {XK_F4, NoSymbol, "FK04"}, 35634345a63Smrg {XK_F5, NoSymbol, "FK05"}, 35734345a63Smrg {XK_F6, NoSymbol, "FK06"}, 35834345a63Smrg {XK_F7, NoSymbol, "FK07"}, 35934345a63Smrg {XK_F8, NoSymbol, "FK08"}, 36034345a63Smrg {XK_F9, NoSymbol, "FK09"}, 36134345a63Smrg {XK_F10, NoSymbol, "FK10"}, 36234345a63Smrg {XK_F11, NoSymbol, "FK11"}, 36334345a63Smrg {XK_F12, NoSymbol, "FK12"}, 36434345a63Smrg {XK_Print, NoSymbol, "PRSC"}, 36534345a63Smrg {XK_Scroll_Lock, NoSymbol, "SCLK"}, 36634345a63Smrg {XK_Pause, NoSymbol, "PAUS"}, 36734345a63Smrg {XK_Insert, NoSymbol, "INS\0"}, 36834345a63Smrg {XK_Home, NoSymbol, "HOME"}, 36934345a63Smrg {XK_Prior, NoSymbol, "PGUP"}, 37034345a63Smrg {XK_Delete, NoSymbol, "DELE"}, 37134345a63Smrg {XK_End, NoSymbol, "END"}, 37234345a63Smrg {XK_Next, NoSymbol, "PGDN"}, 37334345a63Smrg {XK_Up, NoSymbol, "UP\0\0"}, 37434345a63Smrg {XK_Left, NoSymbol, "LEFT"}, 37534345a63Smrg {XK_Down, NoSymbol, "DOWN"}, 37634345a63Smrg {XK_Right, NoSymbol, "RGHT"}, 37734345a63Smrg {XK_Num_Lock, NoSymbol, "NMLK"}, 37834345a63Smrg {XK_KP_Divide, NoSymbol, "KPDV"}, 37934345a63Smrg {XK_KP_Multiply, NoSymbol, "KPMU"}, 38034345a63Smrg {XK_KP_Subtract, NoSymbol, "KPSU"}, 38134345a63Smrg {NoSymbol, XK_KP_7, "KP7\0"}, 38234345a63Smrg {NoSymbol, XK_KP_8, "KP8\0"}, 38334345a63Smrg {NoSymbol, XK_KP_9, "KP9\0"}, 38434345a63Smrg {XK_KP_Add, NoSymbol, "KPAD"}, 38534345a63Smrg {NoSymbol, XK_KP_4, "KP4\0"}, 38634345a63Smrg {NoSymbol, XK_KP_5, "KP5\0"}, 38734345a63Smrg {NoSymbol, XK_KP_6, "KP6\0"}, 38834345a63Smrg {NoSymbol, XK_KP_1, "KP1\0"}, 38934345a63Smrg {NoSymbol, XK_KP_2, "KP2\0"}, 39034345a63Smrg {NoSymbol, XK_KP_3, "KP3\0"}, 39134345a63Smrg {XK_KP_Enter, NoSymbol, "KPEN"}, 39234345a63Smrg {NoSymbol, XK_KP_0, "KP0\0"}, 39334345a63Smrg {XK_KP_Delete, NoSymbol, "KPDL"}, 39434345a63Smrg {XK_less, XK_greater, "LSGT"}, 39534345a63Smrg {XK_KP_Separator, NoSymbol, "KPCO"}, 39634345a63Smrg {XK_Find, NoSymbol, "FIND"}, 39734345a63Smrg {NoSymbol, NoSymbol, "\0\0\0\0"} 398f46a6179Smrg}; 399f46a6179Smrg 400f46a6179SmrgStatus 401f46a6179SmrgComputeKbdDefaults(XkbDescPtr xkb) 402f46a6179Smrg{ 40334345a63Smrg Status rtrn; 40434345a63Smrg register int i, tmp, nUnknown; 40534345a63Smrg KeyNameDesc *name; 40634345a63Smrg KeySym *syms; 40734345a63Smrg char tmpname[XkbKeyNameLength + 1]; 40834345a63Smrg 40934345a63Smrg if ((xkb->names == NULL) || (xkb->names->keys == NULL)) 41034345a63Smrg { 41134345a63Smrg if ((rtrn = XkbAllocNames(xkb, XkbKeyNamesMask, 0, 0)) != Success) 41234345a63Smrg return rtrn; 413f46a6179Smrg } 41434345a63Smrg for (name = dfltKeys; (name->name[0] != '\0'); name++) 41534345a63Smrg { 41634345a63Smrg name->used = False; 417f46a6179Smrg } 41834345a63Smrg nUnknown = 0; 41934345a63Smrg for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) 42034345a63Smrg { 42134345a63Smrg tmp = XkbKeyNumSyms(xkb, i); 42234345a63Smrg if ((xkb->names->keys[i].name[0] == '\0') && (tmp > 0)) 42334345a63Smrg { 42434345a63Smrg tmp = XkbKeyGroupsWidth(xkb, i); 42534345a63Smrg syms = XkbKeySymsPtr(xkb, i); 42634345a63Smrg for (name = dfltKeys; (name->name[0] != '\0'); name++) 42734345a63Smrg { 42834345a63Smrg Bool match = True; 42934345a63Smrg if (((name->level1 != syms[0]) 43034345a63Smrg && (name->level1 != NoSymbol)) 43134345a63Smrg || ((name->level2 != NoSymbol) && (tmp < 2)) 43234345a63Smrg || ((name->level2 != syms[1]) 43334345a63Smrg && (name->level2 != NoSymbol))) 43434345a63Smrg { 43534345a63Smrg match = False; 43634345a63Smrg } 43734345a63Smrg if (match) 43834345a63Smrg { 43934345a63Smrg if (!name->used) 44034345a63Smrg { 44134345a63Smrg memcpy(xkb->names->keys[i].name, name->name, 44234345a63Smrg XkbKeyNameLength); 44334345a63Smrg name->used = True; 44434345a63Smrg } 44534345a63Smrg else 44634345a63Smrg { 44734345a63Smrg if (warningLevel > 2) 44834345a63Smrg { 449bfe6082cSmrg WARN 45034345a63Smrg ("Several keys match pattern for %s\n", 45134345a63Smrg XkbKeyNameText(name->name, XkbMessage)); 452bfe6082cSmrg ACTION("Using <U%03d> for key %d\n", 45334345a63Smrg nUnknown, i); 45434345a63Smrg } 45534345a63Smrg snprintf(tmpname, sizeof(tmpname), "U%03d", 45634345a63Smrg nUnknown++); 45734345a63Smrg memcpy(xkb->names->keys[i].name, tmpname, 45834345a63Smrg XkbKeyNameLength); 45934345a63Smrg } 46034345a63Smrg break; 46134345a63Smrg } 46234345a63Smrg } 46334345a63Smrg if (xkb->names->keys[i].name[0] == '\0') 46434345a63Smrg { 46534345a63Smrg if (warningLevel > 2) 46634345a63Smrg { 467bfe6082cSmrg WARN("Key %d does not match any defaults\n", i); 468bfe6082cSmrg ACTION("Using name <U%03d>\n", nUnknown); 46934345a63Smrg snprintf(tmpname, sizeof(tmpname), "U%03d", nUnknown++); 47034345a63Smrg memcpy(xkb->names->keys[i].name, tmpname, 47134345a63Smrg XkbKeyNameLength); 47234345a63Smrg } 47334345a63Smrg } 47434345a63Smrg } 475f46a6179Smrg } 476f46a6179Smrg return Success; 477f46a6179Smrg} 478f46a6179Smrg 47934345a63Smrg/** 48034345a63Smrg * Find the key with the given name and return its keycode in kc_rtrn. 48134345a63Smrg * 48234345a63Smrg * @param name The 4-letter name of the key as a long. 48334345a63Smrg * @param kc_rtrn Set to the keycode if the key was found, otherwise 0. 48434345a63Smrg * @param use_aliases True if the key aliases should be searched too. 48534345a63Smrg * @param create If True and the key is not found, it is added to the 48634345a63Smrg * xkb->names at the first free keycode. 48734345a63Smrg * @param start_from Keycode to start searching from. 48834345a63Smrg * 48934345a63Smrg * @return True if found, False otherwise. 49034345a63Smrg */ 491f46a6179SmrgBool 49234345a63SmrgFindNamedKey(XkbDescPtr xkb, 49334345a63Smrg unsigned long name, 49434345a63Smrg unsigned int *kc_rtrn, 49534345a63Smrg Bool use_aliases, Bool create, int start_from) 496f46a6179Smrg{ 49734345a63Smrg register unsigned n; 498f46a6179Smrg 49934345a63Smrg if (start_from < xkb->min_key_code) 50034345a63Smrg { 50134345a63Smrg start_from = xkb->min_key_code; 502f46a6179Smrg } 50334345a63Smrg else if (start_from > xkb->max_key_code) 50434345a63Smrg { 50534345a63Smrg return False; 506f46a6179Smrg } 507f46a6179Smrg 50834345a63Smrg *kc_rtrn = 0; /* some callers rely on this */ 50934345a63Smrg if (xkb && xkb->names && xkb->names->keys) 51034345a63Smrg { 51134345a63Smrg for (n = start_from; n <= xkb->max_key_code; n++) 51234345a63Smrg { 51334345a63Smrg unsigned long tmp; 51434345a63Smrg tmp = KeyNameToLong(xkb->names->keys[n].name); 51534345a63Smrg if (tmp == name) 51634345a63Smrg { 51734345a63Smrg *kc_rtrn = n; 51834345a63Smrg return True; 51934345a63Smrg } 52034345a63Smrg } 52134345a63Smrg if (use_aliases) 52234345a63Smrg { 52334345a63Smrg unsigned long new_name; 52434345a63Smrg if (FindKeyNameForAlias(xkb, name, &new_name)) 52534345a63Smrg return FindNamedKey(xkb, new_name, kc_rtrn, False, create, 0); 52634345a63Smrg } 527f46a6179Smrg } 52834345a63Smrg if (create) 52934345a63Smrg { 53034345a63Smrg if ((!xkb->names) || (!xkb->names->keys)) 53134345a63Smrg { 53234345a63Smrg if (xkb->min_key_code < XkbMinLegalKeyCode) 53334345a63Smrg { 53434345a63Smrg xkb->min_key_code = XkbMinLegalKeyCode; 53534345a63Smrg xkb->max_key_code = XkbMaxLegalKeyCode; 53634345a63Smrg } 53734345a63Smrg if (XkbAllocNames(xkb, XkbKeyNamesMask, 0, 0) != Success) 53834345a63Smrg { 53934345a63Smrg if (warningLevel > 0) 54034345a63Smrg { 54134345a63Smrg WARN("Couldn't allocate key names in FindNamedKey\n"); 542bfe6082cSmrg ACTION("Key \"%s\" not automatically created\n", 54334345a63Smrg longText(name, XkbMessage)); 54434345a63Smrg } 54534345a63Smrg return False; 54634345a63Smrg } 54734345a63Smrg } 54834345a63Smrg /* Find first unused keycode and store our key here */ 54934345a63Smrg for (n = xkb->min_key_code; n <= xkb->max_key_code; n++) 55034345a63Smrg { 55134345a63Smrg if (xkb->names->keys[n].name[0] == '\0') 55234345a63Smrg { 55334345a63Smrg char buf[XkbKeyNameLength + 1]; 55434345a63Smrg LongToKeyName(name, buf); 55534345a63Smrg memcpy(xkb->names->keys[n].name, buf, XkbKeyNameLength); 55634345a63Smrg *kc_rtrn = n; 55734345a63Smrg return True; 55834345a63Smrg } 55934345a63Smrg } 560f46a6179Smrg } 561f46a6179Smrg return False; 562f46a6179Smrg} 563f46a6179Smrg 564f46a6179SmrgBool 56534345a63SmrgFindKeyNameForAlias(XkbDescPtr xkb, unsigned long lname, 56634345a63Smrg unsigned long *real_name) 567f46a6179Smrg{ 56834345a63Smrg register int i; 56934345a63Smrg char name[XkbKeyNameLength + 1]; 57034345a63Smrg 57134345a63Smrg if (xkb && xkb->geom && xkb->geom->key_aliases) 57234345a63Smrg { 57334345a63Smrg XkbKeyAliasPtr a; 57434345a63Smrg a = xkb->geom->key_aliases; 57534345a63Smrg LongToKeyName(lname, name); 57634345a63Smrg name[XkbKeyNameLength] = '\0'; 57734345a63Smrg for (i = 0; i < xkb->geom->num_key_aliases; i++, a++) 57834345a63Smrg { 57934345a63Smrg if (strncmp(name, a->alias, XkbKeyNameLength) == 0) 58034345a63Smrg { 58134345a63Smrg *real_name = KeyNameToLong(a->real); 58234345a63Smrg return True; 58334345a63Smrg } 58434345a63Smrg } 585f46a6179Smrg } 58634345a63Smrg if (xkb && xkb->names && xkb->names->key_aliases) 58734345a63Smrg { 58834345a63Smrg XkbKeyAliasPtr a; 58934345a63Smrg a = xkb->names->key_aliases; 59034345a63Smrg LongToKeyName(lname, name); 59134345a63Smrg name[XkbKeyNameLength] = '\0'; 59234345a63Smrg for (i = 0; i < xkb->names->num_key_aliases; i++, a++) 59334345a63Smrg { 59434345a63Smrg if (strncmp(name, a->alias, XkbKeyNameLength) == 0) 59534345a63Smrg { 59634345a63Smrg *real_name = KeyNameToLong(a->real); 59734345a63Smrg return True; 59834345a63Smrg } 59934345a63Smrg } 600f46a6179Smrg } 601f46a6179Smrg return False; 602f46a6179Smrg} 603