xkbtext.c revision 05b261ec
105b261ecSmrg/************************************************************
205b261ecSmrg Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
305b261ecSmrg
405b261ecSmrg Permission to use, copy, modify, and distribute this
505b261ecSmrg software and its documentation for any purpose and without
605b261ecSmrg fee is hereby granted, provided that the above copyright
705b261ecSmrg notice appear in all copies and that both that copyright
805b261ecSmrg notice and this permission notice appear in supporting
905b261ecSmrg documentation, and that the name of Silicon Graphics not be
1005b261ecSmrg used in advertising or publicity pertaining to distribution
1105b261ecSmrg of the software without specific prior written permission.
1205b261ecSmrg Silicon Graphics makes no representation about the suitability
1305b261ecSmrg of this software for any purpose. It is provided "as is"
1405b261ecSmrg without any express or implied warranty.
1505b261ecSmrg
1605b261ecSmrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1705b261ecSmrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1805b261ecSmrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
1905b261ecSmrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
2005b261ecSmrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2105b261ecSmrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
2205b261ecSmrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
2305b261ecSmrg THE USE OR PERFORMANCE OF THIS SOFTWARE.
2405b261ecSmrg
2505b261ecSmrg ********************************************************/
2605b261ecSmrg
2705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
2805b261ecSmrg#include <dix-config.h>
2905b261ecSmrg#endif
3005b261ecSmrg
3105b261ecSmrg#include <stdio.h>
3205b261ecSmrg#include <ctype.h>
3305b261ecSmrg#include <stdlib.h>
3405b261ecSmrg
3505b261ecSmrg#include <X11/Xos.h>
3605b261ecSmrg
3705b261ecSmrg#include <X11/X.h>
3805b261ecSmrg#define	NEED_EVENTS
3905b261ecSmrg#include <X11/Xproto.h>
4005b261ecSmrg#include "misc.h"
4105b261ecSmrg#include "inputstr.h"
4205b261ecSmrg#include "dix.h"
4305b261ecSmrg#include <X11/extensions/XKBstr.h>
4405b261ecSmrg#define XKBSRV_NEED_FILE_FUNCS	1
4505b261ecSmrg#include <xkbsrv.h>
4605b261ecSmrg#include <X11/extensions/XKBgeom.h>
4705b261ecSmrg
4805b261ecSmrg/***====================================================================***/
4905b261ecSmrg
5005b261ecSmrg#define	BUFFER_SIZE	512
5105b261ecSmrg
5205b261ecSmrgstatic char textBuffer[BUFFER_SIZE];
5305b261ecSmrgstatic int  tbNext= 0;
5405b261ecSmrg
5505b261ecSmrgstatic char *
5605b261ecSmrgtbGetBuffer(unsigned size)
5705b261ecSmrg{
5805b261ecSmrgchar *rtrn;
5905b261ecSmrg
6005b261ecSmrg    if (size>=BUFFER_SIZE)
6105b261ecSmrg	return NULL;
6205b261ecSmrg    if ((BUFFER_SIZE-tbNext)<=size)
6305b261ecSmrg	tbNext= 0;
6405b261ecSmrg    rtrn= &textBuffer[tbNext];
6505b261ecSmrg    tbNext+= size;
6605b261ecSmrg    return rtrn;
6705b261ecSmrg}
6805b261ecSmrg
6905b261ecSmrg/***====================================================================***/
7005b261ecSmrg
7105b261ecSmrgchar *
7205b261ecSmrgXkbAtomText(Display *dpy,Atom atm,unsigned format)
7305b261ecSmrg{
7405b261ecSmrgchar	*rtrn,*tmp;
7505b261ecSmrg
7605b261ecSmrg    tmp= XkbAtomGetString(dpy,atm);
7705b261ecSmrg    if (tmp!=NULL) {
7805b261ecSmrg	int	len;
7905b261ecSmrg	len= strlen(tmp)+1;
8005b261ecSmrg	if (len>BUFFER_SIZE)
8105b261ecSmrg	    len= BUFFER_SIZE-2;
8205b261ecSmrg	rtrn= tbGetBuffer(len);
8305b261ecSmrg	strncpy(rtrn,tmp,len);
8405b261ecSmrg	rtrn[len]= '\0';
8505b261ecSmrg    }
8605b261ecSmrg    else {
8705b261ecSmrg	rtrn= tbGetBuffer(1);
8805b261ecSmrg	rtrn[0]= '\0';
8905b261ecSmrg    }
9005b261ecSmrg    if (format==XkbCFile) {
9105b261ecSmrg	for (tmp=rtrn;*tmp!='\0';tmp++) {
9205b261ecSmrg	    if ((tmp==rtrn)&&(!isalpha(*tmp)))
9305b261ecSmrg		*tmp= '_';
9405b261ecSmrg	    else if (!isalnum(*tmp))
9505b261ecSmrg		*tmp= '_';
9605b261ecSmrg	}
9705b261ecSmrg    }
9805b261ecSmrg    return XkbStringText(rtrn,format);
9905b261ecSmrg}
10005b261ecSmrg
10105b261ecSmrg/***====================================================================***/
10205b261ecSmrg
10305b261ecSmrgchar *
10405b261ecSmrgXkbVModIndexText(Display *dpy,XkbDescPtr xkb,unsigned ndx,unsigned format)
10505b261ecSmrg{
10605b261ecSmrgregister int len;
10705b261ecSmrgregister Atom *vmodNames;
10805b261ecSmrgchar *rtrn,*tmp;
10905b261ecSmrgchar  numBuf[20];
11005b261ecSmrg
11105b261ecSmrg    if (xkb && xkb->names)
11205b261ecSmrg	 vmodNames= xkb->names->vmods;
11305b261ecSmrg    else vmodNames= NULL;
11405b261ecSmrg
11505b261ecSmrg    tmp= NULL;
11605b261ecSmrg    if (ndx>=XkbNumVirtualMods)
11705b261ecSmrg	 tmp= "illegal";
11805b261ecSmrg    else if (vmodNames&&(vmodNames[ndx]!=None))
11905b261ecSmrg	 tmp= XkbAtomGetString(dpy,vmodNames[ndx]);
12005b261ecSmrg    if (tmp==NULL)
12105b261ecSmrg	sprintf(tmp=numBuf,"%d",ndx);
12205b261ecSmrg
12305b261ecSmrg    len= strlen(tmp)+1;
12405b261ecSmrg    if (format==XkbCFile)
12505b261ecSmrg	len+= 4;
12605b261ecSmrg    if (len>=BUFFER_SIZE)
12705b261ecSmrg	len= BUFFER_SIZE-1;
12805b261ecSmrg    rtrn= tbGetBuffer(len);
12905b261ecSmrg    if (format==XkbCFile) {
13005b261ecSmrg	 strcpy(rtrn,"vmod_");
13105b261ecSmrg	 strncpy(&rtrn[5],tmp,len-4);
13205b261ecSmrg    }
13305b261ecSmrg    else strncpy(rtrn,tmp,len);
13405b261ecSmrg    return rtrn;
13505b261ecSmrg}
13605b261ecSmrg
13705b261ecSmrgchar *
13805b261ecSmrgXkbVModMaskText(	Display *	dpy,
13905b261ecSmrg			XkbDescPtr	xkb,
14005b261ecSmrg			unsigned	modMask,
14105b261ecSmrg			unsigned	mask,
14205b261ecSmrg			unsigned	format)
14305b261ecSmrg{
14405b261ecSmrgregister int i,bit;
14505b261ecSmrgint	 len;
14605b261ecSmrgchar *mm,*rtrn;
14705b261ecSmrgchar *str,buf[BUFFER_SIZE];
14805b261ecSmrg
14905b261ecSmrg    if ((modMask==0)&&(mask==0)) {
15005b261ecSmrg	rtrn= tbGetBuffer(5);
15105b261ecSmrg	if (format==XkbCFile)
15205b261ecSmrg	     sprintf(rtrn,"0");
15305b261ecSmrg	else sprintf(rtrn,"none");
15405b261ecSmrg	return rtrn;
15505b261ecSmrg    }
15605b261ecSmrg    if (modMask!=0)
15705b261ecSmrg	 mm= XkbModMaskText(modMask,format);
15805b261ecSmrg    else mm= NULL;
15905b261ecSmrg
16005b261ecSmrg    str= buf;
16105b261ecSmrg    buf[0]= '\0';
16205b261ecSmrg    if (mask) {
16305b261ecSmrg	char *tmp;
16405b261ecSmrg	for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
16505b261ecSmrg	    if (mask&bit) {
16605b261ecSmrg		tmp= XkbVModIndexText(dpy,xkb,i,format);
16705b261ecSmrg		len= strlen(tmp)+1+(str==buf?0:1);
16805b261ecSmrg		if (format==XkbCFile)
16905b261ecSmrg		    len+= 4;
17005b261ecSmrg		if ((str-(buf+len))<=BUFFER_SIZE) {
17105b261ecSmrg		    if (str!=buf) {
17205b261ecSmrg			if (format==XkbCFile)	*str++= '|';
17305b261ecSmrg			else			*str++= '+';
17405b261ecSmrg			len--;
17505b261ecSmrg		    }
17605b261ecSmrg		}
17705b261ecSmrg		if (format==XkbCFile)
17805b261ecSmrg		     sprintf(str,"%sMask",tmp);
17905b261ecSmrg		else strcpy(str,tmp);
18005b261ecSmrg		str= &str[len-1];
18105b261ecSmrg	    }
18205b261ecSmrg	}
18305b261ecSmrg	str= buf;
18405b261ecSmrg    }
18505b261ecSmrg    else str= NULL;
18605b261ecSmrg    if (mm)
18705b261ecSmrg	len= strlen(mm);
18805b261ecSmrg    else	len= 0;
18905b261ecSmrg    if (str)
19005b261ecSmrg	len+= strlen(str)+(mm==NULL?0:1);
19105b261ecSmrg    if (len>=BUFFER_SIZE)
19205b261ecSmrg	len= BUFFER_SIZE-1;
19305b261ecSmrg    rtrn= tbGetBuffer(len+1);
19405b261ecSmrg    rtrn[0]= '\0';
19505b261ecSmrg
19605b261ecSmrg    if (mm!=NULL) {
19705b261ecSmrg	i= strlen(mm);
19805b261ecSmrg	if (i>len)
19905b261ecSmrg	    i= len;
20005b261ecSmrg	strcpy(rtrn,mm);
20105b261ecSmrg    }
20205b261ecSmrg    else {
20305b261ecSmrg	i=0;
20405b261ecSmrg    }
20505b261ecSmrg    if (str!=NULL) {
20605b261ecSmrg	if (mm!=NULL) {
20705b261ecSmrg	    if (format==XkbCFile)	strcat(rtrn,"|");
20805b261ecSmrg	    else			strcat(rtrn,"+");
20905b261ecSmrg	}
21005b261ecSmrg	strncat(rtrn,str,len-i);
21105b261ecSmrg    }
21205b261ecSmrg    rtrn[len]= '\0';
21305b261ecSmrg    return rtrn;
21405b261ecSmrg}
21505b261ecSmrg
21605b261ecSmrgstatic char *modNames[XkbNumModifiers] = {
21705b261ecSmrg    "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5"
21805b261ecSmrg};
21905b261ecSmrg
22005b261ecSmrgchar *
22105b261ecSmrgXkbModIndexText(unsigned ndx,unsigned format)
22205b261ecSmrg{
22305b261ecSmrgchar *	rtrn;
22405b261ecSmrgchar	buf[100];
22505b261ecSmrg
22605b261ecSmrg    if (format==XkbCFile) {
22705b261ecSmrg	if (ndx<XkbNumModifiers)
22805b261ecSmrg	     sprintf(buf,"%sMapIndex",modNames[ndx]);
22905b261ecSmrg	else if (ndx==XkbNoModifier)
23005b261ecSmrg	     sprintf(buf,"XkbNoModifier");
23105b261ecSmrg	else sprintf(buf,"0x%02x",ndx);
23205b261ecSmrg    }
23305b261ecSmrg    else {
23405b261ecSmrg	if (ndx<XkbNumModifiers)
23505b261ecSmrg	     strcpy(buf,modNames[ndx]);
23605b261ecSmrg	else if (ndx==XkbNoModifier)
23705b261ecSmrg	     strcpy(buf,"none");
23805b261ecSmrg	else sprintf(buf,"ILLEGAL_%02x",ndx);
23905b261ecSmrg    }
24005b261ecSmrg    rtrn= tbGetBuffer(strlen(buf)+1);
24105b261ecSmrg    strcpy(rtrn,buf);
24205b261ecSmrg    return rtrn;
24305b261ecSmrg}
24405b261ecSmrg
24505b261ecSmrgchar *
24605b261ecSmrgXkbModMaskText(unsigned mask,unsigned format)
24705b261ecSmrg{
24805b261ecSmrgregister int i,bit;
24905b261ecSmrgchar buf[64],*rtrn;
25005b261ecSmrg
25105b261ecSmrg    if ((mask&0xff)==0xff) {
25205b261ecSmrg	if (format==XkbCFile) 		strcpy(buf,"0xff");
25305b261ecSmrg	else				strcpy(buf,"all");
25405b261ecSmrg    }
25505b261ecSmrg    else if ((mask&0xff)==0) {
25605b261ecSmrg	if (format==XkbCFile)		strcpy(buf,"0");
25705b261ecSmrg	else				strcpy(buf,"none");
25805b261ecSmrg    }
25905b261ecSmrg    else {
26005b261ecSmrg	char *str= buf;
26105b261ecSmrg	buf[0]= '\0';
26205b261ecSmrg	for (i=0,bit=1;i<XkbNumModifiers;i++,bit<<=1) {
26305b261ecSmrg	    if (mask&bit) {
26405b261ecSmrg		if (str!=buf) {
26505b261ecSmrg		    if (format==XkbCFile)	*str++= '|';
26605b261ecSmrg		    else			*str++= '+';
26705b261ecSmrg		}
26805b261ecSmrg		strcpy(str,modNames[i]);
26905b261ecSmrg		str= &str[strlen(str)];
27005b261ecSmrg		if (format==XkbCFile) {
27105b261ecSmrg		    strcpy(str,"Mask");
27205b261ecSmrg		    str+= 4;
27305b261ecSmrg		}
27405b261ecSmrg	    }
27505b261ecSmrg	}
27605b261ecSmrg    }
27705b261ecSmrg    rtrn= tbGetBuffer(strlen(buf)+1);
27805b261ecSmrg    strcpy(rtrn,buf);
27905b261ecSmrg    return rtrn;
28005b261ecSmrg}
28105b261ecSmrg
28205b261ecSmrg/***====================================================================***/
28305b261ecSmrg
28405b261ecSmrg/*ARGSUSED*/
28505b261ecSmrgchar *
28605b261ecSmrgXkbConfigText(unsigned config,unsigned format)
28705b261ecSmrg{
28805b261ecSmrgstatic char *buf;
28905b261ecSmrg
29005b261ecSmrg    buf= tbGetBuffer(32);
29105b261ecSmrg    switch (config) {
29205b261ecSmrg	case XkmSemanticsFile:
29305b261ecSmrg	    strcpy(buf,"Semantics");
29405b261ecSmrg	    break;
29505b261ecSmrg	case XkmLayoutFile:
29605b261ecSmrg	    strcpy(buf,"Layout");
29705b261ecSmrg	    break;
29805b261ecSmrg	case XkmKeymapFile:
29905b261ecSmrg	    strcpy(buf,"Keymap");
30005b261ecSmrg	    break;
30105b261ecSmrg	case XkmGeometryFile:
30205b261ecSmrg	case XkmGeometryIndex:
30305b261ecSmrg	    strcpy(buf,"Geometry");
30405b261ecSmrg	    break;
30505b261ecSmrg	case XkmTypesIndex:
30605b261ecSmrg	    strcpy(buf,"Types");
30705b261ecSmrg	    break;
30805b261ecSmrg	case XkmCompatMapIndex:
30905b261ecSmrg	    strcpy(buf,"CompatMap");
31005b261ecSmrg	    break;
31105b261ecSmrg	case XkmSymbolsIndex:
31205b261ecSmrg	    strcpy(buf,"Symbols");
31305b261ecSmrg	    break;
31405b261ecSmrg	case XkmIndicatorsIndex:
31505b261ecSmrg	    strcpy(buf,"Indicators");
31605b261ecSmrg	    break;
31705b261ecSmrg	case XkmKeyNamesIndex:
31805b261ecSmrg	    strcpy(buf,"KeyNames");
31905b261ecSmrg	    break;
32005b261ecSmrg	case XkmVirtualModsIndex:
32105b261ecSmrg	    strcpy(buf,"VirtualMods");
32205b261ecSmrg	    break;
32305b261ecSmrg	default:
32405b261ecSmrg	    sprintf(buf,"unknown(%d)",config);
32505b261ecSmrg	    break;
32605b261ecSmrg    }
32705b261ecSmrg    return buf;
32805b261ecSmrg}
32905b261ecSmrg
33005b261ecSmrg/***====================================================================***/
33105b261ecSmrg
33205b261ecSmrgchar *
33305b261ecSmrgXkbKeysymText(KeySym sym,unsigned format)
33405b261ecSmrg{
33505b261ecSmrgstatic char buf[32],*rtrn;
33605b261ecSmrg
33705b261ecSmrg    if (sym==NoSymbol)
33805b261ecSmrg	 strcpy(rtrn=buf,"NoSymbol");
33905b261ecSmrg    else sprintf(rtrn=buf, "0x%lx", (long)sym);
34005b261ecSmrg    return rtrn;
34105b261ecSmrg}
34205b261ecSmrg
34305b261ecSmrgchar *
34405b261ecSmrgXkbKeyNameText(char *name,unsigned format)
34505b261ecSmrg{
34605b261ecSmrgchar *buf;
34705b261ecSmrg
34805b261ecSmrg    if (format==XkbCFile) {
34905b261ecSmrg	buf= tbGetBuffer(5);
35005b261ecSmrg	memcpy(buf,name,4);
35105b261ecSmrg	buf[4]= '\0';
35205b261ecSmrg    }
35305b261ecSmrg    else {
35405b261ecSmrg	int len;
35505b261ecSmrg	buf= tbGetBuffer(7);
35605b261ecSmrg	buf[0]= '<';
35705b261ecSmrg	memcpy(&buf[1],name,4);
35805b261ecSmrg	buf[5]= '\0';
35905b261ecSmrg	len= strlen(buf);
36005b261ecSmrg	buf[len++]= '>';
36105b261ecSmrg	buf[len]= '\0';
36205b261ecSmrg    }
36305b261ecSmrg    return buf;
36405b261ecSmrg}
36505b261ecSmrg
36605b261ecSmrg/***====================================================================***/
36705b261ecSmrg
36805b261ecSmrgstatic char *siMatchText[5] = {
36905b261ecSmrg	"NoneOf", "AnyOfOrNone", "AnyOf", "AllOf", "Exactly"
37005b261ecSmrg};
37105b261ecSmrg
37205b261ecSmrgchar *
37305b261ecSmrgXkbSIMatchText(unsigned type,unsigned format)
37405b261ecSmrg{
37505b261ecSmrgstatic char buf[40];
37605b261ecSmrgchar *rtrn;
37705b261ecSmrg
37805b261ecSmrg    switch (type&XkbSI_OpMask) {
37905b261ecSmrg	case XkbSI_NoneOf:	rtrn= siMatchText[0]; break;
38005b261ecSmrg	case XkbSI_AnyOfOrNone:	rtrn= siMatchText[1]; break;
38105b261ecSmrg	case XkbSI_AnyOf:	rtrn= siMatchText[2]; break;
38205b261ecSmrg	case XkbSI_AllOf:	rtrn= siMatchText[3]; break;
38305b261ecSmrg	case XkbSI_Exactly:	rtrn= siMatchText[4]; break;
38405b261ecSmrg	default:		sprintf(buf,"0x%x",type&XkbSI_OpMask);
38505b261ecSmrg				return buf;
38605b261ecSmrg    }
38705b261ecSmrg    if (format==XkbCFile) {
38805b261ecSmrg	if (type&XkbSI_LevelOneOnly)
38905b261ecSmrg	     sprintf(buf,"XkbSI_LevelOneOnly|XkbSI_%s",rtrn);
39005b261ecSmrg	else sprintf(buf,"XkbSI_%s",rtrn);
39105b261ecSmrg	rtrn= buf;
39205b261ecSmrg    }
39305b261ecSmrg    return rtrn;
39405b261ecSmrg}
39505b261ecSmrg
39605b261ecSmrg/***====================================================================***/
39705b261ecSmrg
39805b261ecSmrgstatic char *imWhichNames[]= {
39905b261ecSmrg	"base",
40005b261ecSmrg	"latched",
40105b261ecSmrg	"locked",
40205b261ecSmrg	"effective",
40305b261ecSmrg	"compat"
40405b261ecSmrg};
40505b261ecSmrg
40605b261ecSmrgchar *
40705b261ecSmrgXkbIMWhichStateMaskText(unsigned use_which,unsigned format)
40805b261ecSmrg{
40905b261ecSmrgint		len;
41005b261ecSmrgunsigned	i,bit,tmp;
41105b261ecSmrgchar *		buf;
41205b261ecSmrg
41305b261ecSmrg    if (use_which==0) {
41405b261ecSmrg	buf= tbGetBuffer(2);
41505b261ecSmrg	strcpy(buf,"0");
41605b261ecSmrg	return buf;
41705b261ecSmrg    }
41805b261ecSmrg    tmp= use_which&XkbIM_UseAnyMods;
41905b261ecSmrg    for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) {
42005b261ecSmrg	if (tmp&bit) {
42105b261ecSmrg	    tmp&= ~bit;
42205b261ecSmrg	    len+= strlen(imWhichNames[i])+1;
42305b261ecSmrg	    if (format==XkbCFile)
42405b261ecSmrg		len+= 9;
42505b261ecSmrg	}
42605b261ecSmrg    }
42705b261ecSmrg    buf= tbGetBuffer(len+1);
42805b261ecSmrg    tmp= use_which&XkbIM_UseAnyMods;
42905b261ecSmrg    for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) {
43005b261ecSmrg	if (tmp&bit) {
43105b261ecSmrg	    tmp&= ~bit;
43205b261ecSmrg	    if (format==XkbCFile) {
43305b261ecSmrg		if (len!=0)
43405b261ecSmrg		    buf[len++]= '|';
43505b261ecSmrg		sprintf(&buf[len],"XkbIM_Use%s",imWhichNames[i]);
43605b261ecSmrg		buf[len+9]= toupper(buf[len+9]);
43705b261ecSmrg	    }
43805b261ecSmrg	    else {
43905b261ecSmrg		if (len!=0)
44005b261ecSmrg		    buf[len++]= '+';
44105b261ecSmrg		sprintf(&buf[len],"%s",imWhichNames[i]);
44205b261ecSmrg	    }
44305b261ecSmrg	    len+= strlen(&buf[len]);
44405b261ecSmrg	}
44505b261ecSmrg    }
44605b261ecSmrg    return buf;
44705b261ecSmrg}
44805b261ecSmrg
44905b261ecSmrgstatic char *ctrlNames[] = {
45005b261ecSmrg	"repeatKeys",
45105b261ecSmrg	"slowKeys",
45205b261ecSmrg	"bounceKeys",
45305b261ecSmrg	"stickyKeys",
45405b261ecSmrg	"mouseKeys",
45505b261ecSmrg	"mouseKeysAccel",
45605b261ecSmrg	"accessXKeys",
45705b261ecSmrg	"accessXTimeout",
45805b261ecSmrg	"accessXFeedback",
45905b261ecSmrg	"audibleBell",
46005b261ecSmrg	"overlay1",
46105b261ecSmrg	"overlay2",
46205b261ecSmrg	"ignoreGroupLock"
46305b261ecSmrg};
46405b261ecSmrg
46505b261ecSmrgchar *
46605b261ecSmrgXkbControlsMaskText(unsigned ctrls,unsigned format)
46705b261ecSmrg{
46805b261ecSmrgint		len;
46905b261ecSmrgunsigned	i,bit,tmp;
47005b261ecSmrgchar *		buf;
47105b261ecSmrg
47205b261ecSmrg    if (ctrls==0) {
47305b261ecSmrg	buf= tbGetBuffer(5);
47405b261ecSmrg	if (format==XkbCFile)
47505b261ecSmrg	     strcpy(buf,"0");
47605b261ecSmrg	else strcpy(buf,"none");
47705b261ecSmrg	return buf;
47805b261ecSmrg    }
47905b261ecSmrg    tmp= ctrls&XkbAllBooleanCtrlsMask;
48005b261ecSmrg    for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) {
48105b261ecSmrg	if (tmp&bit) {
48205b261ecSmrg	    tmp&= ~bit;
48305b261ecSmrg	    len+= strlen(ctrlNames[i])+1;
48405b261ecSmrg	    if (format==XkbCFile)
48505b261ecSmrg		len+= 7;
48605b261ecSmrg	}
48705b261ecSmrg    }
48805b261ecSmrg    buf= tbGetBuffer(len+1);
48905b261ecSmrg    tmp= ctrls&XkbAllBooleanCtrlsMask;
49005b261ecSmrg    for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) {
49105b261ecSmrg	if (tmp&bit) {
49205b261ecSmrg	    tmp&= ~bit;
49305b261ecSmrg	    if (format==XkbCFile) {
49405b261ecSmrg		if (len!=0)
49505b261ecSmrg		    buf[len++]= '|';
49605b261ecSmrg		sprintf(&buf[len],"Xkb%sMask",ctrlNames[i]);
49705b261ecSmrg		buf[len+3]= toupper(buf[len+3]);
49805b261ecSmrg	    }
49905b261ecSmrg	    else {
50005b261ecSmrg		if (len!=0)
50105b261ecSmrg		    buf[len++]= '+';
50205b261ecSmrg		sprintf(&buf[len],"%s",ctrlNames[i]);
50305b261ecSmrg	    }
50405b261ecSmrg	    len+= strlen(&buf[len]);
50505b261ecSmrg	}
50605b261ecSmrg    }
50705b261ecSmrg    return buf;
50805b261ecSmrg}
50905b261ecSmrg
51005b261ecSmrg/***====================================================================***/
51105b261ecSmrg
51205b261ecSmrgchar *
51305b261ecSmrgXkbStringText(char *str,unsigned format)
51405b261ecSmrg{
51505b261ecSmrgchar *	buf;
51605b261ecSmrgregister char *in,*out;
51705b261ecSmrgint	len;
51805b261ecSmrgBool	ok;
51905b261ecSmrg
52005b261ecSmrg    if (str==NULL) {
52105b261ecSmrg	buf= tbGetBuffer(2);
52205b261ecSmrg	buf[0]='\0';
52305b261ecSmrg	return buf;
52405b261ecSmrg    }
52505b261ecSmrg    else if (format==XkbXKMFile)
52605b261ecSmrg	return str;
52705b261ecSmrg    for (ok= True,len=0,in=str;*in!='\0';in++,len++) {
52805b261ecSmrg	if (!isprint(*in)) {
52905b261ecSmrg	    ok= False;
53005b261ecSmrg	    switch (*in) {
53105b261ecSmrg		case '\n': case '\t': case '\v':
53205b261ecSmrg		case '\b': case '\r': case '\f':
53305b261ecSmrg		    len++;
53405b261ecSmrg		    break;
53505b261ecSmrg		default:
53605b261ecSmrg		    len+= 4;
53705b261ecSmrg		    break;
53805b261ecSmrg	    }
53905b261ecSmrg	}
54005b261ecSmrg    }
54105b261ecSmrg    if (ok)
54205b261ecSmrg	return str;
54305b261ecSmrg    buf= tbGetBuffer(len+1);
54405b261ecSmrg    for (in=str,out=buf;*in!='\0';in++) {
54505b261ecSmrg	if (isprint(*in))
54605b261ecSmrg	    *out++= *in;
54705b261ecSmrg	else {
54805b261ecSmrg	    *out++= '\\';
54905b261ecSmrg	    if (*in=='\n')	*out++= 'n';
55005b261ecSmrg	    else if (*in=='\t')	*out++= 't';
55105b261ecSmrg	    else if (*in=='\v')	*out++= 'v';
55205b261ecSmrg	    else if (*in=='\b')	*out++= 'b';
55305b261ecSmrg	    else if (*in=='\r')	*out++= 'r';
55405b261ecSmrg	    else if (*in=='\f')	*out++= 'f';
55505b261ecSmrg	    else if ((*in=='\033')&&(format==XkbXKMFile)) {
55605b261ecSmrg		*out++= 'e';
55705b261ecSmrg	    }
55805b261ecSmrg	    else {
55905b261ecSmrg		*out++= '0';
56005b261ecSmrg		sprintf(out,"%o",*in);
56105b261ecSmrg		while (*out!='\0')
56205b261ecSmrg		    out++;
56305b261ecSmrg	    }
56405b261ecSmrg	}
56505b261ecSmrg    }
56605b261ecSmrg    *out++= '\0';
56705b261ecSmrg    return buf;
56805b261ecSmrg}
56905b261ecSmrg
57005b261ecSmrg/***====================================================================***/
57105b261ecSmrg
57205b261ecSmrgchar *
57305b261ecSmrgXkbGeomFPText(int val,unsigned format)
57405b261ecSmrg{
57505b261ecSmrgint	whole,frac;
57605b261ecSmrgchar *	buf;
57705b261ecSmrg
57805b261ecSmrg    buf= tbGetBuffer(12);
57905b261ecSmrg    if (format==XkbCFile) {
58005b261ecSmrg	sprintf(buf,"%d",val);
58105b261ecSmrg    }
58205b261ecSmrg    else {
58305b261ecSmrg	whole= val/XkbGeomPtsPerMM;
58405b261ecSmrg	frac= val%XkbGeomPtsPerMM;
58505b261ecSmrg	if (frac!=0)
58605b261ecSmrg	     sprintf(buf,"%d.%d",whole,frac);
58705b261ecSmrg	else sprintf(buf,"%d",whole);
58805b261ecSmrg    }
58905b261ecSmrg    return buf;
59005b261ecSmrg}
59105b261ecSmrg
59205b261ecSmrgchar *
59305b261ecSmrgXkbDoodadTypeText(unsigned type,unsigned format)
59405b261ecSmrg{
59505b261ecSmrgchar *	buf;
59605b261ecSmrg    if (format==XkbCFile) {
59705b261ecSmrg	buf= tbGetBuffer(24);
59805b261ecSmrg	if (type==XkbOutlineDoodad)	   strcpy(buf,"XkbOutlineDoodad");
59905b261ecSmrg	else if (type==XkbSolidDoodad)	   strcpy(buf,"XkbSolidDoodad");
60005b261ecSmrg	else if (type==XkbTextDoodad)	   strcpy(buf,"XkbTextDoodad");
60105b261ecSmrg	else if (type==XkbIndicatorDoodad) strcpy(buf,"XkbIndicatorDoodad");
60205b261ecSmrg	else if (type==XkbLogoDoodad)	   strcpy(buf,"XkbLogoDoodad");
60305b261ecSmrg	else				   sprintf(buf,"UnknownDoodad%d",type);
60405b261ecSmrg    }
60505b261ecSmrg    else {
60605b261ecSmrg	buf= tbGetBuffer(12);
60705b261ecSmrg	if (type==XkbOutlineDoodad)	   strcpy(buf,"outline");
60805b261ecSmrg	else if (type==XkbSolidDoodad)	   strcpy(buf,"solid");
60905b261ecSmrg	else if (type==XkbTextDoodad)	   strcpy(buf,"text");
61005b261ecSmrg	else if (type==XkbIndicatorDoodad) strcpy(buf,"indicator");
61105b261ecSmrg	else if (type==XkbLogoDoodad)	   strcpy(buf,"logo");
61205b261ecSmrg	else				   sprintf(buf,"unknown%d",type);
61305b261ecSmrg    }
61405b261ecSmrg    return buf;
61505b261ecSmrg}
61605b261ecSmrg
61705b261ecSmrgstatic char *actionTypeNames[XkbSA_NumActions]= {
61805b261ecSmrg    "NoAction",
61905b261ecSmrg    "SetMods",      "LatchMods",    "LockMods",
62005b261ecSmrg    "SetGroup",     "LatchGroup",   "LockGroup",
62105b261ecSmrg    "MovePtr",
62205b261ecSmrg    "PtrBtn",       "LockPtrBtn",
62305b261ecSmrg    "SetPtrDflt",
62405b261ecSmrg    "ISOLock",
62505b261ecSmrg    "Terminate",    "SwitchScreen",
62605b261ecSmrg    "SetControls",  "LockControls",
62705b261ecSmrg    "ActionMessage",
62805b261ecSmrg    "RedirectKey",
62905b261ecSmrg    "DeviceBtn",    "LockDeviceBtn"
63005b261ecSmrg};
63105b261ecSmrg
63205b261ecSmrgchar *
63305b261ecSmrgXkbActionTypeText(unsigned type,unsigned format)
63405b261ecSmrg{
63505b261ecSmrgstatic char buf[32];
63605b261ecSmrgchar *rtrn;
63705b261ecSmrg
63805b261ecSmrg    if (type<=XkbSA_LastAction) {
63905b261ecSmrg	rtrn= actionTypeNames[type];
64005b261ecSmrg	if (format==XkbCFile) {
64105b261ecSmrg	    sprintf(buf,"XkbSA_%s",rtrn);
64205b261ecSmrg	    return buf;
64305b261ecSmrg	}
64405b261ecSmrg	return rtrn;
64505b261ecSmrg    }
64605b261ecSmrg    sprintf(buf,"Private");
64705b261ecSmrg    return buf;
64805b261ecSmrg}
64905b261ecSmrg
65005b261ecSmrg/***====================================================================***/
65105b261ecSmrg
65205b261ecSmrgstatic int
65305b261ecSmrgTryCopyStr(char *to,char *from,int *pLeft)
65405b261ecSmrg{
65505b261ecSmrgregister int len;
65605b261ecSmrg    if (*pLeft>0) {
65705b261ecSmrg	len= strlen(from);
65805b261ecSmrg	if (len<((*pLeft)-3)) {
65905b261ecSmrg	    strcat(to,from);
66005b261ecSmrg	    *pLeft-= len;
66105b261ecSmrg	    return True;
66205b261ecSmrg	}
66305b261ecSmrg    }
66405b261ecSmrg    *pLeft= -1;
66505b261ecSmrg    return False;
66605b261ecSmrg}
66705b261ecSmrg
66805b261ecSmrg/*ARGSUSED*/
66905b261ecSmrgstatic Bool
67005b261ecSmrgCopyNoActionArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int*sz)
67105b261ecSmrg{
67205b261ecSmrg    return True;
67305b261ecSmrg}
67405b261ecSmrg
67505b261ecSmrgstatic Bool
67605b261ecSmrgCopyModActionArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
67705b261ecSmrg								int* sz)
67805b261ecSmrg{
67905b261ecSmrgXkbModAction *	act;
68005b261ecSmrgunsigned	tmp;
68105b261ecSmrg
68205b261ecSmrg    act= &action->mods;
68305b261ecSmrg    tmp= XkbModActionVMods(act);
68405b261ecSmrg    TryCopyStr(buf,"modifiers=",sz);
68505b261ecSmrg    if (act->flags&XkbSA_UseModMapMods)
68605b261ecSmrg	  TryCopyStr(buf,"modMapMods",sz);
68705b261ecSmrg    else if (act->real_mods || tmp) {
68805b261ecSmrg	 TryCopyStr(buf,
68905b261ecSmrg		     XkbVModMaskText(dpy,xkb,act->real_mods,tmp,XkbXKBFile),
69005b261ecSmrg		     sz);
69105b261ecSmrg    }
69205b261ecSmrg    else TryCopyStr(buf,"none",sz);
69305b261ecSmrg    if (act->type==XkbSA_LockMods)
69405b261ecSmrg	return True;
69505b261ecSmrg    if (act->flags&XkbSA_ClearLocks)
69605b261ecSmrg	TryCopyStr(buf,",clearLocks",sz);
69705b261ecSmrg    if (act->flags&XkbSA_LatchToLock)
69805b261ecSmrg	TryCopyStr(buf,",latchToLock",sz);
69905b261ecSmrg    return True;
70005b261ecSmrg}
70105b261ecSmrg
70205b261ecSmrg/*ARGSUSED*/
70305b261ecSmrgstatic Bool
70405b261ecSmrgCopyGroupActionArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
70505b261ecSmrg								int *sz)
70605b261ecSmrg{
70705b261ecSmrgXkbGroupAction *	act;
70805b261ecSmrgchar			tbuf[32];
70905b261ecSmrg
71005b261ecSmrg    act= &action->group;
71105b261ecSmrg    TryCopyStr(buf,"group=",sz);
71205b261ecSmrg    if (act->flags&XkbSA_GroupAbsolute)
71305b261ecSmrg	 sprintf(tbuf,"%d",XkbSAGroup(act)+1);
71405b261ecSmrg    else if (XkbSAGroup(act)<0)
71505b261ecSmrg	 sprintf(tbuf,"%d",XkbSAGroup(act));
71605b261ecSmrg    else sprintf(tbuf,"+%d",XkbSAGroup(act));
71705b261ecSmrg    TryCopyStr(buf,tbuf,sz);
71805b261ecSmrg    if (act->type==XkbSA_LockGroup)
71905b261ecSmrg	return True;
72005b261ecSmrg    if (act->flags&XkbSA_ClearLocks)
72105b261ecSmrg	TryCopyStr(buf,",clearLocks",sz);
72205b261ecSmrg    if (act->flags&XkbSA_LatchToLock)
72305b261ecSmrg	TryCopyStr(buf,",latchToLock",sz);
72405b261ecSmrg    return True;
72505b261ecSmrg}
72605b261ecSmrg
72705b261ecSmrg/*ARGSUSED*/
72805b261ecSmrgstatic Bool
72905b261ecSmrgCopyMovePtrArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int *sz)
73005b261ecSmrg{
73105b261ecSmrgXkbPtrAction *	act;
73205b261ecSmrgint		x,y;
73305b261ecSmrgchar		tbuf[32];
73405b261ecSmrg
73505b261ecSmrg    act= &action->ptr;
73605b261ecSmrg    x= XkbPtrActionX(act);
73705b261ecSmrg    y= XkbPtrActionY(act);
73805b261ecSmrg    if ((act->flags&XkbSA_MoveAbsoluteX)||(x<0))
73905b261ecSmrg	 sprintf(tbuf,"x=%d",x);
74005b261ecSmrg    else sprintf(tbuf,"x=+%d",x);
74105b261ecSmrg    TryCopyStr(buf,tbuf,sz);
74205b261ecSmrg
74305b261ecSmrg    if ((act->flags&XkbSA_MoveAbsoluteY)||(y<0))
74405b261ecSmrg	 sprintf(tbuf,",y=%d",y);
74505b261ecSmrg    else sprintf(tbuf,",y=+%d",y);
74605b261ecSmrg    TryCopyStr(buf,tbuf,sz);
74705b261ecSmrg    if (act->flags&XkbSA_NoAcceleration)
74805b261ecSmrg	TryCopyStr(buf,",!accel",sz);
74905b261ecSmrg    return True;
75005b261ecSmrg}
75105b261ecSmrg
75205b261ecSmrg/*ARGSUSED*/
75305b261ecSmrgstatic Bool
75405b261ecSmrgCopyPtrBtnArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int *sz)
75505b261ecSmrg{
75605b261ecSmrgXkbPtrBtnAction *	act;
75705b261ecSmrgchar			tbuf[32];
75805b261ecSmrg
75905b261ecSmrg    act= &action->btn;
76005b261ecSmrg    TryCopyStr(buf,"button=",sz);
76105b261ecSmrg    if ((act->button>0)&&(act->button<6)) {
76205b261ecSmrg	 sprintf(tbuf,"%d",act->button);
76305b261ecSmrg	 TryCopyStr(buf,tbuf,sz);
76405b261ecSmrg    }
76505b261ecSmrg    else TryCopyStr(buf,"default",sz);
76605b261ecSmrg    if (act->count>0) {
76705b261ecSmrg	sprintf(tbuf,",count=%d",act->count);
76805b261ecSmrg	TryCopyStr(buf,tbuf,sz);
76905b261ecSmrg    }
77005b261ecSmrg    if (action->type==XkbSA_LockPtrBtn) {
77105b261ecSmrg	switch (act->flags&(XkbSA_LockNoUnlock|XkbSA_LockNoLock)) {
77205b261ecSmrg	    case XkbSA_LockNoLock:
77305b261ecSmrg		sprintf(tbuf,",affect=unlock"); break;
77405b261ecSmrg	    case XkbSA_LockNoUnlock:
77505b261ecSmrg		sprintf(tbuf,",affect=lock"); break;
77605b261ecSmrg	    case XkbSA_LockNoUnlock|XkbSA_LockNoLock:
77705b261ecSmrg		sprintf(tbuf,",affect=neither"); break;
77805b261ecSmrg	    default:
77905b261ecSmrg		sprintf(tbuf,",affect=both"); break;
78005b261ecSmrg	}
78105b261ecSmrg	TryCopyStr(buf,tbuf,sz);
78205b261ecSmrg    }
78305b261ecSmrg    return True;
78405b261ecSmrg}
78505b261ecSmrg
78605b261ecSmrg/*ARGSUSED*/
78705b261ecSmrgstatic Bool
78805b261ecSmrgCopySetPtrDfltArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
78905b261ecSmrg								int *sz)
79005b261ecSmrg{
79105b261ecSmrgXkbPtrDfltAction *	act;
79205b261ecSmrgchar			tbuf[32];
79305b261ecSmrg
79405b261ecSmrg    act= &action->dflt;
79505b261ecSmrg    if (act->affect==XkbSA_AffectDfltBtn) {
79605b261ecSmrg	TryCopyStr(buf,"affect=button,button=",sz);
79705b261ecSmrg	if ((act->flags&XkbSA_DfltBtnAbsolute)||(XkbSAPtrDfltValue(act)<0))
79805b261ecSmrg	     sprintf(tbuf,"%d",XkbSAPtrDfltValue(act));
79905b261ecSmrg	else sprintf(tbuf,"+%d",XkbSAPtrDfltValue(act));
80005b261ecSmrg	TryCopyStr(buf,tbuf,sz);
80105b261ecSmrg    }
80205b261ecSmrg    return True;
80305b261ecSmrg}
80405b261ecSmrg
80505b261ecSmrgstatic Bool
80605b261ecSmrgCopyISOLockArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int *sz)
80705b261ecSmrg{
80805b261ecSmrgXkbISOAction *	act;
80905b261ecSmrgchar		tbuf[64];
81005b261ecSmrg
81105b261ecSmrg    act= &action->iso;
81205b261ecSmrg    if (act->flags&XkbSA_ISODfltIsGroup) {
81305b261ecSmrg	TryCopyStr(tbuf,"group=",sz);
81405b261ecSmrg	if (act->flags&XkbSA_GroupAbsolute)
81505b261ecSmrg	     sprintf(tbuf,"%d",XkbSAGroup(act)+1);
81605b261ecSmrg	else if (XkbSAGroup(act)<0)
81705b261ecSmrg	     sprintf(tbuf,"%d",XkbSAGroup(act));
81805b261ecSmrg	else sprintf(tbuf,"+%d",XkbSAGroup(act));
81905b261ecSmrg	TryCopyStr(buf,tbuf,sz);
82005b261ecSmrg    }
82105b261ecSmrg    else {
82205b261ecSmrg	unsigned tmp;
82305b261ecSmrg	tmp= XkbModActionVMods(act);
82405b261ecSmrg	TryCopyStr(buf,"modifiers=",sz);
82505b261ecSmrg	if (act->flags&XkbSA_UseModMapMods)
82605b261ecSmrg	     TryCopyStr(buf,"modMapMods",sz);
82705b261ecSmrg	else if (act->real_mods || tmp) {
82805b261ecSmrg	    if (act->real_mods) {
82905b261ecSmrg		TryCopyStr(buf,XkbModMaskText(act->real_mods,XkbXKBFile),sz);
83005b261ecSmrg		if (tmp)
83105b261ecSmrg		    TryCopyStr(buf,"+",sz);
83205b261ecSmrg	    }
83305b261ecSmrg	    if (tmp)
83405b261ecSmrg		TryCopyStr(buf,XkbVModMaskText(dpy,xkb,0,tmp,XkbXKBFile),sz);
83505b261ecSmrg	}
83605b261ecSmrg	else TryCopyStr(buf,"none",sz);
83705b261ecSmrg    }
83805b261ecSmrg    TryCopyStr(buf,",affect=",sz);
83905b261ecSmrg    if ((act->affect&XkbSA_ISOAffectMask)==0)
84005b261ecSmrg	TryCopyStr(buf,"all",sz);
84105b261ecSmrg    else {
84205b261ecSmrg	int nOut= 0;
84305b261ecSmrg	if ((act->affect&XkbSA_ISONoAffectMods)==0) {
84405b261ecSmrg	    TryCopyStr(buf,"mods",sz);
84505b261ecSmrg	    nOut++;
84605b261ecSmrg	}
84705b261ecSmrg	if ((act->affect&XkbSA_ISONoAffectGroup)==0) {
84805b261ecSmrg	    sprintf(tbuf,"%sgroups",(nOut>0?"+":""));
84905b261ecSmrg	    TryCopyStr(buf,tbuf,sz);
85005b261ecSmrg	    nOut++;
85105b261ecSmrg	}
85205b261ecSmrg	if ((act->affect&XkbSA_ISONoAffectPtr)==0) {
85305b261ecSmrg	    sprintf(tbuf,"%spointer",(nOut>0?"+":""));
85405b261ecSmrg	    TryCopyStr(buf,tbuf,sz);
85505b261ecSmrg	    nOut++;
85605b261ecSmrg	}
85705b261ecSmrg	if ((act->affect&XkbSA_ISONoAffectCtrls)==0) {
85805b261ecSmrg	    sprintf(tbuf,"%scontrols",(nOut>0?"+":""));
85905b261ecSmrg	    TryCopyStr(buf,tbuf,sz);
86005b261ecSmrg	    nOut++;
86105b261ecSmrg	}
86205b261ecSmrg    }
86305b261ecSmrg    return True;
86405b261ecSmrg}
86505b261ecSmrg
86605b261ecSmrg/*ARGSUSED*/
86705b261ecSmrgstatic Bool
86805b261ecSmrgCopySwitchScreenArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
86905b261ecSmrg								int *sz)
87005b261ecSmrg{
87105b261ecSmrgXkbSwitchScreenAction *	act;
87205b261ecSmrgchar			tbuf[32];
87305b261ecSmrg
87405b261ecSmrg    act= &action->screen;
87505b261ecSmrg    if ((act->flags&XkbSA_SwitchAbsolute)||(XkbSAScreen(act)<0))
87605b261ecSmrg	 sprintf(tbuf,"screen=%d",XkbSAScreen(act));
87705b261ecSmrg    else sprintf(tbuf,"screen=+%d",XkbSAScreen(act));
87805b261ecSmrg    TryCopyStr(buf,tbuf,sz);
87905b261ecSmrg    if (act->flags&XkbSA_SwitchApplication)
88005b261ecSmrg	 TryCopyStr(buf,",!same",sz);
88105b261ecSmrg    else TryCopyStr(buf,",same",sz);
88205b261ecSmrg    return True;
88305b261ecSmrg}
88405b261ecSmrg
88505b261ecSmrg/*ARGSUSED*/
88605b261ecSmrgstatic Bool
88705b261ecSmrgCopySetLockControlsArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,
88805b261ecSmrg							char *buf,int *sz)
88905b261ecSmrg{
89005b261ecSmrgXkbCtrlsAction *	act;
89105b261ecSmrgunsigned		tmp;
89205b261ecSmrgchar			tbuf[32];
89305b261ecSmrg
89405b261ecSmrg    act= &action->ctrls;
89505b261ecSmrg    tmp= XkbActionCtrls(act);
89605b261ecSmrg    TryCopyStr(buf,"controls=",sz);
89705b261ecSmrg    if (tmp==0)
89805b261ecSmrg	TryCopyStr(buf,"none",sz);
89905b261ecSmrg    else if ((tmp&XkbAllBooleanCtrlsMask)==XkbAllBooleanCtrlsMask)
90005b261ecSmrg	TryCopyStr(buf,"all",sz);
90105b261ecSmrg    else {
90205b261ecSmrg	int nOut= 0;
90305b261ecSmrg	if (tmp&XkbRepeatKeysMask) {
90405b261ecSmrg	    sprintf(tbuf,"%sRepeatKeys",(nOut>0?"+":""));
90505b261ecSmrg	    TryCopyStr(buf,tbuf,sz);
90605b261ecSmrg	    nOut++;
90705b261ecSmrg	}
90805b261ecSmrg	if (tmp&XkbSlowKeysMask) {
90905b261ecSmrg	    sprintf(tbuf,"%sSlowKeys",(nOut>0?"+":""));
91005b261ecSmrg	    TryCopyStr(buf,tbuf,sz);
91105b261ecSmrg	    nOut++;
91205b261ecSmrg	}
91305b261ecSmrg	if (tmp&XkbBounceKeysMask) {
91405b261ecSmrg	    sprintf(tbuf,"%sBounceKeys",(nOut>0?"+":""));
91505b261ecSmrg	    TryCopyStr(buf,tbuf,sz);
91605b261ecSmrg	    nOut++;
91705b261ecSmrg	}
91805b261ecSmrg	if (tmp&XkbStickyKeysMask) {
91905b261ecSmrg	    sprintf(tbuf,"%sStickyKeys",(nOut>0?"+":""));
92005b261ecSmrg	    TryCopyStr(buf,tbuf,sz);
92105b261ecSmrg	    nOut++;
92205b261ecSmrg	}
92305b261ecSmrg	if (tmp&XkbMouseKeysMask) {
92405b261ecSmrg	    sprintf(tbuf,"%sMouseKeys",(nOut>0?"+":""));
92505b261ecSmrg	    TryCopyStr(buf,tbuf,sz);
92605b261ecSmrg	    nOut++;
92705b261ecSmrg	}
92805b261ecSmrg	if (tmp&XkbMouseKeysAccelMask) {
92905b261ecSmrg	    sprintf(tbuf,"%sMouseKeysAccel",(nOut>0?"+":""));
93005b261ecSmrg	    TryCopyStr(buf,tbuf,sz);
93105b261ecSmrg	    nOut++;
93205b261ecSmrg	}
93305b261ecSmrg	if (tmp&XkbAccessXKeysMask) {
93405b261ecSmrg	    sprintf(tbuf,"%sAccessXKeys",(nOut>0?"+":""));
93505b261ecSmrg	    TryCopyStr(buf,tbuf,sz);
93605b261ecSmrg	    nOut++;
93705b261ecSmrg	}
93805b261ecSmrg	if (tmp&XkbAccessXTimeoutMask) {
93905b261ecSmrg	    sprintf(tbuf,"%sAccessXTimeout",(nOut>0?"+":""));
94005b261ecSmrg	    TryCopyStr(buf,tbuf,sz);
94105b261ecSmrg	    nOut++;
94205b261ecSmrg	}
94305b261ecSmrg	if (tmp&XkbAccessXFeedbackMask) {
94405b261ecSmrg	    sprintf(tbuf,"%sAccessXFeedback",(nOut>0?"+":""));
94505b261ecSmrg	    TryCopyStr(buf,tbuf,sz);
94605b261ecSmrg	    nOut++;
94705b261ecSmrg	}
94805b261ecSmrg	if (tmp&XkbAudibleBellMask) {
94905b261ecSmrg	    sprintf(tbuf,"%sAudibleBell",(nOut>0?"+":""));
95005b261ecSmrg	    TryCopyStr(buf,tbuf,sz);
95105b261ecSmrg	    nOut++;
95205b261ecSmrg	}
95305b261ecSmrg	if (tmp&XkbOverlay1Mask) {
95405b261ecSmrg	    sprintf(tbuf,"%sOverlay1",(nOut>0?"+":""));
95505b261ecSmrg	    TryCopyStr(buf,tbuf,sz);
95605b261ecSmrg	    nOut++;
95705b261ecSmrg	}
95805b261ecSmrg	if (tmp&XkbOverlay2Mask) {
95905b261ecSmrg	    sprintf(tbuf,"%sOverlay2",(nOut>0?"+":""));
96005b261ecSmrg	    TryCopyStr(buf,tbuf,sz);
96105b261ecSmrg	    nOut++;
96205b261ecSmrg	}
96305b261ecSmrg	if (tmp&XkbIgnoreGroupLockMask) {
96405b261ecSmrg	    sprintf(tbuf,"%sIgnoreGroupLock",(nOut>0?"+":""));
96505b261ecSmrg	    TryCopyStr(buf,tbuf,sz);
96605b261ecSmrg	    nOut++;
96705b261ecSmrg	}
96805b261ecSmrg    }
96905b261ecSmrg    return True;
97005b261ecSmrg}
97105b261ecSmrg
97205b261ecSmrg/*ARGSUSED*/
97305b261ecSmrgstatic Bool
97405b261ecSmrgCopyActionMessageArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
97505b261ecSmrg								int *sz)
97605b261ecSmrg{
97705b261ecSmrgXkbMessageAction *	act;
97805b261ecSmrgunsigned		all;
97905b261ecSmrgchar			tbuf[32];
98005b261ecSmrg
98105b261ecSmrg    act= &action->msg;
98205b261ecSmrg    all= XkbSA_MessageOnPress|XkbSA_MessageOnRelease;
98305b261ecSmrg    TryCopyStr(buf,"report=",sz);
98405b261ecSmrg    if ((act->flags&all)==0)
98505b261ecSmrg	TryCopyStr(buf,"none",sz);
98605b261ecSmrg    else if ((act->flags&all)==all)
98705b261ecSmrg	TryCopyStr(buf,"all",sz);
98805b261ecSmrg    else if (act->flags&XkbSA_MessageOnPress)
98905b261ecSmrg	 TryCopyStr(buf,"KeyPress",sz);
99005b261ecSmrg    else TryCopyStr(buf,"KeyRelease",sz);
99105b261ecSmrg    sprintf(tbuf,",data[0]=0x%02x",act->message[0]); TryCopyStr(buf,tbuf,sz);
99205b261ecSmrg    sprintf(tbuf,",data[1]=0x%02x",act->message[1]); TryCopyStr(buf,tbuf,sz);
99305b261ecSmrg    sprintf(tbuf,",data[2]=0x%02x",act->message[2]); TryCopyStr(buf,tbuf,sz);
99405b261ecSmrg    sprintf(tbuf,",data[3]=0x%02x",act->message[3]); TryCopyStr(buf,tbuf,sz);
99505b261ecSmrg    sprintf(tbuf,",data[4]=0x%02x",act->message[4]); TryCopyStr(buf,tbuf,sz);
99605b261ecSmrg    sprintf(tbuf,",data[5]=0x%02x",act->message[5]); TryCopyStr(buf,tbuf,sz);
99705b261ecSmrg    return True;
99805b261ecSmrg}
99905b261ecSmrg
100005b261ecSmrgstatic Bool
100105b261ecSmrgCopyRedirectKeyArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
100205b261ecSmrg								int *sz)
100305b261ecSmrg{
100405b261ecSmrgXkbRedirectKeyAction *	act;
100505b261ecSmrgchar			tbuf[32],*tmp;
100605b261ecSmrgunsigned		kc;
100705b261ecSmrgunsigned		vmods,vmods_mask;
100805b261ecSmrg
100905b261ecSmrg    act= &action->redirect;
101005b261ecSmrg    kc= act->new_key;
101105b261ecSmrg    vmods= XkbSARedirectVMods(act);
101205b261ecSmrg    vmods_mask= XkbSARedirectVModsMask(act);
101305b261ecSmrg    if (xkb && xkb->names && xkb->names->keys && (kc<=xkb->max_key_code) &&
101405b261ecSmrg				(xkb->names->keys[kc].name[0]!='\0')) {
101505b261ecSmrg	char *kn;
101605b261ecSmrg	kn= XkbKeyNameText(xkb->names->keys[kc].name,XkbXKBFile);
101705b261ecSmrg	sprintf(tbuf,"key=%s",kn);
101805b261ecSmrg    }
101905b261ecSmrg    else sprintf(tbuf,"key=%d",kc);
102005b261ecSmrg    TryCopyStr(buf,tbuf,sz);
102105b261ecSmrg    if ((act->mods_mask==0)&&(vmods_mask==0))
102205b261ecSmrg	return True;
102305b261ecSmrg    if ((act->mods_mask==XkbAllModifiersMask)&&
102405b261ecSmrg	(vmods_mask==XkbAllVirtualModsMask)) {
102505b261ecSmrg	tmp= XkbVModMaskText(dpy,xkb,act->mods,vmods,XkbXKBFile);
102605b261ecSmrg	TryCopyStr(buf,",mods=",sz);
102705b261ecSmrg	TryCopyStr(buf,tmp,sz);
102805b261ecSmrg    }
102905b261ecSmrg    else {
103005b261ecSmrg	if ((act->mods_mask&act->mods)||(vmods_mask&vmods)) {
103105b261ecSmrg	    tmp= XkbVModMaskText(dpy,xkb,act->mods_mask&act->mods,
103205b261ecSmrg					 vmods_mask&vmods,XkbXKBFile);
103305b261ecSmrg	    TryCopyStr(buf,",mods= ",sz);
103405b261ecSmrg	    TryCopyStr(buf,tmp,sz);
103505b261ecSmrg	}
103605b261ecSmrg	if ((act->mods_mask&(~act->mods))||(vmods_mask&(~vmods))) {
103705b261ecSmrg	    tmp= XkbVModMaskText(dpy,xkb,act->mods_mask&(~act->mods),
103805b261ecSmrg					 vmods_mask&(~vmods),XkbXKBFile);
103905b261ecSmrg	    TryCopyStr(buf,",clearMods= ",sz);
104005b261ecSmrg	    TryCopyStr(buf,tmp,sz);
104105b261ecSmrg	}
104205b261ecSmrg    }
104305b261ecSmrg    return True;
104405b261ecSmrg}
104505b261ecSmrg
104605b261ecSmrg/*ARGSUSED*/
104705b261ecSmrgstatic Bool
104805b261ecSmrgCopyDeviceBtnArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
104905b261ecSmrg								int *sz)
105005b261ecSmrg{
105105b261ecSmrgXkbDeviceBtnAction *	act;
105205b261ecSmrgchar			tbuf[32];
105305b261ecSmrg
105405b261ecSmrg    act= &action->devbtn;
105505b261ecSmrg    sprintf(tbuf,"device= %d",act->device); TryCopyStr(buf,tbuf,sz);
105605b261ecSmrg    TryCopyStr(buf,",button=",sz);
105705b261ecSmrg    sprintf(tbuf,"%d",act->button);
105805b261ecSmrg    TryCopyStr(buf,tbuf,sz);
105905b261ecSmrg    if (act->count>0) {
106005b261ecSmrg	sprintf(tbuf,",count=%d",act->count);
106105b261ecSmrg	TryCopyStr(buf,tbuf,sz);
106205b261ecSmrg    }
106305b261ecSmrg    if (action->type==XkbSA_LockDeviceBtn) {
106405b261ecSmrg	switch (act->flags&(XkbSA_LockNoUnlock|XkbSA_LockNoLock)) {
106505b261ecSmrg	    case XkbSA_LockNoLock:
106605b261ecSmrg		sprintf(tbuf,",affect=unlock"); break;
106705b261ecSmrg	    case XkbSA_LockNoUnlock:
106805b261ecSmrg		sprintf(tbuf,",affect=lock"); break;
106905b261ecSmrg	    case XkbSA_LockNoUnlock|XkbSA_LockNoLock:
107005b261ecSmrg		sprintf(tbuf,",affect=neither"); break;
107105b261ecSmrg	    default:
107205b261ecSmrg		sprintf(tbuf,",affect=both"); break;
107305b261ecSmrg	}
107405b261ecSmrg	TryCopyStr(buf,tbuf,sz);
107505b261ecSmrg    }
107605b261ecSmrg    return True;
107705b261ecSmrg}
107805b261ecSmrg
107905b261ecSmrg/*ARGSUSED*/
108005b261ecSmrgstatic Bool
108105b261ecSmrgCopyOtherArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int *sz)
108205b261ecSmrg{
108305b261ecSmrgXkbAnyAction *	act;
108405b261ecSmrgchar		tbuf[32];
108505b261ecSmrg
108605b261ecSmrg    act= &action->any;
108705b261ecSmrg    sprintf(tbuf,"type=0x%02x",act->type); TryCopyStr(buf,tbuf,sz);
108805b261ecSmrg    sprintf(tbuf,",data[0]=0x%02x",act->data[0]); TryCopyStr(buf,tbuf,sz);
108905b261ecSmrg    sprintf(tbuf,",data[1]=0x%02x",act->data[1]); TryCopyStr(buf,tbuf,sz);
109005b261ecSmrg    sprintf(tbuf,",data[2]=0x%02x",act->data[2]); TryCopyStr(buf,tbuf,sz);
109105b261ecSmrg    sprintf(tbuf,",data[3]=0x%02x",act->data[3]); TryCopyStr(buf,tbuf,sz);
109205b261ecSmrg    sprintf(tbuf,",data[4]=0x%02x",act->data[4]); TryCopyStr(buf,tbuf,sz);
109305b261ecSmrg    sprintf(tbuf,",data[5]=0x%02x",act->data[5]); TryCopyStr(buf,tbuf,sz);
109405b261ecSmrg    sprintf(tbuf,",data[6]=0x%02x",act->data[6]); TryCopyStr(buf,tbuf,sz);
109505b261ecSmrg    return True;
109605b261ecSmrg}
109705b261ecSmrg
109805b261ecSmrgtypedef	Bool	(*actionCopy)(
109905b261ecSmrg	Display *	/* dpy */,
110005b261ecSmrg	XkbDescPtr 	/* xkb */,
110105b261ecSmrg	XkbAction *	/* action */,
110205b261ecSmrg	char *		/* buf */,
110305b261ecSmrg	int*		/* sz */
110405b261ecSmrg);
110505b261ecSmrgstatic actionCopy	copyActionArgs[XkbSA_NumActions] = {
110605b261ecSmrg	CopyNoActionArgs		/* NoAction	*/,
110705b261ecSmrg	CopyModActionArgs		/* SetMods	*/,
110805b261ecSmrg	CopyModActionArgs		/* LatchMods	*/,
110905b261ecSmrg	CopyModActionArgs		/* LockMods	*/,
111005b261ecSmrg	CopyGroupActionArgs		/* SetGroup	*/,
111105b261ecSmrg	CopyGroupActionArgs		/* LatchGroup	*/,
111205b261ecSmrg	CopyGroupActionArgs		/* LockGroup	*/,
111305b261ecSmrg	CopyMovePtrArgs			/* MovePtr	*/,
111405b261ecSmrg	CopyPtrBtnArgs			/* PtrBtn	*/,
111505b261ecSmrg	CopyPtrBtnArgs			/* LockPtrBtn	*/,
111605b261ecSmrg	CopySetPtrDfltArgs		/* SetPtrDflt	*/,
111705b261ecSmrg	CopyISOLockArgs			/* ISOLock	*/,
111805b261ecSmrg	CopyNoActionArgs		/* Terminate	*/,
111905b261ecSmrg	CopySwitchScreenArgs		/* SwitchScreen	*/,
112005b261ecSmrg	CopySetLockControlsArgs		/* SetControls	*/,
112105b261ecSmrg	CopySetLockControlsArgs		/* LockControls	*/,
112205b261ecSmrg	CopyActionMessageArgs		/* ActionMessage*/,
112305b261ecSmrg	CopyRedirectKeyArgs		/* RedirectKey	*/,
112405b261ecSmrg	CopyDeviceBtnArgs		/* DeviceBtn	*/,
112505b261ecSmrg	CopyDeviceBtnArgs		/* LockDeviceBtn*/
112605b261ecSmrg};
112705b261ecSmrg
112805b261ecSmrg#define	ACTION_SZ	256
112905b261ecSmrg
113005b261ecSmrgchar *
113105b261ecSmrgXkbActionText(Display *dpy,XkbDescPtr xkb,XkbAction *action,unsigned format)
113205b261ecSmrg{
113305b261ecSmrgchar	buf[ACTION_SZ],*tmp;
113405b261ecSmrgint	sz;
113505b261ecSmrg
113605b261ecSmrg    if (format==XkbCFile) {
113705b261ecSmrg	sprintf(buf,
113805b261ecSmrg	    "{ %20s, { 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x } }",
113905b261ecSmrg	    XkbActionTypeText(action->type,XkbCFile),
114005b261ecSmrg	    action->any.data[0],action->any.data[1],action->any.data[2],
114105b261ecSmrg	    action->any.data[3],action->any.data[4],action->any.data[5],
114205b261ecSmrg	    action->any.data[6]);
114305b261ecSmrg    }
114405b261ecSmrg    else {
114505b261ecSmrg	sprintf(buf,"%s(",XkbActionTypeText(action->type,XkbXKBFile));
114605b261ecSmrg	sz= ACTION_SZ-strlen(buf)+2; /* room for close paren and NULL */
114705b261ecSmrg	if (action->type<(unsigned)XkbSA_NumActions)
114805b261ecSmrg	     (*copyActionArgs[action->type])(dpy,xkb,action,buf,&sz);
114905b261ecSmrg	else CopyOtherArgs(dpy,xkb,action,buf,&sz);
115005b261ecSmrg	TryCopyStr(buf,")",&sz);
115105b261ecSmrg    }
115205b261ecSmrg    tmp= tbGetBuffer(strlen(buf)+1);
115305b261ecSmrg    if (tmp!=NULL)
115405b261ecSmrg	strcpy(tmp,buf);
115505b261ecSmrg    return tmp;
115605b261ecSmrg}
115705b261ecSmrg
115805b261ecSmrgchar *
115905b261ecSmrgXkbBehaviorText(XkbDescPtr xkb,XkbBehavior *behavior,unsigned format)
116005b261ecSmrg{
116105b261ecSmrgchar	buf[256],*tmp;
116205b261ecSmrg
116305b261ecSmrg    if (format==XkbCFile) {
116405b261ecSmrg	if (behavior->type==XkbKB_Default)
116505b261ecSmrg	     sprintf(buf,"{   0,    0 }");
116605b261ecSmrg	else sprintf(buf,"{ %3d, 0x%02x }",behavior->type,behavior->data);
116705b261ecSmrg    }
116805b261ecSmrg    else {
116905b261ecSmrg	unsigned 	type,permanent;
117005b261ecSmrg	type= behavior->type&XkbKB_OpMask;
117105b261ecSmrg	permanent=((behavior->type&XkbKB_Permanent)!=0);
117205b261ecSmrg
117305b261ecSmrg	if (type==XkbKB_Lock) {
117405b261ecSmrg	    sprintf(buf,"lock= %s",(permanent?"Permanent":"True"));
117505b261ecSmrg	}
117605b261ecSmrg	else if (type==XkbKB_RadioGroup) {
117705b261ecSmrg	    int 	g;
117805b261ecSmrg	    char	*tmp;
117905b261ecSmrg	    g= ((behavior->data)&(~XkbKB_RGAllowNone))+1;
118005b261ecSmrg	    if (XkbKB_RGAllowNone&behavior->data) {
118105b261ecSmrg		sprintf(buf,"allowNone,");
118205b261ecSmrg		tmp= &buf[strlen(buf)];
118305b261ecSmrg	    }
118405b261ecSmrg	    else tmp= buf;
118505b261ecSmrg	    if (permanent)
118605b261ecSmrg		 sprintf(tmp,"permanentRadioGroup= %d",g);
118705b261ecSmrg	    else sprintf(tmp,"radioGroup= %d",g);
118805b261ecSmrg	}
118905b261ecSmrg	else if ((type==XkbKB_Overlay1)||(type==XkbKB_Overlay2)) {
119005b261ecSmrg	    int ndx,kc;
119105b261ecSmrg	    char *kn;
119205b261ecSmrg
119305b261ecSmrg	    ndx= ((type==XkbKB_Overlay1)?1:2);
119405b261ecSmrg	    kc= behavior->data;
119505b261ecSmrg	    if ((xkb)&&(xkb->names)&&(xkb->names->keys))
119605b261ecSmrg		kn= XkbKeyNameText(xkb->names->keys[kc].name,XkbXKBFile);
119705b261ecSmrg	    else {
119805b261ecSmrg		static char tbuf[8];
119905b261ecSmrg		sprintf(tbuf,"%d",kc);
120005b261ecSmrg		kn= tbuf;
120105b261ecSmrg	    }
120205b261ecSmrg	    if (permanent)
120305b261ecSmrg		 sprintf(buf,"permanentOverlay%d= %s",ndx,kn);
120405b261ecSmrg	    else sprintf(buf,"overlay%d= %s",ndx,kn);
120505b261ecSmrg	}
120605b261ecSmrg    }
120705b261ecSmrg    tmp= tbGetBuffer(strlen(buf)+1);
120805b261ecSmrg    if (tmp!=NULL)
120905b261ecSmrg	strcpy(tmp,buf);
121005b261ecSmrg    return tmp;
121105b261ecSmrg}
121205b261ecSmrg
121305b261ecSmrg/***====================================================================***/
121405b261ecSmrg
121505b261ecSmrgchar *
121605b261ecSmrgXkbIndentText(unsigned size)
121705b261ecSmrg{
121805b261ecSmrgstatic char buf[32];
121905b261ecSmrgregister int i;
122005b261ecSmrg
122105b261ecSmrg    if (size>31)
122205b261ecSmrg	size= 31;
122305b261ecSmrg
122405b261ecSmrg    for (i=0;i<size;i++) {
122505b261ecSmrg	buf[i]= ' ';
122605b261ecSmrg    }
122705b261ecSmrg    buf[size]= '\0';
122805b261ecSmrg    return buf;
122905b261ecSmrg}
1230