1706f2543Smrg/************************************************************
2706f2543Smrg Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3706f2543Smrg
4706f2543Smrg Permission to use, copy, modify, and distribute this
5706f2543Smrg software and its documentation for any purpose and without
6706f2543Smrg fee is hereby granted, provided that the above copyright
7706f2543Smrg notice appear in all copies and that both that copyright
8706f2543Smrg notice and this permission notice appear in supporting
9706f2543Smrg documentation, and that the name of Silicon Graphics not be
10706f2543Smrg used in advertising or publicity pertaining to distribution
11706f2543Smrg of the software without specific prior written permission.
12706f2543Smrg Silicon Graphics makes no representation about the suitability
13706f2543Smrg of this software for any purpose. It is provided "as is"
14706f2543Smrg without any express or implied warranty.
15706f2543Smrg
16706f2543Smrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17706f2543Smrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18706f2543Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19706f2543Smrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20706f2543Smrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21706f2543Smrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22706f2543Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23706f2543Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE.
24706f2543Smrg
25706f2543Smrg ********************************************************/
26706f2543Smrg
27706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
28706f2543Smrg#include <dix-config.h>
29706f2543Smrg#endif
30706f2543Smrg
31706f2543Smrg#include <stdio.h>
32706f2543Smrg#include <ctype.h>
33706f2543Smrg#include <stdlib.h>
34706f2543Smrg
35706f2543Smrg#include <X11/Xos.h>
36706f2543Smrg
37706f2543Smrg#include <X11/X.h>
38706f2543Smrg#include <X11/Xproto.h>
39706f2543Smrg#include <X11/extensions/XKMformat.h>
40706f2543Smrg#include "misc.h"
41706f2543Smrg#include "inputstr.h"
42706f2543Smrg#include "dix.h"
43706f2543Smrg#include "xkbstr.h"
44706f2543Smrg#define XKBSRV_NEED_FILE_FUNCS	1
45706f2543Smrg#include <xkbsrv.h>
46706f2543Smrg#include "xkbgeom.h"
47706f2543Smrg
48706f2543Smrg/***====================================================================***/
49706f2543Smrg
50706f2543Smrg#define	BUFFER_SIZE	512
51706f2543Smrg
52706f2543Smrgstatic char textBuffer[BUFFER_SIZE];
53706f2543Smrgstatic int  tbNext= 0;
54706f2543Smrg
55706f2543Smrgstatic char *
56706f2543SmrgtbGetBuffer(unsigned size)
57706f2543Smrg{
58706f2543Smrgchar *rtrn;
59706f2543Smrg
60706f2543Smrg    if (size>=BUFFER_SIZE)
61706f2543Smrg	return NULL;
62706f2543Smrg    if ((BUFFER_SIZE-tbNext)<=size)
63706f2543Smrg	tbNext= 0;
64706f2543Smrg    rtrn= &textBuffer[tbNext];
65706f2543Smrg    tbNext+= size;
66706f2543Smrg    return rtrn;
67706f2543Smrg}
68706f2543Smrg
69706f2543Smrg/***====================================================================***/
70706f2543Smrg
71706f2543Smrgchar *
72706f2543SmrgXkbAtomText(Atom atm,unsigned format)
73706f2543Smrg{
74706f2543Smrgconst char	*atmstr;
75706f2543Smrgchar	*rtrn,*tmp;
76706f2543Smrg
77706f2543Smrg    atmstr = NameForAtom(atm);
78706f2543Smrg    if (atmstr != NULL) {
79706f2543Smrg	int	len;
80706f2543Smrg	len= strlen(atmstr)+1;
81706f2543Smrg	if (len>BUFFER_SIZE)
82706f2543Smrg	    len= BUFFER_SIZE-2;
83706f2543Smrg	rtrn= tbGetBuffer(len);
84706f2543Smrg	strncpy(rtrn,atmstr,len);
85706f2543Smrg	rtrn[len]= '\0';
86706f2543Smrg    }
87706f2543Smrg    else {
88706f2543Smrg	rtrn= tbGetBuffer(1);
89706f2543Smrg	rtrn[0]= '\0';
90706f2543Smrg    }
91706f2543Smrg    if (format==XkbCFile) {
92706f2543Smrg	for (tmp=rtrn;*tmp!='\0';tmp++) {
93706f2543Smrg	    if ((tmp==rtrn)&&(!isalpha(*tmp)))
94706f2543Smrg		*tmp= '_';
95706f2543Smrg	    else if (!isalnum(*tmp))
96706f2543Smrg		*tmp= '_';
97706f2543Smrg	}
98706f2543Smrg    }
99706f2543Smrg    return XkbStringText(rtrn,format);
100706f2543Smrg}
101706f2543Smrg
102706f2543Smrg/***====================================================================***/
103706f2543Smrg
104706f2543Smrgchar *
105706f2543SmrgXkbVModIndexText(XkbDescPtr xkb,unsigned ndx,unsigned format)
106706f2543Smrg{
107706f2543Smrgregister int len;
108706f2543Smrgregister Atom *vmodNames;
109706f2543Smrgchar *rtrn;
110706f2543Smrgconst char *tmp;
111706f2543Smrgchar  numBuf[20];
112706f2543Smrg
113706f2543Smrg    if (xkb && xkb->names)
114706f2543Smrg	 vmodNames= xkb->names->vmods;
115706f2543Smrg    else vmodNames= NULL;
116706f2543Smrg
117706f2543Smrg    tmp= NULL;
118706f2543Smrg    if (ndx>=XkbNumVirtualMods)
119706f2543Smrg	 tmp= "illegal";
120706f2543Smrg    else if (vmodNames&&(vmodNames[ndx]!=None))
121706f2543Smrg	 tmp= NameForAtom(vmodNames[ndx]);
122706f2543Smrg    if (tmp==NULL) {
123706f2543Smrg	sprintf(numBuf,"%d",ndx);
124706f2543Smrg	tmp = numBuf;
125706f2543Smrg    }
126706f2543Smrg
127706f2543Smrg    len= strlen(tmp)+1;
128706f2543Smrg    if (format==XkbCFile)
129706f2543Smrg	len+= 4;
130706f2543Smrg    if (len>=BUFFER_SIZE)
131706f2543Smrg	len= BUFFER_SIZE-1;
132706f2543Smrg    rtrn= tbGetBuffer(len);
133706f2543Smrg    if (format==XkbCFile) {
134706f2543Smrg	 strcpy(rtrn,"vmod_");
135706f2543Smrg	 strncpy(&rtrn[5],tmp,len-4);
136706f2543Smrg    }
137706f2543Smrg    else strncpy(rtrn,tmp,len);
138706f2543Smrg    return rtrn;
139706f2543Smrg}
140706f2543Smrg
141706f2543Smrgchar *
142706f2543SmrgXkbVModMaskText(        XkbDescPtr	xkb,
143706f2543Smrg			unsigned	modMask,
144706f2543Smrg			unsigned	mask,
145706f2543Smrg			unsigned	format)
146706f2543Smrg{
147706f2543Smrgregister int i,bit;
148706f2543Smrgint	 len;
149706f2543Smrgchar *mm,*rtrn;
150706f2543Smrgchar *str,buf[BUFFER_SIZE];
151706f2543Smrg
152706f2543Smrg    if ((modMask==0)&&(mask==0)) {
153706f2543Smrg	rtrn= tbGetBuffer(5);
154706f2543Smrg	if (format==XkbCFile)
155706f2543Smrg	     sprintf(rtrn,"0");
156706f2543Smrg	else sprintf(rtrn,"none");
157706f2543Smrg	return rtrn;
158706f2543Smrg    }
159706f2543Smrg    if (modMask!=0)
160706f2543Smrg	 mm= XkbModMaskText(modMask,format);
161706f2543Smrg    else mm= NULL;
162706f2543Smrg
163706f2543Smrg    str= buf;
164706f2543Smrg    buf[0]= '\0';
165706f2543Smrg    if (mask) {
166706f2543Smrg	char *tmp;
167706f2543Smrg	for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
168706f2543Smrg	    if (mask&bit) {
169706f2543Smrg		tmp= XkbVModIndexText(xkb,i,format);
170706f2543Smrg		len= strlen(tmp)+1+(str==buf?0:1);
171706f2543Smrg		if (format==XkbCFile)
172706f2543Smrg		    len+= 4;
173706f2543Smrg		if ((str-(buf+len))<=BUFFER_SIZE) {
174706f2543Smrg		    if (str!=buf) {
175706f2543Smrg			if (format==XkbCFile)	*str++= '|';
176706f2543Smrg			else			*str++= '+';
177706f2543Smrg			len--;
178706f2543Smrg		    }
179706f2543Smrg		}
180706f2543Smrg		if (format==XkbCFile)
181706f2543Smrg		     sprintf(str,"%sMask",tmp);
182706f2543Smrg		else strcpy(str,tmp);
183706f2543Smrg		str= &str[len-1];
184706f2543Smrg	    }
185706f2543Smrg	}
186706f2543Smrg	str= buf;
187706f2543Smrg    }
188706f2543Smrg    else str= NULL;
189706f2543Smrg    if (mm)
190706f2543Smrg	len= strlen(mm);
191706f2543Smrg    else	len= 0;
192706f2543Smrg    if (str)
193706f2543Smrg	len+= strlen(str)+(mm==NULL?0:1);
194706f2543Smrg    if (len>=BUFFER_SIZE)
195706f2543Smrg	len= BUFFER_SIZE-1;
196706f2543Smrg    rtrn= tbGetBuffer(len+1);
197706f2543Smrg    rtrn[0]= '\0';
198706f2543Smrg
199706f2543Smrg    if (mm!=NULL) {
200706f2543Smrg	i= strlen(mm);
201706f2543Smrg	if (i>len)
202706f2543Smrg	    i= len;
203706f2543Smrg	strcpy(rtrn,mm);
204706f2543Smrg    }
205706f2543Smrg    else {
206706f2543Smrg	i=0;
207706f2543Smrg    }
208706f2543Smrg    if (str!=NULL) {
209706f2543Smrg	if (mm!=NULL) {
210706f2543Smrg	    if (format==XkbCFile)	strcat(rtrn,"|");
211706f2543Smrg	    else			strcat(rtrn,"+");
212706f2543Smrg	}
213706f2543Smrg	strncat(rtrn,str,len-i);
214706f2543Smrg    }
215706f2543Smrg    rtrn[len]= '\0';
216706f2543Smrg    return rtrn;
217706f2543Smrg}
218706f2543Smrg
219706f2543Smrgstatic char *modNames[XkbNumModifiers] = {
220706f2543Smrg    "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5"
221706f2543Smrg};
222706f2543Smrg
223706f2543Smrgchar *
224706f2543SmrgXkbModIndexText(unsigned ndx,unsigned format)
225706f2543Smrg{
226706f2543Smrgchar *	rtrn;
227706f2543Smrgchar	buf[100];
228706f2543Smrg
229706f2543Smrg    if (format==XkbCFile) {
230706f2543Smrg	if (ndx<XkbNumModifiers)
231706f2543Smrg	     sprintf(buf,"%sMapIndex",modNames[ndx]);
232706f2543Smrg	else if (ndx==XkbNoModifier)
233706f2543Smrg	     sprintf(buf,"XkbNoModifier");
234706f2543Smrg	else sprintf(buf,"0x%02x",ndx);
235706f2543Smrg    }
236706f2543Smrg    else {
237706f2543Smrg	if (ndx<XkbNumModifiers)
238706f2543Smrg	     strcpy(buf,modNames[ndx]);
239706f2543Smrg	else if (ndx==XkbNoModifier)
240706f2543Smrg	     strcpy(buf,"none");
241706f2543Smrg	else sprintf(buf,"ILLEGAL_%02x",ndx);
242706f2543Smrg    }
243706f2543Smrg    rtrn= tbGetBuffer(strlen(buf)+1);
244706f2543Smrg    strcpy(rtrn,buf);
245706f2543Smrg    return rtrn;
246706f2543Smrg}
247706f2543Smrg
248706f2543Smrgchar *
249706f2543SmrgXkbModMaskText(unsigned mask,unsigned format)
250706f2543Smrg{
251706f2543Smrgregister int i,bit;
252706f2543Smrgchar buf[64],*rtrn;
253706f2543Smrg
254706f2543Smrg    if ((mask&0xff)==0xff) {
255706f2543Smrg	if (format==XkbCFile) 		strcpy(buf,"0xff");
256706f2543Smrg	else				strcpy(buf,"all");
257706f2543Smrg    }
258706f2543Smrg    else if ((mask&0xff)==0) {
259706f2543Smrg	if (format==XkbCFile)		strcpy(buf,"0");
260706f2543Smrg	else				strcpy(buf,"none");
261706f2543Smrg    }
262706f2543Smrg    else {
263706f2543Smrg	char *str= buf;
264706f2543Smrg	buf[0]= '\0';
265706f2543Smrg	for (i=0,bit=1;i<XkbNumModifiers;i++,bit<<=1) {
266706f2543Smrg	    if (mask&bit) {
267706f2543Smrg		if (str!=buf) {
268706f2543Smrg		    if (format==XkbCFile)	*str++= '|';
269706f2543Smrg		    else			*str++= '+';
270706f2543Smrg		}
271706f2543Smrg		strcpy(str,modNames[i]);
272706f2543Smrg		str= &str[strlen(str)];
273706f2543Smrg		if (format==XkbCFile) {
274706f2543Smrg		    strcpy(str,"Mask");
275706f2543Smrg		    str+= 4;
276706f2543Smrg		}
277706f2543Smrg	    }
278706f2543Smrg	}
279706f2543Smrg    }
280706f2543Smrg    rtrn= tbGetBuffer(strlen(buf)+1);
281706f2543Smrg    strcpy(rtrn,buf);
282706f2543Smrg    return rtrn;
283706f2543Smrg}
284706f2543Smrg
285706f2543Smrg/***====================================================================***/
286706f2543Smrg
287706f2543Smrg/*ARGSUSED*/
288706f2543Smrgchar *
289706f2543SmrgXkbConfigText(unsigned config,unsigned format)
290706f2543Smrg{
291706f2543Smrgstatic char *buf;
292706f2543Smrg
293706f2543Smrg    buf= tbGetBuffer(32);
294706f2543Smrg    switch (config) {
295706f2543Smrg	case XkmSemanticsFile:
296706f2543Smrg	    strcpy(buf,"Semantics");
297706f2543Smrg	    break;
298706f2543Smrg	case XkmLayoutFile:
299706f2543Smrg	    strcpy(buf,"Layout");
300706f2543Smrg	    break;
301706f2543Smrg	case XkmKeymapFile:
302706f2543Smrg	    strcpy(buf,"Keymap");
303706f2543Smrg	    break;
304706f2543Smrg	case XkmGeometryFile:
305706f2543Smrg	case XkmGeometryIndex:
306706f2543Smrg	    strcpy(buf,"Geometry");
307706f2543Smrg	    break;
308706f2543Smrg	case XkmTypesIndex:
309706f2543Smrg	    strcpy(buf,"Types");
310706f2543Smrg	    break;
311706f2543Smrg	case XkmCompatMapIndex:
312706f2543Smrg	    strcpy(buf,"CompatMap");
313706f2543Smrg	    break;
314706f2543Smrg	case XkmSymbolsIndex:
315706f2543Smrg	    strcpy(buf,"Symbols");
316706f2543Smrg	    break;
317706f2543Smrg	case XkmIndicatorsIndex:
318706f2543Smrg	    strcpy(buf,"Indicators");
319706f2543Smrg	    break;
320706f2543Smrg	case XkmKeyNamesIndex:
321706f2543Smrg	    strcpy(buf,"KeyNames");
322706f2543Smrg	    break;
323706f2543Smrg	case XkmVirtualModsIndex:
324706f2543Smrg	    strcpy(buf,"VirtualMods");
325706f2543Smrg	    break;
326706f2543Smrg	default:
327706f2543Smrg	    sprintf(buf,"unknown(%d)",config);
328706f2543Smrg	    break;
329706f2543Smrg    }
330706f2543Smrg    return buf;
331706f2543Smrg}
332706f2543Smrg
333706f2543Smrg/***====================================================================***/
334706f2543Smrg
335706f2543Smrgchar *
336706f2543SmrgXkbKeysymText(KeySym sym,unsigned format)
337706f2543Smrg{
338706f2543Smrgstatic char buf[32],*rtrn;
339706f2543Smrg
340706f2543Smrg    if (sym==NoSymbol)
341706f2543Smrg	 strcpy(rtrn=buf,"NoSymbol");
342706f2543Smrg    else sprintf(rtrn=buf, "0x%lx", (long)sym);
343706f2543Smrg    return rtrn;
344706f2543Smrg}
345706f2543Smrg
346706f2543Smrgchar *
347706f2543SmrgXkbKeyNameText(char *name,unsigned format)
348706f2543Smrg{
349706f2543Smrgchar *buf;
350706f2543Smrg
351706f2543Smrg    if (format==XkbCFile) {
352706f2543Smrg	buf= tbGetBuffer(5);
353706f2543Smrg	memcpy(buf,name,4);
354706f2543Smrg	buf[4]= '\0';
355706f2543Smrg    }
356706f2543Smrg    else {
357706f2543Smrg	int len;
358706f2543Smrg	buf= tbGetBuffer(7);
359706f2543Smrg	buf[0]= '<';
360706f2543Smrg	memcpy(&buf[1],name,4);
361706f2543Smrg	buf[5]= '\0';
362706f2543Smrg	len= strlen(buf);
363706f2543Smrg	buf[len++]= '>';
364706f2543Smrg	buf[len]= '\0';
365706f2543Smrg    }
366706f2543Smrg    return buf;
367706f2543Smrg}
368706f2543Smrg
369706f2543Smrg/***====================================================================***/
370706f2543Smrg
371706f2543Smrgstatic char *siMatchText[5] = {
372706f2543Smrg	"NoneOf", "AnyOfOrNone", "AnyOf", "AllOf", "Exactly"
373706f2543Smrg};
374706f2543Smrg
375706f2543Smrgchar *
376706f2543SmrgXkbSIMatchText(unsigned type,unsigned format)
377706f2543Smrg{
378706f2543Smrgstatic char buf[40];
379706f2543Smrgchar *rtrn;
380706f2543Smrg
381706f2543Smrg    switch (type&XkbSI_OpMask) {
382706f2543Smrg	case XkbSI_NoneOf:	rtrn= siMatchText[0]; break;
383706f2543Smrg	case XkbSI_AnyOfOrNone:	rtrn= siMatchText[1]; break;
384706f2543Smrg	case XkbSI_AnyOf:	rtrn= siMatchText[2]; break;
385706f2543Smrg	case XkbSI_AllOf:	rtrn= siMatchText[3]; break;
386706f2543Smrg	case XkbSI_Exactly:	rtrn= siMatchText[4]; break;
387706f2543Smrg	default:		sprintf(buf,"0x%x",type&XkbSI_OpMask);
388706f2543Smrg				return buf;
389706f2543Smrg    }
390706f2543Smrg    if (format==XkbCFile) {
391706f2543Smrg	if (type&XkbSI_LevelOneOnly)
392706f2543Smrg	     sprintf(buf,"XkbSI_LevelOneOnly|XkbSI_%s",rtrn);
393706f2543Smrg	else sprintf(buf,"XkbSI_%s",rtrn);
394706f2543Smrg	rtrn= buf;
395706f2543Smrg    }
396706f2543Smrg    return rtrn;
397706f2543Smrg}
398706f2543Smrg
399706f2543Smrg/***====================================================================***/
400706f2543Smrg
401706f2543Smrgstatic char *imWhichNames[]= {
402706f2543Smrg	"base",
403706f2543Smrg	"latched",
404706f2543Smrg	"locked",
405706f2543Smrg	"effective",
406706f2543Smrg	"compat"
407706f2543Smrg};
408706f2543Smrg
409706f2543Smrgchar *
410706f2543SmrgXkbIMWhichStateMaskText(unsigned use_which,unsigned format)
411706f2543Smrg{
412706f2543Smrgint		len;
413706f2543Smrgunsigned	i,bit,tmp;
414706f2543Smrgchar *		buf;
415706f2543Smrg
416706f2543Smrg    if (use_which==0) {
417706f2543Smrg	buf= tbGetBuffer(2);
418706f2543Smrg	strcpy(buf,"0");
419706f2543Smrg	return buf;
420706f2543Smrg    }
421706f2543Smrg    tmp= use_which&XkbIM_UseAnyMods;
422706f2543Smrg    for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) {
423706f2543Smrg	if (tmp&bit) {
424706f2543Smrg	    tmp&= ~bit;
425706f2543Smrg	    len+= strlen(imWhichNames[i])+1;
426706f2543Smrg	    if (format==XkbCFile)
427706f2543Smrg		len+= 9;
428706f2543Smrg	}
429706f2543Smrg    }
430706f2543Smrg    buf= tbGetBuffer(len+1);
431706f2543Smrg    tmp= use_which&XkbIM_UseAnyMods;
432706f2543Smrg    for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) {
433706f2543Smrg	if (tmp&bit) {
434706f2543Smrg	    tmp&= ~bit;
435706f2543Smrg	    if (format==XkbCFile) {
436706f2543Smrg		if (len!=0)
437706f2543Smrg		    buf[len++]= '|';
438706f2543Smrg		sprintf(&buf[len],"XkbIM_Use%s",imWhichNames[i]);
439706f2543Smrg		buf[len+9]= toupper(buf[len+9]);
440706f2543Smrg	    }
441706f2543Smrg	    else {
442706f2543Smrg		if (len!=0)
443706f2543Smrg		    buf[len++]= '+';
444706f2543Smrg		sprintf(&buf[len],"%s",imWhichNames[i]);
445706f2543Smrg	    }
446706f2543Smrg	    len+= strlen(&buf[len]);
447706f2543Smrg	}
448706f2543Smrg    }
449706f2543Smrg    return buf;
450706f2543Smrg}
451706f2543Smrg
452706f2543Smrgstatic char *ctrlNames[] = {
453706f2543Smrg	"repeatKeys",
454706f2543Smrg	"slowKeys",
455706f2543Smrg	"bounceKeys",
456706f2543Smrg	"stickyKeys",
457706f2543Smrg	"mouseKeys",
458706f2543Smrg	"mouseKeysAccel",
459706f2543Smrg	"accessXKeys",
460706f2543Smrg	"accessXTimeout",
461706f2543Smrg	"accessXFeedback",
462706f2543Smrg	"audibleBell",
463706f2543Smrg	"overlay1",
464706f2543Smrg	"overlay2",
465706f2543Smrg	"ignoreGroupLock"
466706f2543Smrg};
467706f2543Smrg
468706f2543Smrgchar *
469706f2543SmrgXkbControlsMaskText(unsigned ctrls,unsigned format)
470706f2543Smrg{
471706f2543Smrgint		len;
472706f2543Smrgunsigned	i,bit,tmp;
473706f2543Smrgchar *		buf;
474706f2543Smrg
475706f2543Smrg    if (ctrls==0) {
476706f2543Smrg	buf= tbGetBuffer(5);
477706f2543Smrg	if (format==XkbCFile)
478706f2543Smrg	     strcpy(buf,"0");
479706f2543Smrg	else strcpy(buf,"none");
480706f2543Smrg	return buf;
481706f2543Smrg    }
482706f2543Smrg    tmp= ctrls&XkbAllBooleanCtrlsMask;
483706f2543Smrg    for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) {
484706f2543Smrg	if (tmp&bit) {
485706f2543Smrg	    tmp&= ~bit;
486706f2543Smrg	    len+= strlen(ctrlNames[i])+1;
487706f2543Smrg	    if (format==XkbCFile)
488706f2543Smrg		len+= 7;
489706f2543Smrg	}
490706f2543Smrg    }
491706f2543Smrg    buf= tbGetBuffer(len+1);
492706f2543Smrg    tmp= ctrls&XkbAllBooleanCtrlsMask;
493706f2543Smrg    for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) {
494706f2543Smrg	if (tmp&bit) {
495706f2543Smrg	    tmp&= ~bit;
496706f2543Smrg	    if (format==XkbCFile) {
497706f2543Smrg		if (len!=0)
498706f2543Smrg		    buf[len++]= '|';
499706f2543Smrg		sprintf(&buf[len],"Xkb%sMask",ctrlNames[i]);
500706f2543Smrg		buf[len+3]= toupper(buf[len+3]);
501706f2543Smrg	    }
502706f2543Smrg	    else {
503706f2543Smrg		if (len!=0)
504706f2543Smrg		    buf[len++]= '+';
505706f2543Smrg		sprintf(&buf[len],"%s",ctrlNames[i]);
506706f2543Smrg	    }
507706f2543Smrg	    len+= strlen(&buf[len]);
508706f2543Smrg	}
509706f2543Smrg    }
510706f2543Smrg    return buf;
511706f2543Smrg}
512706f2543Smrg
513706f2543Smrg/***====================================================================***/
514706f2543Smrg
515706f2543Smrgchar *
516706f2543SmrgXkbStringText(char *str,unsigned format)
517706f2543Smrg{
518706f2543Smrgchar *	buf;
519706f2543Smrgregister char *in,*out;
520706f2543Smrgint	len;
521706f2543SmrgBool	ok;
522706f2543Smrg
523706f2543Smrg    if (str==NULL) {
524706f2543Smrg	buf= tbGetBuffer(2);
525706f2543Smrg	buf[0]='\0';
526706f2543Smrg	return buf;
527706f2543Smrg    }
528706f2543Smrg    else if (format==XkbXKMFile)
529706f2543Smrg	return str;
530706f2543Smrg    for (ok= TRUE,len=0,in=str;*in!='\0';in++,len++) {
531706f2543Smrg	if (!isprint(*in)) {
532706f2543Smrg	    ok= FALSE;
533706f2543Smrg	    switch (*in) {
534706f2543Smrg		case '\n': case '\t': case '\v':
535706f2543Smrg		case '\b': case '\r': case '\f':
536706f2543Smrg		    len++;
537706f2543Smrg		    break;
538706f2543Smrg		default:
539706f2543Smrg		    len+= 4;
540706f2543Smrg		    break;
541706f2543Smrg	    }
542706f2543Smrg	}
543706f2543Smrg    }
544706f2543Smrg    if (ok)
545706f2543Smrg	return str;
546706f2543Smrg    buf= tbGetBuffer(len+1);
547706f2543Smrg    for (in=str,out=buf;*in!='\0';in++) {
548706f2543Smrg	if (isprint(*in))
549706f2543Smrg	    *out++= *in;
550706f2543Smrg	else {
551706f2543Smrg	    *out++= '\\';
552706f2543Smrg	    if (*in=='\n')	*out++= 'n';
553706f2543Smrg	    else if (*in=='\t')	*out++= 't';
554706f2543Smrg	    else if (*in=='\v')	*out++= 'v';
555706f2543Smrg	    else if (*in=='\b')	*out++= 'b';
556706f2543Smrg	    else if (*in=='\r')	*out++= 'r';
557706f2543Smrg	    else if (*in=='\f')	*out++= 'f';
558706f2543Smrg	    else if ((*in=='\033')&&(format==XkbXKMFile)) {
559706f2543Smrg		*out++= 'e';
560706f2543Smrg	    }
561706f2543Smrg	    else {
562706f2543Smrg		*out++= '0';
563706f2543Smrg		sprintf(out,"%o",*in);
564706f2543Smrg		while (*out!='\0')
565706f2543Smrg		    out++;
566706f2543Smrg	    }
567706f2543Smrg	}
568706f2543Smrg    }
569706f2543Smrg    *out++= '\0';
570706f2543Smrg    return buf;
571706f2543Smrg}
572706f2543Smrg
573706f2543Smrg/***====================================================================***/
574706f2543Smrg
575706f2543Smrgchar *
576706f2543SmrgXkbGeomFPText(int val,unsigned format)
577706f2543Smrg{
578706f2543Smrgint	whole,frac;
579706f2543Smrgchar *	buf;
580706f2543Smrg
581706f2543Smrg    buf= tbGetBuffer(12);
582706f2543Smrg    if (format==XkbCFile) {
583706f2543Smrg	sprintf(buf,"%d",val);
584706f2543Smrg    }
585706f2543Smrg    else {
586706f2543Smrg	whole= val/XkbGeomPtsPerMM;
587706f2543Smrg	frac= val%XkbGeomPtsPerMM;
588706f2543Smrg	if (frac!=0)
589706f2543Smrg	     sprintf(buf,"%d.%d",whole,frac);
590706f2543Smrg	else sprintf(buf,"%d",whole);
591706f2543Smrg    }
592706f2543Smrg    return buf;
593706f2543Smrg}
594706f2543Smrg
595706f2543Smrgchar *
596706f2543SmrgXkbDoodadTypeText(unsigned type,unsigned format)
597706f2543Smrg{
598706f2543Smrgchar *	buf;
599706f2543Smrg    if (format==XkbCFile) {
600706f2543Smrg	buf= tbGetBuffer(24);
601706f2543Smrg	if (type==XkbOutlineDoodad)	   strcpy(buf,"XkbOutlineDoodad");
602706f2543Smrg	else if (type==XkbSolidDoodad)	   strcpy(buf,"XkbSolidDoodad");
603706f2543Smrg	else if (type==XkbTextDoodad)	   strcpy(buf,"XkbTextDoodad");
604706f2543Smrg	else if (type==XkbIndicatorDoodad) strcpy(buf,"XkbIndicatorDoodad");
605706f2543Smrg	else if (type==XkbLogoDoodad)	   strcpy(buf,"XkbLogoDoodad");
606706f2543Smrg	else				   sprintf(buf,"UnknownDoodad%d",type);
607706f2543Smrg    }
608706f2543Smrg    else {
609706f2543Smrg	buf= tbGetBuffer(12);
610706f2543Smrg	if (type==XkbOutlineDoodad)	   strcpy(buf,"outline");
611706f2543Smrg	else if (type==XkbSolidDoodad)	   strcpy(buf,"solid");
612706f2543Smrg	else if (type==XkbTextDoodad)	   strcpy(buf,"text");
613706f2543Smrg	else if (type==XkbIndicatorDoodad) strcpy(buf,"indicator");
614706f2543Smrg	else if (type==XkbLogoDoodad)	   strcpy(buf,"logo");
615706f2543Smrg	else				   sprintf(buf,"unknown%d",type);
616706f2543Smrg    }
617706f2543Smrg    return buf;
618706f2543Smrg}
619706f2543Smrg
620706f2543Smrgstatic char *actionTypeNames[XkbSA_NumActions]= {
621706f2543Smrg    "NoAction",
622706f2543Smrg    "SetMods",      "LatchMods",    "LockMods",
623706f2543Smrg    "SetGroup",     "LatchGroup",   "LockGroup",
624706f2543Smrg    "MovePtr",
625706f2543Smrg    "PtrBtn",       "LockPtrBtn",
626706f2543Smrg    "SetPtrDflt",
627706f2543Smrg    "ISOLock",
628706f2543Smrg    "Terminate",    "SwitchScreen",
629706f2543Smrg    "SetControls",  "LockControls",
630706f2543Smrg    "ActionMessage",
631706f2543Smrg    "RedirectKey",
632706f2543Smrg    "DeviceBtn",    "LockDeviceBtn"
633706f2543Smrg};
634706f2543Smrg
635706f2543Smrgchar *
636706f2543SmrgXkbActionTypeText(unsigned type,unsigned format)
637706f2543Smrg{
638706f2543Smrgstatic char buf[32];
639706f2543Smrgchar *rtrn;
640706f2543Smrg
641706f2543Smrg    if (type<=XkbSA_LastAction) {
642706f2543Smrg	rtrn= actionTypeNames[type];
643706f2543Smrg	if (format==XkbCFile) {
644706f2543Smrg	    sprintf(buf,"XkbSA_%s",rtrn);
645706f2543Smrg	    return buf;
646706f2543Smrg	}
647706f2543Smrg	return rtrn;
648706f2543Smrg    }
649706f2543Smrg    sprintf(buf,"Private");
650706f2543Smrg    return buf;
651706f2543Smrg}
652706f2543Smrg
653706f2543Smrg/***====================================================================***/
654706f2543Smrg
655706f2543Smrgstatic int
656706f2543SmrgTryCopyStr(char *to,char *from,int *pLeft)
657706f2543Smrg{
658706f2543Smrgregister int len;
659706f2543Smrg    if (*pLeft>0) {
660706f2543Smrg	len= strlen(from);
661706f2543Smrg	if (len<((*pLeft)-3)) {
662706f2543Smrg	    strcat(to,from);
663706f2543Smrg	    *pLeft-= len;
664706f2543Smrg	    return TRUE;
665706f2543Smrg	}
666706f2543Smrg    }
667706f2543Smrg    *pLeft= -1;
668706f2543Smrg    return FALSE;
669706f2543Smrg}
670706f2543Smrg
671706f2543Smrg/*ARGSUSED*/
672706f2543Smrgstatic Bool
673706f2543SmrgCopyNoActionArgs(XkbDescPtr xkb,XkbAction *action,char *buf,int*sz)
674706f2543Smrg{
675706f2543Smrg    return TRUE;
676706f2543Smrg}
677706f2543Smrg
678706f2543Smrgstatic Bool
679706f2543SmrgCopyModActionArgs(XkbDescPtr xkb,XkbAction *action,char *buf,
680706f2543Smrg								int* sz)
681706f2543Smrg{
682706f2543SmrgXkbModAction *	act;
683706f2543Smrgunsigned	tmp;
684706f2543Smrg
685706f2543Smrg    act= &action->mods;
686706f2543Smrg    tmp= XkbModActionVMods(act);
687706f2543Smrg    TryCopyStr(buf,"modifiers=",sz);
688706f2543Smrg    if (act->flags&XkbSA_UseModMapMods)
689706f2543Smrg	  TryCopyStr(buf,"modMapMods",sz);
690706f2543Smrg    else if (act->real_mods || tmp) {
691706f2543Smrg	 TryCopyStr(buf,
692706f2543Smrg		     XkbVModMaskText(xkb,act->real_mods,tmp,XkbXKBFile),
693706f2543Smrg		     sz);
694706f2543Smrg    }
695706f2543Smrg    else TryCopyStr(buf,"none",sz);
696706f2543Smrg    if (act->type==XkbSA_LockMods)
697706f2543Smrg	return TRUE;
698706f2543Smrg    if (act->flags&XkbSA_ClearLocks)
699706f2543Smrg	TryCopyStr(buf,",clearLocks",sz);
700706f2543Smrg    if (act->flags&XkbSA_LatchToLock)
701706f2543Smrg	TryCopyStr(buf,",latchToLock",sz);
702706f2543Smrg    return TRUE;
703706f2543Smrg}
704706f2543Smrg
705706f2543Smrg/*ARGSUSED*/
706706f2543Smrgstatic Bool
707706f2543SmrgCopyGroupActionArgs(XkbDescPtr xkb,XkbAction *action,char *buf,
708706f2543Smrg								int *sz)
709706f2543Smrg{
710706f2543SmrgXkbGroupAction *	act;
711706f2543Smrgchar			tbuf[32];
712706f2543Smrg
713706f2543Smrg    act= &action->group;
714706f2543Smrg    TryCopyStr(buf,"group=",sz);
715706f2543Smrg    if (act->flags&XkbSA_GroupAbsolute)
716706f2543Smrg	 sprintf(tbuf,"%d",XkbSAGroup(act)+1);
717706f2543Smrg    else if (XkbSAGroup(act)<0)
718706f2543Smrg	 sprintf(tbuf,"%d",XkbSAGroup(act));
719706f2543Smrg    else sprintf(tbuf,"+%d",XkbSAGroup(act));
720706f2543Smrg    TryCopyStr(buf,tbuf,sz);
721706f2543Smrg    if (act->type==XkbSA_LockGroup)
722706f2543Smrg	return TRUE;
723706f2543Smrg    if (act->flags&XkbSA_ClearLocks)
724706f2543Smrg	TryCopyStr(buf,",clearLocks",sz);
725706f2543Smrg    if (act->flags&XkbSA_LatchToLock)
726706f2543Smrg	TryCopyStr(buf,",latchToLock",sz);
727706f2543Smrg    return TRUE;
728706f2543Smrg}
729706f2543Smrg
730706f2543Smrg/*ARGSUSED*/
731706f2543Smrgstatic Bool
732706f2543SmrgCopyMovePtrArgs(XkbDescPtr xkb,XkbAction *action,char *buf,int *sz)
733706f2543Smrg{
734706f2543SmrgXkbPtrAction *	act;
735706f2543Smrgint		x,y;
736706f2543Smrgchar		tbuf[32];
737706f2543Smrg
738706f2543Smrg    act= &action->ptr;
739706f2543Smrg    x= XkbPtrActionX(act);
740706f2543Smrg    y= XkbPtrActionY(act);
741706f2543Smrg    if ((act->flags&XkbSA_MoveAbsoluteX)||(x<0))
742706f2543Smrg	 sprintf(tbuf,"x=%d",x);
743706f2543Smrg    else sprintf(tbuf,"x=+%d",x);
744706f2543Smrg    TryCopyStr(buf,tbuf,sz);
745706f2543Smrg
746706f2543Smrg    if ((act->flags&XkbSA_MoveAbsoluteY)||(y<0))
747706f2543Smrg	 sprintf(tbuf,",y=%d",y);
748706f2543Smrg    else sprintf(tbuf,",y=+%d",y);
749706f2543Smrg    TryCopyStr(buf,tbuf,sz);
750706f2543Smrg    if (act->flags&XkbSA_NoAcceleration)
751706f2543Smrg	TryCopyStr(buf,",!accel",sz);
752706f2543Smrg    return TRUE;
753706f2543Smrg}
754706f2543Smrg
755706f2543Smrg/*ARGSUSED*/
756706f2543Smrgstatic Bool
757706f2543SmrgCopyPtrBtnArgs(XkbDescPtr xkb,XkbAction *action,char *buf,int *sz)
758706f2543Smrg{
759706f2543SmrgXkbPtrBtnAction *	act;
760706f2543Smrgchar			tbuf[32];
761706f2543Smrg
762706f2543Smrg    act= &action->btn;
763706f2543Smrg    TryCopyStr(buf,"button=",sz);
764706f2543Smrg    if ((act->button>0)&&(act->button<6)) {
765706f2543Smrg	 sprintf(tbuf,"%d",act->button);
766706f2543Smrg	 TryCopyStr(buf,tbuf,sz);
767706f2543Smrg    }
768706f2543Smrg    else TryCopyStr(buf,"default",sz);
769706f2543Smrg    if (act->count>0) {
770706f2543Smrg	sprintf(tbuf,",count=%d",act->count);
771706f2543Smrg	TryCopyStr(buf,tbuf,sz);
772706f2543Smrg    }
773706f2543Smrg    if (action->type==XkbSA_LockPtrBtn) {
774706f2543Smrg	switch (act->flags&(XkbSA_LockNoUnlock|XkbSA_LockNoLock)) {
775706f2543Smrg	    case XkbSA_LockNoLock:
776706f2543Smrg		sprintf(tbuf,",affect=unlock"); break;
777706f2543Smrg	    case XkbSA_LockNoUnlock:
778706f2543Smrg		sprintf(tbuf,",affect=lock"); break;
779706f2543Smrg	    case XkbSA_LockNoUnlock|XkbSA_LockNoLock:
780706f2543Smrg		sprintf(tbuf,",affect=neither"); break;
781706f2543Smrg	    default:
782706f2543Smrg		sprintf(tbuf,",affect=both"); break;
783706f2543Smrg	}
784706f2543Smrg	TryCopyStr(buf,tbuf,sz);
785706f2543Smrg    }
786706f2543Smrg    return TRUE;
787706f2543Smrg}
788706f2543Smrg
789706f2543Smrg/*ARGSUSED*/
790706f2543Smrgstatic Bool
791706f2543SmrgCopySetPtrDfltArgs(XkbDescPtr xkb,XkbAction *action,char *buf,
792706f2543Smrg								int *sz)
793706f2543Smrg{
794706f2543SmrgXkbPtrDfltAction *	act;
795706f2543Smrgchar			tbuf[32];
796706f2543Smrg
797706f2543Smrg    act= &action->dflt;
798706f2543Smrg    if (act->affect==XkbSA_AffectDfltBtn) {
799706f2543Smrg	TryCopyStr(buf,"affect=button,button=",sz);
800706f2543Smrg	if ((act->flags&XkbSA_DfltBtnAbsolute)||(XkbSAPtrDfltValue(act)<0))
801706f2543Smrg	     sprintf(tbuf,"%d",XkbSAPtrDfltValue(act));
802706f2543Smrg	else sprintf(tbuf,"+%d",XkbSAPtrDfltValue(act));
803706f2543Smrg	TryCopyStr(buf,tbuf,sz);
804706f2543Smrg    }
805706f2543Smrg    return TRUE;
806706f2543Smrg}
807706f2543Smrg
808706f2543Smrgstatic Bool
809706f2543SmrgCopyISOLockArgs(XkbDescPtr xkb,XkbAction *action,char *buf,int *sz)
810706f2543Smrg{
811706f2543SmrgXkbISOAction *	act;
812706f2543Smrgchar		tbuf[64];
813706f2543Smrg
814706f2543Smrg    act= &action->iso;
815706f2543Smrg    if (act->flags&XkbSA_ISODfltIsGroup) {
816706f2543Smrg	TryCopyStr(tbuf,"group=",sz);
817706f2543Smrg	if (act->flags&XkbSA_GroupAbsolute)
818706f2543Smrg	     sprintf(tbuf,"%d",XkbSAGroup(act)+1);
819706f2543Smrg	else if (XkbSAGroup(act)<0)
820706f2543Smrg	     sprintf(tbuf,"%d",XkbSAGroup(act));
821706f2543Smrg	else sprintf(tbuf,"+%d",XkbSAGroup(act));
822706f2543Smrg	TryCopyStr(buf,tbuf,sz);
823706f2543Smrg    }
824706f2543Smrg    else {
825706f2543Smrg	unsigned tmp;
826706f2543Smrg	tmp= XkbModActionVMods(act);
827706f2543Smrg	TryCopyStr(buf,"modifiers=",sz);
828706f2543Smrg	if (act->flags&XkbSA_UseModMapMods)
829706f2543Smrg	     TryCopyStr(buf,"modMapMods",sz);
830706f2543Smrg	else if (act->real_mods || tmp) {
831706f2543Smrg	    if (act->real_mods) {
832706f2543Smrg		TryCopyStr(buf,XkbModMaskText(act->real_mods,XkbXKBFile),sz);
833706f2543Smrg		if (tmp)
834706f2543Smrg		    TryCopyStr(buf,"+",sz);
835706f2543Smrg	    }
836706f2543Smrg	    if (tmp)
837706f2543Smrg		TryCopyStr(buf,XkbVModMaskText(xkb,0,tmp,XkbXKBFile),sz);
838706f2543Smrg	}
839706f2543Smrg	else TryCopyStr(buf,"none",sz);
840706f2543Smrg    }
841706f2543Smrg    TryCopyStr(buf,",affect=",sz);
842706f2543Smrg    if ((act->affect&XkbSA_ISOAffectMask)==0)
843706f2543Smrg	TryCopyStr(buf,"all",sz);
844706f2543Smrg    else {
845706f2543Smrg	int nOut= 0;
846706f2543Smrg	if ((act->affect&XkbSA_ISONoAffectMods)==0) {
847706f2543Smrg	    TryCopyStr(buf,"mods",sz);
848706f2543Smrg	    nOut++;
849706f2543Smrg	}
850706f2543Smrg	if ((act->affect&XkbSA_ISONoAffectGroup)==0) {
851706f2543Smrg	    sprintf(tbuf,"%sgroups",(nOut>0?"+":""));
852706f2543Smrg	    TryCopyStr(buf,tbuf,sz);
853706f2543Smrg	    nOut++;
854706f2543Smrg	}
855706f2543Smrg	if ((act->affect&XkbSA_ISONoAffectPtr)==0) {
856706f2543Smrg	    sprintf(tbuf,"%spointer",(nOut>0?"+":""));
857706f2543Smrg	    TryCopyStr(buf,tbuf,sz);
858706f2543Smrg	    nOut++;
859706f2543Smrg	}
860706f2543Smrg	if ((act->affect&XkbSA_ISONoAffectCtrls)==0) {
861706f2543Smrg	    sprintf(tbuf,"%scontrols",(nOut>0?"+":""));
862706f2543Smrg	    TryCopyStr(buf,tbuf,sz);
863706f2543Smrg	    nOut++;
864706f2543Smrg	}
865706f2543Smrg    }
866706f2543Smrg    return TRUE;
867706f2543Smrg}
868706f2543Smrg
869706f2543Smrg/*ARGSUSED*/
870706f2543Smrgstatic Bool
871706f2543SmrgCopySwitchScreenArgs(XkbDescPtr xkb,XkbAction *action,char *buf,
872706f2543Smrg								int *sz)
873706f2543Smrg{
874706f2543SmrgXkbSwitchScreenAction *	act;
875706f2543Smrgchar			tbuf[32];
876706f2543Smrg
877706f2543Smrg    act= &action->screen;
878706f2543Smrg    if ((act->flags&XkbSA_SwitchAbsolute)||(XkbSAScreen(act)<0))
879706f2543Smrg	 sprintf(tbuf,"screen=%d",XkbSAScreen(act));
880706f2543Smrg    else sprintf(tbuf,"screen=+%d",XkbSAScreen(act));
881706f2543Smrg    TryCopyStr(buf,tbuf,sz);
882706f2543Smrg    if (act->flags&XkbSA_SwitchApplication)
883706f2543Smrg	 TryCopyStr(buf,",!same",sz);
884706f2543Smrg    else TryCopyStr(buf,",same",sz);
885706f2543Smrg    return TRUE;
886706f2543Smrg}
887706f2543Smrg
888706f2543Smrg/*ARGSUSED*/
889706f2543Smrgstatic Bool
890706f2543SmrgCopySetLockControlsArgs(XkbDescPtr xkb,XkbAction *action,
891706f2543Smrg							char *buf,int *sz)
892706f2543Smrg{
893706f2543SmrgXkbCtrlsAction *	act;
894706f2543Smrgunsigned		tmp;
895706f2543Smrgchar			tbuf[32];
896706f2543Smrg
897706f2543Smrg    act= &action->ctrls;
898706f2543Smrg    tmp= XkbActionCtrls(act);
899706f2543Smrg    TryCopyStr(buf,"controls=",sz);
900706f2543Smrg    if (tmp==0)
901706f2543Smrg	TryCopyStr(buf,"none",sz);
902706f2543Smrg    else if ((tmp&XkbAllBooleanCtrlsMask)==XkbAllBooleanCtrlsMask)
903706f2543Smrg	TryCopyStr(buf,"all",sz);
904706f2543Smrg    else {
905706f2543Smrg	int nOut= 0;
906706f2543Smrg	if (tmp&XkbRepeatKeysMask) {
907706f2543Smrg	    sprintf(tbuf,"%sRepeatKeys",(nOut>0?"+":""));
908706f2543Smrg	    TryCopyStr(buf,tbuf,sz);
909706f2543Smrg	    nOut++;
910706f2543Smrg	}
911706f2543Smrg	if (tmp&XkbSlowKeysMask) {
912706f2543Smrg	    sprintf(tbuf,"%sSlowKeys",(nOut>0?"+":""));
913706f2543Smrg	    TryCopyStr(buf,tbuf,sz);
914706f2543Smrg	    nOut++;
915706f2543Smrg	}
916706f2543Smrg	if (tmp&XkbBounceKeysMask) {
917706f2543Smrg	    sprintf(tbuf,"%sBounceKeys",(nOut>0?"+":""));
918706f2543Smrg	    TryCopyStr(buf,tbuf,sz);
919706f2543Smrg	    nOut++;
920706f2543Smrg	}
921706f2543Smrg	if (tmp&XkbStickyKeysMask) {
922706f2543Smrg	    sprintf(tbuf,"%sStickyKeys",(nOut>0?"+":""));
923706f2543Smrg	    TryCopyStr(buf,tbuf,sz);
924706f2543Smrg	    nOut++;
925706f2543Smrg	}
926706f2543Smrg	if (tmp&XkbMouseKeysMask) {
927706f2543Smrg	    sprintf(tbuf,"%sMouseKeys",(nOut>0?"+":""));
928706f2543Smrg	    TryCopyStr(buf,tbuf,sz);
929706f2543Smrg	    nOut++;
930706f2543Smrg	}
931706f2543Smrg	if (tmp&XkbMouseKeysAccelMask) {
932706f2543Smrg	    sprintf(tbuf,"%sMouseKeysAccel",(nOut>0?"+":""));
933706f2543Smrg	    TryCopyStr(buf,tbuf,sz);
934706f2543Smrg	    nOut++;
935706f2543Smrg	}
936706f2543Smrg	if (tmp&XkbAccessXKeysMask) {
937706f2543Smrg	    sprintf(tbuf,"%sAccessXKeys",(nOut>0?"+":""));
938706f2543Smrg	    TryCopyStr(buf,tbuf,sz);
939706f2543Smrg	    nOut++;
940706f2543Smrg	}
941706f2543Smrg	if (tmp&XkbAccessXTimeoutMask) {
942706f2543Smrg	    sprintf(tbuf,"%sAccessXTimeout",(nOut>0?"+":""));
943706f2543Smrg	    TryCopyStr(buf,tbuf,sz);
944706f2543Smrg	    nOut++;
945706f2543Smrg	}
946706f2543Smrg	if (tmp&XkbAccessXFeedbackMask) {
947706f2543Smrg	    sprintf(tbuf,"%sAccessXFeedback",(nOut>0?"+":""));
948706f2543Smrg	    TryCopyStr(buf,tbuf,sz);
949706f2543Smrg	    nOut++;
950706f2543Smrg	}
951706f2543Smrg	if (tmp&XkbAudibleBellMask) {
952706f2543Smrg	    sprintf(tbuf,"%sAudibleBell",(nOut>0?"+":""));
953706f2543Smrg	    TryCopyStr(buf,tbuf,sz);
954706f2543Smrg	    nOut++;
955706f2543Smrg	}
956706f2543Smrg	if (tmp&XkbOverlay1Mask) {
957706f2543Smrg	    sprintf(tbuf,"%sOverlay1",(nOut>0?"+":""));
958706f2543Smrg	    TryCopyStr(buf,tbuf,sz);
959706f2543Smrg	    nOut++;
960706f2543Smrg	}
961706f2543Smrg	if (tmp&XkbOverlay2Mask) {
962706f2543Smrg	    sprintf(tbuf,"%sOverlay2",(nOut>0?"+":""));
963706f2543Smrg	    TryCopyStr(buf,tbuf,sz);
964706f2543Smrg	    nOut++;
965706f2543Smrg	}
966706f2543Smrg	if (tmp&XkbIgnoreGroupLockMask) {
967706f2543Smrg	    sprintf(tbuf,"%sIgnoreGroupLock",(nOut>0?"+":""));
968706f2543Smrg	    TryCopyStr(buf,tbuf,sz);
969706f2543Smrg	    nOut++;
970706f2543Smrg	}
971706f2543Smrg    }
972706f2543Smrg    return TRUE;
973706f2543Smrg}
974706f2543Smrg
975706f2543Smrg/*ARGSUSED*/
976706f2543Smrgstatic Bool
977706f2543SmrgCopyActionMessageArgs(XkbDescPtr xkb,XkbAction *action,char *buf,
978706f2543Smrg								int *sz)
979706f2543Smrg{
980706f2543SmrgXkbMessageAction *	act;
981706f2543Smrgunsigned		all;
982706f2543Smrgchar			tbuf[32];
983706f2543Smrg
984706f2543Smrg    act= &action->msg;
985706f2543Smrg    all= XkbSA_MessageOnPress|XkbSA_MessageOnRelease;
986706f2543Smrg    TryCopyStr(buf,"report=",sz);
987706f2543Smrg    if ((act->flags&all)==0)
988706f2543Smrg	TryCopyStr(buf,"none",sz);
989706f2543Smrg    else if ((act->flags&all)==all)
990706f2543Smrg	TryCopyStr(buf,"all",sz);
991706f2543Smrg    else if (act->flags&XkbSA_MessageOnPress)
992706f2543Smrg	 TryCopyStr(buf,"KeyPress",sz);
993706f2543Smrg    else TryCopyStr(buf,"KeyRelease",sz);
994706f2543Smrg    sprintf(tbuf,",data[0]=0x%02x",act->message[0]); TryCopyStr(buf,tbuf,sz);
995706f2543Smrg    sprintf(tbuf,",data[1]=0x%02x",act->message[1]); TryCopyStr(buf,tbuf,sz);
996706f2543Smrg    sprintf(tbuf,",data[2]=0x%02x",act->message[2]); TryCopyStr(buf,tbuf,sz);
997706f2543Smrg    sprintf(tbuf,",data[3]=0x%02x",act->message[3]); TryCopyStr(buf,tbuf,sz);
998706f2543Smrg    sprintf(tbuf,",data[4]=0x%02x",act->message[4]); TryCopyStr(buf,tbuf,sz);
999706f2543Smrg    sprintf(tbuf,",data[5]=0x%02x",act->message[5]); TryCopyStr(buf,tbuf,sz);
1000706f2543Smrg    return TRUE;
1001706f2543Smrg}
1002706f2543Smrg
1003706f2543Smrgstatic Bool
1004706f2543SmrgCopyRedirectKeyArgs(XkbDescPtr xkb,XkbAction *action,char *buf,
1005706f2543Smrg								int *sz)
1006706f2543Smrg{
1007706f2543SmrgXkbRedirectKeyAction *	act;
1008706f2543Smrgchar			tbuf[32],*tmp;
1009706f2543Smrgunsigned		kc;
1010706f2543Smrgunsigned		vmods,vmods_mask;
1011706f2543Smrg
1012706f2543Smrg    act= &action->redirect;
1013706f2543Smrg    kc= act->new_key;
1014706f2543Smrg    vmods= XkbSARedirectVMods(act);
1015706f2543Smrg    vmods_mask= XkbSARedirectVModsMask(act);
1016706f2543Smrg    if (xkb && xkb->names && xkb->names->keys && (kc<=xkb->max_key_code) &&
1017706f2543Smrg				(xkb->names->keys[kc].name[0]!='\0')) {
1018706f2543Smrg	char *kn;
1019706f2543Smrg	kn= XkbKeyNameText(xkb->names->keys[kc].name,XkbXKBFile);
1020706f2543Smrg	sprintf(tbuf,"key=%s",kn);
1021706f2543Smrg    }
1022706f2543Smrg    else sprintf(tbuf,"key=%d",kc);
1023706f2543Smrg    TryCopyStr(buf,tbuf,sz);
1024706f2543Smrg    if ((act->mods_mask==0)&&(vmods_mask==0))
1025706f2543Smrg	return TRUE;
1026706f2543Smrg    if ((act->mods_mask==XkbAllModifiersMask)&&
1027706f2543Smrg	(vmods_mask==XkbAllVirtualModsMask)) {
1028706f2543Smrg	tmp= XkbVModMaskText(xkb,act->mods,vmods,XkbXKBFile);
1029706f2543Smrg	TryCopyStr(buf,",mods=",sz);
1030706f2543Smrg	TryCopyStr(buf,tmp,sz);
1031706f2543Smrg    }
1032706f2543Smrg    else {
1033706f2543Smrg	if ((act->mods_mask&act->mods)||(vmods_mask&vmods)) {
1034706f2543Smrg	    tmp= XkbVModMaskText(xkb,act->mods_mask&act->mods,
1035706f2543Smrg					 vmods_mask&vmods,XkbXKBFile);
1036706f2543Smrg	    TryCopyStr(buf,",mods= ",sz);
1037706f2543Smrg	    TryCopyStr(buf,tmp,sz);
1038706f2543Smrg	}
1039706f2543Smrg	if ((act->mods_mask&(~act->mods))||(vmods_mask&(~vmods))) {
1040706f2543Smrg	    tmp= XkbVModMaskText(xkb,act->mods_mask&(~act->mods),
1041706f2543Smrg					 vmods_mask&(~vmods),XkbXKBFile);
1042706f2543Smrg	    TryCopyStr(buf,",clearMods= ",sz);
1043706f2543Smrg	    TryCopyStr(buf,tmp,sz);
1044706f2543Smrg	}
1045706f2543Smrg    }
1046706f2543Smrg    return TRUE;
1047706f2543Smrg}
1048706f2543Smrg
1049706f2543Smrg/*ARGSUSED*/
1050706f2543Smrgstatic Bool
1051706f2543SmrgCopyDeviceBtnArgs(XkbDescPtr xkb,XkbAction *action,char *buf,
1052706f2543Smrg								int *sz)
1053706f2543Smrg{
1054706f2543SmrgXkbDeviceBtnAction *	act;
1055706f2543Smrgchar			tbuf[32];
1056706f2543Smrg
1057706f2543Smrg    act= &action->devbtn;
1058706f2543Smrg    sprintf(tbuf,"device= %d",act->device); TryCopyStr(buf,tbuf,sz);
1059706f2543Smrg    TryCopyStr(buf,",button=",sz);
1060706f2543Smrg    sprintf(tbuf,"%d",act->button);
1061706f2543Smrg    TryCopyStr(buf,tbuf,sz);
1062706f2543Smrg    if (act->count>0) {
1063706f2543Smrg	sprintf(tbuf,",count=%d",act->count);
1064706f2543Smrg	TryCopyStr(buf,tbuf,sz);
1065706f2543Smrg    }
1066706f2543Smrg    if (action->type==XkbSA_LockDeviceBtn) {
1067706f2543Smrg	switch (act->flags&(XkbSA_LockNoUnlock|XkbSA_LockNoLock)) {
1068706f2543Smrg	    case XkbSA_LockNoLock:
1069706f2543Smrg		sprintf(tbuf,",affect=unlock"); break;
1070706f2543Smrg	    case XkbSA_LockNoUnlock:
1071706f2543Smrg		sprintf(tbuf,",affect=lock"); break;
1072706f2543Smrg	    case XkbSA_LockNoUnlock|XkbSA_LockNoLock:
1073706f2543Smrg		sprintf(tbuf,",affect=neither"); break;
1074706f2543Smrg	    default:
1075706f2543Smrg		sprintf(tbuf,",affect=both"); break;
1076706f2543Smrg	}
1077706f2543Smrg	TryCopyStr(buf,tbuf,sz);
1078706f2543Smrg    }
1079706f2543Smrg    return TRUE;
1080706f2543Smrg}
1081706f2543Smrg
1082706f2543Smrg/*ARGSUSED*/
1083706f2543Smrgstatic Bool
1084706f2543SmrgCopyOtherArgs(XkbDescPtr xkb,XkbAction *action,char *buf,int *sz)
1085706f2543Smrg{
1086706f2543SmrgXkbAnyAction *	act;
1087706f2543Smrgchar		tbuf[32];
1088706f2543Smrg
1089706f2543Smrg    act= &action->any;
1090706f2543Smrg    sprintf(tbuf,"type=0x%02x",act->type); TryCopyStr(buf,tbuf,sz);
1091706f2543Smrg    sprintf(tbuf,",data[0]=0x%02x",act->data[0]); TryCopyStr(buf,tbuf,sz);
1092706f2543Smrg    sprintf(tbuf,",data[1]=0x%02x",act->data[1]); TryCopyStr(buf,tbuf,sz);
1093706f2543Smrg    sprintf(tbuf,",data[2]=0x%02x",act->data[2]); TryCopyStr(buf,tbuf,sz);
1094706f2543Smrg    sprintf(tbuf,",data[3]=0x%02x",act->data[3]); TryCopyStr(buf,tbuf,sz);
1095706f2543Smrg    sprintf(tbuf,",data[4]=0x%02x",act->data[4]); TryCopyStr(buf,tbuf,sz);
1096706f2543Smrg    sprintf(tbuf,",data[5]=0x%02x",act->data[5]); TryCopyStr(buf,tbuf,sz);
1097706f2543Smrg    sprintf(tbuf,",data[6]=0x%02x",act->data[6]); TryCopyStr(buf,tbuf,sz);
1098706f2543Smrg    return TRUE;
1099706f2543Smrg}
1100706f2543Smrg
1101706f2543Smrgtypedef	Bool	(*actionCopy)(
1102706f2543Smrg	XkbDescPtr 	/* xkb */,
1103706f2543Smrg	XkbAction *	/* action */,
1104706f2543Smrg	char *		/* buf */,
1105706f2543Smrg	int*		/* sz */
1106706f2543Smrg);
1107706f2543Smrgstatic actionCopy	copyActionArgs[XkbSA_NumActions] = {
1108706f2543Smrg	CopyNoActionArgs		/* NoAction	*/,
1109706f2543Smrg	CopyModActionArgs		/* SetMods	*/,
1110706f2543Smrg	CopyModActionArgs		/* LatchMods	*/,
1111706f2543Smrg	CopyModActionArgs		/* LockMods	*/,
1112706f2543Smrg	CopyGroupActionArgs		/* SetGroup	*/,
1113706f2543Smrg	CopyGroupActionArgs		/* LatchGroup	*/,
1114706f2543Smrg	CopyGroupActionArgs		/* LockGroup	*/,
1115706f2543Smrg	CopyMovePtrArgs			/* MovePtr	*/,
1116706f2543Smrg	CopyPtrBtnArgs			/* PtrBtn	*/,
1117706f2543Smrg	CopyPtrBtnArgs			/* LockPtrBtn	*/,
1118706f2543Smrg	CopySetPtrDfltArgs		/* SetPtrDflt	*/,
1119706f2543Smrg	CopyISOLockArgs			/* ISOLock	*/,
1120706f2543Smrg	CopyNoActionArgs		/* Terminate	*/,
1121706f2543Smrg	CopySwitchScreenArgs		/* SwitchScreen	*/,
1122706f2543Smrg	CopySetLockControlsArgs		/* SetControls	*/,
1123706f2543Smrg	CopySetLockControlsArgs		/* LockControls	*/,
1124706f2543Smrg	CopyActionMessageArgs		/* ActionMessage*/,
1125706f2543Smrg	CopyRedirectKeyArgs		/* RedirectKey	*/,
1126706f2543Smrg	CopyDeviceBtnArgs		/* DeviceBtn	*/,
1127706f2543Smrg	CopyDeviceBtnArgs		/* LockDeviceBtn*/
1128706f2543Smrg};
1129706f2543Smrg
1130706f2543Smrg#define	ACTION_SZ	256
1131706f2543Smrg
1132706f2543Smrgchar *
1133706f2543SmrgXkbActionText(XkbDescPtr xkb,XkbAction *action,unsigned format)
1134706f2543Smrg{
1135706f2543Smrgchar	buf[ACTION_SZ],*tmp;
1136706f2543Smrgint	sz;
1137706f2543Smrg
1138706f2543Smrg    if (format==XkbCFile) {
1139706f2543Smrg	sprintf(buf,
1140706f2543Smrg	    "{ %20s, { 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x } }",
1141706f2543Smrg	    XkbActionTypeText(action->type,XkbCFile),
1142706f2543Smrg	    action->any.data[0],action->any.data[1],action->any.data[2],
1143706f2543Smrg	    action->any.data[3],action->any.data[4],action->any.data[5],
1144706f2543Smrg	    action->any.data[6]);
1145706f2543Smrg    }
1146706f2543Smrg    else {
1147706f2543Smrg	sprintf(buf,"%s(",XkbActionTypeText(action->type,XkbXKBFile));
1148706f2543Smrg	sz= ACTION_SZ-strlen(buf)+2; /* room for close paren and NULL */
1149706f2543Smrg	if (action->type<(unsigned)XkbSA_NumActions)
1150706f2543Smrg	     (*copyActionArgs[action->type])(xkb,action,buf,&sz);
1151706f2543Smrg	else CopyOtherArgs(xkb,action,buf,&sz);
1152706f2543Smrg	TryCopyStr(buf,")",&sz);
1153706f2543Smrg    }
1154706f2543Smrg    tmp= tbGetBuffer(strlen(buf)+1);
1155706f2543Smrg    if (tmp!=NULL)
1156706f2543Smrg	strcpy(tmp,buf);
1157706f2543Smrg    return tmp;
1158706f2543Smrg}
1159706f2543Smrg
1160706f2543Smrgchar *
1161706f2543SmrgXkbBehaviorText(XkbDescPtr xkb,XkbBehavior *behavior,unsigned format)
1162706f2543Smrg{
1163706f2543Smrgchar	buf[256],*tmp;
1164706f2543Smrg
1165706f2543Smrg    if (format==XkbCFile) {
1166706f2543Smrg	if (behavior->type==XkbKB_Default)
1167706f2543Smrg	     sprintf(buf,"{   0,    0 }");
1168706f2543Smrg	else sprintf(buf,"{ %3d, 0x%02x }",behavior->type,behavior->data);
1169706f2543Smrg    }
1170706f2543Smrg    else {
1171706f2543Smrg	unsigned 	type,permanent;
1172706f2543Smrg	type= behavior->type&XkbKB_OpMask;
1173706f2543Smrg	permanent=((behavior->type&XkbKB_Permanent)!=0);
1174706f2543Smrg
1175706f2543Smrg	if (type==XkbKB_Lock) {
1176706f2543Smrg	    sprintf(buf,"lock= %s",(permanent?"Permanent":"TRUE"));
1177706f2543Smrg	}
1178706f2543Smrg	else if (type==XkbKB_RadioGroup) {
1179706f2543Smrg	    int 	g;
1180706f2543Smrg	    char	*tmp;
1181706f2543Smrg	    g= ((behavior->data)&(~XkbKB_RGAllowNone))+1;
1182706f2543Smrg	    if (XkbKB_RGAllowNone&behavior->data) {
1183706f2543Smrg		sprintf(buf,"allowNone,");
1184706f2543Smrg		tmp= &buf[strlen(buf)];
1185706f2543Smrg	    }
1186706f2543Smrg	    else tmp= buf;
1187706f2543Smrg	    if (permanent)
1188706f2543Smrg		 sprintf(tmp,"permanentRadioGroup= %d",g);
1189706f2543Smrg	    else sprintf(tmp,"radioGroup= %d",g);
1190706f2543Smrg	}
1191706f2543Smrg	else if ((type==XkbKB_Overlay1)||(type==XkbKB_Overlay2)) {
1192706f2543Smrg	    int ndx,kc;
1193706f2543Smrg	    char *kn;
1194706f2543Smrg
1195706f2543Smrg	    ndx= ((type==XkbKB_Overlay1)?1:2);
1196706f2543Smrg	    kc= behavior->data;
1197706f2543Smrg	    if ((xkb)&&(xkb->names)&&(xkb->names->keys))
1198706f2543Smrg		kn= XkbKeyNameText(xkb->names->keys[kc].name,XkbXKBFile);
1199706f2543Smrg	    else {
1200706f2543Smrg		static char tbuf[8];
1201706f2543Smrg		sprintf(tbuf,"%d",kc);
1202706f2543Smrg		kn= tbuf;
1203706f2543Smrg	    }
1204706f2543Smrg	    if (permanent)
1205706f2543Smrg		 sprintf(buf,"permanentOverlay%d= %s",ndx,kn);
1206706f2543Smrg	    else sprintf(buf,"overlay%d= %s",ndx,kn);
1207706f2543Smrg	}
1208706f2543Smrg    }
1209706f2543Smrg    tmp= tbGetBuffer(strlen(buf)+1);
1210706f2543Smrg    if (tmp!=NULL)
1211706f2543Smrg	strcpy(tmp,buf);
1212706f2543Smrg    return tmp;
1213706f2543Smrg}
1214706f2543Smrg
1215706f2543Smrg/***====================================================================***/
1216706f2543Smrg
1217706f2543Smrgchar *
1218706f2543SmrgXkbIndentText(unsigned size)
1219706f2543Smrg{
1220706f2543Smrgstatic char buf[32];
1221706f2543Smrgregister int i;
1222706f2543Smrg
1223706f2543Smrg    if (size>31)
1224706f2543Smrg	size= 31;
1225706f2543Smrg
1226706f2543Smrg    for (i=0;i<size;i++) {
1227706f2543Smrg	buf[i]= ' ';
1228706f2543Smrg    }
1229706f2543Smrg    buf[size]= '\0';
1230706f2543Smrg    return buf;
1231706f2543Smrg}
1232