xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

xkbtext.c (37441B)


      1 /************************************************************
      2  Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
      3 
      4  Permission to use, copy, modify, and distribute this
      5  software and its documentation for any purpose and without
      6  fee is hereby granted, provided that the above copyright
      7  notice appear in all copies and that both that copyright
      8  notice and this permission notice appear in supporting
      9  documentation, and that the name of Silicon Graphics not be
     10  used in advertising or publicity pertaining to distribution
     11  of the software without specific prior written permission.
     12  Silicon Graphics makes no representation about the suitability
     13  of this software for any purpose. It is provided "as is"
     14  without any express or implied warranty.
     15 
     16  SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
     17  SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
     18  AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
     19  GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
     20  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     21  DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
     22  OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
     23  THE USE OR PERFORMANCE OF THIS SOFTWARE.
     24 
     25  ********************************************************/
     26 
     27 #ifdef HAVE_DIX_CONFIG_H
     28 #include <dix-config.h>
     29 #endif
     30 
     31 #include <stdio.h>
     32 #include <ctype.h>
     33 #include <stdlib.h>
     34 
     35 #include <X11/Xos.h>
     36 
     37 #include <X11/X.h>
     38 #include <X11/Xproto.h>
     39 #include <X11/extensions/XKMformat.h>
     40 #include "misc.h"
     41 #include "inputstr.h"
     42 #include "dix.h"
     43 #include "xkbstr.h"
     44 #define XKBSRV_NEED_FILE_FUNCS	1
     45 #include <xkbsrv.h>
     46 #include "xkbgeom.h"
     47 
     48 /***====================================================================***/
     49 
     50 #define NUM_BUFFER      8
     51 static struct textBuffer {
     52     int size;
     53     char *buffer;
     54 } textBuffer[NUM_BUFFER];
     55 static int textBufferIndex;
     56 
     57 static char *
     58 tbGetBuffer(unsigned size)
     59 {
     60     struct textBuffer *tb;
     61 
     62     tb = &textBuffer[textBufferIndex];
     63     textBufferIndex = (textBufferIndex + 1) % NUM_BUFFER;
     64 
     65     if (size > tb->size) {
     66         free(tb->buffer);
     67         tb->buffer = xnfalloc(size);
     68         tb->size = size;
     69     }
     70     return tb->buffer;
     71 }
     72 
     73 /***====================================================================***/
     74 
     75 char *
     76 XkbAtomText(Atom atm, unsigned format)
     77 {
     78     const char *atmstr;
     79     char *rtrn, *tmp;
     80 
     81     atmstr = NameForAtom(atm);
     82     if (atmstr != NULL) {
     83         int len;
     84 
     85         len = strlen(atmstr) + 1;
     86         rtrn = tbGetBuffer(len);
     87         strlcpy(rtrn, atmstr, len);
     88     }
     89     else {
     90         rtrn = tbGetBuffer(1);
     91         rtrn[0] = '\0';
     92     }
     93     if (format == XkbCFile) {
     94         for (tmp = rtrn; *tmp != '\0'; tmp++) {
     95             if ((tmp == rtrn) && (!isalpha(*tmp)))
     96                 *tmp = '_';
     97             else if (!isalnum(*tmp))
     98                 *tmp = '_';
     99         }
    100     }
    101     return XkbStringText(rtrn, format);
    102 }
    103 
    104 /***====================================================================***/
    105 
    106 char *
    107 XkbVModIndexText(XkbDescPtr xkb, unsigned ndx, unsigned format)
    108 {
    109     register int len;
    110     register Atom *vmodNames;
    111     char *rtrn;
    112     const char *tmp;
    113     char numBuf[20];
    114 
    115     if (xkb && xkb->names)
    116         vmodNames = xkb->names->vmods;
    117     else
    118         vmodNames = NULL;
    119 
    120     tmp = NULL;
    121     if (ndx >= XkbNumVirtualMods)
    122         tmp = "illegal";
    123     else if (vmodNames && (vmodNames[ndx] != None))
    124         tmp = NameForAtom(vmodNames[ndx]);
    125     if (tmp == NULL) {
    126         snprintf(numBuf, sizeof(numBuf), "%d", ndx);
    127         tmp = numBuf;
    128     }
    129 
    130     len = strlen(tmp) + 1;
    131     if (format == XkbCFile)
    132         len += 4;
    133     rtrn = tbGetBuffer(len);
    134     if (format == XkbCFile) {
    135         strcpy(rtrn, "vmod_");
    136         strncpy(&rtrn[5], tmp, len - 4);
    137     }
    138     else
    139         strncpy(rtrn, tmp, len);
    140     return rtrn;
    141 }
    142 
    143 #define VMOD_BUFFER_SIZE        512
    144 
    145 char *
    146 XkbVModMaskText(XkbDescPtr xkb,
    147                 unsigned modMask, unsigned mask, unsigned format)
    148 {
    149     register int i, bit;
    150     int len;
    151     char *mm, *rtrn;
    152     char *str, buf[VMOD_BUFFER_SIZE];
    153 
    154     if ((modMask == 0) && (mask == 0)) {
    155         rtrn = tbGetBuffer(5);
    156         if (format == XkbCFile)
    157             sprintf(rtrn, "0");
    158         else
    159             sprintf(rtrn, "none");
    160         return rtrn;
    161     }
    162     if (modMask != 0)
    163         mm = XkbModMaskText(modMask, format);
    164     else
    165         mm = NULL;
    166 
    167     str = buf;
    168     buf[0] = '\0';
    169     if (mask) {
    170         char *tmp;
    171 
    172         for (i = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
    173             if (mask & bit) {
    174                 tmp = XkbVModIndexText(xkb, i, format);
    175                 len = strlen(tmp) + 1 + (str == buf ? 0 : 1);
    176                 if (format == XkbCFile)
    177                     len += 4;
    178                 if ((str - (buf + len)) <= VMOD_BUFFER_SIZE) {
    179                     if (str != buf) {
    180                         if (format == XkbCFile)
    181                             *str++ = '|';
    182                         else
    183                             *str++ = '+';
    184                         len--;
    185                     }
    186                 }
    187                 if (format == XkbCFile)
    188                     sprintf(str, "%sMask", tmp);
    189                 else
    190                     strcpy(str, tmp);
    191                 str = &str[len - 1];
    192             }
    193         }
    194         str = buf;
    195     }
    196     else
    197         str = NULL;
    198     if (mm)
    199         len = strlen(mm);
    200     else
    201         len = 0;
    202     if (str)
    203         len += strlen(str) + (mm == NULL ? 0 : 1);
    204     rtrn = tbGetBuffer(len + 1);
    205     rtrn[0] = '\0';
    206 
    207     if (mm != NULL) {
    208         i = strlen(mm);
    209         if (i > len)
    210             i = len;
    211         strcpy(rtrn, mm);
    212     }
    213     else {
    214         i = 0;
    215     }
    216     if (str != NULL) {
    217         if (mm != NULL) {
    218             if (format == XkbCFile)
    219                 strcat(rtrn, "|");
    220             else
    221                 strcat(rtrn, "+");
    222         }
    223         strncat(rtrn, str, len - i);
    224     }
    225     rtrn[len] = '\0';
    226     return rtrn;
    227 }
    228 
    229 static const char *modNames[XkbNumModifiers] = {
    230     "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5"
    231 };
    232 
    233 char *
    234 XkbModIndexText(unsigned ndx, unsigned format)
    235 {
    236     char *rtrn;
    237     char buf[100];
    238 
    239     if (format == XkbCFile) {
    240         if (ndx < XkbNumModifiers)
    241             snprintf(buf, sizeof(buf), "%sMapIndex", modNames[ndx]);
    242         else if (ndx == XkbNoModifier)
    243             snprintf(buf, sizeof(buf), "XkbNoModifier");
    244         else
    245             snprintf(buf, sizeof(buf), "0x%02x", ndx);
    246     }
    247     else {
    248         if (ndx < XkbNumModifiers)
    249             strcpy(buf, modNames[ndx]);
    250         else if (ndx == XkbNoModifier)
    251             strcpy(buf, "none");
    252         else
    253             snprintf(buf, sizeof(buf), "ILLEGAL_%02x", ndx);
    254     }
    255     rtrn = tbGetBuffer(strlen(buf) + 1);
    256     strcpy(rtrn, buf);
    257     return rtrn;
    258 }
    259 
    260 char *
    261 XkbModMaskText(unsigned mask, unsigned format)
    262 {
    263     register int i, bit;
    264     char buf[64], *rtrn;
    265 
    266     if ((mask & 0xff) == 0xff) {
    267         if (format == XkbCFile)
    268             strcpy(buf, "0xff");
    269         else
    270             strcpy(buf, "all");
    271     }
    272     else if ((mask & 0xff) == 0) {
    273         if (format == XkbCFile)
    274             strcpy(buf, "0");
    275         else
    276             strcpy(buf, "none");
    277     }
    278     else {
    279         char *str = buf;
    280 
    281         buf[0] = '\0';
    282         for (i = 0, bit = 1; i < XkbNumModifiers; i++, bit <<= 1) {
    283             if (mask & bit) {
    284                 if (str != buf) {
    285                     if (format == XkbCFile)
    286                         *str++ = '|';
    287                     else
    288                         *str++ = '+';
    289                 }
    290                 strcpy(str, modNames[i]);
    291                 str = &str[strlen(str)];
    292                 if (format == XkbCFile) {
    293                     strcpy(str, "Mask");
    294                     str += 4;
    295                 }
    296             }
    297         }
    298     }
    299     rtrn = tbGetBuffer(strlen(buf) + 1);
    300     strcpy(rtrn, buf);
    301     return rtrn;
    302 }
    303 
    304 /***====================================================================***/
    305 
    306  /*ARGSUSED*/ char *
    307 XkbConfigText(unsigned config, unsigned format)
    308 {
    309     static char *buf;
    310 
    311     buf = tbGetBuffer(32);
    312     switch (config) {
    313     case XkmSemanticsFile:
    314         strcpy(buf, "Semantics");
    315         break;
    316     case XkmLayoutFile:
    317         strcpy(buf, "Layout");
    318         break;
    319     case XkmKeymapFile:
    320         strcpy(buf, "Keymap");
    321         break;
    322     case XkmGeometryFile:
    323     case XkmGeometryIndex:
    324         strcpy(buf, "Geometry");
    325         break;
    326     case XkmTypesIndex:
    327         strcpy(buf, "Types");
    328         break;
    329     case XkmCompatMapIndex:
    330         strcpy(buf, "CompatMap");
    331         break;
    332     case XkmSymbolsIndex:
    333         strcpy(buf, "Symbols");
    334         break;
    335     case XkmIndicatorsIndex:
    336         strcpy(buf, "Indicators");
    337         break;
    338     case XkmKeyNamesIndex:
    339         strcpy(buf, "KeyNames");
    340         break;
    341     case XkmVirtualModsIndex:
    342         strcpy(buf, "VirtualMods");
    343         break;
    344     default:
    345         sprintf(buf, "unknown(%d)", config);
    346         break;
    347     }
    348     return buf;
    349 }
    350 
    351 /***====================================================================***/
    352 
    353 char *
    354 XkbKeysymText(KeySym sym, unsigned format)
    355 {
    356     static char buf[32];
    357 
    358     if (sym == NoSymbol)
    359         strcpy(buf, "NoSymbol");
    360     else
    361         snprintf(buf, sizeof(buf), "0x%lx", (long) sym);
    362     return buf;
    363 }
    364 
    365 char *
    366 XkbKeyNameText(char *name, unsigned format)
    367 {
    368     char *buf;
    369 
    370     if (format == XkbCFile) {
    371         buf = tbGetBuffer(5);
    372         memcpy(buf, name, 4);
    373         buf[4] = '\0';
    374     }
    375     else {
    376         int len;
    377 
    378         buf = tbGetBuffer(7);
    379         buf[0] = '<';
    380         memcpy(&buf[1], name, 4);
    381         buf[5] = '\0';
    382         len = strlen(buf);
    383         buf[len++] = '>';
    384         buf[len] = '\0';
    385     }
    386     return buf;
    387 }
    388 
    389 /***====================================================================***/
    390 
    391 static const char *siMatchText[5] = {
    392     "NoneOf", "AnyOfOrNone", "AnyOf", "AllOf", "Exactly"
    393 };
    394 
    395 const char *
    396 XkbSIMatchText(unsigned type, unsigned format)
    397 {
    398     static char buf[40];
    399     const char *rtrn;
    400 
    401     switch (type & XkbSI_OpMask) {
    402     case XkbSI_NoneOf:
    403         rtrn = siMatchText[0];
    404         break;
    405     case XkbSI_AnyOfOrNone:
    406         rtrn = siMatchText[1];
    407         break;
    408     case XkbSI_AnyOf:
    409         rtrn = siMatchText[2];
    410         break;
    411     case XkbSI_AllOf:
    412         rtrn = siMatchText[3];
    413         break;
    414     case XkbSI_Exactly:
    415         rtrn = siMatchText[4];
    416         break;
    417     default:
    418         snprintf(buf, sizeof(buf), "0x%x", type & XkbSI_OpMask);
    419         return buf;
    420     }
    421     if (format == XkbCFile) {
    422         if (type & XkbSI_LevelOneOnly)
    423             snprintf(buf, sizeof(buf), "XkbSI_LevelOneOnly|XkbSI_%s", rtrn);
    424         else
    425             snprintf(buf, sizeof(buf), "XkbSI_%s", rtrn);
    426         rtrn = buf;
    427     }
    428     return rtrn;
    429 }
    430 
    431 /***====================================================================***/
    432 
    433 static const char *imWhichNames[] = {
    434     "base",
    435     "latched",
    436     "locked",
    437     "effective",
    438     "compat"
    439 };
    440 
    441 char *
    442 XkbIMWhichStateMaskText(unsigned use_which, unsigned format)
    443 {
    444     int len;
    445     unsigned i, bit, tmp;
    446     char *buf;
    447 
    448     if (use_which == 0) {
    449         buf = tbGetBuffer(2);
    450         strcpy(buf, "0");
    451         return buf;
    452     }
    453     tmp = use_which & XkbIM_UseAnyMods;
    454     for (len = i = 0, bit = 1; tmp != 0; i++, bit <<= 1) {
    455         if (tmp & bit) {
    456             tmp &= ~bit;
    457             len += strlen(imWhichNames[i]) + 1;
    458             if (format == XkbCFile)
    459                 len += 9;
    460         }
    461     }
    462     buf = tbGetBuffer(len + 1);
    463     tmp = use_which & XkbIM_UseAnyMods;
    464     for (len = i = 0, bit = 1; tmp != 0; i++, bit <<= 1) {
    465         if (tmp & bit) {
    466             tmp &= ~bit;
    467             if (format == XkbCFile) {
    468                 if (len != 0)
    469                     buf[len++] = '|';
    470                 sprintf(&buf[len], "XkbIM_Use%s", imWhichNames[i]);
    471                 buf[len + 9] = toupper(buf[len + 9]);
    472             }
    473             else {
    474                 if (len != 0)
    475                     buf[len++] = '+';
    476                 sprintf(&buf[len], "%s", imWhichNames[i]);
    477             }
    478             len += strlen(&buf[len]);
    479         }
    480     }
    481     return buf;
    482 }
    483 
    484 static const char *ctrlNames[] = {
    485     "repeatKeys",
    486     "slowKeys",
    487     "bounceKeys",
    488     "stickyKeys",
    489     "mouseKeys",
    490     "mouseKeysAccel",
    491     "accessXKeys",
    492     "accessXTimeout",
    493     "accessXFeedback",
    494     "audibleBell",
    495     "overlay1",
    496     "overlay2",
    497     "ignoreGroupLock"
    498 };
    499 
    500 char *
    501 XkbControlsMaskText(unsigned ctrls, unsigned format)
    502 {
    503     int len;
    504     unsigned i, bit, tmp;
    505     char *buf;
    506 
    507     if (ctrls == 0) {
    508         buf = tbGetBuffer(5);
    509         if (format == XkbCFile)
    510             strcpy(buf, "0");
    511         else
    512             strcpy(buf, "none");
    513         return buf;
    514     }
    515     tmp = ctrls & XkbAllBooleanCtrlsMask;
    516     for (len = i = 0, bit = 1; tmp != 0; i++, bit <<= 1) {
    517         if (tmp & bit) {
    518             tmp &= ~bit;
    519             len += strlen(ctrlNames[i]) + 1;
    520             if (format == XkbCFile)
    521                 len += 7;
    522         }
    523     }
    524     buf = tbGetBuffer(len + 1);
    525     tmp = ctrls & XkbAllBooleanCtrlsMask;
    526     for (len = i = 0, bit = 1; tmp != 0; i++, bit <<= 1) {
    527         if (tmp & bit) {
    528             tmp &= ~bit;
    529             if (format == XkbCFile) {
    530                 if (len != 0)
    531                     buf[len++] = '|';
    532                 sprintf(&buf[len], "Xkb%sMask", ctrlNames[i]);
    533                 buf[len + 3] = toupper(buf[len + 3]);
    534             }
    535             else {
    536                 if (len != 0)
    537                     buf[len++] = '+';
    538                 sprintf(&buf[len], "%s", ctrlNames[i]);
    539             }
    540             len += strlen(&buf[len]);
    541         }
    542     }
    543     return buf;
    544 }
    545 
    546 /***====================================================================***/
    547 
    548 char *
    549 XkbStringText(char *str, unsigned format)
    550 {
    551     char *buf;
    552     register char *in, *out;
    553     int len;
    554     Bool ok;
    555 
    556     if (str == NULL) {
    557         buf = tbGetBuffer(2);
    558         buf[0] = '\0';
    559         return buf;
    560     }
    561     else if (format == XkbXKMFile)
    562         return str;
    563     for (ok = TRUE, len = 0, in = str; *in != '\0'; in++, len++) {
    564         if (!isprint(*in)) {
    565             ok = FALSE;
    566             switch (*in) {
    567             case '\n':
    568             case '\t':
    569             case '\v':
    570             case '\b':
    571             case '\r':
    572             case '\f':
    573                 len++;
    574                 break;
    575             default:
    576                 len += 4;
    577                 break;
    578             }
    579         }
    580     }
    581     if (ok)
    582         return str;
    583     buf = tbGetBuffer(len + 1);
    584     for (in = str, out = buf; *in != '\0'; in++) {
    585         if (isprint(*in))
    586             *out++ = *in;
    587         else {
    588             *out++ = '\\';
    589             if (*in == '\n')
    590                 *out++ = 'n';
    591             else if (*in == '\t')
    592                 *out++ = 't';
    593             else if (*in == '\v')
    594                 *out++ = 'v';
    595             else if (*in == '\b')
    596                 *out++ = 'b';
    597             else if (*in == '\r')
    598                 *out++ = 'r';
    599             else if (*in == '\f')
    600                 *out++ = 'f';
    601             else if ((*in == '\033') && (format == XkbXKMFile)) {
    602                 *out++ = 'e';
    603             }
    604             else {
    605                 *out++ = '0';
    606                 sprintf(out, "%o", (unsigned char) *in);
    607                 while (*out != '\0')
    608                     out++;
    609             }
    610         }
    611     }
    612     *out++ = '\0';
    613     return buf;
    614 }
    615 
    616 /***====================================================================***/
    617 
    618 char *
    619 XkbGeomFPText(int val, unsigned format)
    620 {
    621     int whole, frac;
    622     char *buf;
    623 
    624     buf = tbGetBuffer(12);
    625     if (format == XkbCFile) {
    626         sprintf(buf, "%d", val);
    627     }
    628     else {
    629         whole = val / XkbGeomPtsPerMM;
    630         frac = val % XkbGeomPtsPerMM;
    631         if (frac != 0)
    632             sprintf(buf, "%d.%d", whole, frac);
    633         else
    634             sprintf(buf, "%d", whole);
    635     }
    636     return buf;
    637 }
    638 
    639 char *
    640 XkbDoodadTypeText(unsigned type, unsigned format)
    641 {
    642     char *buf;
    643 
    644     if (format == XkbCFile) {
    645         buf = tbGetBuffer(24);
    646         if (type == XkbOutlineDoodad)
    647             strcpy(buf, "XkbOutlineDoodad");
    648         else if (type == XkbSolidDoodad)
    649             strcpy(buf, "XkbSolidDoodad");
    650         else if (type == XkbTextDoodad)
    651             strcpy(buf, "XkbTextDoodad");
    652         else if (type == XkbIndicatorDoodad)
    653             strcpy(buf, "XkbIndicatorDoodad");
    654         else if (type == XkbLogoDoodad)
    655             strcpy(buf, "XkbLogoDoodad");
    656         else
    657             sprintf(buf, "UnknownDoodad%d", type);
    658     }
    659     else {
    660         buf = tbGetBuffer(12);
    661         if (type == XkbOutlineDoodad)
    662             strcpy(buf, "outline");
    663         else if (type == XkbSolidDoodad)
    664             strcpy(buf, "solid");
    665         else if (type == XkbTextDoodad)
    666             strcpy(buf, "text");
    667         else if (type == XkbIndicatorDoodad)
    668             strcpy(buf, "indicator");
    669         else if (type == XkbLogoDoodad)
    670             strcpy(buf, "logo");
    671         else
    672             sprintf(buf, "unknown%d", type);
    673     }
    674     return buf;
    675 }
    676 
    677 static const char *actionTypeNames[XkbSA_NumActions] = {
    678     "NoAction",
    679     "SetMods", "LatchMods", "LockMods",
    680     "SetGroup", "LatchGroup", "LockGroup",
    681     "MovePtr",
    682     "PtrBtn", "LockPtrBtn",
    683     "SetPtrDflt",
    684     "ISOLock",
    685     "Terminate", "SwitchScreen",
    686     "SetControls", "LockControls",
    687     "ActionMessage",
    688     "RedirectKey",
    689     "DeviceBtn", "LockDeviceBtn"
    690 };
    691 
    692 const char *
    693 XkbActionTypeText(unsigned type, unsigned format)
    694 {
    695     static char buf[32];
    696     const char *rtrn;
    697 
    698     if (type <= XkbSA_LastAction) {
    699         rtrn = actionTypeNames[type];
    700         if (format == XkbCFile) {
    701             snprintf(buf, sizeof(buf), "XkbSA_%s", rtrn);
    702             return buf;
    703         }
    704         return rtrn;
    705     }
    706     snprintf(buf, sizeof(buf), "Private");
    707     return buf;
    708 }
    709 
    710 /***====================================================================***/
    711 
    712 static int
    713 TryCopyStr(char *to, const char *from, int *pLeft)
    714 {
    715     register int len;
    716 
    717     if (*pLeft > 0) {
    718         len = strlen(from);
    719         if (len < ((*pLeft) - 3)) {
    720             strcat(to, from);
    721             *pLeft -= len;
    722             return TRUE;
    723         }
    724     }
    725     *pLeft = -1;
    726     return FALSE;
    727 }
    728 
    729  /*ARGSUSED*/ static Bool
    730 CopyNoActionArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
    731 {
    732     return TRUE;
    733 }
    734 
    735 static Bool
    736 CopyModActionArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
    737 {
    738     XkbModAction *act;
    739     unsigned tmp;
    740 
    741     act = &action->mods;
    742     tmp = XkbModActionVMods(act);
    743     TryCopyStr(buf, "modifiers=", sz);
    744     if (act->flags & XkbSA_UseModMapMods)
    745         TryCopyStr(buf, "modMapMods", sz);
    746     else if (act->real_mods || tmp) {
    747         TryCopyStr(buf,
    748                    XkbVModMaskText(xkb, act->real_mods, tmp, XkbXKBFile), sz);
    749     }
    750     else
    751         TryCopyStr(buf, "none", sz);
    752     if (act->type == XkbSA_LockMods)
    753         return TRUE;
    754     if (act->flags & XkbSA_ClearLocks)
    755         TryCopyStr(buf, ",clearLocks", sz);
    756     if (act->flags & XkbSA_LatchToLock)
    757         TryCopyStr(buf, ",latchToLock", sz);
    758     return TRUE;
    759 }
    760 
    761  /*ARGSUSED*/ static Bool
    762 CopyGroupActionArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
    763 {
    764     XkbGroupAction *act;
    765     char tbuf[32];
    766 
    767     act = &action->group;
    768     TryCopyStr(buf, "group=", sz);
    769     if (act->flags & XkbSA_GroupAbsolute)
    770         snprintf(tbuf, sizeof(tbuf), "%d", XkbSAGroup(act) + 1);
    771     else if (XkbSAGroup(act) < 0)
    772         snprintf(tbuf, sizeof(tbuf), "%d", XkbSAGroup(act));
    773     else
    774         snprintf(tbuf, sizeof(tbuf), "+%d", XkbSAGroup(act));
    775     TryCopyStr(buf, tbuf, sz);
    776     if (act->type == XkbSA_LockGroup)
    777         return TRUE;
    778     if (act->flags & XkbSA_ClearLocks)
    779         TryCopyStr(buf, ",clearLocks", sz);
    780     if (act->flags & XkbSA_LatchToLock)
    781         TryCopyStr(buf, ",latchToLock", sz);
    782     return TRUE;
    783 }
    784 
    785  /*ARGSUSED*/ static Bool
    786 CopyMovePtrArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
    787 {
    788     XkbPtrAction *act;
    789     int x, y;
    790     char tbuf[32];
    791 
    792     act = &action->ptr;
    793     x = XkbPtrActionX(act);
    794     y = XkbPtrActionY(act);
    795     if ((act->flags & XkbSA_MoveAbsoluteX) || (x < 0))
    796         snprintf(tbuf, sizeof(tbuf), "x=%d", x);
    797     else
    798         snprintf(tbuf, sizeof(tbuf), "x=+%d", x);
    799     TryCopyStr(buf, tbuf, sz);
    800 
    801     if ((act->flags & XkbSA_MoveAbsoluteY) || (y < 0))
    802         snprintf(tbuf, sizeof(tbuf), ",y=%d", y);
    803     else
    804         snprintf(tbuf, sizeof(tbuf), ",y=+%d", y);
    805     TryCopyStr(buf, tbuf, sz);
    806     if (act->flags & XkbSA_NoAcceleration)
    807         TryCopyStr(buf, ",!accel", sz);
    808     return TRUE;
    809 }
    810 
    811  /*ARGSUSED*/ static Bool
    812 CopyPtrBtnArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
    813 {
    814     XkbPtrBtnAction *act;
    815     char tbuf[32];
    816 
    817     act = &action->btn;
    818     TryCopyStr(buf, "button=", sz);
    819     if ((act->button > 0) && (act->button < 6)) {
    820         snprintf(tbuf, sizeof(tbuf), "%d", act->button);
    821         TryCopyStr(buf, tbuf, sz);
    822     }
    823     else
    824         TryCopyStr(buf, "default", sz);
    825     if (act->count > 0) {
    826         snprintf(tbuf, sizeof(tbuf), ",count=%d", act->count);
    827         TryCopyStr(buf, tbuf, sz);
    828     }
    829     if (action->type == XkbSA_LockPtrBtn) {
    830         switch (act->flags & (XkbSA_LockNoUnlock | XkbSA_LockNoLock)) {
    831         case XkbSA_LockNoLock:
    832             TryCopyStr(buf, ",affect=unlock", sz);
    833             break;
    834         case XkbSA_LockNoUnlock:
    835             TryCopyStr(buf, ",affect=lock", sz);
    836             break;
    837         case XkbSA_LockNoUnlock | XkbSA_LockNoLock:
    838             TryCopyStr(buf, ",affect=neither", sz);
    839             break;
    840         default:
    841             TryCopyStr(buf, ",affect=both", sz);
    842             break;
    843         }
    844     }
    845     return TRUE;
    846 }
    847 
    848  /*ARGSUSED*/ static Bool
    849 CopySetPtrDfltArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
    850 {
    851     XkbPtrDfltAction *act;
    852     char tbuf[32];
    853 
    854     act = &action->dflt;
    855     if (act->affect == XkbSA_AffectDfltBtn) {
    856         TryCopyStr(buf, "affect=button,button=", sz);
    857         if ((act->flags & XkbSA_DfltBtnAbsolute) ||
    858             (XkbSAPtrDfltValue(act) < 0))
    859             snprintf(tbuf, sizeof(tbuf), "%d", XkbSAPtrDfltValue(act));
    860         else
    861             snprintf(tbuf, sizeof(tbuf), "+%d", XkbSAPtrDfltValue(act));
    862         TryCopyStr(buf, tbuf, sz);
    863     }
    864     return TRUE;
    865 }
    866 
    867 static Bool
    868 CopyISOLockArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
    869 {
    870     XkbISOAction *act;
    871     char tbuf[64];
    872 
    873     memset(tbuf, 0, sizeof(tbuf));
    874     act = &action->iso;
    875     if (act->flags & XkbSA_ISODfltIsGroup) {
    876         TryCopyStr(tbuf, "group=", sz);
    877         if (act->flags & XkbSA_GroupAbsolute)
    878             snprintf(tbuf, sizeof(tbuf), "%d", XkbSAGroup(act) + 1);
    879         else if (XkbSAGroup(act) < 0)
    880             snprintf(tbuf, sizeof(tbuf), "%d", XkbSAGroup(act));
    881         else
    882             snprintf(tbuf, sizeof(tbuf), "+%d", XkbSAGroup(act));
    883         TryCopyStr(buf, tbuf, sz);
    884     }
    885     else {
    886         unsigned tmp;
    887 
    888         tmp = XkbModActionVMods(act);
    889         TryCopyStr(buf, "modifiers=", sz);
    890         if (act->flags & XkbSA_UseModMapMods)
    891             TryCopyStr(buf, "modMapMods", sz);
    892         else if (act->real_mods || tmp) {
    893             if (act->real_mods) {
    894                 TryCopyStr(buf, XkbModMaskText(act->real_mods, XkbXKBFile), sz);
    895                 if (tmp)
    896                     TryCopyStr(buf, "+", sz);
    897             }
    898             if (tmp)
    899                 TryCopyStr(buf, XkbVModMaskText(xkb, 0, tmp, XkbXKBFile), sz);
    900         }
    901         else
    902             TryCopyStr(buf, "none", sz);
    903     }
    904     TryCopyStr(buf, ",affect=", sz);
    905     if ((act->affect & XkbSA_ISOAffectMask) == 0)
    906         TryCopyStr(buf, "all", sz);
    907     else {
    908         int nOut = 0;
    909 
    910         if ((act->affect & XkbSA_ISONoAffectMods) == 0) {
    911             TryCopyStr(buf, "mods", sz);
    912             nOut++;
    913         }
    914         if ((act->affect & XkbSA_ISONoAffectGroup) == 0) {
    915             snprintf(tbuf, sizeof(tbuf), "%sgroups", (nOut > 0 ? "+" : ""));
    916             TryCopyStr(buf, tbuf, sz);
    917             nOut++;
    918         }
    919         if ((act->affect & XkbSA_ISONoAffectPtr) == 0) {
    920             snprintf(tbuf, sizeof(tbuf), "%spointer", (nOut > 0 ? "+" : ""));
    921             TryCopyStr(buf, tbuf, sz);
    922             nOut++;
    923         }
    924         if ((act->affect & XkbSA_ISONoAffectCtrls) == 0) {
    925             snprintf(tbuf, sizeof(tbuf), "%scontrols", (nOut > 0 ? "+" : ""));
    926             TryCopyStr(buf, tbuf, sz);
    927             nOut++;
    928         }
    929     }
    930     return TRUE;
    931 }
    932 
    933  /*ARGSUSED*/ static Bool
    934 CopySwitchScreenArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
    935 {
    936     XkbSwitchScreenAction *act;
    937     char tbuf[32];
    938 
    939     act = &action->screen;
    940     if ((act->flags & XkbSA_SwitchAbsolute) || (XkbSAScreen(act) < 0))
    941         snprintf(tbuf, sizeof(tbuf), "screen=%d", XkbSAScreen(act));
    942     else
    943         snprintf(tbuf, sizeof(tbuf), "screen=+%d", XkbSAScreen(act));
    944     TryCopyStr(buf, tbuf, sz);
    945     if (act->flags & XkbSA_SwitchApplication)
    946         TryCopyStr(buf, ",!same", sz);
    947     else
    948         TryCopyStr(buf, ",same", sz);
    949     return TRUE;
    950 }
    951 
    952  /*ARGSUSED*/ static Bool
    953 CopySetLockControlsArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
    954 {
    955     XkbCtrlsAction *act;
    956     unsigned tmp;
    957     char tbuf[32];
    958 
    959     act = &action->ctrls;
    960     tmp = XkbActionCtrls(act);
    961     TryCopyStr(buf, "controls=", sz);
    962     if (tmp == 0)
    963         TryCopyStr(buf, "none", sz);
    964     else if ((tmp & XkbAllBooleanCtrlsMask) == XkbAllBooleanCtrlsMask)
    965         TryCopyStr(buf, "all", sz);
    966     else {
    967         int nOut = 0;
    968 
    969         if (tmp & XkbRepeatKeysMask) {
    970             snprintf(tbuf, sizeof(tbuf), "%sRepeatKeys", (nOut > 0 ? "+" : ""));
    971             TryCopyStr(buf, tbuf, sz);
    972             nOut++;
    973         }
    974         if (tmp & XkbSlowKeysMask) {
    975             snprintf(tbuf, sizeof(tbuf), "%sSlowKeys", (nOut > 0 ? "+" : ""));
    976             TryCopyStr(buf, tbuf, sz);
    977             nOut++;
    978         }
    979         if (tmp & XkbBounceKeysMask) {
    980             snprintf(tbuf, sizeof(tbuf), "%sBounceKeys", (nOut > 0 ? "+" : ""));
    981             TryCopyStr(buf, tbuf, sz);
    982             nOut++;
    983         }
    984         if (tmp & XkbStickyKeysMask) {
    985             snprintf(tbuf, sizeof(tbuf), "%sStickyKeys", (nOut > 0 ? "+" : ""));
    986             TryCopyStr(buf, tbuf, sz);
    987             nOut++;
    988         }
    989         if (tmp & XkbMouseKeysMask) {
    990             snprintf(tbuf, sizeof(tbuf), "%sMouseKeys", (nOut > 0 ? "+" : ""));
    991             TryCopyStr(buf, tbuf, sz);
    992             nOut++;
    993         }
    994         if (tmp & XkbMouseKeysAccelMask) {
    995             snprintf(tbuf, sizeof(tbuf), "%sMouseKeysAccel",
    996                      (nOut > 0 ? "+" : ""));
    997             TryCopyStr(buf, tbuf, sz);
    998             nOut++;
    999         }
   1000         if (tmp & XkbAccessXKeysMask) {
   1001             snprintf(tbuf, sizeof(tbuf), "%sAccessXKeys",
   1002                      (nOut > 0 ? "+" : ""));
   1003             TryCopyStr(buf, tbuf, sz);
   1004             nOut++;
   1005         }
   1006         if (tmp & XkbAccessXTimeoutMask) {
   1007             snprintf(tbuf, sizeof(tbuf), "%sAccessXTimeout",
   1008                      (nOut > 0 ? "+" : ""));
   1009             TryCopyStr(buf, tbuf, sz);
   1010             nOut++;
   1011         }
   1012         if (tmp & XkbAccessXFeedbackMask) {
   1013             snprintf(tbuf, sizeof(tbuf), "%sAccessXFeedback",
   1014                      (nOut > 0 ? "+" : ""));
   1015             TryCopyStr(buf, tbuf, sz);
   1016             nOut++;
   1017         }
   1018         if (tmp & XkbAudibleBellMask) {
   1019             snprintf(tbuf, sizeof(tbuf), "%sAudibleBell",
   1020                      (nOut > 0 ? "+" : ""));
   1021             TryCopyStr(buf, tbuf, sz);
   1022             nOut++;
   1023         }
   1024         if (tmp & XkbOverlay1Mask) {
   1025             snprintf(tbuf, sizeof(tbuf), "%sOverlay1", (nOut > 0 ? "+" : ""));
   1026             TryCopyStr(buf, tbuf, sz);
   1027             nOut++;
   1028         }
   1029         if (tmp & XkbOverlay2Mask) {
   1030             snprintf(tbuf, sizeof(tbuf), "%sOverlay2", (nOut > 0 ? "+" : ""));
   1031             TryCopyStr(buf, tbuf, sz);
   1032             nOut++;
   1033         }
   1034         if (tmp & XkbIgnoreGroupLockMask) {
   1035             snprintf(tbuf, sizeof(tbuf), "%sIgnoreGroupLock",
   1036                      (nOut > 0 ? "+" : ""));
   1037             TryCopyStr(buf, tbuf, sz);
   1038             nOut++;
   1039         }
   1040     }
   1041     return TRUE;
   1042 }
   1043 
   1044  /*ARGSUSED*/ static Bool
   1045 CopyActionMessageArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
   1046 {
   1047     XkbMessageAction *act;
   1048     unsigned all;
   1049     char tbuf[32];
   1050 
   1051     act = &action->msg;
   1052     all = XkbSA_MessageOnPress | XkbSA_MessageOnRelease;
   1053     TryCopyStr(buf, "report=", sz);
   1054     if ((act->flags & all) == 0)
   1055         TryCopyStr(buf, "none", sz);
   1056     else if ((act->flags & all) == all)
   1057         TryCopyStr(buf, "all", sz);
   1058     else if (act->flags & XkbSA_MessageOnPress)
   1059         TryCopyStr(buf, "KeyPress", sz);
   1060     else
   1061         TryCopyStr(buf, "KeyRelease", sz);
   1062     snprintf(tbuf, sizeof(tbuf), ",data[0]=0x%02x", act->message[0]);
   1063     TryCopyStr(buf, tbuf, sz);
   1064     snprintf(tbuf, sizeof(tbuf), ",data[1]=0x%02x", act->message[1]);
   1065     TryCopyStr(buf, tbuf, sz);
   1066     snprintf(tbuf, sizeof(tbuf), ",data[2]=0x%02x", act->message[2]);
   1067     TryCopyStr(buf, tbuf, sz);
   1068     snprintf(tbuf, sizeof(tbuf), ",data[3]=0x%02x", act->message[3]);
   1069     TryCopyStr(buf, tbuf, sz);
   1070     snprintf(tbuf, sizeof(tbuf), ",data[4]=0x%02x", act->message[4]);
   1071     TryCopyStr(buf, tbuf, sz);
   1072     snprintf(tbuf, sizeof(tbuf), ",data[5]=0x%02x", act->message[5]);
   1073     TryCopyStr(buf, tbuf, sz);
   1074     return TRUE;
   1075 }
   1076 
   1077 static Bool
   1078 CopyRedirectKeyArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
   1079 {
   1080     XkbRedirectKeyAction *act;
   1081     char tbuf[32], *tmp;
   1082     unsigned kc;
   1083     unsigned vmods, vmods_mask;
   1084 
   1085     act = &action->redirect;
   1086     kc = act->new_key;
   1087     vmods = XkbSARedirectVMods(act);
   1088     vmods_mask = XkbSARedirectVModsMask(act);
   1089     if (xkb && xkb->names && xkb->names->keys && (kc <= xkb->max_key_code) &&
   1090         (xkb->names->keys[kc].name[0] != '\0')) {
   1091         char *kn;
   1092 
   1093         kn = XkbKeyNameText(xkb->names->keys[kc].name, XkbXKBFile);
   1094         snprintf(tbuf, sizeof(tbuf), "key=%s", kn);
   1095     }
   1096     else
   1097         snprintf(tbuf, sizeof(tbuf), "key=%d", kc);
   1098     TryCopyStr(buf, tbuf, sz);
   1099     if ((act->mods_mask == 0) && (vmods_mask == 0))
   1100         return TRUE;
   1101     if ((act->mods_mask == XkbAllModifiersMask) &&
   1102         (vmods_mask == XkbAllVirtualModsMask)) {
   1103         tmp = XkbVModMaskText(xkb, act->mods, vmods, XkbXKBFile);
   1104         TryCopyStr(buf, ",mods=", sz);
   1105         TryCopyStr(buf, tmp, sz);
   1106     }
   1107     else {
   1108         if ((act->mods_mask & act->mods) || (vmods_mask & vmods)) {
   1109             tmp = XkbVModMaskText(xkb, act->mods_mask & act->mods,
   1110                                   vmods_mask & vmods, XkbXKBFile);
   1111             TryCopyStr(buf, ",mods= ", sz);
   1112             TryCopyStr(buf, tmp, sz);
   1113         }
   1114         if ((act->mods_mask & (~act->mods)) || (vmods_mask & (~vmods))) {
   1115             tmp = XkbVModMaskText(xkb, act->mods_mask & (~act->mods),
   1116                                   vmods_mask & (~vmods), XkbXKBFile);
   1117             TryCopyStr(buf, ",clearMods= ", sz);
   1118             TryCopyStr(buf, tmp, sz);
   1119         }
   1120     }
   1121     return TRUE;
   1122 }
   1123 
   1124  /*ARGSUSED*/ static Bool
   1125 CopyDeviceBtnArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
   1126 {
   1127     XkbDeviceBtnAction *act;
   1128     char tbuf[32];
   1129 
   1130     act = &action->devbtn;
   1131     snprintf(tbuf, sizeof(tbuf), "device= %d", act->device);
   1132     TryCopyStr(buf, tbuf, sz);
   1133     TryCopyStr(buf, ",button=", sz);
   1134     snprintf(tbuf, sizeof(tbuf), "%d", act->button);
   1135     TryCopyStr(buf, tbuf, sz);
   1136     if (act->count > 0) {
   1137         snprintf(tbuf, sizeof(tbuf), ",count=%d", act->count);
   1138         TryCopyStr(buf, tbuf, sz);
   1139     }
   1140     if (action->type == XkbSA_LockDeviceBtn) {
   1141         switch (act->flags & (XkbSA_LockNoUnlock | XkbSA_LockNoLock)) {
   1142         case XkbSA_LockNoLock:
   1143             TryCopyStr(buf, ",affect=unlock", sz);
   1144             break;
   1145         case XkbSA_LockNoUnlock:
   1146             TryCopyStr(buf, ",affect=lock", sz);
   1147             break;
   1148         case XkbSA_LockNoUnlock | XkbSA_LockNoLock:
   1149             TryCopyStr(buf, ",affect=neither", sz);
   1150             break;
   1151         default:
   1152             TryCopyStr(buf, ",affect=both", sz);
   1153             break;
   1154         }
   1155     }
   1156     return TRUE;
   1157 }
   1158 
   1159  /*ARGSUSED*/ static Bool
   1160 CopyOtherArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
   1161 {
   1162     XkbAnyAction *act;
   1163     char tbuf[32];
   1164 
   1165     act = &action->any;
   1166     snprintf(tbuf, sizeof(tbuf), "type=0x%02x", act->type);
   1167     TryCopyStr(buf, tbuf, sz);
   1168     snprintf(tbuf, sizeof(tbuf), ",data[0]=0x%02x", act->data[0]);
   1169     TryCopyStr(buf, tbuf, sz);
   1170     snprintf(tbuf, sizeof(tbuf), ",data[1]=0x%02x", act->data[1]);
   1171     TryCopyStr(buf, tbuf, sz);
   1172     snprintf(tbuf, sizeof(tbuf), ",data[2]=0x%02x", act->data[2]);
   1173     TryCopyStr(buf, tbuf, sz);
   1174     snprintf(tbuf, sizeof(tbuf), ",data[3]=0x%02x", act->data[3]);
   1175     TryCopyStr(buf, tbuf, sz);
   1176     snprintf(tbuf, sizeof(tbuf), ",data[4]=0x%02x", act->data[4]);
   1177     TryCopyStr(buf, tbuf, sz);
   1178     snprintf(tbuf, sizeof(tbuf), ",data[5]=0x%02x", act->data[5]);
   1179     TryCopyStr(buf, tbuf, sz);
   1180     snprintf(tbuf, sizeof(tbuf), ",data[6]=0x%02x", act->data[6]);
   1181     TryCopyStr(buf, tbuf, sz);
   1182     return TRUE;
   1183 }
   1184 
   1185 typedef Bool (*actionCopy) (XkbDescPtr /* xkb */ ,
   1186                             XkbAction * /* action */ ,
   1187                             char * /* buf */ ,
   1188                             int *       /* sz */
   1189     );
   1190 
   1191 static actionCopy copyActionArgs[XkbSA_NumActions] = {
   1192     CopyNoActionArgs /* NoAction     */ ,
   1193     CopyModActionArgs /* SetMods      */ ,
   1194     CopyModActionArgs /* LatchMods    */ ,
   1195     CopyModActionArgs /* LockMods     */ ,
   1196     CopyGroupActionArgs /* SetGroup     */ ,
   1197     CopyGroupActionArgs /* LatchGroup   */ ,
   1198     CopyGroupActionArgs /* LockGroup    */ ,
   1199     CopyMovePtrArgs /* MovePtr      */ ,
   1200     CopyPtrBtnArgs /* PtrBtn       */ ,
   1201     CopyPtrBtnArgs /* LockPtrBtn   */ ,
   1202     CopySetPtrDfltArgs /* SetPtrDflt   */ ,
   1203     CopyISOLockArgs /* ISOLock      */ ,
   1204     CopyNoActionArgs /* Terminate    */ ,
   1205     CopySwitchScreenArgs /* SwitchScreen */ ,
   1206     CopySetLockControlsArgs /* SetControls  */ ,
   1207     CopySetLockControlsArgs /* LockControls */ ,
   1208     CopyActionMessageArgs /* ActionMessage */ ,
   1209     CopyRedirectKeyArgs /* RedirectKey  */ ,
   1210     CopyDeviceBtnArgs /* DeviceBtn    */ ,
   1211     CopyDeviceBtnArgs           /* LockDeviceBtn */
   1212 };
   1213 
   1214 #define	ACTION_SZ	256
   1215 
   1216 char *
   1217 XkbActionText(XkbDescPtr xkb, XkbAction *action, unsigned format)
   1218 {
   1219     char buf[ACTION_SZ], *tmp;
   1220     int sz;
   1221 
   1222     if (format == XkbCFile) {
   1223         snprintf(buf, sizeof(buf),
   1224                  "{ %20s, { 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x } }",
   1225                  XkbActionTypeText(action->type, XkbCFile),
   1226                  action->any.data[0], action->any.data[1], action->any.data[2],
   1227                  action->any.data[3], action->any.data[4], action->any.data[5],
   1228                  action->any.data[6]);
   1229     }
   1230     else {
   1231         snprintf(buf, sizeof(buf), "%s(",
   1232                  XkbActionTypeText(action->type, XkbXKBFile));
   1233         sz = ACTION_SZ - strlen(buf) + 2;       /* room for close paren and NULL */
   1234         if (action->type < (unsigned) XkbSA_NumActions)
   1235             (*copyActionArgs[action->type]) (xkb, action, buf, &sz);
   1236         else
   1237             CopyOtherArgs(xkb, action, buf, &sz);
   1238         TryCopyStr(buf, ")", &sz);
   1239     }
   1240     tmp = tbGetBuffer(strlen(buf) + 1);
   1241     if (tmp != NULL)
   1242         strcpy(tmp, buf);
   1243     return tmp;
   1244 }
   1245 
   1246 char *
   1247 XkbBehaviorText(XkbDescPtr xkb, XkbBehavior * behavior, unsigned format)
   1248 {
   1249     char buf[256], *tmp;
   1250 
   1251     if (format == XkbCFile) {
   1252         if (behavior->type == XkbKB_Default)
   1253             snprintf(buf, sizeof(buf), "{   0,    0 }");
   1254         else
   1255             snprintf(buf, sizeof(buf), "{ %3d, 0x%02x }", behavior->type,
   1256                      behavior->data);
   1257     }
   1258     else {
   1259         unsigned type, permanent;
   1260 
   1261         type = behavior->type & XkbKB_OpMask;
   1262         permanent = ((behavior->type & XkbKB_Permanent) != 0);
   1263 
   1264         if (type == XkbKB_Lock) {
   1265             snprintf(buf, sizeof(buf), "lock= %s",
   1266                      (permanent ? "Permanent" : "TRUE"));
   1267         }
   1268         else if (type == XkbKB_RadioGroup) {
   1269             int g;
   1270 
   1271             g = ((behavior->data) & (~XkbKB_RGAllowNone)) + 1;
   1272             if (XkbKB_RGAllowNone & behavior->data) {
   1273                 snprintf(buf, sizeof(buf), "allowNone,");
   1274                 tmp = &buf[strlen(buf)];
   1275             }
   1276             else
   1277                 tmp = buf;
   1278             if (permanent)
   1279                 sprintf(tmp, "permanentRadioGroup= %d", g);
   1280             else
   1281                 sprintf(tmp, "radioGroup= %d", g);
   1282         }
   1283         else if ((type == XkbKB_Overlay1) || (type == XkbKB_Overlay2)) {
   1284             int ndx, kc;
   1285             char *kn;
   1286 
   1287             ndx = ((type == XkbKB_Overlay1) ? 1 : 2);
   1288             kc = behavior->data;
   1289             if ((xkb) && (xkb->names) && (xkb->names->keys))
   1290                 kn = XkbKeyNameText(xkb->names->keys[kc].name, XkbXKBFile);
   1291             else {
   1292                 static char tbuf[8];
   1293 
   1294                 snprintf(tbuf, sizeof(tbuf), "%d", kc);
   1295                 kn = tbuf;
   1296             }
   1297             if (permanent)
   1298                 snprintf(buf, sizeof(buf), "permanentOverlay%d= %s", ndx, kn);
   1299             else
   1300                 snprintf(buf, sizeof(buf), "overlay%d= %s", ndx, kn);
   1301         }
   1302     }
   1303     tmp = tbGetBuffer(strlen(buf) + 1);
   1304     if (tmp != NULL)
   1305         strcpy(tmp, buf);
   1306     return tmp;
   1307 }
   1308 
   1309 /***====================================================================***/
   1310 
   1311 char *
   1312 XkbIndentText(unsigned size)
   1313 {
   1314     static char buf[32];
   1315     register int i;
   1316 
   1317     if (size > 31)
   1318         size = 31;
   1319 
   1320     for (i = 0; i < size; i++) {
   1321         buf[i] = ' ';
   1322     }
   1323     buf[size] = '\0';
   1324     return buf;
   1325 }