xkbtext.c revision 54cef2dd
18c9fbc29Smrg/************************************************************
28c9fbc29Smrg Copyright (c) 1994 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
398c9fbc29Smrg
408c9fbc29Smrg#include <X11/Xlib.h>
418c9fbc29Smrg#include <X11/XKBlib.h>
428c9fbc29Smrg#include <X11/extensions/XKBgeom.h>
438c9fbc29Smrg
448c9fbc29Smrg#include "XKMformat.h"
458c9fbc29Smrg#include "XKBfileInt.h"
468c9fbc29Smrg
478c9fbc29Smrg
488c9fbc29Smrg/***====================================================================***/
498c9fbc29Smrg
508c9fbc29Smrg#define	BUFFER_SIZE	512
518c9fbc29Smrg
528c9fbc29Smrgstatic char textBuffer[BUFFER_SIZE];
5370728a38Smrgstatic int tbNext = 0;
548c9fbc29Smrg
558c9fbc29Smrgstatic char *
568c9fbc29SmrgtbGetBuffer(unsigned size)
578c9fbc29Smrg{
5870728a38Smrg    char *rtrn;
5970728a38Smrg
6070728a38Smrg    if (size >= BUFFER_SIZE)
6170728a38Smrg        return NULL;
6270728a38Smrg    if ((BUFFER_SIZE - tbNext) <= size)
6370728a38Smrg        tbNext = 0;
6470728a38Smrg    rtrn = &textBuffer[tbNext];
6570728a38Smrg    tbNext += size;
668c9fbc29Smrg    return rtrn;
678c9fbc29Smrg}
688c9fbc29Smrg
698c9fbc29Smrg/***====================================================================***/
708c9fbc29Smrg
718c9fbc29Smrgchar *
7270728a38SmrgXkbAtomText(Display *dpy, Atom atm, unsigned format)
738c9fbc29Smrg{
7470728a38Smrg    char *rtrn, *tmp;
7570728a38Smrg
7670728a38Smrg    tmp = XkbAtomGetString(dpy, atm);
7770728a38Smrg    if (tmp != NULL) {
7870728a38Smrg        int len;
7970728a38Smrg
8070728a38Smrg        len = strlen(tmp) + 1;
8170728a38Smrg        if (len > BUFFER_SIZE)
8270728a38Smrg            len = BUFFER_SIZE - 2;
8370728a38Smrg        rtrn = tbGetBuffer(len);
8470728a38Smrg        strncpy(rtrn, tmp, len);
8570728a38Smrg        rtrn[len] = '\0';
868c9fbc29Smrg        _XkbFree(tmp);
878c9fbc29Smrg    }
888c9fbc29Smrg    else {
8970728a38Smrg        rtrn = tbGetBuffer(1);
9070728a38Smrg        rtrn[0] = '\0';
9170728a38Smrg    }
9270728a38Smrg    if (format == XkbCFile) {
9370728a38Smrg        for (tmp = rtrn; *tmp != '\0'; tmp++) {
9470728a38Smrg            if ((tmp == rtrn) && (!isalpha(*tmp)))
9570728a38Smrg                *tmp = '_';
9670728a38Smrg            else if (!isalnum(*tmp))
9770728a38Smrg                *tmp = '_';
9870728a38Smrg        }
9970728a38Smrg    }
10070728a38Smrg    return XkbStringText(rtrn, format);
1018c9fbc29Smrg}
1028c9fbc29Smrg
1038c9fbc29Smrg/***====================================================================***/
1048c9fbc29Smrg
1058c9fbc29Smrgchar *
10670728a38SmrgXkbVModIndexText(Display *dpy, XkbDescPtr xkb, unsigned ndx, unsigned format)
1078c9fbc29Smrg{
10870728a38Smrg    register int len;
10970728a38Smrg    register Atom *vmodNames;
11070728a38Smrg    char *rtrn, *tmp;
1118c9fbc29Smrg
1128c9fbc29Smrg    if (xkb && xkb->names)
11370728a38Smrg        vmodNames = xkb->names->vmods;
11470728a38Smrg    else
11570728a38Smrg        vmodNames = NULL;
11670728a38Smrg
11770728a38Smrg    tmp = NULL;
11870728a38Smrg    if (ndx >= XkbNumVirtualMods)
11970728a38Smrg        tmp = strdup("illegal");
12070728a38Smrg    else if (vmodNames && (vmodNames[ndx] != None))
12170728a38Smrg        tmp = XkbAtomGetString(dpy, vmodNames[ndx]);
12270728a38Smrg    if (tmp == NULL) {
12370728a38Smrg        tmp = (char *) _XkbAlloc(20 * sizeof(char));
12470728a38Smrg        snprintf(tmp, 20, "%d", ndx);
12570728a38Smrg    }
12670728a38Smrg
12770728a38Smrg    len = strlen(tmp) + 1;
12870728a38Smrg    if (format == XkbCFile)
12954cef2ddSmrg        len += 5;
13070728a38Smrg    if (len >= BUFFER_SIZE)
13170728a38Smrg        len = BUFFER_SIZE - 1;
13270728a38Smrg    rtrn = tbGetBuffer(len);
13370728a38Smrg    if (format == XkbCFile) {
13470728a38Smrg        snprintf(rtrn, len, "vmod_%s", tmp);
13570728a38Smrg    }
13670728a38Smrg    else
13770728a38Smrg        strncpy(rtrn, tmp, len);
1388c9fbc29Smrg    _XkbFree(tmp);
1398c9fbc29Smrg    return rtrn;
1408c9fbc29Smrg}
1418c9fbc29Smrg
1428c9fbc29Smrgchar *
14370728a38SmrgXkbVModMaskText(Display *       dpy,
14470728a38Smrg                XkbDescPtr      xkb,
14570728a38Smrg                unsigned        modMask,
14670728a38Smrg                unsigned        mask,
14770728a38Smrg                unsigned        format)
1488c9fbc29Smrg{
14970728a38Smrg    register int i, bit;
15070728a38Smrg    int len;
15170728a38Smrg    char *mm, *rtrn;
15270728a38Smrg    char *str, buf[BUFFER_SIZE];
15370728a38Smrg
15470728a38Smrg    if ((modMask == 0) && (mask == 0)) {
15570728a38Smrg        const int rtrnsize = 5;
15670728a38Smrg        rtrn = tbGetBuffer(rtrnsize);
15770728a38Smrg        if (format == XkbCFile)
15870728a38Smrg            snprintf(rtrn, rtrnsize, "0");
15970728a38Smrg        else
16070728a38Smrg            snprintf(rtrn, rtrnsize, "none");
16170728a38Smrg        return rtrn;
16270728a38Smrg    }
16370728a38Smrg    if (modMask != 0)
16470728a38Smrg        mm = XkbModMaskText(modMask, format);
16570728a38Smrg    else
16670728a38Smrg        mm = NULL;
16770728a38Smrg
16870728a38Smrg    str = buf;
16970728a38Smrg    buf[0] = '\0';
1708c9fbc29Smrg    if (mask) {
17170728a38Smrg        char *tmp;
17270728a38Smrg
17370728a38Smrg        for (i = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
17470728a38Smrg            if (mask & bit) {
17570728a38Smrg                tmp = XkbVModIndexText(dpy, xkb, i, format);
17670728a38Smrg                len = strlen(tmp) + 1 + (str == buf ? 0 : 1);
17770728a38Smrg                if (format == XkbCFile)
17870728a38Smrg                    len += 4;
17970728a38Smrg                if ((str - (buf + len)) <= BUFFER_SIZE) {
18070728a38Smrg                    if (str != buf) {
18170728a38Smrg                        if (format == XkbCFile)
18270728a38Smrg                            *str++ = '|';
18370728a38Smrg                        else
18470728a38Smrg                            *str++ = '+';
18570728a38Smrg                        len--;
18670728a38Smrg                    }
18770728a38Smrg                }
18870728a38Smrg                if (format == XkbCFile)
18970728a38Smrg                    sprintf(str, "%sMask", tmp);
19070728a38Smrg                else
19170728a38Smrg                    strcpy(str, tmp);
19270728a38Smrg                str = &str[len - 1];
19370728a38Smrg            }
19470728a38Smrg        }
19570728a38Smrg        str = buf;
19670728a38Smrg    }
19770728a38Smrg    else
19870728a38Smrg        str = NULL;
1994cd6a3aeSmrg    if (mm)
20070728a38Smrg        len = strlen(mm);
20170728a38Smrg    else
20270728a38Smrg        len = 0;
2038c9fbc29Smrg    if (str)
20470728a38Smrg        len += strlen(str) + (mm == NULL ? 0 : 1);
20570728a38Smrg    if (len >= BUFFER_SIZE)
20670728a38Smrg        len = BUFFER_SIZE - 1;
20770728a38Smrg    rtrn = tbGetBuffer(len + 1);
20870728a38Smrg    rtrn[0] = '\0';
20970728a38Smrg
21070728a38Smrg    if (mm != NULL) {
21170728a38Smrg        i = strlen(mm);
21270728a38Smrg        if (i > len)
21370728a38Smrg            i = len;
21470728a38Smrg        strcpy(rtrn, mm);
2158c9fbc29Smrg    }
2168c9fbc29Smrg    else {
21770728a38Smrg        i = 0;
21870728a38Smrg    }
21970728a38Smrg    if (str != NULL) {
22070728a38Smrg        if (mm != NULL) {
22170728a38Smrg            if (format == XkbCFile)
22270728a38Smrg                strcat(rtrn, "|");
22370728a38Smrg            else
22470728a38Smrg                strcat(rtrn, "+");
22570728a38Smrg        }
22670728a38Smrg        strncat(rtrn, str, len - i);
22770728a38Smrg    }
22870728a38Smrg    rtrn[len] = '\0';
2298c9fbc29Smrg    return rtrn;
2308c9fbc29Smrg}
2318c9fbc29Smrg
2324cd6a3aeSmrgstatic const char *modNames[XkbNumModifiers] = {
2338c9fbc29Smrg    "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5"
2348c9fbc29Smrg};
2358c9fbc29Smrg
2368c9fbc29Smrgchar *
23770728a38SmrgXkbModIndexText(unsigned ndx, unsigned format)
2388c9fbc29Smrg{
23970728a38Smrg    char *rtrn;
24070728a38Smrg    char buf[100];
2418c9fbc29Smrg
24270728a38Smrg    if (format == XkbCFile) {
24370728a38Smrg        if (ndx < XkbNumModifiers)
24470728a38Smrg            snprintf(buf, sizeof(buf), "%sMapIndex", modNames[ndx]);
24570728a38Smrg        else if (ndx == XkbNoModifier)
24670728a38Smrg            snprintf(buf, sizeof(buf), "XkbNoModifier");
24770728a38Smrg        else
24870728a38Smrg            snprintf(buf, sizeof(buf), "0x%02x", ndx);
2498c9fbc29Smrg    }
2508c9fbc29Smrg    else {
25170728a38Smrg        if (ndx < XkbNumModifiers)
25270728a38Smrg            strcpy(buf, modNames[ndx]);
25370728a38Smrg        else if (ndx == XkbNoModifier)
25470728a38Smrg            strcpy(buf, "none");
25570728a38Smrg        else
25670728a38Smrg            snprintf(buf, sizeof(buf), "ILLEGAL_%02x", ndx);
25770728a38Smrg    }
25870728a38Smrg    rtrn = tbGetBuffer(strlen(buf) + 1);
25970728a38Smrg    strcpy(rtrn, buf);
2608c9fbc29Smrg    return rtrn;
2618c9fbc29Smrg}
2628c9fbc29Smrg
2638c9fbc29Smrgchar *
26470728a38SmrgXkbModMaskText(unsigned mask, unsigned format)
2658c9fbc29Smrg{
26670728a38Smrg    register int i, bit;
26770728a38Smrg    char buf[64], *rtrn;
2688c9fbc29Smrg
26970728a38Smrg    if ((mask & 0xff) == 0xff) {
27070728a38Smrg        if (format == XkbCFile)
27170728a38Smrg            strcpy(buf, "0xff");
27270728a38Smrg        else
27370728a38Smrg            strcpy(buf, "all");
2748c9fbc29Smrg    }
27570728a38Smrg    else if ((mask & 0xff) == 0) {
27670728a38Smrg        if (format == XkbCFile)
27770728a38Smrg            strcpy(buf, "0");
27870728a38Smrg        else
27970728a38Smrg            strcpy(buf, "none");
2808c9fbc29Smrg    }
2818c9fbc29Smrg    else {
28270728a38Smrg        char *str = buf;
28370728a38Smrg
28470728a38Smrg        buf[0] = '\0';
28570728a38Smrg        for (i = 0, bit = 1; i < XkbNumModifiers; i++, bit <<= 1) {
28670728a38Smrg            if (mask & bit) {
28770728a38Smrg                if (str != buf) {
28870728a38Smrg                    if (format == XkbCFile)
28970728a38Smrg                        *str++ = '|';
29070728a38Smrg                    else
29170728a38Smrg                        *str++ = '+';
29270728a38Smrg                }
29370728a38Smrg                strcpy(str, modNames[i]);
29470728a38Smrg                str = &str[strlen(str)];
29570728a38Smrg                if (format == XkbCFile) {
29670728a38Smrg                    strcpy(str, "Mask");
29770728a38Smrg                    str += 4;
29870728a38Smrg                }
29970728a38Smrg            }
30070728a38Smrg        }
30170728a38Smrg    }
30270728a38Smrg    rtrn = tbGetBuffer(strlen(buf) + 1);
30370728a38Smrg    strcpy(rtrn, buf);
3048c9fbc29Smrg    return rtrn;
3058c9fbc29Smrg}
3068c9fbc29Smrg
3078c9fbc29Smrg/***====================================================================***/
3088c9fbc29Smrg
3098c9fbc29Smrg/*ARGSUSED*/
3108c9fbc29Smrgchar *
31170728a38SmrgXkbConfigText(unsigned config, unsigned format)
3128c9fbc29Smrg{
31370728a38Smrg    static char *buf;
31470728a38Smrg    const int bufsize = 32;
3158c9fbc29Smrg
31670728a38Smrg    buf = tbGetBuffer(bufsize);
3178c9fbc29Smrg    switch (config) {
31870728a38Smrg    case XkmSemanticsFile:
31970728a38Smrg        strcpy(buf, "Semantics");
32070728a38Smrg        break;
32170728a38Smrg    case XkmLayoutFile:
32270728a38Smrg        strcpy(buf, "Layout");
32370728a38Smrg        break;
32470728a38Smrg    case XkmKeymapFile:
32570728a38Smrg        strcpy(buf, "Keymap");
32670728a38Smrg        break;
32770728a38Smrg    case XkmGeometryFile:
32870728a38Smrg    case XkmGeometryIndex:
32970728a38Smrg        strcpy(buf, "Geometry");
33070728a38Smrg        break;
33170728a38Smrg    case XkmTypesIndex:
33270728a38Smrg        strcpy(buf, "Types");
33370728a38Smrg        break;
33470728a38Smrg    case XkmCompatMapIndex:
33570728a38Smrg        strcpy(buf, "CompatMap");
33670728a38Smrg        break;
33770728a38Smrg    case XkmSymbolsIndex:
33870728a38Smrg        strcpy(buf, "Symbols");
33970728a38Smrg        break;
34070728a38Smrg    case XkmIndicatorsIndex:
34170728a38Smrg        strcpy(buf, "Indicators");
34270728a38Smrg        break;
34370728a38Smrg    case XkmKeyNamesIndex:
34470728a38Smrg        strcpy(buf, "KeyNames");
34570728a38Smrg        break;
34670728a38Smrg    case XkmVirtualModsIndex:
34770728a38Smrg        strcpy(buf, "VirtualMods");
34870728a38Smrg        break;
34970728a38Smrg    default:
35070728a38Smrg        snprintf(buf, bufsize, "unknown(%d)", config);
35170728a38Smrg        break;
3528c9fbc29Smrg    }
3538c9fbc29Smrg    return buf;
3548c9fbc29Smrg}
3558c9fbc29Smrg
3568c9fbc29Smrg/***====================================================================***/
3578c9fbc29Smrg
3588c9fbc29Smrgchar *
35970728a38SmrgXkbKeysymText(KeySym sym, unsigned format)
3608c9fbc29Smrg{
36170728a38Smrg    static char buf[32], *rtrn;
3628c9fbc29Smrg
36370728a38Smrg    if (sym == NoSymbol)
36470728a38Smrg        strcpy(rtrn = buf, "NoSymbol");
36570728a38Smrg    else if ((rtrn = XKeysymToString(sym)) == NULL) {
36670728a38Smrg        snprintf(buf, sizeof(buf), "0x%lx", (long) sym);
36770728a38Smrg        rtrn = buf;
36870728a38Smrg    }
36970728a38Smrg    else if (format == XkbCFile) {
37070728a38Smrg        snprintf(buf, sizeof(buf), "XK_%s", rtrn);
37170728a38Smrg        rtrn = buf;
3728c9fbc29Smrg    }
3738c9fbc29Smrg    return rtrn;
3748c9fbc29Smrg}
3758c9fbc29Smrg
3768c9fbc29Smrgchar *
37770728a38SmrgXkbKeyNameText(char *name, unsigned format)
3788c9fbc29Smrg{
37970728a38Smrg    char *buf;
3808c9fbc29Smrg
38170728a38Smrg    if (format == XkbCFile) {
38270728a38Smrg        buf = tbGetBuffer(5);
38370728a38Smrg        memcpy(buf, name, 4);
38470728a38Smrg        buf[4] = '\0';
3858c9fbc29Smrg    }
3868c9fbc29Smrg    else {
38770728a38Smrg        int len;
38870728a38Smrg
38970728a38Smrg        buf = tbGetBuffer(7);
39070728a38Smrg        buf[0] = '<';
39170728a38Smrg        memcpy(&buf[1], name, 4);
39270728a38Smrg        buf[5] = '\0';
39370728a38Smrg        len = strlen(buf);
39470728a38Smrg        buf[len++] = '>';
39570728a38Smrg        buf[len] = '\0';
3968c9fbc29Smrg    }
3978c9fbc29Smrg    return buf;
3988c9fbc29Smrg}
3998c9fbc29Smrg
4008c9fbc29Smrg/***====================================================================***/
4018c9fbc29Smrg
4028c9fbc29Smrgstatic char *siMatchText[5] = {
40370728a38Smrg    "NoneOf", "AnyOfOrNone", "AnyOf", "AllOf", "Exactly"
4048c9fbc29Smrg};
4058c9fbc29Smrg
4068c9fbc29Smrgchar *
40770728a38SmrgXkbSIMatchText(unsigned type, unsigned format)
4088c9fbc29Smrg{
40970728a38Smrg    static char buf[40];
41070728a38Smrg
41170728a38Smrg    char *rtrn;
41270728a38Smrg
41370728a38Smrg    switch (type & XkbSI_OpMask) {
41470728a38Smrg    case XkbSI_NoneOf:      rtrn = siMatchText[0]; break;
41570728a38Smrg    case XkbSI_AnyOfOrNone: rtrn = siMatchText[1]; break;
41670728a38Smrg    case XkbSI_AnyOf:       rtrn = siMatchText[2]; break;
41770728a38Smrg    case XkbSI_AllOf:       rtrn = siMatchText[3]; break;
41870728a38Smrg    case XkbSI_Exactly:     rtrn = siMatchText[4]; break;
41970728a38Smrg    default:
42070728a38Smrg        snprintf(buf, sizeof(buf), "0x%x", type & XkbSI_OpMask);
42170728a38Smrg        return buf;
42270728a38Smrg    }
42370728a38Smrg    if (format == XkbCFile) {
42470728a38Smrg        if (type & XkbSI_LevelOneOnly)
42570728a38Smrg            snprintf(buf, sizeof(buf), "XkbSI_LevelOneOnly|XkbSI_%s", rtrn);
42670728a38Smrg        else
42770728a38Smrg            snprintf(buf, sizeof(buf), "XkbSI_%s", rtrn);
42870728a38Smrg        rtrn = buf;
4298c9fbc29Smrg    }
4308c9fbc29Smrg    return rtrn;
4318c9fbc29Smrg}
4328c9fbc29Smrg
4338c9fbc29Smrg/***====================================================================***/
4348c9fbc29Smrg
43570728a38Smrgstatic const char *imWhichNames[] = {
43670728a38Smrg    "base",
43770728a38Smrg    "latched",
43870728a38Smrg    "locked",
43970728a38Smrg    "effective",
44070728a38Smrg    "compat"
4418c9fbc29Smrg};
4428c9fbc29Smrg
4438c9fbc29Smrgchar *
44470728a38SmrgXkbIMWhichStateMaskText(unsigned use_which, unsigned format)
4458c9fbc29Smrg{
44670728a38Smrg    int len, bufsize;
44770728a38Smrg    unsigned i, bit, tmp;
44870728a38Smrg    char *buf;
44970728a38Smrg
45070728a38Smrg    if (use_which == 0) {
45170728a38Smrg        buf = tbGetBuffer(2);
45270728a38Smrg        strcpy(buf, "0");
45370728a38Smrg        return buf;
45470728a38Smrg    }
45570728a38Smrg    tmp = use_which & XkbIM_UseAnyMods;
45670728a38Smrg    for (len = i = 0, bit = 1; tmp != 0; i++, bit <<= 1) {
45770728a38Smrg        if (tmp & bit) {
45870728a38Smrg            tmp &= ~bit;
45970728a38Smrg            len += strlen(imWhichNames[i]) + 1;
46070728a38Smrg            if (format == XkbCFile)
46170728a38Smrg                len += 9;
46270728a38Smrg        }
46370728a38Smrg    }
46470728a38Smrg    bufsize = len + 1;
46570728a38Smrg    buf = tbGetBuffer(bufsize);
46670728a38Smrg    tmp = use_which & XkbIM_UseAnyMods;
46770728a38Smrg    for (len = i = 0, bit = 1; tmp != 0; i++, bit <<= 1) {
46870728a38Smrg        if (tmp & bit) {
46970728a38Smrg            tmp &= ~bit;
47070728a38Smrg            if (format == XkbCFile) {
47170728a38Smrg                if (len != 0)
47270728a38Smrg                    buf[len++] = '|';
47370728a38Smrg                snprintf(&buf[len], bufsize - len,
47470728a38Smrg                         "XkbIM_Use%s", imWhichNames[i]);
47570728a38Smrg                buf[len + 9] = toupper(buf[len + 9]);
47670728a38Smrg            }
47770728a38Smrg            else {
47870728a38Smrg                if (len != 0)
47970728a38Smrg                    buf[len++] = '+';
48070728a38Smrg                snprintf(&buf[len], bufsize - len,
48170728a38Smrg                         "%s", imWhichNames[i]);
48270728a38Smrg            }
48370728a38Smrg            len += strlen(&buf[len]);
48470728a38Smrg        }
4858c9fbc29Smrg    }
4868c9fbc29Smrg    return buf;
4878c9fbc29Smrg}
4888c9fbc29Smrg
4898c9fbc29Smrgchar *
49070728a38SmrgXkbAccessXDetailText(unsigned state, unsigned format)
4918c9fbc29Smrg{
49270728a38Smrg    char *buf;
49370728a38Smrg    const char *prefix;
49470728a38Smrg    const int bufsize = 32;
49570728a38Smrg
49670728a38Smrg    buf = tbGetBuffer(bufsize);
49770728a38Smrg    if (format == XkbMessage)
49870728a38Smrg        prefix = "";
49970728a38Smrg    else
50070728a38Smrg        prefix = "XkbAXN_";
50170728a38Smrg    switch (state) {
50270728a38Smrg    case XkbAXN_SKPress:
50370728a38Smrg        snprintf(buf, bufsize, "%sSKPress", prefix);
50470728a38Smrg        break;
50570728a38Smrg    case XkbAXN_SKAccept:
50670728a38Smrg        snprintf(buf, bufsize, "%sSKAccept", prefix);
50770728a38Smrg        break;
50870728a38Smrg    case XkbAXN_SKRelease:
50970728a38Smrg        snprintf(buf, bufsize, "%sSKRelease", prefix);
51070728a38Smrg        break;
51170728a38Smrg    case XkbAXN_SKReject:
51270728a38Smrg        snprintf(buf, bufsize, "%sSKReject", prefix);
51370728a38Smrg        break;
51470728a38Smrg    case XkbAXN_BKAccept:
51570728a38Smrg        snprintf(buf, bufsize, "%sBKAccept", prefix);
51670728a38Smrg        break;
51770728a38Smrg    case XkbAXN_BKReject:
51870728a38Smrg        snprintf(buf, bufsize, "%sBKReject", prefix);
51970728a38Smrg        break;
52070728a38Smrg    case XkbAXN_AXKWarning:
52170728a38Smrg        snprintf(buf, bufsize, "%sAXKWarning", prefix);
52270728a38Smrg        break;
52370728a38Smrg    default:
52470728a38Smrg        snprintf(buf, bufsize, "ILLEGAL");
52570728a38Smrg        break;
5268c9fbc29Smrg    }
5278c9fbc29Smrg    return buf;
5288c9fbc29Smrg}
5298c9fbc29Smrg
5304cd6a3aeSmrgstatic const char *nknNames[] = {
53170728a38Smrg    "keycodes", "geometry", "deviceID"
5328c9fbc29Smrg};
5338c9fbc29Smrg#define	NUM_NKN	(sizeof(nknNames)/sizeof(char *))
5348c9fbc29Smrg
5358c9fbc29Smrgchar *
53670728a38SmrgXkbNKNDetailMaskText(unsigned detail, unsigned format)
5378c9fbc29Smrg{
53870728a38Smrg    char *buf;
53970728a38Smrg    const char *prefix, *suffix;
54070728a38Smrg    register int i;
54170728a38Smrg    register unsigned bit;
54270728a38Smrg    int len, plen, slen;
54370728a38Smrg
54470728a38Smrg    if ((detail & XkbAllNewKeyboardEventsMask) == 0) {
54570728a38Smrg        const char *tmp = "";
54670728a38Smrg
54770728a38Smrg        if (format == XkbCFile)
54870728a38Smrg            tmp = "0";
54970728a38Smrg        else if (format == XkbMessage)
55070728a38Smrg            tmp = "none";
55170728a38Smrg        buf = tbGetBuffer(strlen(tmp) + 1);
55270728a38Smrg        strcpy(buf, tmp);
55370728a38Smrg        return buf;
55470728a38Smrg    }
55570728a38Smrg    else if ((detail & XkbAllNewKeyboardEventsMask) ==
55670728a38Smrg             XkbAllNewKeyboardEventsMask) {
55770728a38Smrg        const char *tmp;
55870728a38Smrg
55970728a38Smrg        if (format == XkbCFile)
56070728a38Smrg            tmp = "XkbAllNewKeyboardEventsMask";
56170728a38Smrg        else
56270728a38Smrg            tmp = "all";
56370728a38Smrg        buf = tbGetBuffer(strlen(tmp) + 1);
56470728a38Smrg        strcpy(buf, tmp);
56570728a38Smrg        return buf;
56670728a38Smrg    }
56770728a38Smrg    if (format == XkbMessage) {
56870728a38Smrg        prefix = "";
56970728a38Smrg        suffix = "";
57070728a38Smrg        slen = plen = 0;
5718c9fbc29Smrg    }
5728c9fbc29Smrg    else {
57370728a38Smrg        prefix = "XkbNKN_";
57470728a38Smrg        plen = 7;
57570728a38Smrg        if (format == XkbCFile)
57670728a38Smrg            suffix = "Mask";
57770728a38Smrg        else
57870728a38Smrg            suffix = "";
57970728a38Smrg        slen = strlen(suffix);
58070728a38Smrg    }
58170728a38Smrg    for (len = 0, i = 0, bit = 1; i < NUM_NKN; i++, bit <<= 1) {
58270728a38Smrg        if (detail & bit) {
58370728a38Smrg            if (len != 0)
58470728a38Smrg                len += 1;       /* room for '+' or '|' */
58570728a38Smrg            len += plen + slen + strlen(nknNames[i]);
58670728a38Smrg        }
58770728a38Smrg    }
58870728a38Smrg    buf = tbGetBuffer(len + 1);
58970728a38Smrg    buf[0] = '\0';
59070728a38Smrg    for (len = 0, i = 0, bit = 1; i < NUM_NKN; i++, bit <<= 1) {
59170728a38Smrg        if (detail & bit) {
59270728a38Smrg            if (len != 0) {
59370728a38Smrg                if (format == XkbCFile)
59470728a38Smrg                    buf[len++] = '|';
59570728a38Smrg                else
59670728a38Smrg                    buf[len++] = '+';
59770728a38Smrg            }
59870728a38Smrg            if (plen) {
59970728a38Smrg                strcpy(&buf[len], prefix);
60070728a38Smrg                len += plen;
60170728a38Smrg            }
60270728a38Smrg            strcpy(&buf[len], nknNames[i]);
60370728a38Smrg            len += strlen(nknNames[i]);
60470728a38Smrg            if (slen) {
60570728a38Smrg                strcpy(&buf[len], suffix);
60670728a38Smrg                len += slen;
60770728a38Smrg            }
60870728a38Smrg        }
60970728a38Smrg    }
61070728a38Smrg    buf[len++] = '\0';
6118c9fbc29Smrg    return buf;
6128c9fbc29Smrg}
6138c9fbc29Smrg
6144cd6a3aeSmrgstatic const char *ctrlNames[] = {
61570728a38Smrg    "repeatKeys",
61670728a38Smrg    "slowKeys",
61770728a38Smrg    "bounceKeys",
61870728a38Smrg    "stickyKeys",
61970728a38Smrg    "mouseKeys",
62070728a38Smrg    "mouseKeysAccel",
62170728a38Smrg    "accessXKeys",
62270728a38Smrg    "accessXTimeout",
62370728a38Smrg    "accessXFeedback",
62470728a38Smrg    "audibleBell",
62570728a38Smrg    "overlay1",
62670728a38Smrg    "overlay2",
62770728a38Smrg    "ignoreGroupLock"
6288c9fbc29Smrg};
6298c9fbc29Smrg
6308c9fbc29Smrgchar *
63170728a38SmrgXkbControlsMaskText(unsigned ctrls, unsigned format)
6328c9fbc29Smrg{
63370728a38Smrg    int len;
63470728a38Smrg    unsigned i, bit, tmp;
63570728a38Smrg    char *buf;
63670728a38Smrg
63770728a38Smrg    if (ctrls == 0) {
63870728a38Smrg        buf = tbGetBuffer(5);
63970728a38Smrg        if (format == XkbCFile)
64070728a38Smrg            strcpy(buf, "0");
64170728a38Smrg        else
64270728a38Smrg            strcpy(buf, "none");
64370728a38Smrg        return buf;
64470728a38Smrg    }
64570728a38Smrg    tmp = ctrls & XkbAllBooleanCtrlsMask;
64670728a38Smrg    for (len = i = 0, bit = 1; tmp != 0; i++, bit <<= 1) {
64770728a38Smrg        if (tmp & bit) {
64870728a38Smrg            tmp &= ~bit;
64970728a38Smrg            len += strlen(ctrlNames[i]) + 1;
65070728a38Smrg            if (format == XkbCFile)
65170728a38Smrg                len += 7;
65270728a38Smrg        }
65370728a38Smrg    }
65470728a38Smrg    buf = tbGetBuffer(len + 1);
65570728a38Smrg    tmp = ctrls & XkbAllBooleanCtrlsMask;
65670728a38Smrg    for (len = i = 0, bit = 1; tmp != 0; i++, bit <<= 1) {
65770728a38Smrg        if (tmp & bit) {
65870728a38Smrg            tmp &= ~bit;
65970728a38Smrg            if (format == XkbCFile) {
66070728a38Smrg                if (len != 0)
66170728a38Smrg                    buf[len++] = '|';
66270728a38Smrg                sprintf(&buf[len], "Xkb%sMask", ctrlNames[i]);
66370728a38Smrg                buf[len + 3] = toupper(buf[len + 3]);
66470728a38Smrg            }
66570728a38Smrg            else {
66670728a38Smrg                if (len != 0)
66770728a38Smrg                    buf[len++] = '+';
66870728a38Smrg                sprintf(&buf[len], "%s", ctrlNames[i]);
66970728a38Smrg            }
67070728a38Smrg            len += strlen(&buf[len]);
67170728a38Smrg        }
6728c9fbc29Smrg    }
6738c9fbc29Smrg    return buf;
6748c9fbc29Smrg}
6758c9fbc29Smrg
6768c9fbc29Smrg/***====================================================================***/
6778c9fbc29Smrg
6788c9fbc29Smrgchar *
67970728a38SmrgXkbStringText(char *str, unsigned format)
6808c9fbc29Smrg{
68170728a38Smrg    char *buf;
68270728a38Smrg    register char *in, *out;
68370728a38Smrg    int len;
68470728a38Smrg    Bool ok;
68570728a38Smrg
68670728a38Smrg    if (str == NULL) {
68770728a38Smrg        buf = tbGetBuffer(2);
68870728a38Smrg        buf[0] = '\0';
68970728a38Smrg        return buf;
69070728a38Smrg    }
69170728a38Smrg    else if (format == XkbXKMFile)
69270728a38Smrg        return str;
69370728a38Smrg    for (ok = True, len = 0, in = str; *in != '\0'; in++, len++) {
69470728a38Smrg        if (!isprint(*in)) {
69570728a38Smrg            ok = False;
69670728a38Smrg            switch (*in) {
69770728a38Smrg            case '\n':
69870728a38Smrg            case '\t':
69970728a38Smrg            case '\v':
70070728a38Smrg            case '\b':
70170728a38Smrg            case '\r':
70270728a38Smrg            case '\f':
70370728a38Smrg                len++;
70470728a38Smrg                break;
70570728a38Smrg            default:
70670728a38Smrg                len += 4;
70770728a38Smrg                break;
70870728a38Smrg            }
70970728a38Smrg        }
7108c9fbc29Smrg    }
7118c9fbc29Smrg    if (ok)
71270728a38Smrg        return str;
71370728a38Smrg    buf = tbGetBuffer(len + 1);
71470728a38Smrg    for (in = str, out = buf; *in != '\0'; in++) {
71570728a38Smrg        if (isprint(*in))
71670728a38Smrg            *out++ = *in;
71770728a38Smrg        else {
71870728a38Smrg            *out++ = '\\';
71970728a38Smrg            if (*in == '\n')
72070728a38Smrg                *out++ = 'n';
72170728a38Smrg            else if (*in == '\t')
72270728a38Smrg                *out++ = 't';
72370728a38Smrg            else if (*in == '\v')
72470728a38Smrg                *out++ = 'v';
72570728a38Smrg            else if (*in == '\b')
72670728a38Smrg                *out++ = 'b';
72770728a38Smrg            else if (*in == '\r')
72870728a38Smrg                *out++ = 'r';
72970728a38Smrg            else if (*in == '\f')
73070728a38Smrg                *out++ = 'f';
73170728a38Smrg            else if ((*in == '\033') && (format == XkbXKMFile)) {
73270728a38Smrg                *out++ = 'e';
73370728a38Smrg            }
73470728a38Smrg            else {
73570728a38Smrg                *out++ = '0';
73654cef2ddSmrg                sprintf(out, "%o", (unsigned char)*in);
73770728a38Smrg                while (*out != '\0')
73870728a38Smrg                    out++;
73970728a38Smrg            }
74070728a38Smrg        }
74170728a38Smrg    }
74270728a38Smrg    *out++ = '\0';
7438c9fbc29Smrg    return buf;
7448c9fbc29Smrg}
7458c9fbc29Smrg
7468c9fbc29Smrg/***====================================================================***/
7478c9fbc29Smrg
7488c9fbc29Smrgchar *
74970728a38SmrgXkbGeomFPText(int val, unsigned format)
7508c9fbc29Smrg{
75170728a38Smrg    int whole, frac;
75270728a38Smrg    char *buf;
75370728a38Smrg    const int bufsize = 12;
7548c9fbc29Smrg
75570728a38Smrg    buf = tbGetBuffer(bufsize);
75670728a38Smrg    if (format == XkbCFile) {
75770728a38Smrg        snprintf(buf, bufsize, "%d", val);
7588c9fbc29Smrg    }
7598c9fbc29Smrg    else {
76070728a38Smrg        whole = val / XkbGeomPtsPerMM;
76154044362Smrg        frac = abs(val % XkbGeomPtsPerMM);
76254044362Smrg        if (frac != 0) {
76354044362Smrg            if (val < 0)
76454044362Smrg            {
76554044362Smrg                int wholeabs;
76654044362Smrg                wholeabs = abs(whole);
76754044362Smrg                snprintf(buf, bufsize, "-%d.%d", wholeabs, frac);
76854044362Smrg            }
76954044362Smrg            else
77054044362Smrg                snprintf(buf, bufsize, "%d.%d", whole, frac);
77154044362Smrg        }
77270728a38Smrg        else
77370728a38Smrg            snprintf(buf, bufsize, "%d", whole);
7748c9fbc29Smrg    }
7758c9fbc29Smrg    return buf;
7768c9fbc29Smrg}
7778c9fbc29Smrg
7788c9fbc29Smrgchar *
77970728a38SmrgXkbDoodadTypeText(unsigned type, unsigned format)
7808c9fbc29Smrg{
78170728a38Smrg    char *buf;
78270728a38Smrg
78370728a38Smrg    if (format == XkbCFile) {
78470728a38Smrg        const int bufsize = 24;
78570728a38Smrg        buf = tbGetBuffer(bufsize);
78670728a38Smrg        if (type == XkbOutlineDoodad)
78770728a38Smrg            strcpy(buf, "XkbOutlineDoodad");
78870728a38Smrg        else if (type == XkbSolidDoodad)
78970728a38Smrg            strcpy(buf, "XkbSolidDoodad");
79070728a38Smrg        else if (type == XkbTextDoodad)
79170728a38Smrg            strcpy(buf, "XkbTextDoodad");
79270728a38Smrg        else if (type == XkbIndicatorDoodad)
79370728a38Smrg            strcpy(buf, "XkbIndicatorDoodad");
79470728a38Smrg        else if (type == XkbLogoDoodad)
79570728a38Smrg            strcpy(buf, "XkbLogoDoodad");
79670728a38Smrg        else
79770728a38Smrg            snprintf(buf, bufsize, "UnknownDoodad%d", type);
7988c9fbc29Smrg    }
7998c9fbc29Smrg    else {
80070728a38Smrg        const int bufsize = 12;
80170728a38Smrg        buf = tbGetBuffer(bufsize);
80270728a38Smrg        if (type == XkbOutlineDoodad)
80370728a38Smrg            strcpy(buf, "outline");
80470728a38Smrg        else if (type == XkbSolidDoodad)
80570728a38Smrg            strcpy(buf, "solid");
80670728a38Smrg        else if (type == XkbTextDoodad)
80770728a38Smrg            strcpy(buf, "text");
80870728a38Smrg        else if (type == XkbIndicatorDoodad)
80970728a38Smrg            strcpy(buf, "indicator");
81070728a38Smrg        else if (type == XkbLogoDoodad)
81170728a38Smrg            strcpy(buf, "logo");
81270728a38Smrg        else
81370728a38Smrg            snprintf(buf, bufsize, "unknown%d", type);
8148c9fbc29Smrg    }
8158c9fbc29Smrg    return buf;
8168c9fbc29Smrg}
8178c9fbc29Smrg
81870728a38Smrgstatic char *actionTypeNames[XkbSA_NumActions] = {
8194cd6a3aeSmrg    "NoAction",
8204cd6a3aeSmrg    "SetMods",      "LatchMods",    "LockMods",
8218c9fbc29Smrg    "SetGroup",     "LatchGroup",   "LockGroup",
8228c9fbc29Smrg    "MovePtr",
8238c9fbc29Smrg    "PtrBtn",       "LockPtrBtn",
8248c9fbc29Smrg    "SetPtrDflt",
8258c9fbc29Smrg    "ISOLock",
8264cd6a3aeSmrg    "Terminate",    "SwitchScreen",
8278c9fbc29Smrg    "SetControls",  "LockControls",
8288c9fbc29Smrg    "ActionMessage",
8298c9fbc29Smrg    "RedirectKey",
8308c9fbc29Smrg    "DeviceBtn",    "LockDeviceBtn"
8318c9fbc29Smrg};
8328c9fbc29Smrg
8338c9fbc29Smrgchar *
83470728a38SmrgXkbActionTypeText(unsigned type, unsigned format)
8358c9fbc29Smrg{
83670728a38Smrg    static char buf[32];
83770728a38Smrg    char *rtrn;
83870728a38Smrg
83970728a38Smrg    if (type <= XkbSA_LastAction) {
84070728a38Smrg        rtrn = actionTypeNames[type];
84170728a38Smrg        if (format == XkbCFile) {
84270728a38Smrg            snprintf(buf, sizeof(buf), "XkbSA_%s", rtrn);
84370728a38Smrg            return buf;
84470728a38Smrg        }
84570728a38Smrg        return rtrn;
84670728a38Smrg    }
84770728a38Smrg    snprintf(buf, sizeof(buf), "Private");
8488c9fbc29Smrg    return buf;
8498c9fbc29Smrg}
8508c9fbc29Smrg
8518c9fbc29Smrg/***====================================================================***/
8528c9fbc29Smrg
8538c9fbc29Smrgstatic int
85470728a38SmrgTryCopyStr(char *to, const char *from, int *pLeft)
8558c9fbc29Smrg{
85670728a38Smrg    register int len;
85770728a38Smrg
85870728a38Smrg    if (*pLeft > 0) {
85970728a38Smrg        len = strlen(from);
86070728a38Smrg        if (len < ((*pLeft) - 3)) {
86170728a38Smrg            strcat(to, from);
86270728a38Smrg            *pLeft -= len;
86370728a38Smrg            return True;
86470728a38Smrg        }
86570728a38Smrg    }
86670728a38Smrg    *pLeft = -1;
8678c9fbc29Smrg    return False;
8688c9fbc29Smrg}
8698c9fbc29Smrg
8708c9fbc29Smrg/*ARGSUSED*/
8718c9fbc29Smrgstatic Bool
87270728a38SmrgCopyNoActionArgs(Display *dpy, XkbDescPtr xkb, XkbAction *action,
87370728a38Smrg                 char *buf, int *sz)
8748c9fbc29Smrg{
8758c9fbc29Smrg    return True;
8768c9fbc29Smrg}
8778c9fbc29Smrg
8788c9fbc29Smrgstatic Bool
87970728a38SmrgCopyModActionArgs(Display *dpy, XkbDescPtr xkb, XkbAction *action,
88070728a38Smrg                  char *buf, int *sz)
8818c9fbc29Smrg{
88270728a38Smrg    XkbModAction *act;
88370728a38Smrg    unsigned tmp;
88470728a38Smrg
88570728a38Smrg    act = &action->mods;
88670728a38Smrg    tmp = XkbModActionVMods(act);
88770728a38Smrg    TryCopyStr(buf, "modifiers=", sz);
88870728a38Smrg    if (act->flags & XkbSA_UseModMapMods)
88970728a38Smrg        TryCopyStr(buf, "modMapMods", sz);
8908c9fbc29Smrg    else if (act->real_mods || tmp) {
89170728a38Smrg        TryCopyStr(buf,
89270728a38Smrg                   XkbVModMaskText(dpy, xkb, act->real_mods, tmp, XkbXKBFile),
89370728a38Smrg                   sz);
89470728a38Smrg    }
89570728a38Smrg    else
89670728a38Smrg        TryCopyStr(buf, "none", sz);
89754044362Smrg    if (act->type == XkbSA_LockMods) {
89854044362Smrg        switch (act->flags & (XkbSA_LockNoUnlock | XkbSA_LockNoLock)) {
89954044362Smrg        case XkbSA_LockNoLock:
90054044362Smrg            TryCopyStr(buf, ",affect=unlock", sz);
90154044362Smrg            break;
90254044362Smrg        case XkbSA_LockNoUnlock:
90354044362Smrg            TryCopyStr(buf, ",affect=lock", sz);
90454044362Smrg            break;
90554044362Smrg        case XkbSA_LockNoUnlock|XkbSA_LockNoLock:
90654044362Smrg            TryCopyStr(buf, ",affect=neither", sz);
90754044362Smrg            break;
90854044362Smrg        default:
90954044362Smrg            break;
91054044362Smrg        }
91170728a38Smrg        return True;
91254044362Smrg    }
91370728a38Smrg    if (act->flags & XkbSA_ClearLocks)
91470728a38Smrg        TryCopyStr(buf, ",clearLocks", sz);
91570728a38Smrg    if (act->flags & XkbSA_LatchToLock)
91670728a38Smrg        TryCopyStr(buf, ",latchToLock", sz);
9178c9fbc29Smrg    return True;
9188c9fbc29Smrg}
9198c9fbc29Smrg
9208c9fbc29Smrg/*ARGSUSED*/
9218c9fbc29Smrgstatic Bool
92270728a38SmrgCopyGroupActionArgs(Display *dpy, XkbDescPtr xkb, XkbAction *action,
92370728a38Smrg                    char *buf, int *sz)
9248c9fbc29Smrg{
92570728a38Smrg    XkbGroupAction *act;
92670728a38Smrg    char tbuf[32];
92770728a38Smrg
92870728a38Smrg    act = &action->group;
92970728a38Smrg    TryCopyStr(buf, "group=", sz);
93070728a38Smrg    if (act->flags & XkbSA_GroupAbsolute)
93154044362Smrg        snprintf(tbuf, sizeof(tbuf), "%d", XkbSAGroup(act) + 1);
93270728a38Smrg    else if (XkbSAGroup(act) < 0)
93354044362Smrg        snprintf(tbuf, sizeof(tbuf), "%d", XkbSAGroup(act));
93470728a38Smrg    else
93554044362Smrg        snprintf(tbuf, sizeof(tbuf), "+%d", XkbSAGroup(act));
93670728a38Smrg    TryCopyStr(buf, tbuf, sz);
93770728a38Smrg    if (act->type == XkbSA_LockGroup)
93870728a38Smrg        return True;
93970728a38Smrg    if (act->flags & XkbSA_ClearLocks)
94070728a38Smrg        TryCopyStr(buf, ",clearLocks", sz);
94170728a38Smrg    if (act->flags & XkbSA_LatchToLock)
94270728a38Smrg        TryCopyStr(buf, ",latchToLock", sz);
9438c9fbc29Smrg    return True;
9448c9fbc29Smrg}
9458c9fbc29Smrg
9468c9fbc29Smrg/*ARGSUSED*/
9478c9fbc29Smrgstatic Bool
94870728a38SmrgCopyMovePtrArgs(Display *dpy, XkbDescPtr xkb, XkbAction *action,
94970728a38Smrg                char *buf, int *sz)
9508c9fbc29Smrg{
95170728a38Smrg    XkbPtrAction *act;
95270728a38Smrg    int x, y;
95370728a38Smrg    char tbuf[32];
95470728a38Smrg
95570728a38Smrg    act = &action->ptr;
95670728a38Smrg    x = XkbPtrActionX(act);
95770728a38Smrg    y = XkbPtrActionY(act);
95870728a38Smrg    if ((act->flags & XkbSA_MoveAbsoluteX) || (x < 0))
95970728a38Smrg        snprintf(tbuf, sizeof(tbuf), "x=%d", x);
96070728a38Smrg    else
96170728a38Smrg        snprintf(tbuf, sizeof(tbuf), "x=+%d", x);
96270728a38Smrg    TryCopyStr(buf, tbuf, sz);
96370728a38Smrg
96470728a38Smrg    if ((act->flags & XkbSA_MoveAbsoluteY) || (y < 0))
96570728a38Smrg        snprintf(tbuf, sizeof(tbuf), ",y=%d", y);
96670728a38Smrg    else
96770728a38Smrg        snprintf(tbuf, sizeof(tbuf), ",y=+%d", y);
96870728a38Smrg    TryCopyStr(buf, tbuf, sz);
96970728a38Smrg    if (act->flags & XkbSA_NoAcceleration)
97070728a38Smrg        TryCopyStr(buf, ",!accel", sz);
9718c9fbc29Smrg    return True;
9728c9fbc29Smrg}
9738c9fbc29Smrg
9748c9fbc29Smrg/*ARGSUSED*/
9758c9fbc29Smrgstatic Bool
97670728a38SmrgCopyPtrBtnArgs(Display *dpy, XkbDescPtr xkb, XkbAction *action,
97770728a38Smrg               char *buf, int *sz)
9788c9fbc29Smrg{
97970728a38Smrg    XkbPtrBtnAction *act;
98070728a38Smrg    char tbuf[32];
98170728a38Smrg
98270728a38Smrg    act = &action->btn;
98370728a38Smrg    TryCopyStr(buf, "button=", sz);
98470728a38Smrg    if ((act->button > 0) && (act->button < 6)) {
98570728a38Smrg        snprintf(tbuf, sizeof(tbuf), "%d", act->button);
98670728a38Smrg        TryCopyStr(buf, tbuf, sz);
98770728a38Smrg    }
98870728a38Smrg    else
98970728a38Smrg        TryCopyStr(buf, "default", sz);
99070728a38Smrg    if (act->count > 0) {
99170728a38Smrg        snprintf(tbuf, sizeof(tbuf), ",count=%d", act->count);
99270728a38Smrg        TryCopyStr(buf, tbuf, sz);
99370728a38Smrg    }
99470728a38Smrg    if (action->type == XkbSA_LockPtrBtn) {
99570728a38Smrg        switch (act->flags & (XkbSA_LockNoUnlock | XkbSA_LockNoLock)) {
99670728a38Smrg        case XkbSA_LockNoLock:
99770728a38Smrg            snprintf(tbuf, sizeof(tbuf), ",affect=unlock");
99870728a38Smrg            break;
99970728a38Smrg        case XkbSA_LockNoUnlock:
100070728a38Smrg            snprintf(tbuf, sizeof(tbuf), ",affect=lock");
100170728a38Smrg            break;
100270728a38Smrg        case XkbSA_LockNoUnlock | XkbSA_LockNoLock:
100370728a38Smrg            snprintf(tbuf, sizeof(tbuf), ",affect=neither");
100470728a38Smrg            break;
100570728a38Smrg        default:
100670728a38Smrg            snprintf(tbuf, sizeof(tbuf), ",affect=both");
100770728a38Smrg            break;
100870728a38Smrg        }
100970728a38Smrg        TryCopyStr(buf, tbuf, sz);
10108c9fbc29Smrg    }
10118c9fbc29Smrg    return True;
10128c9fbc29Smrg}
10138c9fbc29Smrg
10148c9fbc29Smrg/*ARGSUSED*/
10158c9fbc29Smrgstatic Bool
101670728a38SmrgCopySetPtrDfltArgs(Display *dpy, XkbDescPtr xkb, XkbAction *action,
101770728a38Smrg                   char *buf, int *sz)
10188c9fbc29Smrg{
101970728a38Smrg    XkbPtrDfltAction *act;
102070728a38Smrg    char tbuf[32];
102170728a38Smrg
102270728a38Smrg    act = &action->dflt;
102370728a38Smrg    if (act->affect == XkbSA_AffectDfltBtn) {
102470728a38Smrg        TryCopyStr(buf, "affect=button,button=", sz);
102570728a38Smrg        if ((act->flags & XkbSA_DfltBtnAbsolute) ||
102670728a38Smrg            (XkbSAPtrDfltValue(act) < 0))
102770728a38Smrg            snprintf(tbuf, sizeof(tbuf), "%d", XkbSAPtrDfltValue(act));
102870728a38Smrg        else
102970728a38Smrg            snprintf(tbuf, sizeof(tbuf), "+%d", XkbSAPtrDfltValue(act));
103070728a38Smrg        TryCopyStr(buf, tbuf, sz);
10318c9fbc29Smrg    }
10328c9fbc29Smrg    return True;
10338c9fbc29Smrg}
10348c9fbc29Smrg
10358c9fbc29Smrgstatic Bool
103670728a38SmrgCopyISOLockArgs(Display *dpy, XkbDescPtr xkb, XkbAction *action,
103770728a38Smrg                char *buf, int *sz)
10388c9fbc29Smrg{
103970728a38Smrg    XkbISOAction *act;
104070728a38Smrg    char tbuf[64];
104170728a38Smrg
104270728a38Smrg    act = &action->iso;
104370728a38Smrg    if (act->flags & XkbSA_ISODfltIsGroup) {
104470728a38Smrg        TryCopyStr(tbuf, "group=", sz);
104570728a38Smrg        if (act->flags & XkbSA_GroupAbsolute)
104670728a38Smrg            snprintf(tbuf, sizeof(tbuf), "%d", XkbSAGroup(act) + 1);
104770728a38Smrg        else if (XkbSAGroup(act) < 0)
104870728a38Smrg            snprintf(tbuf, sizeof(tbuf), "%d", XkbSAGroup(act));
104970728a38Smrg        else
105070728a38Smrg            snprintf(tbuf, sizeof(tbuf), "+%d", XkbSAGroup(act));
105170728a38Smrg        TryCopyStr(buf, tbuf, sz);
10528c9fbc29Smrg    }
10538c9fbc29Smrg    else {
105470728a38Smrg        unsigned tmp;
105570728a38Smrg
105670728a38Smrg        tmp = XkbModActionVMods(act);
105770728a38Smrg        TryCopyStr(buf, "modifiers=", sz);
105870728a38Smrg        if (act->flags & XkbSA_UseModMapMods)
105970728a38Smrg            TryCopyStr(buf, "modMapMods", sz);
106070728a38Smrg        else if (act->real_mods || tmp) {
106170728a38Smrg            if (act->real_mods) {
106270728a38Smrg                TryCopyStr(buf, XkbModMaskText(act->real_mods, XkbXKBFile), sz);
106370728a38Smrg                if (tmp)
106470728a38Smrg                    TryCopyStr(buf, "+", sz);
106570728a38Smrg            }
106670728a38Smrg            if (tmp)
106770728a38Smrg                TryCopyStr(buf, XkbVModMaskText(dpy, xkb, 0, tmp, XkbXKBFile),
106870728a38Smrg                           sz);
106970728a38Smrg        }
107070728a38Smrg        else
107170728a38Smrg            TryCopyStr(buf, "none", sz);
107270728a38Smrg    }
107370728a38Smrg    TryCopyStr(buf, ",affect=", sz);
107454044362Smrg    if ((act->affect & XkbSA_ISOAffectMask) == 0) {
107570728a38Smrg        TryCopyStr(buf, "all", sz);
107654044362Smrg    }
107754044362Smrg    else if ((act->affect & XkbSA_ISOAffectMask) == XkbSA_ISOAffectMask) {
107854044362Smrg        TryCopyStr(buf, "none", sz);
107954044362Smrg    }
10808c9fbc29Smrg    else {
108170728a38Smrg        int nOut = 0;
108270728a38Smrg
108370728a38Smrg        if ((act->affect & XkbSA_ISONoAffectMods) == 0) {
108470728a38Smrg            TryCopyStr(buf, "mods", sz);
108570728a38Smrg            nOut++;
108670728a38Smrg        }
108770728a38Smrg        if ((act->affect & XkbSA_ISONoAffectGroup) == 0) {
108870728a38Smrg            snprintf(tbuf, sizeof(tbuf), "%sgroups", (nOut > 0 ? "+" : ""));
108970728a38Smrg            TryCopyStr(buf, tbuf, sz);
109070728a38Smrg            nOut++;
109170728a38Smrg        }
109270728a38Smrg        if ((act->affect & XkbSA_ISONoAffectPtr) == 0) {
109370728a38Smrg            snprintf(tbuf, sizeof(tbuf), "%spointer", (nOut > 0 ? "+" : ""));
109470728a38Smrg            TryCopyStr(buf, tbuf, sz);
109570728a38Smrg            nOut++;
109670728a38Smrg        }
109770728a38Smrg        if ((act->affect & XkbSA_ISONoAffectCtrls) == 0) {
109870728a38Smrg            snprintf(tbuf, sizeof(tbuf), "%scontrols", (nOut > 0 ? "+" : ""));
109970728a38Smrg            TryCopyStr(buf, tbuf, sz);
110070728a38Smrg            nOut++;
110170728a38Smrg        }
11028c9fbc29Smrg    }
110354044362Smrg    switch (act->flags & (XkbSA_LockNoUnlock | XkbSA_LockNoLock)) {
110454044362Smrg    case XkbSA_LockNoLock:
110554044362Smrg        TryCopyStr(buf, "+unlock", sz);
110654044362Smrg        break;
110754044362Smrg    case XkbSA_LockNoUnlock:
110854044362Smrg        TryCopyStr(buf, "+lock", sz);
110954044362Smrg        break;
111054044362Smrg    case XkbSA_LockNoUnlock | XkbSA_LockNoLock:
111154044362Smrg        TryCopyStr(buf, "+neither", sz);
111254044362Smrg        break;
111354044362Smrg    default: ;
111454044362Smrg    }
11158c9fbc29Smrg    return True;
11168c9fbc29Smrg}
11178c9fbc29Smrg
11188c9fbc29Smrg/*ARGSUSED*/
11198c9fbc29Smrgstatic Bool
112070728a38SmrgCopySwitchScreenArgs(Display *dpy, XkbDescPtr xkb, XkbAction *action,
112170728a38Smrg                     char *buf, int *sz)
11228c9fbc29Smrg{
112370728a38Smrg    XkbSwitchScreenAction *act;
112470728a38Smrg    char tbuf[32];
112570728a38Smrg
112670728a38Smrg    act = &action->screen;
112770728a38Smrg    if ((act->flags & XkbSA_SwitchAbsolute) || (XkbSAScreen(act) < 0))
112870728a38Smrg        snprintf(tbuf, sizeof(tbuf), "screen=%d", XkbSAScreen(act));
112970728a38Smrg    else
113070728a38Smrg        snprintf(tbuf, sizeof(tbuf), "screen=+%d", XkbSAScreen(act));
113170728a38Smrg    TryCopyStr(buf, tbuf, sz);
113270728a38Smrg    if (act->flags & XkbSA_SwitchApplication)
113370728a38Smrg        TryCopyStr(buf, ",!same", sz);
113470728a38Smrg    else
113570728a38Smrg        TryCopyStr(buf, ",same", sz);
11368c9fbc29Smrg    return True;
11378c9fbc29Smrg}
11388c9fbc29Smrg
11398c9fbc29Smrg/*ARGSUSED*/
11408c9fbc29Smrgstatic Bool
114170728a38SmrgCopySetLockControlsArgs(Display *dpy, XkbDescPtr xkb, XkbAction *action,
114270728a38Smrg                        char *buf, int *sz)
11438c9fbc29Smrg{
114470728a38Smrg    XkbCtrlsAction *act;
114570728a38Smrg    unsigned tmp;
114670728a38Smrg    char tbuf[32];
114770728a38Smrg
114870728a38Smrg    act = &action->ctrls;
114970728a38Smrg    tmp = XkbActionCtrls(act);
115070728a38Smrg    TryCopyStr(buf, "controls=", sz);
115170728a38Smrg    if (tmp == 0)
115270728a38Smrg        TryCopyStr(buf, "none", sz);
115370728a38Smrg    else if ((tmp & XkbAllBooleanCtrlsMask) == XkbAllBooleanCtrlsMask)
115470728a38Smrg        TryCopyStr(buf, "all", sz);
11558c9fbc29Smrg    else {
115670728a38Smrg        int nOut = 0;
115770728a38Smrg
115870728a38Smrg        if (tmp & XkbRepeatKeysMask) {
115970728a38Smrg            snprintf(tbuf, sizeof(tbuf), "%sRepeatKeys", (nOut > 0 ? "+" : ""));
116070728a38Smrg            TryCopyStr(buf, tbuf, sz);
116170728a38Smrg            nOut++;
116270728a38Smrg        }
116370728a38Smrg        if (tmp & XkbSlowKeysMask) {
116470728a38Smrg            snprintf(tbuf, sizeof(tbuf), "%sSlowKeys", (nOut > 0 ? "+" : ""));
116570728a38Smrg            TryCopyStr(buf, tbuf, sz);
116670728a38Smrg            nOut++;
116770728a38Smrg        }
116870728a38Smrg        if (tmp & XkbBounceKeysMask) {
116970728a38Smrg            snprintf(tbuf, sizeof(tbuf), "%sBounceKeys", (nOut > 0 ? "+" : ""));
117070728a38Smrg            TryCopyStr(buf, tbuf, sz);
117170728a38Smrg            nOut++;
117270728a38Smrg        }
117370728a38Smrg        if (tmp & XkbStickyKeysMask) {
117470728a38Smrg            snprintf(tbuf, sizeof(tbuf), "%sStickyKeys", (nOut > 0 ? "+" : ""));
117570728a38Smrg            TryCopyStr(buf, tbuf, sz);
117670728a38Smrg            nOut++;
117770728a38Smrg        }
117870728a38Smrg        if (tmp & XkbMouseKeysMask) {
117970728a38Smrg            snprintf(tbuf, sizeof(tbuf), "%sMouseKeys", (nOut > 0 ? "+" : ""));
118070728a38Smrg            TryCopyStr(buf, tbuf, sz);
118170728a38Smrg            nOut++;
118270728a38Smrg        }
118370728a38Smrg        if (tmp & XkbMouseKeysAccelMask) {
118470728a38Smrg            snprintf(tbuf, sizeof(tbuf), "%sMouseKeysAccel", (nOut > 0 ? "+" : ""));
118570728a38Smrg            TryCopyStr(buf, tbuf, sz);
118670728a38Smrg            nOut++;
118770728a38Smrg        }
118870728a38Smrg        if (tmp & XkbAccessXKeysMask) {
118970728a38Smrg            snprintf(tbuf, sizeof(tbuf), "%sAccessXKeys", (nOut > 0 ? "+" : ""));
119070728a38Smrg            TryCopyStr(buf, tbuf, sz);
119170728a38Smrg            nOut++;
119270728a38Smrg        }
119370728a38Smrg        if (tmp & XkbAccessXTimeoutMask) {
119470728a38Smrg            snprintf(tbuf, sizeof(tbuf), "%sAccessXTimeout", (nOut > 0 ? "+" : ""));
119570728a38Smrg            TryCopyStr(buf, tbuf, sz);
119670728a38Smrg            nOut++;
119770728a38Smrg        }
119870728a38Smrg        if (tmp & XkbAccessXFeedbackMask) {
119970728a38Smrg            snprintf(tbuf, sizeof(tbuf), "%sAccessXFeedback", (nOut > 0 ? "+" : ""));
120070728a38Smrg            TryCopyStr(buf, tbuf, sz);
120170728a38Smrg            nOut++;
120270728a38Smrg        }
120370728a38Smrg        if (tmp & XkbAudibleBellMask) {
120470728a38Smrg            snprintf(tbuf, sizeof(tbuf), "%sAudibleBell", (nOut > 0 ? "+" : ""));
120570728a38Smrg            TryCopyStr(buf, tbuf, sz);
120670728a38Smrg            nOut++;
120770728a38Smrg        }
120870728a38Smrg        if (tmp & XkbOverlay1Mask) {
120970728a38Smrg            snprintf(tbuf, sizeof(tbuf), "%sOverlay1", (nOut > 0 ? "+" : ""));
121070728a38Smrg            TryCopyStr(buf, tbuf, sz);
121170728a38Smrg            nOut++;
121270728a38Smrg        }
121370728a38Smrg        if (tmp & XkbOverlay2Mask) {
121470728a38Smrg            snprintf(tbuf, sizeof(tbuf), "%sOverlay2", (nOut > 0 ? "+" : ""));
121570728a38Smrg            TryCopyStr(buf, tbuf, sz);
121670728a38Smrg            nOut++;
121770728a38Smrg        }
121870728a38Smrg        if (tmp & XkbIgnoreGroupLockMask) {
121970728a38Smrg            snprintf(tbuf, sizeof(tbuf), "%sIgnoreGroupLock", (nOut > 0 ? "+" : ""));
122070728a38Smrg            TryCopyStr(buf, tbuf, sz);
122170728a38Smrg            nOut++;
122270728a38Smrg        }
12238c9fbc29Smrg    }
122454044362Smrg    if (action->type == XkbSA_LockControls) {
122554044362Smrg        switch (act->flags & (XkbSA_LockNoUnlock | XkbSA_LockNoLock)) {
122654044362Smrg        case XkbSA_LockNoLock:
122754044362Smrg            TryCopyStr(buf, ",affect=unlock", sz);
122854044362Smrg            break;
122954044362Smrg        case XkbSA_LockNoUnlock:
123054044362Smrg            TryCopyStr(buf, ",affect=lock", sz);
123154044362Smrg            break;
123254044362Smrg        case XkbSA_LockNoUnlock | XkbSA_LockNoLock:
123354044362Smrg            TryCopyStr(buf, ",affect=neither", sz);
123454044362Smrg            break;
123554044362Smrg        default: ;
123654044362Smrg        }
123754044362Smrg    }
12388c9fbc29Smrg    return True;
12398c9fbc29Smrg}
12408c9fbc29Smrg
12418c9fbc29Smrg/*ARGSUSED*/
12428c9fbc29Smrgstatic Bool
124370728a38SmrgCopyActionMessageArgs(Display *dpy, XkbDescPtr xkb, XkbAction *action,
124470728a38Smrg                      char *buf, int *sz)
12458c9fbc29Smrg{
124670728a38Smrg    XkbMessageAction *act;
124770728a38Smrg    unsigned all;
124870728a38Smrg    char tbuf[32];
124970728a38Smrg
125070728a38Smrg    act = &action->msg;
125170728a38Smrg    all = XkbSA_MessageOnPress | XkbSA_MessageOnRelease;
125270728a38Smrg    TryCopyStr(buf, "report=", sz);
125370728a38Smrg    if ((act->flags & all) == 0)
125470728a38Smrg        TryCopyStr(buf, "none", sz);
125570728a38Smrg    else if ((act->flags & all) == all)
125670728a38Smrg        TryCopyStr(buf, "all", sz);
125770728a38Smrg    else if (act->flags & XkbSA_MessageOnPress)
125870728a38Smrg        TryCopyStr(buf, "KeyPress", sz);
125970728a38Smrg    else
126070728a38Smrg        TryCopyStr(buf, "KeyRelease", sz);
126170728a38Smrg    snprintf(tbuf, sizeof(tbuf), ",data[0]=0x%02x", act->message[0]);
126270728a38Smrg    TryCopyStr(buf, tbuf, sz);
126370728a38Smrg    snprintf(tbuf, sizeof(tbuf), ",data[1]=0x%02x", act->message[1]);
126470728a38Smrg    TryCopyStr(buf, tbuf, sz);
126570728a38Smrg    snprintf(tbuf, sizeof(tbuf), ",data[2]=0x%02x", act->message[2]);
126670728a38Smrg    TryCopyStr(buf, tbuf, sz);
126770728a38Smrg    snprintf(tbuf, sizeof(tbuf), ",data[3]=0x%02x", act->message[3]);
126870728a38Smrg    TryCopyStr(buf, tbuf, sz);
126970728a38Smrg    snprintf(tbuf, sizeof(tbuf), ",data[4]=0x%02x", act->message[4]);
127070728a38Smrg    TryCopyStr(buf, tbuf, sz);
127170728a38Smrg    snprintf(tbuf, sizeof(tbuf), ",data[5]=0x%02x", act->message[5]);
127270728a38Smrg    TryCopyStr(buf, tbuf, sz);
127354044362Smrg    if (act->flags & XkbSA_MessageGenKeyEvent)
127454044362Smrg        TryCopyStr(buf, ",genKeyEvent", sz);
12758c9fbc29Smrg    return True;
12768c9fbc29Smrg}
12778c9fbc29Smrg
12788c9fbc29Smrgstatic Bool
127970728a38SmrgCopyRedirectKeyArgs(Display *dpy, XkbDescPtr xkb, XkbAction *action,
128070728a38Smrg                    char *buf, int *sz)
12818c9fbc29Smrg{
128270728a38Smrg    XkbRedirectKeyAction *act;
128370728a38Smrg    char tbuf[32], *tmp;
128470728a38Smrg    unsigned kc;
128570728a38Smrg    unsigned vmods, vmods_mask;
128670728a38Smrg
128770728a38Smrg    act = &action->redirect;
128870728a38Smrg    kc = act->new_key;
128970728a38Smrg    vmods = XkbSARedirectVMods(act);
129070728a38Smrg    vmods_mask = XkbSARedirectVModsMask(act);
129170728a38Smrg    if (xkb && xkb->names && xkb->names->keys && (kc <= xkb->max_key_code) &&
129270728a38Smrg        (xkb->names->keys[kc].name[0] != '\0')) {
129370728a38Smrg        char *kn;
129470728a38Smrg
129570728a38Smrg        kn = XkbKeyNameText(xkb->names->keys[kc].name, XkbXKBFile);
129670728a38Smrg        snprintf(tbuf, sizeof(tbuf), "key=%s", kn);
129770728a38Smrg    }
129870728a38Smrg    else
129970728a38Smrg        snprintf(tbuf, sizeof(tbuf), "key=%d", kc);
130070728a38Smrg    TryCopyStr(buf, tbuf, sz);
130170728a38Smrg    if ((act->mods_mask == 0) && (vmods_mask == 0))
130270728a38Smrg        return True;
130370728a38Smrg    if ((act->mods_mask == XkbAllModifiersMask) &&
130470728a38Smrg        (vmods_mask == XkbAllVirtualModsMask)) {
130570728a38Smrg        tmp = XkbVModMaskText(dpy, xkb, act->mods, vmods, XkbXKBFile);
130670728a38Smrg        TryCopyStr(buf, ",mods=", sz);
130770728a38Smrg        TryCopyStr(buf, tmp, sz);
13088c9fbc29Smrg    }
13098c9fbc29Smrg    else {
131070728a38Smrg        if ((act->mods_mask & act->mods) || (vmods_mask & vmods)) {
131170728a38Smrg            tmp = XkbVModMaskText(dpy, xkb, act->mods_mask & act->mods,
131270728a38Smrg                                  vmods_mask & vmods, XkbXKBFile);
131370728a38Smrg            TryCopyStr(buf, ",mods= ", sz);
131470728a38Smrg            TryCopyStr(buf, tmp, sz);
131570728a38Smrg        }
131670728a38Smrg        if ((act->mods_mask & (~act->mods)) || (vmods_mask & (~vmods))) {
131770728a38Smrg            tmp = XkbVModMaskText(dpy, xkb, act->mods_mask & (~act->mods),
131870728a38Smrg                                  vmods_mask & (~vmods), XkbXKBFile);
131970728a38Smrg            TryCopyStr(buf, ",clearMods= ", sz);
132070728a38Smrg            TryCopyStr(buf, tmp, sz);
132170728a38Smrg        }
13228c9fbc29Smrg    }
13238c9fbc29Smrg    return True;
13248c9fbc29Smrg}
13258c9fbc29Smrg
13268c9fbc29Smrg/*ARGSUSED*/
13278c9fbc29Smrgstatic Bool
132870728a38SmrgCopyDeviceBtnArgs(Display *dpy, XkbDescPtr xkb, XkbAction *action,
132970728a38Smrg                  char *buf, int *sz)
13308c9fbc29Smrg{
133170728a38Smrg    XkbDeviceBtnAction *act;
133270728a38Smrg    char tbuf[32];
133370728a38Smrg
133470728a38Smrg    act = &action->devbtn;
133570728a38Smrg    snprintf(tbuf, sizeof(tbuf), "device= %d", act->device);
133670728a38Smrg    TryCopyStr(buf, tbuf, sz);
133770728a38Smrg    TryCopyStr(buf, ",button=", sz);
133870728a38Smrg    snprintf(tbuf, sizeof(tbuf), "%d", act->button);
133970728a38Smrg    TryCopyStr(buf, tbuf, sz);
134070728a38Smrg    if (act->count > 0) {
134170728a38Smrg        snprintf(tbuf, sizeof(tbuf), ",count=%d", act->count);
134270728a38Smrg        TryCopyStr(buf, tbuf, sz);
134370728a38Smrg    }
134470728a38Smrg    if (action->type == XkbSA_LockDeviceBtn) {
134570728a38Smrg        switch (act->flags & (XkbSA_LockNoUnlock | XkbSA_LockNoLock)) {
134670728a38Smrg        case XkbSA_LockNoLock:
134770728a38Smrg            snprintf(tbuf, sizeof(tbuf), ",affect=unlock");
134870728a38Smrg            break;
134970728a38Smrg        case XkbSA_LockNoUnlock:
135070728a38Smrg            snprintf(tbuf, sizeof(tbuf), ",affect=lock");
135170728a38Smrg            break;
135270728a38Smrg        case XkbSA_LockNoUnlock | XkbSA_LockNoLock:
135370728a38Smrg            snprintf(tbuf, sizeof(tbuf), ",affect=neither");
135470728a38Smrg            break;
135570728a38Smrg        default:
135670728a38Smrg            snprintf(tbuf, sizeof(tbuf), ",affect=both");
135770728a38Smrg            break;
135870728a38Smrg        }
135970728a38Smrg        TryCopyStr(buf, tbuf, sz);
13608c9fbc29Smrg    }
13618c9fbc29Smrg    return True;
13628c9fbc29Smrg}
13638c9fbc29Smrg
13648c9fbc29Smrg/*ARGSUSED*/
13658c9fbc29Smrgstatic Bool
136670728a38SmrgCopyOtherArgs(Display *dpy, XkbDescPtr xkb, XkbAction *action,
136770728a38Smrg              char *buf, int *sz)
13688c9fbc29Smrg{
136970728a38Smrg    XkbAnyAction *act;
137070728a38Smrg    char tbuf[32];
137170728a38Smrg
137270728a38Smrg    act = &action->any;
137370728a38Smrg    snprintf(tbuf, sizeof(tbuf), "type=0x%02x", act->type);
137470728a38Smrg    TryCopyStr(buf, tbuf, sz);
137570728a38Smrg    snprintf(tbuf, sizeof(tbuf), ",data[0]=0x%02x", act->data[0]);
137670728a38Smrg    TryCopyStr(buf, tbuf, sz);
137770728a38Smrg    snprintf(tbuf, sizeof(tbuf), ",data[1]=0x%02x", act->data[1]);
137870728a38Smrg    TryCopyStr(buf, tbuf, sz);
137970728a38Smrg    snprintf(tbuf, sizeof(tbuf), ",data[2]=0x%02x", act->data[2]);
138070728a38Smrg    TryCopyStr(buf, tbuf, sz);
138170728a38Smrg    snprintf(tbuf, sizeof(tbuf), ",data[3]=0x%02x", act->data[3]);
138270728a38Smrg    TryCopyStr(buf, tbuf, sz);
138370728a38Smrg    snprintf(tbuf, sizeof(tbuf), ",data[4]=0x%02x", act->data[4]);
138470728a38Smrg    TryCopyStr(buf, tbuf, sz);
138570728a38Smrg    snprintf(tbuf, sizeof(tbuf), ",data[5]=0x%02x", act->data[5]);
138670728a38Smrg    TryCopyStr(buf, tbuf, sz);
138770728a38Smrg    snprintf(tbuf, sizeof(tbuf), ",data[6]=0x%02x", act->data[6]);
138870728a38Smrg    TryCopyStr(buf, tbuf, sz);
13898c9fbc29Smrg    return True;
13908c9fbc29Smrg}
13918c9fbc29Smrg
139270728a38Smrgtypedef Bool (*actionCopy) (Display *   /* dpy */ ,
139370728a38Smrg                            XkbDescPtr  /* xkb */ ,
139470728a38Smrg                            XkbAction * /* action */ ,
139570728a38Smrg                            char *      /* buf */ ,
139670728a38Smrg                            int *       /* sz */
139770728a38Smrg    );
139870728a38Smrg
139970728a38Smrgstatic actionCopy copyActionArgs[XkbSA_NumActions] = {
140070728a38Smrg    CopyNoActionArgs            /* NoAction     */ ,
140170728a38Smrg    CopyModActionArgs           /* SetMods      */ ,
140270728a38Smrg    CopyModActionArgs           /* LatchMods    */ ,
140370728a38Smrg    CopyModActionArgs           /* LockMods     */ ,
140470728a38Smrg    CopyGroupActionArgs         /* SetGroup     */ ,
140570728a38Smrg    CopyGroupActionArgs         /* LatchGroup   */ ,
140670728a38Smrg    CopyGroupActionArgs         /* LockGroup    */ ,
140770728a38Smrg    CopyMovePtrArgs             /* MovePtr      */ ,
140870728a38Smrg    CopyPtrBtnArgs              /* PtrBtn       */ ,
140970728a38Smrg    CopyPtrBtnArgs              /* LockPtrBtn   */ ,
141070728a38Smrg    CopySetPtrDfltArgs          /* SetPtrDflt   */ ,
141170728a38Smrg    CopyISOLockArgs             /* ISOLock      */ ,
141270728a38Smrg    CopyNoActionArgs            /* Terminate    */ ,
141370728a38Smrg    CopySwitchScreenArgs        /* SwitchScreen */ ,
141470728a38Smrg    CopySetLockControlsArgs     /* SetControls  */ ,
141570728a38Smrg    CopySetLockControlsArgs     /* LockControls */ ,
141670728a38Smrg    CopyActionMessageArgs       /* ActionMessage */ ,
141770728a38Smrg    CopyRedirectKeyArgs         /* RedirectKey  */ ,
141870728a38Smrg    CopyDeviceBtnArgs           /* DeviceBtn    */ ,
141970728a38Smrg    CopyDeviceBtnArgs           /* LockDeviceBtn */
14208c9fbc29Smrg};
14218c9fbc29Smrg
14228c9fbc29Smrg#define	ACTION_SZ	256
14238c9fbc29Smrg
14248c9fbc29Smrgchar *
142570728a38SmrgXkbActionText(Display *dpy, XkbDescPtr xkb, XkbAction *action, unsigned format)
14268c9fbc29Smrg{
142770728a38Smrg    char buf[ACTION_SZ], *tmp;
142870728a38Smrg    int sz;
14298c9fbc29Smrg
143070728a38Smrg    if (format == XkbCFile) {
143170728a38Smrg        snprintf(buf, sizeof(buf),
143270728a38Smrg                "{ %20s, { 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x } }",
143370728a38Smrg                XkbActionTypeText(action->type, XkbCFile),
143470728a38Smrg                action->any.data[0], action->any.data[1], action->any.data[2],
143570728a38Smrg                action->any.data[3], action->any.data[4], action->any.data[5],
143670728a38Smrg                action->any.data[6]);
14378c9fbc29Smrg    }
14388c9fbc29Smrg    else {
143970728a38Smrg        snprintf(buf, sizeof(buf),
144070728a38Smrg                 "%s(", XkbActionTypeText(action->type, XkbXKBFile));
144170728a38Smrg        sz = ACTION_SZ - strlen(buf) + 2;       /* room for close paren and NULL */
144270728a38Smrg        if (action->type < (unsigned) XkbSA_NumActions)
144370728a38Smrg            (*copyActionArgs[action->type]) (dpy, xkb, action, buf, &sz);
144470728a38Smrg        else
144570728a38Smrg            CopyOtherArgs(dpy, xkb, action, buf, &sz);
144670728a38Smrg        TryCopyStr(buf, ")", &sz);
144770728a38Smrg    }
144870728a38Smrg    tmp = tbGetBuffer(strlen(buf) + 1);
144970728a38Smrg    if (tmp != NULL)
145070728a38Smrg        strcpy(tmp, buf);
14518c9fbc29Smrg    return tmp;
14528c9fbc29Smrg}
14538c9fbc29Smrg
14548c9fbc29Smrgchar *
145570728a38SmrgXkbBehaviorText(XkbDescPtr xkb, XkbBehavior * behavior, unsigned format)
14568c9fbc29Smrg{
145770728a38Smrg    char buf[256], *tmp;
14588c9fbc29Smrg
145970728a38Smrg    if (format == XkbCFile) {
146070728a38Smrg        if (behavior->type == XkbKB_Default)
146170728a38Smrg            snprintf(buf, sizeof(buf), "{   0,    0 }");
146270728a38Smrg        else
146370728a38Smrg            snprintf(buf, sizeof(buf), "{ %3d, 0x%02x }", behavior->type, behavior->data);
14648c9fbc29Smrg    }
14658c9fbc29Smrg    else {
146670728a38Smrg        unsigned type, permanent;
146770728a38Smrg
146870728a38Smrg        type = behavior->type & XkbKB_OpMask;
146970728a38Smrg        permanent = ((behavior->type & XkbKB_Permanent) != 0);
147070728a38Smrg
147170728a38Smrg        if (type == XkbKB_Lock) {
147270728a38Smrg            snprintf(buf, sizeof(buf), "lock= %s", (permanent ? "Permanent" : "True"));
147370728a38Smrg        }
147470728a38Smrg        else if (type == XkbKB_RadioGroup) {
147570728a38Smrg            int g;
147670728a38Smrg            char *tmp;
147770728a38Smrg            size_t tmpsize;
147870728a38Smrg
147970728a38Smrg            g = ((behavior->data) & (~XkbKB_RGAllowNone)) + 1;
148070728a38Smrg            if (XkbKB_RGAllowNone & behavior->data) {
148170728a38Smrg                snprintf(buf, sizeof(buf), "allowNone,");
148270728a38Smrg                tmp = &buf[strlen(buf)];
148370728a38Smrg            }
148470728a38Smrg            else
148570728a38Smrg                tmp = buf;
148670728a38Smrg            tmpsize = sizeof(buf) - (tmp - buf);
148770728a38Smrg            if (permanent)
148870728a38Smrg                snprintf(tmp, tmpsize, "permanentRadioGroup= %d", g);
148970728a38Smrg            else
149070728a38Smrg                snprintf(tmp, tmpsize, "radioGroup= %d", g);
149170728a38Smrg        }
149270728a38Smrg        else if ((type == XkbKB_Overlay1) || (type == XkbKB_Overlay2)) {
149370728a38Smrg            int ndx, kc;
149470728a38Smrg            char *kn;
149570728a38Smrg
149670728a38Smrg            ndx = ((type == XkbKB_Overlay1) ? 1 : 2);
149770728a38Smrg            kc = behavior->data;
149870728a38Smrg            if ((xkb) && (xkb->names) && (xkb->names->keys))
149970728a38Smrg                kn = XkbKeyNameText(xkb->names->keys[kc].name, XkbXKBFile);
150070728a38Smrg            else {
150170728a38Smrg                static char tbuf[8];
150270728a38Smrg
150370728a38Smrg                snprintf(tbuf, sizeof(tbuf), "%d", kc);
150470728a38Smrg                kn = tbuf;
150570728a38Smrg            }
150670728a38Smrg            if (permanent)
150770728a38Smrg                snprintf(buf, sizeof(buf), "permanentOverlay%d= %s", ndx, kn);
150870728a38Smrg            else
150970728a38Smrg                snprintf(buf, sizeof(buf), "overlay%d= %s", ndx, kn);
151070728a38Smrg        }
151170728a38Smrg    }
151270728a38Smrg    tmp = tbGetBuffer(strlen(buf) + 1);
151370728a38Smrg    if (tmp != NULL)
151470728a38Smrg        strcpy(tmp, buf);
15158c9fbc29Smrg    return tmp;
15168c9fbc29Smrg}
15178c9fbc29Smrg
15188c9fbc29Smrg/***====================================================================***/
15198c9fbc29Smrg
15208c9fbc29Smrgchar *
15218c9fbc29SmrgXkbIndentText(unsigned size)
15228c9fbc29Smrg{
152370728a38Smrg    static char buf[32];
152470728a38Smrg    register int i;
15258c9fbc29Smrg
152670728a38Smrg    if (size > 31)
152770728a38Smrg        size = 31;
15288c9fbc29Smrg
152970728a38Smrg    for (i = 0; i < size; i++) {
153070728a38Smrg        buf[i] = ' ';
15318c9fbc29Smrg    }
153270728a38Smrg    buf[size] = '\0';
15338c9fbc29Smrg    return buf;
15348c9fbc29Smrg}
15358c9fbc29Smrg
15368c9fbc29Smrg
15378c9fbc29Smrg/***====================================================================***/
15388c9fbc29Smrg
15398c9fbc29Smrg#define	PIXEL_MAX	65535
15408c9fbc29Smrg
15418c9fbc29SmrgBool
154270728a38SmrgXkbLookupCanonicalRGBColor(char *def, XColor *color)
15438c9fbc29Smrg{
154470728a38Smrg    int tmp;
154570728a38Smrg
154670728a38Smrg    if (_XkbStrCaseEqual(def, "black")) {
154770728a38Smrg        color->red = color->green = color->blue = 0;
154870728a38Smrg        return True;
154970728a38Smrg    }
155070728a38Smrg    else if (_XkbStrCaseEqual(def, "white")) {
155170728a38Smrg        color->red = color->green = color->blue = PIXEL_MAX;
155270728a38Smrg        return True;
155370728a38Smrg    }
155470728a38Smrg    else if ((sscanf(def, "grey%d", &tmp) == 1) ||
155570728a38Smrg             (sscanf(def, "gray%d", &tmp) == 1) ||
155670728a38Smrg             (sscanf(def, "Grey%d", &tmp) == 1) ||
155770728a38Smrg             (sscanf(def, "Gray%d", &tmp) == 1)) {
155870728a38Smrg        if ((tmp > 0) && (tmp <= 100)) {
155970728a38Smrg            tmp = (PIXEL_MAX * tmp) / 100;
156070728a38Smrg            color->red = color->green = color->blue = tmp;
156170728a38Smrg            return True;
156270728a38Smrg        }
156370728a38Smrg    }
156470728a38Smrg    else if ((tmp = (_XkbStrCaseEqual(def, "red") * 100)) ||
156570728a38Smrg             (sscanf(def, "red%d", &tmp) == 1)) {
156670728a38Smrg        if ((tmp > 0) && (tmp <= 100)) {
156770728a38Smrg            tmp = (PIXEL_MAX * tmp) / 100;
156870728a38Smrg            color->red = tmp;
156970728a38Smrg            color->green = color->blue = 0;
157070728a38Smrg            return True;
157170728a38Smrg        }
157270728a38Smrg    }
157370728a38Smrg    else if ((tmp = (_XkbStrCaseEqual(def, "green") * 100)) ||
157470728a38Smrg             (sscanf(def, "green%d", &tmp) == 1)) {
157570728a38Smrg        if ((tmp > 0) && (tmp <= 100)) {
157670728a38Smrg            tmp = (PIXEL_MAX * tmp) / 100;
157770728a38Smrg            color->green = tmp;
157870728a38Smrg            color->red = color->blue = 0;
157970728a38Smrg            return True;
158070728a38Smrg        }
158170728a38Smrg    }
158270728a38Smrg    else if ((tmp = (_XkbStrCaseEqual(def, "blue") * 100)) ||
158370728a38Smrg             (sscanf(def, "blue%d", &tmp) == 1)) {
158470728a38Smrg        if ((tmp > 0) && (tmp <= 100)) {
158570728a38Smrg            tmp = (PIXEL_MAX * tmp) / 100;
158670728a38Smrg            color->blue = tmp;
158770728a38Smrg            color->red = color->green = 0;
158870728a38Smrg            return True;
158970728a38Smrg        }
159070728a38Smrg    }
159170728a38Smrg    else if ((tmp = (_XkbStrCaseEqual(def, "magenta") * 100)) ||
159270728a38Smrg             (sscanf(def, "magenta%d", &tmp) == 1)) {
159370728a38Smrg        if ((tmp > 0) && (tmp <= 100)) {
159470728a38Smrg            tmp = (PIXEL_MAX * tmp) / 100;
159570728a38Smrg            color->green = 0;
159670728a38Smrg            color->red = color->blue = tmp;
159770728a38Smrg            return True;
159870728a38Smrg        }
159970728a38Smrg    }
160070728a38Smrg    else if ((tmp = (_XkbStrCaseEqual(def, "cyan") * 100)) ||
160170728a38Smrg             (sscanf(def, "cyan%d", &tmp) == 1)) {
160270728a38Smrg        if ((tmp > 0) && (tmp <= 100)) {
160370728a38Smrg            tmp = (PIXEL_MAX * tmp) / 100;
160470728a38Smrg            color->red = 0;
160570728a38Smrg            color->green = color->blue = tmp;
160670728a38Smrg            return True;
160770728a38Smrg        }
160870728a38Smrg    }
160970728a38Smrg    else if ((tmp = (_XkbStrCaseEqual(def, "yellow") * 100)) ||
161070728a38Smrg             (sscanf(def, "yellow%d", &tmp) == 1)) {
161170728a38Smrg        if ((tmp > 0) && (tmp <= 100)) {
161270728a38Smrg            tmp = (PIXEL_MAX * tmp) / 100;
161370728a38Smrg            color->blue = 0;
161470728a38Smrg            color->red = color->green = tmp;
161570728a38Smrg            return True;
161670728a38Smrg        }
16178c9fbc29Smrg    }
16188c9fbc29Smrg    return False;
16198c9fbc29Smrg}
16208c9fbc29Smrg
1621