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