18c9fbc29Smrg/************************************************************
28c9fbc29Smrg Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
38c9fbc29Smrg
48c9fbc29Smrg Permission to use, copy, modify, and distribute this
58c9fbc29Smrg software and its documentation for any purpose and without
68c9fbc29Smrg fee is hereby granted, provided that the above copyright
78c9fbc29Smrg notice appear in all copies and that both that copyright
88c9fbc29Smrg notice and this permission notice appear in supporting
94cd6a3aeSmrg documentation, and that the name of Silicon Graphics not be
104cd6a3aeSmrg used in advertising or publicity pertaining to distribution
118c9fbc29Smrg of the software without specific prior written permission.
124cd6a3aeSmrg Silicon Graphics makes no representation about the suitability
138c9fbc29Smrg of this software for any purpose. It is provided "as is"
148c9fbc29Smrg without any express or implied warranty.
154cd6a3aeSmrg
164cd6a3aeSmrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
174cd6a3aeSmrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
188c9fbc29Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
194cd6a3aeSmrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
204cd6a3aeSmrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
214cd6a3aeSmrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
228c9fbc29Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
238c9fbc29Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE.
248c9fbc29Smrg
258c9fbc29Smrg ********************************************************/
268c9fbc29Smrg
278c9fbc29Smrg#ifdef HAVE_DIX_CONFIG_H
288c9fbc29Smrg#include <dix-config.h>
298c9fbc29Smrg#elif defined(HAVE_CONFIG_H)
308c9fbc29Smrg#include <config.h>
318c9fbc29Smrg#endif
328c9fbc29Smrg
338c9fbc29Smrg#include <stdio.h>
348c9fbc29Smrg#include <ctype.h>
358c9fbc29Smrg#include <stdlib.h>
368c9fbc29Smrg
378c9fbc29Smrg#include <X11/Xos.h>
388c9fbc29Smrg#include <X11/Xfuncs.h>
398c9fbc29Smrg
408c9fbc29Smrg
418c9fbc29Smrg#include <X11/Xlib.h>
428c9fbc29Smrg#include <X11/keysym.h>
438c9fbc29Smrg#include <X11/XKBlib.h>
448c9fbc29Smrg#include <X11/extensions/XKBgeom.h>
458c9fbc29Smrg#include "XKMformat.h"
468c9fbc29Smrg#include "XKBfileInt.h"
478c9fbc29Smrg
488c9fbc29Smrg
498c9fbc29Smrgunsigned
508c9fbc29Smrg_XkbKSCheckCase(KeySym ks)
518c9fbc29Smrg{
5270728a38Smrg    unsigned set, rtrn;
538c9fbc29Smrg
5470728a38Smrg    set = (ks & (~0xff)) >> 8;
5570728a38Smrg    rtrn = 0;
568c9fbc29Smrg    switch (set) {
5770728a38Smrg    case 0:                    /* latin 1 */
5870728a38Smrg        if (((ks >= XK_A) && (ks <= XK_Z)) ||
5970728a38Smrg            ((ks >= XK_Agrave) && (ks <= XK_THORN) && (ks != XK_multiply))) {
6070728a38Smrg            rtrn |= _XkbKSUpper;
6170728a38Smrg        }
6270728a38Smrg        if (((ks >= XK_a) && (ks <= XK_z)) ||
6370728a38Smrg            ((ks >= XK_agrave) && (ks <= XK_ydiaeresis))) {
6470728a38Smrg            rtrn |= _XkbKSLower;
6570728a38Smrg        }
6670728a38Smrg        break;
6770728a38Smrg    case 1:                    /* latin 2 */
6870728a38Smrg        if (((ks >= XK_Aogonek) && (ks <= XK_Zabovedot) && (ks != XK_breve)) ||
6970728a38Smrg            ((ks >= XK_Racute) && (ks <= XK_Tcedilla))) {
7070728a38Smrg            rtrn |= _XkbKSUpper;
7170728a38Smrg        }
7270728a38Smrg        if (((ks >= XK_aogonek) && (ks <= XK_zabovedot) && (ks != XK_caron)) ||
7370728a38Smrg            ((ks >= XK_racute) && (ks <= XK_tcedilla))) {
7470728a38Smrg            rtrn |= _XkbKSLower;
7570728a38Smrg        }
7670728a38Smrg        break;
7770728a38Smrg    case 2:                    /* latin 3 */
7870728a38Smrg        if (((ks >= XK_Hstroke) && (ks <= XK_Jcircumflex)) ||
7970728a38Smrg            ((ks >= XK_Cabovedot) && (ks <= XK_Scircumflex))) {
8070728a38Smrg            rtrn |= _XkbKSUpper;
8170728a38Smrg        }
8270728a38Smrg        if (((ks >= XK_hstroke) && (ks <= XK_jcircumflex)) ||
8370728a38Smrg            ((ks >= XK_cabovedot) && (ks <= XK_scircumflex))) {
8470728a38Smrg            rtrn |= _XkbKSLower;
8570728a38Smrg        }
8670728a38Smrg        break;
8770728a38Smrg    case 3:                    /* latin 4 */
8870728a38Smrg        if (((ks >= XK_Rcedilla) && (ks <= XK_Tslash)) ||
8970728a38Smrg            (ks == XK_ENG) || ((ks >= XK_Amacron) && (ks <= XK_Umacron))) {
9070728a38Smrg            rtrn |= _XkbKSUpper;
9170728a38Smrg        }
9270728a38Smrg        if (((ks >= XK_rcedilla) && (ks <= XK_tslash)) ||
9370728a38Smrg            (ks == XK_eng) || ((ks >= XK_amacron) && (ks <= XK_umacron))) {
9470728a38Smrg            rtrn |= _XkbKSLower;
9570728a38Smrg        }
9670728a38Smrg        break;
9770728a38Smrg    case 18:                   /* latin 8 */
9870728a38Smrg        if ((ks == XK_Babovedot) ||
9970728a38Smrg            ((ks >= XK_Dabovedot) && (ks <= XK_Wacute)) ||
10070728a38Smrg            ((ks >= XK_Ygrave) && (ks <= XK_Fabovedot)) ||
10170728a38Smrg            (ks == XK_Mabovedot) ||
10270728a38Smrg            (ks == XK_Pabovedot) ||
10370728a38Smrg            (ks == XK_Sabovedot) ||
10470728a38Smrg            (ks == XK_Wdiaeresis) ||
10570728a38Smrg            ((ks >= XK_Wcircumflex) && (ks <= XK_Ycircumflex))) {
10670728a38Smrg            rtrn |= _XkbKSUpper;
10770728a38Smrg        }
10870728a38Smrg        if ((ks == XK_babovedot) ||
10970728a38Smrg            (ks == XK_dabovedot) ||
11070728a38Smrg            (ks == XK_fabovedot) ||
11170728a38Smrg            (ks == XK_mabovedot) ||
11270728a38Smrg            ((ks >= XK_wgrave) && (ks <= XK_wacute)) ||
11370728a38Smrg            (ks == XK_ygrave) ||
11470728a38Smrg            ((ks >= XK_wdiaeresis) && (ks <= XK_ycircumflex))) {
11570728a38Smrg            rtrn |= _XkbKSLower;
11670728a38Smrg        }
11770728a38Smrg        break;
11870728a38Smrg    case 19:                   /* latin 9 */
11970728a38Smrg        if ((ks == XK_OE) || (ks == XK_Ydiaeresis)) {
12070728a38Smrg            rtrn |= _XkbKSUpper;
12170728a38Smrg        }
12270728a38Smrg        if (ks == XK_oe) {
12370728a38Smrg            rtrn |= _XkbKSLower;
12470728a38Smrg        }
12570728a38Smrg        break;
1268c9fbc29Smrg    }
1278c9fbc29Smrg    return rtrn;
1288c9fbc29Smrg}
1298c9fbc29Smrg
1308c9fbc29Smrg/***===================================================================***/
1318c9fbc29Smrg
1328c9fbc29SmrgBool
13370728a38SmrgXkbLookupGroupAndLevel(XkbDescPtr       xkb,
13470728a38Smrg                       int              key,
13570728a38Smrg                       int *            mods_inout,
13670728a38Smrg                       int *            grp_inout,
13770728a38Smrg                       int *            lvl_rtrn)
1388c9fbc29Smrg{
13970728a38Smrg    int nG, eG;
1408c9fbc29Smrg
14170728a38Smrg    if ((!xkb) || (!XkbKeycodeInRange(xkb, key)) || (!grp_inout))
14270728a38Smrg        return False;
1438c9fbc29Smrg
14470728a38Smrg    nG = XkbKeyNumGroups(xkb, key);
14570728a38Smrg    eG = *grp_inout;
1468c9fbc29Smrg
14770728a38Smrg    if (nG == 0) {
14870728a38Smrg        *grp_inout = 0;
14970728a38Smrg        if (lvl_rtrn != NULL)
15070728a38Smrg            *lvl_rtrn = 0;
15170728a38Smrg        return False;
1528c9fbc29Smrg    }
15370728a38Smrg    else if (nG == 1) {
15470728a38Smrg        eG = 0;
1558c9fbc29Smrg    }
15670728a38Smrg    else if (eG >= nG) {
15770728a38Smrg        unsigned gI = XkbKeyGroupInfo(xkb, key);
15870728a38Smrg
15970728a38Smrg        switch (XkbOutOfRangeGroupAction(gI)) {
16070728a38Smrg        default:
16170728a38Smrg            eG %= nG;
16270728a38Smrg            break;
16370728a38Smrg        case XkbClampIntoRange:
16470728a38Smrg            eG = nG - 1;
16570728a38Smrg            break;
16670728a38Smrg        case XkbRedirectIntoRange:
16770728a38Smrg            eG = XkbOutOfRangeGroupNumber(gI);
16870728a38Smrg            if (eG >= nG)
16970728a38Smrg                eG = 0;
17070728a38Smrg            break;
17170728a38Smrg        }
1728c9fbc29Smrg    }
17370728a38Smrg    *grp_inout = eG;
17470728a38Smrg    if (mods_inout != NULL) {
17570728a38Smrg        XkbKeyTypePtr type;
17670728a38Smrg        int preserve;
17770728a38Smrg
17870728a38Smrg        type = XkbKeyKeyType(xkb, key, eG);
17970728a38Smrg        if (lvl_rtrn != NULL)
18070728a38Smrg            *lvl_rtrn = 0;
18170728a38Smrg        preserve = 0;
18270728a38Smrg        if (type->map) {        /* find the shift level */
18370728a38Smrg            register int i;
18470728a38Smrg            register XkbKTMapEntryPtr entry;
18570728a38Smrg
18670728a38Smrg            for (i = 0, entry = type->map; i < type->map_count; i++, entry++) {
18770728a38Smrg                if ((entry->active) &&
18870728a38Smrg                    (((*mods_inout) & type->mods.mask) == entry->mods.mask)) {
18970728a38Smrg                    if (lvl_rtrn != NULL)
19070728a38Smrg                        *lvl_rtrn = entry->level;
19170728a38Smrg                    if (type->preserve)
19270728a38Smrg                        preserve = type->preserve[i].mask;
19370728a38Smrg                    break;
19470728a38Smrg                }
19570728a38Smrg            }
19670728a38Smrg        }
19770728a38Smrg        (*mods_inout) &= ~(type->mods.mask & (~preserve));
1988c9fbc29Smrg    }
1998c9fbc29Smrg    return True;
2008c9fbc29Smrg}
2018c9fbc29Smrg
2028c9fbc29Smrg/***===================================================================***/
2038c9fbc29Smrg
2048c9fbc29Smrgstatic Bool
2054cd6a3aeSmrgXkbWriteSectionFromName(FILE *file, const char *sectionName, const char *name)
2068c9fbc29Smrg{
20770728a38Smrg    fprintf(file, "    xkb_%-20s { include \"%s\" };\n", sectionName, name);
2088c9fbc29Smrg    return True;
2098c9fbc29Smrg}
2108c9fbc29Smrg
2118c9fbc29Smrg#define	NEED_DESC(n) ((!n)||((n)[0]=='+')||((n)[0]=='|')||(strchr((n),'%')))
2128c9fbc29Smrg#define	COMPLETE(n)  ((n)&&(!NEED_DESC(n)))
2138c9fbc29Smrg
2148c9fbc29Smrg/* ARGSUSED */
2158c9fbc29Smrgstatic void
21670728a38Smrg_AddIncl(FILE *         file,
21770728a38Smrg         XkbFileInfo *  result,
21870728a38Smrg         Bool           topLevel,
21970728a38Smrg         Bool           showImplicit,
22070728a38Smrg         int            index,
22170728a38Smrg         void *         priv)
2228c9fbc29Smrg{
22370728a38Smrg    if ((priv) && (strcmp((char *) priv, "%") != 0))
22470728a38Smrg        fprintf(file, "    include \"%s\"\n", (char *) priv);
2258c9fbc29Smrg    return;
2268c9fbc29Smrg}
2278c9fbc29Smrg
2288c9fbc29SmrgBool
22970728a38SmrgXkbWriteXKBKeymapForNames(FILE *                file,
23070728a38Smrg                          XkbComponentNamesPtr  names,
23170728a38Smrg                          Display *             dpy,
23270728a38Smrg                          XkbDescPtr            xkb,
23370728a38Smrg                          unsigned              want,
23470728a38Smrg                          unsigned              need)
2358c9fbc29Smrg{
23670728a38Smrg    char *name, *tmp;
23770728a38Smrg    unsigned complete;
23870728a38Smrg    XkbNamesPtr old_names;
23970728a38Smrg    int multi_section;
24070728a38Smrg    unsigned wantNames, wantConfig, wantDflts;
24170728a38Smrg    XkbFileInfo finfo;
24270728a38Smrg
24370728a38Smrg    bzero(&finfo, sizeof(XkbFileInfo));
24470728a38Smrg
24570728a38Smrg    complete = 0;
24670728a38Smrg    if ((name = names->keymap) == NULL)
24770728a38Smrg        name = "default";
24870728a38Smrg    if (COMPLETE(names->keycodes))
24970728a38Smrg        complete |= XkmKeyNamesMask;
25070728a38Smrg    if (COMPLETE(names->types))
25170728a38Smrg        complete |= XkmTypesMask;
25270728a38Smrg    if (COMPLETE(names->compat))
25370728a38Smrg        complete |= XkmCompatMapMask;
25470728a38Smrg    if (COMPLETE(names->symbols))
25570728a38Smrg        complete |= XkmSymbolsMask;
25670728a38Smrg    if (COMPLETE(names->geometry))
25770728a38Smrg        complete |= XkmGeometryMask;
25870728a38Smrg    want |= (complete | need);
25970728a38Smrg    if (want & XkmSymbolsMask)
26070728a38Smrg        want |= XkmKeyNamesMask | XkmTypesMask;
26170728a38Smrg
26270728a38Smrg    if (want == 0)
26370728a38Smrg        return False;
26470728a38Smrg
26570728a38Smrg    if (xkb != NULL) {
26670728a38Smrg        old_names = xkb->names;
26770728a38Smrg        finfo.type = 0;
26870728a38Smrg        finfo.defined = 0;
26970728a38Smrg        finfo.xkb = xkb;
27070728a38Smrg        if (!XkbDetermineFileType(&finfo, XkbXKBFile, NULL))
27170728a38Smrg            return False;
2728c9fbc29Smrg    }
27370728a38Smrg    else
27470728a38Smrg        old_names = NULL;
27570728a38Smrg
27670728a38Smrg    wantConfig = want & (~complete);
27770728a38Smrg    if (xkb != NULL) {
27870728a38Smrg        if (wantConfig & XkmTypesMask) {
27970728a38Smrg            if ((!xkb->map) || (xkb->map->num_types < XkbNumRequiredTypes))
28070728a38Smrg                wantConfig &= ~XkmTypesMask;
28170728a38Smrg        }
28270728a38Smrg        if (wantConfig & XkmCompatMapMask) {
28370728a38Smrg            if ((!xkb->compat) || (xkb->compat->num_si < 1))
28470728a38Smrg                wantConfig &= ~XkmCompatMapMask;
28570728a38Smrg        }
28670728a38Smrg        if (wantConfig & XkmSymbolsMask) {
28770728a38Smrg            if ((!xkb->map) || (!xkb->map->key_sym_map))
28870728a38Smrg                wantConfig &= ~XkmSymbolsMask;
28970728a38Smrg        }
29070728a38Smrg        if (wantConfig & XkmIndicatorsMask) {
29170728a38Smrg            if (!xkb->indicators)
29270728a38Smrg                wantConfig &= ~XkmIndicatorsMask;
29370728a38Smrg        }
29470728a38Smrg        if (wantConfig & XkmKeyNamesMask) {
29570728a38Smrg            if ((!xkb->names) || (!xkb->names->keys))
29670728a38Smrg                wantConfig &= ~XkmKeyNamesMask;
29770728a38Smrg        }
29870728a38Smrg        if ((wantConfig & XkmGeometryMask) && (!xkb->geom))
29970728a38Smrg            wantConfig &= ~XkmGeometryMask;
3008c9fbc29Smrg    }
3018c9fbc29Smrg    else {
30270728a38Smrg        wantConfig = 0;
3038c9fbc29Smrg    }
30470728a38Smrg    complete |= wantConfig;
30570728a38Smrg
30670728a38Smrg    wantDflts = 0;
30770728a38Smrg    wantNames = want & (~complete);
30870728a38Smrg    if ((xkb != NULL) && (old_names != NULL)) {
30970728a38Smrg        if (wantNames & XkmTypesMask) {
31070728a38Smrg            if (old_names->types != None) {
31170728a38Smrg                tmp = XkbAtomGetString(dpy, old_names->types);
31270728a38Smrg                names->types = tmp;
31370728a38Smrg            }
31470728a38Smrg            else {
31570728a38Smrg                wantDflts |= XkmTypesMask;
31670728a38Smrg            }
31770728a38Smrg            complete |= XkmTypesMask;
31870728a38Smrg        }
31970728a38Smrg        if (wantNames & XkmCompatMapMask) {
32070728a38Smrg            if (old_names->compat != None) {
32170728a38Smrg                tmp = XkbAtomGetString(dpy, old_names->compat);
32270728a38Smrg                names->compat = tmp;
32370728a38Smrg            }
32470728a38Smrg            else
32570728a38Smrg                wantDflts |= XkmCompatMapMask;
32670728a38Smrg            complete |= XkmCompatMapMask;
32770728a38Smrg        }
32870728a38Smrg        if (wantNames & XkmSymbolsMask) {
32970728a38Smrg            if (old_names->symbols == None)
33070728a38Smrg                return False;
33170728a38Smrg            tmp = XkbAtomGetString(dpy, old_names->symbols);
33270728a38Smrg            names->symbols = tmp;
33370728a38Smrg            complete |= XkmSymbolsMask;
33470728a38Smrg        }
33570728a38Smrg        if (wantNames & XkmKeyNamesMask) {
33670728a38Smrg            if (old_names->keycodes != None) {
33770728a38Smrg                tmp = XkbAtomGetString(dpy, old_names->keycodes);
33870728a38Smrg                names->keycodes = tmp;
33970728a38Smrg            }
34070728a38Smrg            else
34170728a38Smrg                wantDflts |= XkmKeyNamesMask;
34270728a38Smrg            complete |= XkmKeyNamesMask;
34370728a38Smrg        }
34470728a38Smrg        if (wantNames & XkmGeometryMask) {
34570728a38Smrg            if (old_names->geometry == None)
34670728a38Smrg                return False;
34770728a38Smrg            tmp = XkbAtomGetString(dpy, old_names->geometry);
34870728a38Smrg            names->geometry = tmp;
34970728a38Smrg            complete |= XkmGeometryMask;
35070728a38Smrg            wantNames &= ~XkmGeometryMask;
35170728a38Smrg        }
3528c9fbc29Smrg    }
35370728a38Smrg    if (complete & XkmCompatMapMask)
35470728a38Smrg        complete |= XkmIndicatorsMask | XkmVirtualModsMask;
35570728a38Smrg    else if (complete & (XkmSymbolsMask | XkmTypesMask))
35670728a38Smrg        complete |= XkmVirtualModsMask;
3578c9fbc29Smrg    if (need & (~complete))
35870728a38Smrg        return False;
35970728a38Smrg    if ((complete & XkmSymbolsMask) &&
36070728a38Smrg        ((XkmKeyNamesMask | XkmTypesMask) & (~complete)))
36170728a38Smrg        return False;
36270728a38Smrg
36370728a38Smrg    multi_section = 1;
36470728a38Smrg    if (((complete & XkmKeymapRequired) == XkmKeymapRequired) &&
36570728a38Smrg        ((complete & (~XkmKeymapLegal)) == 0)) {
36670728a38Smrg        fprintf(file, "xkb_keymap \"%s\" {\n", name);
3678c9fbc29Smrg    }
36870728a38Smrg    else if (((complete & XkmSemanticsRequired) == XkmSemanticsRequired) &&
36970728a38Smrg             ((complete & (~XkmSemanticsLegal)) == 0)) {
37070728a38Smrg        fprintf(file, "xkb_semantics \"%s\" {\n", name);
3718c9fbc29Smrg    }
37270728a38Smrg    else if (((complete & XkmLayoutRequired) == XkmLayoutRequired) &&
37370728a38Smrg             ((complete & (~XkmLayoutLegal)) == 0)) {
37470728a38Smrg        fprintf(file, "xkb_layout \"%s\" {\n", name);
3758c9fbc29Smrg    }
37670728a38Smrg    else if (XkmSingleSection(complete & (~XkmVirtualModsMask))) {
37770728a38Smrg        multi_section = 0;
3788c9fbc29Smrg    }
3798c9fbc29Smrg    else {
38070728a38Smrg        return False;
3818c9fbc29Smrg    }
3828c9fbc29Smrg
38370728a38Smrg    wantNames = complete & (~(wantConfig | wantDflts));
38470728a38Smrg    name = names->keycodes;
38570728a38Smrg    if (wantConfig & XkmKeyNamesMask)
38670728a38Smrg        XkbWriteXKBKeycodes(file, &finfo, False, False, _AddIncl, name);
38770728a38Smrg    else if (wantDflts & XkmKeyNamesMask)
38870728a38Smrg        fprintf(stderr, "Default symbols not implemented yet!\n");
38970728a38Smrg    else if (wantNames & XkmKeyNamesMask)
39070728a38Smrg        XkbWriteSectionFromName(file, "keycodes", name);
39170728a38Smrg
39270728a38Smrg    name = names->types;
39370728a38Smrg    if (wantConfig & XkmTypesMask)
39470728a38Smrg        XkbWriteXKBKeyTypes(file, &finfo, False, False, _AddIncl, name);
39570728a38Smrg    else if (wantDflts & XkmTypesMask)
39670728a38Smrg        fprintf(stderr, "Default types not implemented yet!\n");
39770728a38Smrg    else if (wantNames & XkmTypesMask)
39870728a38Smrg        XkbWriteSectionFromName(file, "types", name);
39970728a38Smrg
40070728a38Smrg    name = names->compat;
40170728a38Smrg    if (wantConfig & XkmCompatMapMask)
40270728a38Smrg        XkbWriteXKBCompatMap(file, &finfo, False, False, _AddIncl, name);
40370728a38Smrg    else if (wantDflts & XkmCompatMapMask)
40470728a38Smrg        fprintf(stderr, "Default interps not implemented yet!\n");
40570728a38Smrg    else if (wantNames & XkmCompatMapMask)
40670728a38Smrg        XkbWriteSectionFromName(file, "compatibility", name);
40770728a38Smrg
40870728a38Smrg    name = names->symbols;
40970728a38Smrg    if (wantConfig & XkmSymbolsMask)
41070728a38Smrg        XkbWriteXKBSymbols(file, &finfo, False, False, _AddIncl, name);
41170728a38Smrg    else if (wantNames & XkmSymbolsMask)
41270728a38Smrg        XkbWriteSectionFromName(file, "symbols", name);
41370728a38Smrg
41470728a38Smrg    name = names->geometry;
41570728a38Smrg    if (wantConfig & XkmGeometryMask)
41670728a38Smrg        XkbWriteXKBGeometry(file, &finfo, False, False, _AddIncl, name);
41770728a38Smrg    else if (wantNames & XkmGeometryMask)
41870728a38Smrg        XkbWriteSectionFromName(file, "geometry", name);
4198c9fbc29Smrg
4208c9fbc29Smrg    if (multi_section)
42170728a38Smrg        fprintf(file, "};\n");
4228c9fbc29Smrg    return True;
4238c9fbc29Smrg}
4248c9fbc29Smrg
4258c9fbc29Smrg/***====================================================================***/
4268c9fbc29Smrg
4278c9fbc29Smrg/*ARGSUSED*/
4288c9fbc29SmrgStatus
42970728a38SmrgXkbMergeFile(XkbDescPtr xkb, XkbFileInfo finfo)
4308c9fbc29Smrg{
4318c9fbc29Smrg    return BadImplementation;
4328c9fbc29Smrg}
4338c9fbc29Smrg
4348c9fbc29Smrg/***====================================================================***/
4358c9fbc29Smrg
4368c9fbc29Smrgint
43770728a38SmrgXkbFindKeycodeByName(XkbDescPtr xkb, char *name, Bool use_aliases)
4388c9fbc29Smrg{
43970728a38Smrg    register int i;
4408c9fbc29Smrg
44170728a38Smrg    if ((!xkb) || (!xkb->names) || (!xkb->names->keys))
44270728a38Smrg        return 0;
44370728a38Smrg    for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
44470728a38Smrg        if (strncmp(xkb->names->keys[i].name, name, XkbKeyNameLength) == 0)
44570728a38Smrg            return i;
4468c9fbc29Smrg    }
4478c9fbc29Smrg    if (!use_aliases)
44870728a38Smrg        return 0;
4498c9fbc29Smrg    if (xkb->geom && xkb->geom->key_aliases) {
45070728a38Smrg        XkbKeyAliasPtr a;
45170728a38Smrg
45270728a38Smrg        a = xkb->geom->key_aliases;
45370728a38Smrg        for (i = 0; i < xkb->geom->num_key_aliases; i++, a++) {
45470728a38Smrg            if (strncmp(name, a->alias, XkbKeyNameLength) == 0)
45570728a38Smrg                return XkbFindKeycodeByName(xkb, a->real, False);
45670728a38Smrg        }
4578c9fbc29Smrg    }
4588c9fbc29Smrg    if (xkb->names && xkb->names->key_aliases) {
45970728a38Smrg        XkbKeyAliasPtr a;
46070728a38Smrg
46170728a38Smrg        a = xkb->names->key_aliases;
46270728a38Smrg        for (i = 0; i < xkb->names->num_key_aliases; i++, a++) {
46370728a38Smrg            if (strncmp(name, a->alias, XkbKeyNameLength) == 0)
46470728a38Smrg                return XkbFindKeycodeByName(xkb, a->real, False);
46570728a38Smrg        }
4668c9fbc29Smrg    }
4678c9fbc29Smrg    return 0;
4688c9fbc29Smrg}
4698c9fbc29Smrg
4708c9fbc29Smrgunsigned
47170728a38SmrgXkbConvertGetByNameComponents(Bool toXkm, unsigned orig)
4728c9fbc29Smrg{
47370728a38Smrg    unsigned rtrn;
4748c9fbc29Smrg
47570728a38Smrg    rtrn = 0;
4768c9fbc29Smrg    if (toXkm) {
47770728a38Smrg        if (orig & XkbGBN_TypesMask)
47870728a38Smrg            rtrn |= XkmTypesMask;
47970728a38Smrg        if (orig & XkbGBN_CompatMapMask)
48070728a38Smrg            rtrn |= XkmCompatMapMask;
48170728a38Smrg        if (orig & XkbGBN_SymbolsMask)
48270728a38Smrg            rtrn |= XkmSymbolsMask;
48370728a38Smrg        if (orig & XkbGBN_IndicatorMapMask)
48470728a38Smrg            rtrn |= XkmIndicatorsMask;
48570728a38Smrg        if (orig & XkbGBN_KeyNamesMask)
48670728a38Smrg            rtrn |= XkmKeyNamesMask;
48770728a38Smrg        if (orig & XkbGBN_GeometryMask)
48870728a38Smrg            rtrn |= XkmGeometryMask;
4898c9fbc29Smrg    }
4908c9fbc29Smrg    else {
49170728a38Smrg        if (orig & XkmTypesMask)
49270728a38Smrg            rtrn |= XkbGBN_TypesMask;
49370728a38Smrg        if (orig & XkmCompatMapMask)
49470728a38Smrg            rtrn |= XkbGBN_CompatMapMask;
49570728a38Smrg        if (orig & XkmSymbolsMask)
49670728a38Smrg            rtrn |= XkbGBN_SymbolsMask;
49770728a38Smrg        if (orig & XkmIndicatorsMask)
49870728a38Smrg            rtrn |= XkbGBN_IndicatorMapMask;
49970728a38Smrg        if (orig & XkmKeyNamesMask)
50070728a38Smrg            rtrn |= XkbGBN_KeyNamesMask;
50170728a38Smrg        if (orig & XkmGeometryMask)
50270728a38Smrg            rtrn |= XkbGBN_GeometryMask;
50370728a38Smrg        if (orig != 0)
50470728a38Smrg            rtrn |= XkbGBN_OtherNamesMask;
5058c9fbc29Smrg    }
5068c9fbc29Smrg    return rtrn;
5078c9fbc29Smrg}
5088c9fbc29Smrg
5098c9fbc29Smrgunsigned
51070728a38SmrgXkbConvertXkbComponents(Bool toXkm, unsigned orig)
5118c9fbc29Smrg{
51270728a38Smrg    unsigned rtrn;
5138c9fbc29Smrg
51470728a38Smrg    rtrn = 0;
5158c9fbc29Smrg    if (toXkm) {
51670728a38Smrg        if (orig & XkbClientMapMask)
51770728a38Smrg            rtrn |= XkmTypesMask | XkmSymbolsMask;
51870728a38Smrg        if (orig & XkbServerMapMask)
51970728a38Smrg            rtrn |= XkmTypesMask | XkmSymbolsMask;
52070728a38Smrg        if (orig & XkbCompatMapMask)
52170728a38Smrg            rtrn |= XkmCompatMapMask;
52270728a38Smrg        if (orig & XkbIndicatorMapMask)
52370728a38Smrg            rtrn |= XkmIndicatorsMask;
52470728a38Smrg        if (orig & XkbNamesMask)
52570728a38Smrg            rtrn |= XkmKeyNamesMask;
52670728a38Smrg        if (orig & XkbGeometryMask)
52770728a38Smrg            rtrn |= XkmGeometryMask;
5288c9fbc29Smrg    }
5298c9fbc29Smrg    else {
53070728a38Smrg        if (orig != 0)
53170728a38Smrg            rtrn |= XkbNamesMask;
53270728a38Smrg        if (orig & XkmTypesMask)
53370728a38Smrg            rtrn |= XkbClientMapMask;
53470728a38Smrg        if (orig & XkmCompatMapMask)
53570728a38Smrg            rtrn |= XkbCompatMapMask | XkbIndicatorMapMask;
53670728a38Smrg        if (orig & XkmSymbolsMask)
53770728a38Smrg            rtrn |= XkbClientMapMask | XkbServerMapMask;
53870728a38Smrg        if (orig & XkmIndicatorsMask)
53970728a38Smrg            rtrn |= XkbIndicatorMapMask;
54070728a38Smrg        if (orig & XkmKeyNamesMask)
54170728a38Smrg            rtrn |= XkbNamesMask | XkbIndicatorMapMask;
54270728a38Smrg        if (orig & XkmGeometryMask)
54370728a38Smrg            rtrn |= XkbGeometryMask;
5448c9fbc29Smrg    }
5458c9fbc29Smrg    return rtrn;
5468c9fbc29Smrg}
5478c9fbc29Smrg
5488c9fbc29SmrgBool
54970728a38SmrgXkbDetermineFileType(XkbFileInfoPtr finfo, int format, int *opts_missing)
5508c9fbc29Smrg{
55170728a38Smrg    unsigned present;
55270728a38Smrg    XkbDescPtr xkb;
5538c9fbc29Smrg
55470728a38Smrg    if ((!finfo) || (!finfo->xkb))
55570728a38Smrg        return False;
5568c9fbc29Smrg    if (opts_missing)
55770728a38Smrg        *opts_missing = 0;
55870728a38Smrg    xkb = finfo->xkb;
55970728a38Smrg    present = 0;
56070728a38Smrg    if ((xkb->names) && (xkb->names->keys))
56170728a38Smrg        present |= XkmKeyNamesMask;
56270728a38Smrg    if ((xkb->map) && (xkb->map->types))
56370728a38Smrg        present |= XkmTypesMask;
56470728a38Smrg    if (xkb->compat)
56570728a38Smrg        present |= XkmCompatMapMask;
56670728a38Smrg    if ((xkb->map) && (xkb->map->num_syms > 1))
56770728a38Smrg        present |= XkmSymbolsMask;
56870728a38Smrg    if (xkb->indicators)
56970728a38Smrg        present |= XkmIndicatorsMask;
57070728a38Smrg    if (xkb->geom)
57170728a38Smrg        present |= XkmGeometryMask;
5728c9fbc29Smrg    if (!present)
57370728a38Smrg        return False;
57470728a38Smrg    else
57570728a38Smrg        switch (present) {
57670728a38Smrg        case XkmKeyNamesMask:
57770728a38Smrg            finfo->type = XkmKeyNamesIndex;
57870728a38Smrg            finfo->defined = present;
57970728a38Smrg            return True;
58070728a38Smrg        case XkmTypesMask:
58170728a38Smrg            finfo->type = XkmTypesIndex;
58270728a38Smrg            finfo->defined = present;
58370728a38Smrg            return True;
58470728a38Smrg        case XkmCompatMapMask:
58570728a38Smrg            finfo->type = XkmCompatMapIndex;
58670728a38Smrg            finfo->defined = present;
58770728a38Smrg            return True;
58870728a38Smrg        case XkmSymbolsMask:
58970728a38Smrg            if (format != XkbXKMFile) {
59070728a38Smrg                finfo->type = XkmSymbolsIndex;
59170728a38Smrg                finfo->defined = present;
59270728a38Smrg                return True;
59370728a38Smrg            }
59470728a38Smrg            break;
59570728a38Smrg        case XkmGeometryMask:
59670728a38Smrg            finfo->type = XkmGeometryIndex;
59770728a38Smrg            finfo->defined = present;
59870728a38Smrg            return True;
59970728a38Smrg        }
60070728a38Smrg    if ((present & (~XkmSemanticsLegal)) == 0) {
60170728a38Smrg        if ((XkmSemanticsRequired & present) == XkmSemanticsRequired) {
60270728a38Smrg            if (opts_missing)
60370728a38Smrg                *opts_missing = XkmSemanticsOptional & (~present);
60470728a38Smrg            finfo->type = XkmSemanticsFile;
60570728a38Smrg            finfo->defined = present;
60670728a38Smrg            return True;
60770728a38Smrg        }
6088c9fbc29Smrg    }
60970728a38Smrg    else if ((present & (~XkmLayoutLegal)) == 0) {
61070728a38Smrg        if ((XkmLayoutRequired & present) == XkmLayoutRequired) {
61170728a38Smrg            if (opts_missing)
61270728a38Smrg                *opts_missing = XkmLayoutOptional & (~present);
61370728a38Smrg            finfo->type = XkmLayoutFile;
61470728a38Smrg            finfo->defined = present;
61570728a38Smrg            return True;
61670728a38Smrg        }
6178c9fbc29Smrg    }
61870728a38Smrg    else if ((present & (~XkmKeymapLegal)) == 0) {
61970728a38Smrg        if ((XkmKeymapRequired & present) == XkmKeymapRequired) {
62070728a38Smrg            if (opts_missing)
62170728a38Smrg                *opts_missing = XkmKeymapOptional & (~present);
62270728a38Smrg            finfo->type = XkmKeymapFile;
62370728a38Smrg            finfo->defined = present;
62470728a38Smrg            return True;
62570728a38Smrg        }
6268c9fbc29Smrg    }
6278c9fbc29Smrg    return False;
6288c9fbc29Smrg}
6298c9fbc29Smrg
6308c9fbc29Smrg/* all latin-1 alphanumerics, plus parens, slash, minus, underscore and */
6318c9fbc29Smrg/* wildcards */
6328c9fbc29Smrg
6338c9fbc29Smrgstatic unsigned char componentSpecLegal[] = {
63470728a38Smrg    0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x83,
63570728a38Smrg    0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
63670728a38Smrg    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63770728a38Smrg    0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
6388c9fbc29Smrg};
6398c9fbc29Smrg
6408c9fbc29Smrgvoid
6418c9fbc29SmrgXkbEnsureSafeMapName(char *name)
6428c9fbc29Smrg{
64370728a38Smrg    if (name == NULL)
6448c9fbc29Smrg        return;
64570728a38Smrg    while (*name != '\0') {
64670728a38Smrg        if ((componentSpecLegal[(*name) / 8] & (1 << ((*name) % 8))) == 0)
64770728a38Smrg            *name = '_';
6488c9fbc29Smrg        name++;
6498c9fbc29Smrg    }
6508c9fbc29Smrg    return;
6518c9fbc29Smrg}
6528c9fbc29Smrg
6538c9fbc29Smrg/***====================================================================***/
6548c9fbc29Smrg
6558c9fbc29Smrg#define	UNMATCHABLE(c)	(((c)=='(')||((c)==')')||((c)=='/'))
6568c9fbc29Smrg
6578c9fbc29SmrgBool
65870728a38SmrgXkbNameMatchesPattern(char *name, char *ptrn)
6598c9fbc29Smrg{
66070728a38Smrg    while (ptrn[0] != '\0') {
66170728a38Smrg        if (name[0] == '\0') {
66270728a38Smrg            if (ptrn[0] == '*') {
66370728a38Smrg                ptrn++;
66470728a38Smrg                continue;
66570728a38Smrg            }
66670728a38Smrg            return False;
66770728a38Smrg        }
66870728a38Smrg        if (ptrn[0] == '?') {
66970728a38Smrg            if (UNMATCHABLE(name[0]))
67070728a38Smrg                return False;
67170728a38Smrg        }
67270728a38Smrg        else if (ptrn[0] == '*') {
67370728a38Smrg            if ((!UNMATCHABLE(name[0])) &&
67470728a38Smrg                XkbNameMatchesPattern(name + 1, ptrn))
67570728a38Smrg                return True;
67670728a38Smrg            return XkbNameMatchesPattern(name, ptrn + 1);
67770728a38Smrg        }
67870728a38Smrg        else if (ptrn[0] != name[0])
67970728a38Smrg            return False;
68070728a38Smrg        name++;
68170728a38Smrg        ptrn++;
6828c9fbc29Smrg    }
6838c9fbc29Smrg    /* if we get here, the pattern is exhausted (-:just like me:-) */
68470728a38Smrg    return (name[0] == '\0');
6858c9fbc29Smrg}
6868c9fbc29Smrg
68754cef2ddSmrg#ifndef HAVE_STRCASECMP
6888c9fbc29Smrg_X_HIDDEN int
68970728a38Smrg_XkbStrCaseCmp(char *str1, char *str2)
6908c9fbc29Smrg{
69170728a38Smrg    const u_char *us1 = (const u_char *) str1, *us2 = (const u_char *) str2;
6924cd6a3aeSmrg
6938c9fbc29Smrg    while (tolower(*us1) == tolower(*us2)) {
6948c9fbc29Smrg        if (*us1++ == '\0')
6958c9fbc29Smrg            return (0);
6968c9fbc29Smrg        us2++;
6978c9fbc29Smrg    }
6988c9fbc29Smrg
6998c9fbc29Smrg    return (tolower(*us1) - tolower(*us2));
7008c9fbc29Smrg}
7018c9fbc29Smrg#endif
702