misc.c revision 34345a63
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
9f46a6179Smrg documentation, and that the name of Silicon Graphics not be
10f46a6179Smrg used in advertising or publicity pertaining to distribution
11f46a6179Smrg of the software without specific prior written permission.
12f46a6179Smrg 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.
15f46a6179Smrg
16f46a6179Smrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17f46a6179Smrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18f46a6179Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19f46a6179Smrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20f46a6179Smrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21f46a6179Smrg 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        {
6934345a63Smrg            ERROR2("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)
7834345a63Smrg            INFO1("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);
8334345a63Smrg            ERROR1("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    }
9134345a63Smrg    mapToUse = rtrn;
9234345a63Smrg    if (stmt->map != NULL)
9334345a63Smrg    {
9434345a63Smrg        while ((mapToUse) && ((!uStringEqual(mapToUse->name, stmt->map)) ||
9534345a63Smrg                              (mapToUse->type != file_type)))
9634345a63Smrg        {
9734345a63Smrg            mapToUse = (XkbFile *) mapToUse->common.next;
9834345a63Smrg        }
9934345a63Smrg        if (!mapToUse)
10034345a63Smrg        {
10134345a63Smrg            ERROR3("No %s named \"%s\" in the include file \"%s\"\n",
10234345a63Smrg                   XkbConfigText(file_type, XkbMessage), stmt->map,
10334345a63Smrg                   stmt->file);
10434345a63Smrg            ACTION("Exiting\n");
10534345a63Smrg            return False;
10634345a63Smrg        }
107f46a6179Smrg    }
10834345a63Smrg    else if ((rtrn->common.next != NULL) && (warningLevel > 5))
10934345a63Smrg    {
11034345a63Smrg        WARN1("No map in include statement, but \"%s\" contains several\n",
11134345a63Smrg              stmt->file);
11234345a63Smrg        ACTION1("Using first defined map, \"%s\"\n", rtrn->name);
113f46a6179Smrg    }
11434345a63Smrg    setScanState(oldFile, oldLine);
11534345a63Smrg    if (mapToUse->type != file_type)
11634345a63Smrg    {
11734345a63Smrg        ERROR2("Include file wrong type (expected %s, got %s)\n",
11834345a63Smrg               XkbConfigText(file_type, XkbMessage),
11934345a63Smrg               XkbConfigText(mapToUse->type, XkbMessage));
12034345a63Smrg        ACTION1("Include file \"%s\" ignored\n", stmt->file);
12134345a63Smrg        return False;
122f46a6179Smrg    }
123f46a6179Smrg    /* FIXME: we have to check recursive includes here (or somewhere) */
124f46a6179Smrg
12534345a63Smrg    mapToUse->compiled = True;
12634345a63Smrg    *file_rtrn = mapToUse;
12734345a63Smrg    *merge_rtrn = stmt->merge;
128f46a6179Smrg    return True;
129f46a6179Smrg}
130f46a6179Smrg
131f46a6179Smrg/***====================================================================***/
132f46a6179Smrg
133f46a6179Smrgint
134f46a6179SmrgReportNotArray(const char *type, const char *field, const char *name)
135f46a6179Smrg{
13634345a63Smrg    ERROR2("The %s %s field is not an array\n", type, field);
13734345a63Smrg    ACTION1("Ignoring illegal assignment in %s\n", name);
138f46a6179Smrg    return False;
139f46a6179Smrg}
140f46a6179Smrg
141f46a6179Smrgint
142f46a6179SmrgReportShouldBeArray(const char *type, const char *field, char *name)
143f46a6179Smrg{
14434345a63Smrg    ERROR2("Missing subscript for %s %s\n", type, field);
14534345a63Smrg    ACTION1("Ignoring illegal assignment in %s\n", name);
146f46a6179Smrg    return False;
147f46a6179Smrg}
148f46a6179Smrg
149f46a6179Smrgint
150f46a6179SmrgReportBadType(const char *type, const char *field,
151f46a6179Smrg              const char *name, const char *wanted)
152f46a6179Smrg{
15334345a63Smrg    ERROR3("The %s %s field must be a %s\n", type, field, wanted);
15434345a63Smrg    ACTION1("Ignoring illegal assignment in %s\n", name);
155f46a6179Smrg    return False;
156f46a6179Smrg}
157f46a6179Smrg
158f46a6179Smrgint
15934345a63SmrgReportBadIndexType(char *type, char *field, char *name, char *wanted)
160f46a6179Smrg{
16134345a63Smrg    ERROR3("Index for the %s %s field must be a %s\n", type, field, wanted);
16234345a63Smrg    ACTION1("Ignoring assignment to illegal field in %s\n", name);
163f46a6179Smrg    return False;
164f46a6179Smrg}
165f46a6179Smrg
166f46a6179Smrgint
167f46a6179SmrgReportBadField(const char *type, const char *field, const char *name)
168f46a6179Smrg{
16934345a63Smrg    ERROR3("Unknown %s field %s in %s\n", type, field, name);
17034345a63Smrg    ACTION1("Ignoring assignment to unknown field in %s\n", name);
171f46a6179Smrg    return False;
172f46a6179Smrg}
173f46a6179Smrg
174f46a6179Smrgint
17534345a63SmrgReportMultipleDefs(char *type, char *field, char *name)
176f46a6179Smrg{
17734345a63Smrg    WARN3("Multiple definitions of %s in %s \"%s\"\n", field, type, name);
178f46a6179Smrg    ACTION("Using last definition\n");
179f46a6179Smrg    return False;
180f46a6179Smrg}
181f46a6179Smrg
182f46a6179Smrg/***====================================================================***/
183f46a6179Smrg
18434345a63SmrgBool
18534345a63SmrgUseNewField(unsigned field,
18634345a63Smrg            CommonInfo * oldDefs, CommonInfo * newDefs, unsigned *pCollide)
187f46a6179Smrg{
18834345a63Smrg    Bool useNew;
18934345a63Smrg
19034345a63Smrg    useNew = False;
19134345a63Smrg    if (oldDefs->defined & field)
19234345a63Smrg    {
19334345a63Smrg        if (newDefs->defined & field)
19434345a63Smrg        {
19534345a63Smrg            if (((oldDefs->fileID == newDefs->fileID)
19634345a63Smrg                 && (warningLevel > 0)) || (warningLevel > 9))
19734345a63Smrg            {
19834345a63Smrg                *pCollide |= field;
19934345a63Smrg            }
20034345a63Smrg            if (newDefs->merge != MergeAugment)
20134345a63Smrg                useNew = True;
20234345a63Smrg        }
203f46a6179Smrg    }
20434345a63Smrg    else if (newDefs->defined & field)
20534345a63Smrg        useNew = True;
206f46a6179Smrg    return useNew;
207f46a6179Smrg}
208f46a6179Smrg
20934345a63SmrgBool
21034345a63SmrgMergeNewField(unsigned field,
21134345a63Smrg              CommonInfo * oldDefs, CommonInfo * newDefs, unsigned *pCollide)
212f46a6179Smrg{
21334345a63Smrg    if ((oldDefs->defined & field) && (newDefs->defined & field))
21434345a63Smrg    {
21534345a63Smrg        if (((oldDefs->fileID == newDefs->fileID) && (warningLevel > 0)) ||
21634345a63Smrg            (warningLevel > 9))
21734345a63Smrg        {
21834345a63Smrg            *pCollide |= field;
21934345a63Smrg        }
22034345a63Smrg        if (newDefs->merge == MergeAugment)
22134345a63Smrg            return True;
222f46a6179Smrg    }
223f46a6179Smrg    return False;
224f46a6179Smrg}
225f46a6179Smrg
226f46a6179SmrgXPointer
22734345a63SmrgClearCommonInfo(CommonInfo * cmn)
228f46a6179Smrg{
22934345a63Smrg    if (cmn != NULL)
23034345a63Smrg    {
23134345a63Smrg        CommonInfo *this, *next;
23234345a63Smrg        for (this = cmn; this != NULL; this = next)
23334345a63Smrg        {
23434345a63Smrg            next = this->next;
23534345a63Smrg            uFree(this);
23634345a63Smrg        }
237f46a6179Smrg    }
238f46a6179Smrg    return NULL;
239f46a6179Smrg}
240f46a6179Smrg
241f46a6179SmrgXPointer
24234345a63SmrgAddCommonInfo(CommonInfo * old, CommonInfo * new)
243f46a6179Smrg{
24434345a63Smrg    CommonInfo *first;
245f46a6179Smrg
24634345a63Smrg    first = old;
24734345a63Smrg    while (old && old->next)
24834345a63Smrg    {
24934345a63Smrg        old = old->next;
250f46a6179Smrg    }
25134345a63Smrg    new->next = NULL;
25234345a63Smrg    if (old)
25334345a63Smrg    {
25434345a63Smrg        old->next = new;
25534345a63Smrg        return (XPointer) first;
256f46a6179Smrg    }
25734345a63Smrg    return (XPointer) new;
258f46a6179Smrg}
259f46a6179Smrg
260f46a6179Smrg/***====================================================================***/
261f46a6179Smrg
26234345a63Smrgtypedef struct _KeyNameDesc
26334345a63Smrg{
26434345a63Smrg    KeySym level1;
26534345a63Smrg    KeySym level2;
26634345a63Smrg    char name[5];
26734345a63Smrg    Bool used;
268f46a6179Smrg} KeyNameDesc;
269f46a6179Smrg
27034345a63Smrgstatic KeyNameDesc dfltKeys[] = {
27134345a63Smrg    {XK_Escape, NoSymbol, "ESC\0"},
27234345a63Smrg    {XK_quoteleft, XK_asciitilde, "TLDE"},
27334345a63Smrg    {XK_1, XK_exclam, "AE01"},
27434345a63Smrg    {XK_2, XK_at, "AE02"},
27534345a63Smrg    {XK_3, XK_numbersign, "AE03"},
27634345a63Smrg    {XK_4, XK_dollar, "AE04"},
27734345a63Smrg    {XK_5, XK_percent, "AE05"},
27834345a63Smrg    {XK_6, XK_asciicircum, "AE06"},
27934345a63Smrg    {XK_7, XK_ampersand, "AE07"},
28034345a63Smrg    {XK_8, XK_asterisk, "AE08"},
28134345a63Smrg    {XK_9, XK_parenleft, "AE09"},
28234345a63Smrg    {XK_0, XK_parenright, "AE10"},
28334345a63Smrg    {XK_minus, XK_underscore, "AE11"},
28434345a63Smrg    {XK_equal, XK_plus, "AE12"},
28534345a63Smrg    {XK_BackSpace, NoSymbol, "BKSP"},
28634345a63Smrg    {XK_Tab, NoSymbol, "TAB\0"},
28734345a63Smrg    {XK_q, XK_Q, "AD01"},
28834345a63Smrg    {XK_w, XK_W, "AD02"},
28934345a63Smrg    {XK_e, XK_E, "AD03"},
29034345a63Smrg    {XK_r, XK_R, "AD04"},
29134345a63Smrg    {XK_t, XK_T, "AD05"},
29234345a63Smrg    {XK_y, XK_Y, "AD06"},
29334345a63Smrg    {XK_u, XK_U, "AD07"},
29434345a63Smrg    {XK_i, XK_I, "AD08"},
29534345a63Smrg    {XK_o, XK_O, "AD09"},
29634345a63Smrg    {XK_p, XK_P, "AD10"},
29734345a63Smrg    {XK_bracketleft, XK_braceleft, "AD11"},
29834345a63Smrg    {XK_bracketright, XK_braceright, "AD12"},
29934345a63Smrg    {XK_Return, NoSymbol, "RTRN"},
30034345a63Smrg    {XK_Caps_Lock, NoSymbol, "CAPS"},
30134345a63Smrg    {XK_a, XK_A, "AC01"},
30234345a63Smrg    {XK_s, XK_S, "AC02"},
30334345a63Smrg    {XK_d, XK_D, "AC03"},
30434345a63Smrg    {XK_f, XK_F, "AC04"},
30534345a63Smrg    {XK_g, XK_G, "AC05"},
30634345a63Smrg    {XK_h, XK_H, "AC06"},
30734345a63Smrg    {XK_j, XK_J, "AC07"},
30834345a63Smrg    {XK_k, XK_K, "AC08"},
30934345a63Smrg    {XK_l, XK_L, "AC09"},
31034345a63Smrg    {XK_semicolon, XK_colon, "AC10"},
31134345a63Smrg    {XK_quoteright, XK_quotedbl, "AC11"},
31234345a63Smrg    {XK_Shift_L, NoSymbol, "LFSH"},
31334345a63Smrg    {XK_z, XK_Z, "AB01"},
31434345a63Smrg    {XK_x, XK_X, "AB02"},
31534345a63Smrg    {XK_c, XK_C, "AB03"},
31634345a63Smrg    {XK_v, XK_V, "AB04"},
31734345a63Smrg    {XK_b, XK_B, "AB05"},
31834345a63Smrg    {XK_n, XK_N, "AB06"},
31934345a63Smrg    {XK_m, XK_M, "AB07"},
32034345a63Smrg    {XK_comma, XK_less, "AB08"},
32134345a63Smrg    {XK_period, XK_greater, "AB09"},
32234345a63Smrg    {XK_slash, XK_question, "AB10"},
32334345a63Smrg    {XK_backslash, XK_bar, "BKSL"},
32434345a63Smrg    {XK_Control_L, NoSymbol, "LCTL"},
32534345a63Smrg    {XK_space, NoSymbol, "SPCE"},
32634345a63Smrg    {XK_Shift_R, NoSymbol, "RTSH"},
32734345a63Smrg    {XK_Alt_L, NoSymbol, "LALT"},
32834345a63Smrg    {XK_space, NoSymbol, "SPCE"},
32934345a63Smrg    {XK_Control_R, NoSymbol, "RCTL"},
33034345a63Smrg    {XK_Alt_R, NoSymbol, "RALT"},
33134345a63Smrg    {XK_F1, NoSymbol, "FK01"},
33234345a63Smrg    {XK_F2, NoSymbol, "FK02"},
33334345a63Smrg    {XK_F3, NoSymbol, "FK03"},
33434345a63Smrg    {XK_F4, NoSymbol, "FK04"},
33534345a63Smrg    {XK_F5, NoSymbol, "FK05"},
33634345a63Smrg    {XK_F6, NoSymbol, "FK06"},
33734345a63Smrg    {XK_F7, NoSymbol, "FK07"},
33834345a63Smrg    {XK_F8, NoSymbol, "FK08"},
33934345a63Smrg    {XK_F9, NoSymbol, "FK09"},
34034345a63Smrg    {XK_F10, NoSymbol, "FK10"},
34134345a63Smrg    {XK_F11, NoSymbol, "FK11"},
34234345a63Smrg    {XK_F12, NoSymbol, "FK12"},
34334345a63Smrg    {XK_Print, NoSymbol, "PRSC"},
34434345a63Smrg    {XK_Scroll_Lock, NoSymbol, "SCLK"},
34534345a63Smrg    {XK_Pause, NoSymbol, "PAUS"},
34634345a63Smrg    {XK_Insert, NoSymbol, "INS\0"},
34734345a63Smrg    {XK_Home, NoSymbol, "HOME"},
34834345a63Smrg    {XK_Prior, NoSymbol, "PGUP"},
34934345a63Smrg    {XK_Delete, NoSymbol, "DELE"},
35034345a63Smrg    {XK_End, NoSymbol, "END"},
35134345a63Smrg    {XK_Next, NoSymbol, "PGDN"},
35234345a63Smrg    {XK_Up, NoSymbol, "UP\0\0"},
35334345a63Smrg    {XK_Left, NoSymbol, "LEFT"},
35434345a63Smrg    {XK_Down, NoSymbol, "DOWN"},
35534345a63Smrg    {XK_Right, NoSymbol, "RGHT"},
35634345a63Smrg    {XK_Num_Lock, NoSymbol, "NMLK"},
35734345a63Smrg    {XK_KP_Divide, NoSymbol, "KPDV"},
35834345a63Smrg    {XK_KP_Multiply, NoSymbol, "KPMU"},
35934345a63Smrg    {XK_KP_Subtract, NoSymbol, "KPSU"},
36034345a63Smrg    {NoSymbol, XK_KP_7, "KP7\0"},
36134345a63Smrg    {NoSymbol, XK_KP_8, "KP8\0"},
36234345a63Smrg    {NoSymbol, XK_KP_9, "KP9\0"},
36334345a63Smrg    {XK_KP_Add, NoSymbol, "KPAD"},
36434345a63Smrg    {NoSymbol, XK_KP_4, "KP4\0"},
36534345a63Smrg    {NoSymbol, XK_KP_5, "KP5\0"},
36634345a63Smrg    {NoSymbol, XK_KP_6, "KP6\0"},
36734345a63Smrg    {NoSymbol, XK_KP_1, "KP1\0"},
36834345a63Smrg    {NoSymbol, XK_KP_2, "KP2\0"},
36934345a63Smrg    {NoSymbol, XK_KP_3, "KP3\0"},
37034345a63Smrg    {XK_KP_Enter, NoSymbol, "KPEN"},
37134345a63Smrg    {NoSymbol, XK_KP_0, "KP0\0"},
37234345a63Smrg    {XK_KP_Delete, NoSymbol, "KPDL"},
37334345a63Smrg    {XK_less, XK_greater, "LSGT"},
37434345a63Smrg    {XK_KP_Separator, NoSymbol, "KPCO"},
37534345a63Smrg    {XK_Find, NoSymbol, "FIND"},
37634345a63Smrg    {NoSymbol, NoSymbol, "\0\0\0\0"}
377f46a6179Smrg};
378f46a6179Smrg
379f46a6179SmrgStatus
380f46a6179SmrgComputeKbdDefaults(XkbDescPtr xkb)
381f46a6179Smrg{
38234345a63Smrg    Status rtrn;
38334345a63Smrg    register int i, tmp, nUnknown;
38434345a63Smrg    KeyNameDesc *name;
38534345a63Smrg    KeySym *syms;
38634345a63Smrg    char tmpname[XkbKeyNameLength + 1];
38734345a63Smrg
38834345a63Smrg    if ((xkb->names == NULL) || (xkb->names->keys == NULL))
38934345a63Smrg    {
39034345a63Smrg        if ((rtrn = XkbAllocNames(xkb, XkbKeyNamesMask, 0, 0)) != Success)
39134345a63Smrg            return rtrn;
392f46a6179Smrg    }
39334345a63Smrg    for (name = dfltKeys; (name->name[0] != '\0'); name++)
39434345a63Smrg    {
39534345a63Smrg        name->used = False;
396f46a6179Smrg    }
39734345a63Smrg    nUnknown = 0;
39834345a63Smrg    for (i = xkb->min_key_code; i <= xkb->max_key_code; i++)
39934345a63Smrg    {
40034345a63Smrg        tmp = XkbKeyNumSyms(xkb, i);
40134345a63Smrg        if ((xkb->names->keys[i].name[0] == '\0') && (tmp > 0))
40234345a63Smrg        {
40334345a63Smrg            tmp = XkbKeyGroupsWidth(xkb, i);
40434345a63Smrg            syms = XkbKeySymsPtr(xkb, i);
40534345a63Smrg            for (name = dfltKeys; (name->name[0] != '\0'); name++)
40634345a63Smrg            {
40734345a63Smrg                Bool match = True;
40834345a63Smrg                if (((name->level1 != syms[0])
40934345a63Smrg                     && (name->level1 != NoSymbol))
41034345a63Smrg                    || ((name->level2 != NoSymbol) && (tmp < 2))
41134345a63Smrg                    || ((name->level2 != syms[1])
41234345a63Smrg                        && (name->level2 != NoSymbol)))
41334345a63Smrg                {
41434345a63Smrg                    match = False;
41534345a63Smrg                }
41634345a63Smrg                if (match)
41734345a63Smrg                {
41834345a63Smrg                    if (!name->used)
41934345a63Smrg                    {
42034345a63Smrg                        memcpy(xkb->names->keys[i].name, name->name,
42134345a63Smrg                               XkbKeyNameLength);
42234345a63Smrg                        name->used = True;
42334345a63Smrg                    }
42434345a63Smrg                    else
42534345a63Smrg                    {
42634345a63Smrg                        if (warningLevel > 2)
42734345a63Smrg                        {
42834345a63Smrg                            WARN1
42934345a63Smrg                                ("Several keys match pattern for %s\n",
43034345a63Smrg                                 XkbKeyNameText(name->name, XkbMessage));
43134345a63Smrg                            ACTION2("Using <U%03d> for key %d\n",
43234345a63Smrg                                    nUnknown, i);
43334345a63Smrg                        }
43434345a63Smrg                        snprintf(tmpname, sizeof(tmpname), "U%03d",
43534345a63Smrg                                 nUnknown++);
43634345a63Smrg                        memcpy(xkb->names->keys[i].name, tmpname,
43734345a63Smrg                               XkbKeyNameLength);
43834345a63Smrg                    }
43934345a63Smrg                    break;
44034345a63Smrg                }
44134345a63Smrg            }
44234345a63Smrg            if (xkb->names->keys[i].name[0] == '\0')
44334345a63Smrg            {
44434345a63Smrg                if (warningLevel > 2)
44534345a63Smrg                {
44634345a63Smrg                    WARN1("Key %d does not match any defaults\n", i);
44734345a63Smrg                    ACTION1("Using name <U%03d>\n", nUnknown);
44834345a63Smrg                    snprintf(tmpname, sizeof(tmpname), "U%03d", nUnknown++);
44934345a63Smrg                    memcpy(xkb->names->keys[i].name, tmpname,
45034345a63Smrg                           XkbKeyNameLength);
45134345a63Smrg                }
45234345a63Smrg            }
45334345a63Smrg        }
454f46a6179Smrg    }
455f46a6179Smrg    return Success;
456f46a6179Smrg}
457f46a6179Smrg
45834345a63Smrg/**
45934345a63Smrg * Find the key with the given name and return its keycode in kc_rtrn.
46034345a63Smrg *
46134345a63Smrg * @param name The 4-letter name of the key as a long.
46234345a63Smrg * @param kc_rtrn Set to the keycode if the key was found, otherwise 0.
46334345a63Smrg * @param use_aliases True if the key aliases should be searched too.
46434345a63Smrg * @param create If True and the key is not found, it is added to the
46534345a63Smrg *        xkb->names at the first free keycode.
46634345a63Smrg * @param start_from Keycode to start searching from.
46734345a63Smrg *
46834345a63Smrg * @return True if found, False otherwise.
46934345a63Smrg */
470f46a6179SmrgBool
47134345a63SmrgFindNamedKey(XkbDescPtr xkb,
47234345a63Smrg             unsigned long name,
47334345a63Smrg             unsigned int *kc_rtrn,
47434345a63Smrg             Bool use_aliases, Bool create, int start_from)
475f46a6179Smrg{
47634345a63Smrg    register unsigned n;
477f46a6179Smrg
47834345a63Smrg    if (start_from < xkb->min_key_code)
47934345a63Smrg    {
48034345a63Smrg        start_from = xkb->min_key_code;
481f46a6179Smrg    }
48234345a63Smrg    else if (start_from > xkb->max_key_code)
48334345a63Smrg    {
48434345a63Smrg        return False;
485f46a6179Smrg    }
486f46a6179Smrg
48734345a63Smrg    *kc_rtrn = 0;               /* some callers rely on this */
48834345a63Smrg    if (xkb && xkb->names && xkb->names->keys)
48934345a63Smrg    {
49034345a63Smrg        for (n = start_from; n <= xkb->max_key_code; n++)
49134345a63Smrg        {
49234345a63Smrg            unsigned long tmp;
49334345a63Smrg            tmp = KeyNameToLong(xkb->names->keys[n].name);
49434345a63Smrg            if (tmp == name)
49534345a63Smrg            {
49634345a63Smrg                *kc_rtrn = n;
49734345a63Smrg                return True;
49834345a63Smrg            }
49934345a63Smrg        }
50034345a63Smrg        if (use_aliases)
50134345a63Smrg        {
50234345a63Smrg            unsigned long new_name;
50334345a63Smrg            if (FindKeyNameForAlias(xkb, name, &new_name))
50434345a63Smrg                return FindNamedKey(xkb, new_name, kc_rtrn, False, create, 0);
50534345a63Smrg        }
506f46a6179Smrg    }
50734345a63Smrg    if (create)
50834345a63Smrg    {
50934345a63Smrg        if ((!xkb->names) || (!xkb->names->keys))
51034345a63Smrg        {
51134345a63Smrg            if (xkb->min_key_code < XkbMinLegalKeyCode)
51234345a63Smrg            {
51334345a63Smrg                xkb->min_key_code = XkbMinLegalKeyCode;
51434345a63Smrg                xkb->max_key_code = XkbMaxLegalKeyCode;
51534345a63Smrg            }
51634345a63Smrg            if (XkbAllocNames(xkb, XkbKeyNamesMask, 0, 0) != Success)
51734345a63Smrg            {
51834345a63Smrg                if (warningLevel > 0)
51934345a63Smrg                {
52034345a63Smrg                    WARN("Couldn't allocate key names in FindNamedKey\n");
52134345a63Smrg                    ACTION1("Key \"%s\" not automatically created\n",
52234345a63Smrg                            longText(name, XkbMessage));
52334345a63Smrg                }
52434345a63Smrg                return False;
52534345a63Smrg            }
52634345a63Smrg        }
52734345a63Smrg        /* Find first unused keycode and store our key here */
52834345a63Smrg        for (n = xkb->min_key_code; n <= xkb->max_key_code; n++)
52934345a63Smrg        {
53034345a63Smrg            if (xkb->names->keys[n].name[0] == '\0')
53134345a63Smrg            {
53234345a63Smrg                char buf[XkbKeyNameLength + 1];
53334345a63Smrg                LongToKeyName(name, buf);
53434345a63Smrg                memcpy(xkb->names->keys[n].name, buf, XkbKeyNameLength);
53534345a63Smrg                *kc_rtrn = n;
53634345a63Smrg                return True;
53734345a63Smrg            }
53834345a63Smrg        }
539f46a6179Smrg    }
540f46a6179Smrg    return False;
541f46a6179Smrg}
542f46a6179Smrg
543f46a6179SmrgBool
54434345a63SmrgFindKeyNameForAlias(XkbDescPtr xkb, unsigned long lname,
54534345a63Smrg                    unsigned long *real_name)
546f46a6179Smrg{
54734345a63Smrg    register int i;
54834345a63Smrg    char name[XkbKeyNameLength + 1];
54934345a63Smrg
55034345a63Smrg    if (xkb && xkb->geom && xkb->geom->key_aliases)
55134345a63Smrg    {
55234345a63Smrg        XkbKeyAliasPtr a;
55334345a63Smrg        a = xkb->geom->key_aliases;
55434345a63Smrg        LongToKeyName(lname, name);
55534345a63Smrg        name[XkbKeyNameLength] = '\0';
55634345a63Smrg        for (i = 0; i < xkb->geom->num_key_aliases; i++, a++)
55734345a63Smrg        {
55834345a63Smrg            if (strncmp(name, a->alias, XkbKeyNameLength) == 0)
55934345a63Smrg            {
56034345a63Smrg                *real_name = KeyNameToLong(a->real);
56134345a63Smrg                return True;
56234345a63Smrg            }
56334345a63Smrg        }
564f46a6179Smrg    }
56534345a63Smrg    if (xkb && xkb->names && xkb->names->key_aliases)
56634345a63Smrg    {
56734345a63Smrg        XkbKeyAliasPtr a;
56834345a63Smrg        a = xkb->names->key_aliases;
56934345a63Smrg        LongToKeyName(lname, name);
57034345a63Smrg        name[XkbKeyNameLength] = '\0';
57134345a63Smrg        for (i = 0; i < xkb->names->num_key_aliases; i++, a++)
57234345a63Smrg        {
57334345a63Smrg            if (strncmp(name, a->alias, XkbKeyNameLength) == 0)
57434345a63Smrg            {
57534345a63Smrg                *real_name = KeyNameToLong(a->real);
57634345a63Smrg                return True;
57734345a63Smrg            }
57834345a63Smrg        }
579f46a6179Smrg    }
580f46a6179Smrg    return False;
581f46a6179Smrg}
582