xref: /OK3568_Linux_fs/external/xserver/xkb/xkbtext.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 *
tbGetBuffer(unsigned size)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 *
XkbAtomText(Atom atm,unsigned format)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 *
XkbVModIndexText(XkbDescPtr xkb,unsigned ndx,unsigned format)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 *
XkbVModMaskText(XkbDescPtr xkb,unsigned modMask,unsigned mask,unsigned format)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 *
XkbModIndexText(unsigned ndx,unsigned format)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 *
XkbModMaskText(unsigned mask,unsigned format)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 *
XkbConfigText(unsigned config,unsigned format)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 *
XkbKeysymText(KeySym sym,unsigned format)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 *
XkbKeyNameText(char * name,unsigned format)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 *
XkbSIMatchText(unsigned type,unsigned format)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 *
XkbIMWhichStateMaskText(unsigned use_which,unsigned format)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 *
XkbControlsMaskText(unsigned ctrls,unsigned format)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 *
XkbStringText(char * str,unsigned format)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 *
XkbGeomFPText(int val,unsigned format)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 *
XkbDoodadTypeText(unsigned type,unsigned format)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 *
XkbActionTypeText(unsigned type,unsigned format)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
TryCopyStr(char * to,const char * from,int * pLeft)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
CopyNoActionArgs(XkbDescPtr xkb,XkbAction * action,char * buf,int * sz)730 CopyNoActionArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
731 {
732     return TRUE;
733 }
734 
735 static Bool
CopyModActionArgs(XkbDescPtr xkb,XkbAction * action,char * buf,int * sz)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
CopyGroupActionArgs(XkbDescPtr xkb,XkbAction * action,char * buf,int * sz)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
CopyMovePtrArgs(XkbDescPtr xkb,XkbAction * action,char * buf,int * sz)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
CopyPtrBtnArgs(XkbDescPtr xkb,XkbAction * action,char * buf,int * sz)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
CopySetPtrDfltArgs(XkbDescPtr xkb,XkbAction * action,char * buf,int * sz)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
CopyISOLockArgs(XkbDescPtr xkb,XkbAction * action,char * buf,int * sz)868 CopyISOLockArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
869 {
870     XkbISOAction *act;
871     char tbuf[64];
872 
873     act = &action->iso;
874     if (act->flags & XkbSA_ISODfltIsGroup) {
875         TryCopyStr(tbuf, "group=", sz);
876         if (act->flags & XkbSA_GroupAbsolute)
877             snprintf(tbuf, sizeof(tbuf), "%d", XkbSAGroup(act) + 1);
878         else if (XkbSAGroup(act) < 0)
879             snprintf(tbuf, sizeof(tbuf), "%d", XkbSAGroup(act));
880         else
881             snprintf(tbuf, sizeof(tbuf), "+%d", XkbSAGroup(act));
882         TryCopyStr(buf, tbuf, sz);
883     }
884     else {
885         unsigned tmp;
886 
887         tmp = XkbModActionVMods(act);
888         TryCopyStr(buf, "modifiers=", sz);
889         if (act->flags & XkbSA_UseModMapMods)
890             TryCopyStr(buf, "modMapMods", sz);
891         else if (act->real_mods || tmp) {
892             if (act->real_mods) {
893                 TryCopyStr(buf, XkbModMaskText(act->real_mods, XkbXKBFile), sz);
894                 if (tmp)
895                     TryCopyStr(buf, "+", sz);
896             }
897             if (tmp)
898                 TryCopyStr(buf, XkbVModMaskText(xkb, 0, tmp, XkbXKBFile), sz);
899         }
900         else
901             TryCopyStr(buf, "none", sz);
902     }
903     TryCopyStr(buf, ",affect=", sz);
904     if ((act->affect & XkbSA_ISOAffectMask) == 0)
905         TryCopyStr(buf, "all", sz);
906     else {
907         int nOut = 0;
908 
909         if ((act->affect & XkbSA_ISONoAffectMods) == 0) {
910             TryCopyStr(buf, "mods", sz);
911             nOut++;
912         }
913         if ((act->affect & XkbSA_ISONoAffectGroup) == 0) {
914             snprintf(tbuf, sizeof(tbuf), "%sgroups", (nOut > 0 ? "+" : ""));
915             TryCopyStr(buf, tbuf, sz);
916             nOut++;
917         }
918         if ((act->affect & XkbSA_ISONoAffectPtr) == 0) {
919             snprintf(tbuf, sizeof(tbuf), "%spointer", (nOut > 0 ? "+" : ""));
920             TryCopyStr(buf, tbuf, sz);
921             nOut++;
922         }
923         if ((act->affect & XkbSA_ISONoAffectCtrls) == 0) {
924             snprintf(tbuf, sizeof(tbuf), "%scontrols", (nOut > 0 ? "+" : ""));
925             TryCopyStr(buf, tbuf, sz);
926             nOut++;
927         }
928     }
929     return TRUE;
930 }
931 
932  /*ARGSUSED*/ static Bool
CopySwitchScreenArgs(XkbDescPtr xkb,XkbAction * action,char * buf,int * sz)933 CopySwitchScreenArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
934 {
935     XkbSwitchScreenAction *act;
936     char tbuf[32];
937 
938     act = &action->screen;
939     if ((act->flags & XkbSA_SwitchAbsolute) || (XkbSAScreen(act) < 0))
940         snprintf(tbuf, sizeof(tbuf), "screen=%d", XkbSAScreen(act));
941     else
942         snprintf(tbuf, sizeof(tbuf), "screen=+%d", XkbSAScreen(act));
943     TryCopyStr(buf, tbuf, sz);
944     if (act->flags & XkbSA_SwitchApplication)
945         TryCopyStr(buf, ",!same", sz);
946     else
947         TryCopyStr(buf, ",same", sz);
948     return TRUE;
949 }
950 
951  /*ARGSUSED*/ static Bool
CopySetLockControlsArgs(XkbDescPtr xkb,XkbAction * action,char * buf,int * sz)952 CopySetLockControlsArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
953 {
954     XkbCtrlsAction *act;
955     unsigned tmp;
956     char tbuf[32];
957 
958     act = &action->ctrls;
959     tmp = XkbActionCtrls(act);
960     TryCopyStr(buf, "controls=", sz);
961     if (tmp == 0)
962         TryCopyStr(buf, "none", sz);
963     else if ((tmp & XkbAllBooleanCtrlsMask) == XkbAllBooleanCtrlsMask)
964         TryCopyStr(buf, "all", sz);
965     else {
966         int nOut = 0;
967 
968         if (tmp & XkbRepeatKeysMask) {
969             snprintf(tbuf, sizeof(tbuf), "%sRepeatKeys", (nOut > 0 ? "+" : ""));
970             TryCopyStr(buf, tbuf, sz);
971             nOut++;
972         }
973         if (tmp & XkbSlowKeysMask) {
974             snprintf(tbuf, sizeof(tbuf), "%sSlowKeys", (nOut > 0 ? "+" : ""));
975             TryCopyStr(buf, tbuf, sz);
976             nOut++;
977         }
978         if (tmp & XkbBounceKeysMask) {
979             snprintf(tbuf, sizeof(tbuf), "%sBounceKeys", (nOut > 0 ? "+" : ""));
980             TryCopyStr(buf, tbuf, sz);
981             nOut++;
982         }
983         if (tmp & XkbStickyKeysMask) {
984             snprintf(tbuf, sizeof(tbuf), "%sStickyKeys", (nOut > 0 ? "+" : ""));
985             TryCopyStr(buf, tbuf, sz);
986             nOut++;
987         }
988         if (tmp & XkbMouseKeysMask) {
989             snprintf(tbuf, sizeof(tbuf), "%sMouseKeys", (nOut > 0 ? "+" : ""));
990             TryCopyStr(buf, tbuf, sz);
991             nOut++;
992         }
993         if (tmp & XkbMouseKeysAccelMask) {
994             snprintf(tbuf, sizeof(tbuf), "%sMouseKeysAccel",
995                      (nOut > 0 ? "+" : ""));
996             TryCopyStr(buf, tbuf, sz);
997             nOut++;
998         }
999         if (tmp & XkbAccessXKeysMask) {
1000             snprintf(tbuf, sizeof(tbuf), "%sAccessXKeys",
1001                      (nOut > 0 ? "+" : ""));
1002             TryCopyStr(buf, tbuf, sz);
1003             nOut++;
1004         }
1005         if (tmp & XkbAccessXTimeoutMask) {
1006             snprintf(tbuf, sizeof(tbuf), "%sAccessXTimeout",
1007                      (nOut > 0 ? "+" : ""));
1008             TryCopyStr(buf, tbuf, sz);
1009             nOut++;
1010         }
1011         if (tmp & XkbAccessXFeedbackMask) {
1012             snprintf(tbuf, sizeof(tbuf), "%sAccessXFeedback",
1013                      (nOut > 0 ? "+" : ""));
1014             TryCopyStr(buf, tbuf, sz);
1015             nOut++;
1016         }
1017         if (tmp & XkbAudibleBellMask) {
1018             snprintf(tbuf, sizeof(tbuf), "%sAudibleBell",
1019                      (nOut > 0 ? "+" : ""));
1020             TryCopyStr(buf, tbuf, sz);
1021             nOut++;
1022         }
1023         if (tmp & XkbOverlay1Mask) {
1024             snprintf(tbuf, sizeof(tbuf), "%sOverlay1", (nOut > 0 ? "+" : ""));
1025             TryCopyStr(buf, tbuf, sz);
1026             nOut++;
1027         }
1028         if (tmp & XkbOverlay2Mask) {
1029             snprintf(tbuf, sizeof(tbuf), "%sOverlay2", (nOut > 0 ? "+" : ""));
1030             TryCopyStr(buf, tbuf, sz);
1031             nOut++;
1032         }
1033         if (tmp & XkbIgnoreGroupLockMask) {
1034             snprintf(tbuf, sizeof(tbuf), "%sIgnoreGroupLock",
1035                      (nOut > 0 ? "+" : ""));
1036             TryCopyStr(buf, tbuf, sz);
1037             nOut++;
1038         }
1039     }
1040     return TRUE;
1041 }
1042 
1043  /*ARGSUSED*/ static Bool
CopyActionMessageArgs(XkbDescPtr xkb,XkbAction * action,char * buf,int * sz)1044 CopyActionMessageArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
1045 {
1046     XkbMessageAction *act;
1047     unsigned all;
1048     char tbuf[32];
1049 
1050     act = &action->msg;
1051     all = XkbSA_MessageOnPress | XkbSA_MessageOnRelease;
1052     TryCopyStr(buf, "report=", sz);
1053     if ((act->flags & all) == 0)
1054         TryCopyStr(buf, "none", sz);
1055     else if ((act->flags & all) == all)
1056         TryCopyStr(buf, "all", sz);
1057     else if (act->flags & XkbSA_MessageOnPress)
1058         TryCopyStr(buf, "KeyPress", sz);
1059     else
1060         TryCopyStr(buf, "KeyRelease", sz);
1061     snprintf(tbuf, sizeof(tbuf), ",data[0]=0x%02x", act->message[0]);
1062     TryCopyStr(buf, tbuf, sz);
1063     snprintf(tbuf, sizeof(tbuf), ",data[1]=0x%02x", act->message[1]);
1064     TryCopyStr(buf, tbuf, sz);
1065     snprintf(tbuf, sizeof(tbuf), ",data[2]=0x%02x", act->message[2]);
1066     TryCopyStr(buf, tbuf, sz);
1067     snprintf(tbuf, sizeof(tbuf), ",data[3]=0x%02x", act->message[3]);
1068     TryCopyStr(buf, tbuf, sz);
1069     snprintf(tbuf, sizeof(tbuf), ",data[4]=0x%02x", act->message[4]);
1070     TryCopyStr(buf, tbuf, sz);
1071     snprintf(tbuf, sizeof(tbuf), ",data[5]=0x%02x", act->message[5]);
1072     TryCopyStr(buf, tbuf, sz);
1073     return TRUE;
1074 }
1075 
1076 static Bool
CopyRedirectKeyArgs(XkbDescPtr xkb,XkbAction * action,char * buf,int * sz)1077 CopyRedirectKeyArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
1078 {
1079     XkbRedirectKeyAction *act;
1080     char tbuf[32], *tmp;
1081     unsigned kc;
1082     unsigned vmods, vmods_mask;
1083 
1084     act = &action->redirect;
1085     kc = act->new_key;
1086     vmods = XkbSARedirectVMods(act);
1087     vmods_mask = XkbSARedirectVModsMask(act);
1088     if (xkb && xkb->names && xkb->names->keys && (kc <= xkb->max_key_code) &&
1089         (xkb->names->keys[kc].name[0] != '\0')) {
1090         char *kn;
1091 
1092         kn = XkbKeyNameText(xkb->names->keys[kc].name, XkbXKBFile);
1093         snprintf(tbuf, sizeof(tbuf), "key=%s", kn);
1094     }
1095     else
1096         snprintf(tbuf, sizeof(tbuf), "key=%d", kc);
1097     TryCopyStr(buf, tbuf, sz);
1098     if ((act->mods_mask == 0) && (vmods_mask == 0))
1099         return TRUE;
1100     if ((act->mods_mask == XkbAllModifiersMask) &&
1101         (vmods_mask == XkbAllVirtualModsMask)) {
1102         tmp = XkbVModMaskText(xkb, act->mods, vmods, XkbXKBFile);
1103         TryCopyStr(buf, ",mods=", sz);
1104         TryCopyStr(buf, tmp, sz);
1105     }
1106     else {
1107         if ((act->mods_mask & act->mods) || (vmods_mask & vmods)) {
1108             tmp = XkbVModMaskText(xkb, act->mods_mask & act->mods,
1109                                   vmods_mask & vmods, XkbXKBFile);
1110             TryCopyStr(buf, ",mods= ", sz);
1111             TryCopyStr(buf, tmp, sz);
1112         }
1113         if ((act->mods_mask & (~act->mods)) || (vmods_mask & (~vmods))) {
1114             tmp = XkbVModMaskText(xkb, act->mods_mask & (~act->mods),
1115                                   vmods_mask & (~vmods), XkbXKBFile);
1116             TryCopyStr(buf, ",clearMods= ", sz);
1117             TryCopyStr(buf, tmp, sz);
1118         }
1119     }
1120     return TRUE;
1121 }
1122 
1123  /*ARGSUSED*/ static Bool
CopyDeviceBtnArgs(XkbDescPtr xkb,XkbAction * action,char * buf,int * sz)1124 CopyDeviceBtnArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
1125 {
1126     XkbDeviceBtnAction *act;
1127     char tbuf[32];
1128 
1129     act = &action->devbtn;
1130     snprintf(tbuf, sizeof(tbuf), "device= %d", act->device);
1131     TryCopyStr(buf, tbuf, sz);
1132     TryCopyStr(buf, ",button=", sz);
1133     snprintf(tbuf, sizeof(tbuf), "%d", act->button);
1134     TryCopyStr(buf, tbuf, sz);
1135     if (act->count > 0) {
1136         snprintf(tbuf, sizeof(tbuf), ",count=%d", act->count);
1137         TryCopyStr(buf, tbuf, sz);
1138     }
1139     if (action->type == XkbSA_LockDeviceBtn) {
1140         switch (act->flags & (XkbSA_LockNoUnlock | XkbSA_LockNoLock)) {
1141         case XkbSA_LockNoLock:
1142             TryCopyStr(buf, ",affect=unlock", sz);
1143             break;
1144         case XkbSA_LockNoUnlock:
1145             TryCopyStr(buf, ",affect=lock", sz);
1146             break;
1147         case XkbSA_LockNoUnlock | XkbSA_LockNoLock:
1148             TryCopyStr(buf, ",affect=neither", sz);
1149             break;
1150         default:
1151             TryCopyStr(buf, ",affect=both", sz);
1152             break;
1153         }
1154     }
1155     return TRUE;
1156 }
1157 
1158  /*ARGSUSED*/ static Bool
CopyOtherArgs(XkbDescPtr xkb,XkbAction * action,char * buf,int * sz)1159 CopyOtherArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
1160 {
1161     XkbAnyAction *act;
1162     char tbuf[32];
1163 
1164     act = &action->any;
1165     snprintf(tbuf, sizeof(tbuf), "type=0x%02x", act->type);
1166     TryCopyStr(buf, tbuf, sz);
1167     snprintf(tbuf, sizeof(tbuf), ",data[0]=0x%02x", act->data[0]);
1168     TryCopyStr(buf, tbuf, sz);
1169     snprintf(tbuf, sizeof(tbuf), ",data[1]=0x%02x", act->data[1]);
1170     TryCopyStr(buf, tbuf, sz);
1171     snprintf(tbuf, sizeof(tbuf), ",data[2]=0x%02x", act->data[2]);
1172     TryCopyStr(buf, tbuf, sz);
1173     snprintf(tbuf, sizeof(tbuf), ",data[3]=0x%02x", act->data[3]);
1174     TryCopyStr(buf, tbuf, sz);
1175     snprintf(tbuf, sizeof(tbuf), ",data[4]=0x%02x", act->data[4]);
1176     TryCopyStr(buf, tbuf, sz);
1177     snprintf(tbuf, sizeof(tbuf), ",data[5]=0x%02x", act->data[5]);
1178     TryCopyStr(buf, tbuf, sz);
1179     snprintf(tbuf, sizeof(tbuf), ",data[6]=0x%02x", act->data[6]);
1180     TryCopyStr(buf, tbuf, sz);
1181     return TRUE;
1182 }
1183 
1184 typedef Bool (*actionCopy) (XkbDescPtr /* xkb */ ,
1185                             XkbAction * /* action */ ,
1186                             char * /* buf */ ,
1187                             int *       /* sz */
1188     );
1189 
1190 static actionCopy copyActionArgs[XkbSA_NumActions] = {
1191     CopyNoActionArgs /* NoAction     */ ,
1192     CopyModActionArgs /* SetMods      */ ,
1193     CopyModActionArgs /* LatchMods    */ ,
1194     CopyModActionArgs /* LockMods     */ ,
1195     CopyGroupActionArgs /* SetGroup     */ ,
1196     CopyGroupActionArgs /* LatchGroup   */ ,
1197     CopyGroupActionArgs /* LockGroup    */ ,
1198     CopyMovePtrArgs /* MovePtr      */ ,
1199     CopyPtrBtnArgs /* PtrBtn       */ ,
1200     CopyPtrBtnArgs /* LockPtrBtn   */ ,
1201     CopySetPtrDfltArgs /* SetPtrDflt   */ ,
1202     CopyISOLockArgs /* ISOLock      */ ,
1203     CopyNoActionArgs /* Terminate    */ ,
1204     CopySwitchScreenArgs /* SwitchScreen */ ,
1205     CopySetLockControlsArgs /* SetControls  */ ,
1206     CopySetLockControlsArgs /* LockControls */ ,
1207     CopyActionMessageArgs /* ActionMessage */ ,
1208     CopyRedirectKeyArgs /* RedirectKey  */ ,
1209     CopyDeviceBtnArgs /* DeviceBtn    */ ,
1210     CopyDeviceBtnArgs           /* LockDeviceBtn */
1211 };
1212 
1213 #define	ACTION_SZ	256
1214 
1215 char *
XkbActionText(XkbDescPtr xkb,XkbAction * action,unsigned format)1216 XkbActionText(XkbDescPtr xkb, XkbAction *action, unsigned format)
1217 {
1218     char buf[ACTION_SZ], *tmp;
1219     int sz;
1220 
1221     if (format == XkbCFile) {
1222         snprintf(buf, sizeof(buf),
1223                  "{ %20s, { 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x } }",
1224                  XkbActionTypeText(action->type, XkbCFile),
1225                  action->any.data[0], action->any.data[1], action->any.data[2],
1226                  action->any.data[3], action->any.data[4], action->any.data[5],
1227                  action->any.data[6]);
1228     }
1229     else {
1230         snprintf(buf, sizeof(buf), "%s(",
1231                  XkbActionTypeText(action->type, XkbXKBFile));
1232         sz = ACTION_SZ - strlen(buf) + 2;       /* room for close paren and NULL */
1233         if (action->type < (unsigned) XkbSA_NumActions)
1234             (*copyActionArgs[action->type]) (xkb, action, buf, &sz);
1235         else
1236             CopyOtherArgs(xkb, action, buf, &sz);
1237         TryCopyStr(buf, ")", &sz);
1238     }
1239     tmp = tbGetBuffer(strlen(buf) + 1);
1240     if (tmp != NULL)
1241         strcpy(tmp, buf);
1242     return tmp;
1243 }
1244 
1245 char *
XkbBehaviorText(XkbDescPtr xkb,XkbBehavior * behavior,unsigned format)1246 XkbBehaviorText(XkbDescPtr xkb, XkbBehavior * behavior, unsigned format)
1247 {
1248     char buf[256], *tmp;
1249 
1250     if (format == XkbCFile) {
1251         if (behavior->type == XkbKB_Default)
1252             snprintf(buf, sizeof(buf), "{   0,    0 }");
1253         else
1254             snprintf(buf, sizeof(buf), "{ %3d, 0x%02x }", behavior->type,
1255                      behavior->data);
1256     }
1257     else {
1258         unsigned type, permanent;
1259 
1260         type = behavior->type & XkbKB_OpMask;
1261         permanent = ((behavior->type & XkbKB_Permanent) != 0);
1262 
1263         if (type == XkbKB_Lock) {
1264             snprintf(buf, sizeof(buf), "lock= %s",
1265                      (permanent ? "Permanent" : "TRUE"));
1266         }
1267         else if (type == XkbKB_RadioGroup) {
1268             int g;
1269 
1270             g = ((behavior->data) & (~XkbKB_RGAllowNone)) + 1;
1271             if (XkbKB_RGAllowNone & behavior->data) {
1272                 snprintf(buf, sizeof(buf), "allowNone,");
1273                 tmp = &buf[strlen(buf)];
1274             }
1275             else
1276                 tmp = buf;
1277             if (permanent)
1278                 sprintf(tmp, "permanentRadioGroup= %d", g);
1279             else
1280                 sprintf(tmp, "radioGroup= %d", g);
1281         }
1282         else if ((type == XkbKB_Overlay1) || (type == XkbKB_Overlay2)) {
1283             int ndx, kc;
1284             char *kn;
1285 
1286             ndx = ((type == XkbKB_Overlay1) ? 1 : 2);
1287             kc = behavior->data;
1288             if ((xkb) && (xkb->names) && (xkb->names->keys))
1289                 kn = XkbKeyNameText(xkb->names->keys[kc].name, XkbXKBFile);
1290             else {
1291                 static char tbuf[8];
1292 
1293                 snprintf(tbuf, sizeof(tbuf), "%d", kc);
1294                 kn = tbuf;
1295             }
1296             if (permanent)
1297                 snprintf(buf, sizeof(buf), "permanentOverlay%d= %s", ndx, kn);
1298             else
1299                 snprintf(buf, sizeof(buf), "overlay%d= %s", ndx, kn);
1300         }
1301     }
1302     tmp = tbGetBuffer(strlen(buf) + 1);
1303     if (tmp != NULL)
1304         strcpy(tmp, buf);
1305     return tmp;
1306 }
1307 
1308 /***====================================================================***/
1309 
1310 char *
XkbIndentText(unsigned size)1311 XkbIndentText(unsigned size)
1312 {
1313     static char buf[32];
1314     register int i;
1315 
1316     if (size > 31)
1317         size = 31;
1318 
1319     for (i = 0; i < size; i++) {
1320         buf[i] = ' ';
1321     }
1322     buf[size] = '\0';
1323     return buf;
1324 }
1325