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