Sophie

Sophie

distrib > Mandriva > 2009.1 > i586 > media > main-release-src > by-pkgid > ed850f9ceda4826f28781585a4806f28 > files > 23

x11-server-1.6.1-1mdv2009.1.src.rpm

From eb13879928c5d95ee25ff75da1f19cdafa0764bb Mon Sep 17 00:00:00 2001
From: Ander Conselvan de Oliveira <ander@mandriva.com.br>
Date: Mon, 23 Mar 2009 17:05:45 -0300
Subject: [PATCH 910/910] Port of pcpa's xkb compile cache patch to X server 1.6

---
 configure.ac            |    2 +-
 include/dix-config.h.in |    3 +
 include/xkbsrv.h        |    5 +
 os/utils.c              |   42 ++++--
 xkb/XKBMisc.c           |   12 +-
 xkb/ddxList.c           |  149 +++++++-----------
 xkb/ddxLoad.c           |  319 +++++++++++++++----------------------
 xkb/maprules.c          |    2 +-
 xkb/xkb.h               |   86 ++++++++++
 xkb/xkbActions.c        |    4 +-
 xkb/xkbInit.c           |   62 +++++++-
 xkb/xkbfmisc.c          |   95 +++---------
 xkb/xkbout.c            |  406 ++++++++++++++++++++++++-----------------------
 13 files changed, 603 insertions(+), 584 deletions(-)

diff --git a/configure.ac b/configure.ac
index 5b58ad8..f11d596 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1777,7 +1777,7 @@ if test "$KDRIVE" = yes; then
     KDRIVE_OS_INC='-I$(top_srcdir)/hw/kdrive/linux'
     KDRIVE_INCS="$KDRIVE_PURE_INCS $KDRIVE_OS_INC"
     
-    KDRIVE_CFLAGS="$XSERVER_CFLAGS -DHAVE_KDRIVE_CONFIG_H $TSLIB_CFLAGS"
+    KDRIVE_CFLAGS="$XSERVER_CFLAGS -DHAVE_KDRIVE_CONFIG_H $TSLIB_CFLAGS $SHA1_CFLAGS"
 
     KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB"
     KDRIVE_LIB='$(top_builddir)/hw/kdrive/src/libkdrive.a'
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 2515d83..70dbb3f 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -163,6 +163,9 @@
 /* Define to 1 if you have the <stdint.h> header file. */
 #undef HAVE_STDINT_H
 
+/* Define to use libmd SHA1 functions instead of OpenSSL libcrypto */
+#undef HAVE_SHA1_IN_LIBMD
+
 /* Define to 1 if you have the <stdlib.h> header file. */
 #undef HAVE_STDLIB_H
 
diff --git a/include/xkbsrv.h b/include/xkbsrv.h
index d43755e..2323e73 100644
--- a/include/xkbsrv.h
+++ b/include/xkbsrv.h
@@ -293,6 +293,7 @@ extern int	XkbReqCode;
 extern int	XkbEventBase;
 extern int	XkbDisableLockActions;
 extern int	XkbKeyboardErrorCode;
+extern char *	XkmOutputDirectory;
 extern char *	XkbBaseDirectory;
 extern char *	XkbBinDirectory;
 extern char *	XkbInitialMap;
@@ -354,6 +355,10 @@ extern int XkbProcessArguments(
     int				/* i */
 );
 
+extern void XkbInitGlobals(
+    void
+);
+
 extern	void	XkbSetExtension(DeviceIntPtr device, ProcessInputProc proc);
 
 extern	void	XkbFreeCompatMap(
diff --git a/os/utils.c b/os/utils.c
index 719ebbc..c104762 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -581,6 +581,9 @@ VerifyDisplayName(const char *d)
 void InitGlobals(void)
 {
     ddxInitGlobals();
+#ifdef XKB
+    XkbInitGlobals();
+#endif
 }
 
 
@@ -1378,10 +1381,12 @@ System(char *command)
     case -1:	/* error */
 	p = -1;
     case 0:	/* child */
-	if (setgid(getgid()) == -1)
-	    _exit(127);
-	if (setuid(getuid()) == -1)
-	    _exit(127);
+	if (geteuid() != getuid()) {
+	    if (setgid(getgid()) == -1)
+		_exit(127);
+	    if (setuid(getuid()) == -1)
+		_exit(127);
+	}
 	execl("/bin/sh", "sh", "-c", command, (char *)NULL);
 	_exit(127);
     default:	/* parent */
@@ -1446,10 +1451,12 @@ Popen(char *command, char *type)
 	  perror("signal");
 	return NULL;
     case 0:	/* child */
-	if (setgid(getgid()) == -1)
-	    _exit(127);
-	if (setuid(getuid()) == -1)
-	    _exit(127);
+	if (geteuid() != getuid()) {
+	    if (setgid(getgid()) == -1)
+		_exit(127);
+	    if (setuid(getuid()) == -1)
+		_exit(127);
+	}
 	if (*type == 'r') {
 	    if (pdes[1] != 1) {
 		/* stdout */
@@ -1516,17 +1523,28 @@ Fopen(char *file, char *type)
 	return NULL;
     }
 
+    /* Ignore the smart scheduler while this is going on */
+    old_alarm = signal(SIGALRM, SIG_IGN);
+    if (old_alarm == SIG_ERR) {
+      perror("signal");
+      return NULL;
+    }
+
     switch (pid = fork()) {
     case -1: 	/* error */
 	close(pdes[0]);
 	close(pdes[1]);
 	xfree(cur);
+	if (signal(SIGALRM, old_alarm) == SIG_ERR)
+	  perror("signal");
 	return NULL;
     case 0:	/* child */
-	if (setgid(getgid()) == -1)
-	    _exit(127);
-	if (setuid(getuid()) == -1)
-	    _exit(127);
+	if (geteuid() != getuid()) {
+	    if (setgid(getgid()) == -1)
+		_exit(127);
+	    if (setuid(getuid()) == -1)
+		_exit(127);
+	}
 	if (*type == 'r') {
 	    if (pdes[1] != 1) {
 		/* stdout */
diff --git a/xkb/XKBMisc.c b/xkb/XKBMisc.c
index a9d8b17..cc81d8b 100644
--- a/xkb/XKBMisc.c
+++ b/xkb/XKBMisc.c
@@ -480,7 +480,7 @@ register int	i;
 int		width,nOldGroups,oldWidth,newTypes[XkbNumKbdGroups];
 
     if ((!xkb) || (!XkbKeycodeInRange(xkb,key)) || (!xkb->map) ||
-	(!xkb->map->types)||(!newTypesIn)||((groups&XkbAllGroupsMask)==0)||
+	(!xkb->map->types)||((groups&XkbAllGroupsMask)==0)||
 	(nGroups>XkbNumKbdGroups)) {
 	return BadMatch;
     }
@@ -650,6 +650,7 @@ XkbUpdateKeyTypeVirtualMods(	XkbDescPtr	xkb,
 register unsigned int	i;
 unsigned int		mask;
 
+    mask = 0;
     XkbVirtualModsToReal(xkb,type->mods.vmods,&mask);
     type->mods.mask= type->mods.real_mods|mask;
     if ((type->map_count>0)&&(type->mods.vmods!=0)) {
@@ -694,6 +695,7 @@ XkbApplyVirtualModChanges(XkbDescPtr xkb,unsigned changed,XkbChangesPtr changes)
 {
 register int	i;
 unsigned int	checkState = 0;
+unsigned int	newMask;
 
     if ((!xkb) || (!xkb->map) || (changed==0))
 	return False;
@@ -702,7 +704,7 @@ unsigned int	checkState = 0;
 	XkbUpdateKeyTypeVirtualMods(xkb,&xkb->map->types[i],changed,changes);
     }
     if (changed&xkb->ctrls->internal.vmods) {
-	unsigned int	newMask;
+	newMask = 0;
 	XkbVirtualModsToReal(xkb,xkb->ctrls->internal.vmods,&newMask);
 	newMask|= xkb->ctrls->internal.real_mods;
 	if (xkb->ctrls->internal.mask!=newMask) {
@@ -714,7 +716,7 @@ unsigned int	checkState = 0;
 	}
     }
     if (changed&xkb->ctrls->ignore_lock.vmods) {
-	unsigned int	newMask;
+	newMask = 0;
 	XkbVirtualModsToReal(xkb,xkb->ctrls->ignore_lock.vmods,&newMask);
 	newMask|= xkb->ctrls->ignore_lock.real_mods;
 	if (xkb->ctrls->ignore_lock.mask!=newMask) {
@@ -730,7 +732,7 @@ unsigned int	checkState = 0;
 	map= &xkb->indicators->maps[0];
 	for (i=0;i<XkbNumIndicators;i++,map++) {
 	    if (map->mods.vmods&changed) {
-		unsigned int newMask;
+		newMask = 0;
 		XkbVirtualModsToReal(xkb,map->mods.vmods,&newMask);
 		newMask|= map->mods.real_mods;
 		if (newMask!=map->mods.mask) {
@@ -747,7 +749,7 @@ unsigned int	checkState = 0;
 	XkbCompatMapPtr	compat;
 	compat= xkb->compat;
 	for (i=0;i<XkbNumKbdGroups;i++) {
-	    unsigned int newMask;
+	    newMask = 0;
 	    XkbVirtualModsToReal(xkb,compat->groups[i].vmods,&newMask);
 	    newMask|= compat->groups[i].real_mods;
 	    if (compat->groups[i].mask!=newMask) {
diff --git a/xkb/ddxList.c b/xkb/ddxList.c
index ae3a7f7..4ca1cb2 100644
--- a/xkb/ddxList.c
+++ b/xkb/ddxList.c
@@ -43,20 +43,13 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #include <xkbsrv.h>
 #include <X11/extensions/XI.h>
 
+#include "xkb.h"
+
 #ifdef WIN32
 /* from ddxLoad.c */
-extern const char* Win32TempDir();
 extern int Win32System(const char *cmdline);
 #undef System
 #define System Win32System
-
-#define W32_tmparg " '%s'"
-#define W32_tmpfile ,tmpname
-#define W32_tmplen strlen(tmpname)+3
-#else
-#define W32_tmparg
-#define W32_tmpfile 
-#define W32_tmplen 0
 #endif 
 
 /***====================================================================***/
@@ -125,21 +118,21 @@ XkbDDXListComponent(	DeviceIntPtr 		dev,
 			XkbSrvListInfoPtr	list,
 			ClientPtr		client)
 {
-char 	*file,*map,*tmp,*buf=NULL;
-FILE 	*in;
-Status	status;
-int	rval;
-Bool	haveDir;
-#ifdef WIN32
-char	tmpname[PATH_MAX];
-#endif
+    char 	*file, *map, *tmp, *buf;
+    struct stat	 st;
+    FILE 	*in;
+    void	*cookie;
+    Status	 status;
+    int		 offset;
+    unsigned char name[42];
+    char	 command[8192];
+    char	 lstname[PATH_MAX];
 
     if ((list->pattern[what]==NULL)||(list->pattern[what][0]=='\0'))
 	return Success;
     file= list->pattern[what];
     map= strrchr(file,'(');
     if (map!=NULL) {
-	char *tmp;
 	map++;
 	tmp= strrchr(map,')');
 	if ((tmp==NULL)||(tmp[1]!='\0')) {
@@ -148,74 +141,57 @@ char	tmpname[PATH_MAX];
 	}
     }
 
-    in= NULL;
-    haveDir= True;
-#ifdef WIN32
-    strcpy(tmpname, Win32TempDir());
-    strcat(tmpname, "\\xkb_XXXXXX");
-    (void) mktemp(tmpname);
-#endif
-    if (XkbBaseDirectory!=NULL) {
-	if ((list->pattern[what][0]=='*')&&(list->pattern[what][1]=='\0')) {
-	    buf = Xprintf("%s/%s.dir",XkbBaseDirectory,componentDirs[what]);
-	    in= fopen(buf,"r");
-	}
-	if (!in) {
-	    haveDir= False;
-	    buf = Xprintf(
-		"'%s/xkbcomp' '-R%s/%s' -w %ld -l -vlfhpR '%s'" W32_tmparg,
-                XkbBinDirectory,XkbBaseDirectory,componentDirs[what],(long)
-		((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)),
-		file W32_tmpfile
-                );
-	}
+    if (list->pattern[what][0] == '*' && list->pattern[what][1] == '\0') {
+	buf = Xprintf("%s%s.dir", XkbBaseDirectory, componentDirs[what]);
+	in = fopen(buf, "r");
+	xfree(buf);
     }
-    else {
-	if ((list->pattern[what][0]=='*')&&(list->pattern[what][1]=='\0')) {
-	    buf = Xprintf("%s.dir",componentDirs[what]);
-	    in= fopen(buf,"r");
+    else
+	in = NULL;
+
+    if (!in) {
+	cookie = Xkb_xkbcomp_init();
+	offset = snprintf(command, sizeof(command),
+			  "'%sxkbcomp' "
+			  "'-R%s%s' "
+			  "-w %d -l -vlfhpR "
+			  "'%s'",
+			  XkbBinDirectory,
+			  XkbBaseDirectory, componentDirs[what],
+			  (int)(xkbDebugFlags < 2  ?
+				1 : xkbDebugFlags > 10 ? 10 : xkbDebugFlags),
+			  file);
+	xkb_printf(cookie, "%s", command);
+	Xkb_xkbcomp_final(lstname, name, ".lst");
+
+	status = access(lstname, R_OK) == 0;
+	if (access(lstname, R_OK) == 0) {
+	    if (stat(lstname, &st) != 0 || !S_ISREG(st.st_mode))
+		return (BadAccess);
 	}
-	if (!in) {
-	    haveDir= False;
-	    buf = Xprintf(
-		"xkbcomp -R%s -w %ld -l -vlfhpR '%s'" W32_tmparg,
-                componentDirs[what],(long)
-		((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)),
-		file W32_tmpfile
-                );
+	else {
+	    snprintf(command + offset, sizeof(command) - offset, " %s", lstname);
+	    if (System(command) < 0) {
+		ErrorF("Could not invoke keymap compiler\n");
+		return (BadAccess);
+	    }
 	}
+	in = fopen(lstname, "r");
     }
-    status= Success;
-    if (!haveDir)
-    {  
-#ifndef WIN32
-	in= Popen(buf,"r");
-#else
-        if (xkbDebugFlags)
-            DebugF("[xkb] xkbList executes: %s\n",buf);
-	if (System(buf) < 0)
-	    ErrorF("[xkb] Could not invoke keymap compiler\n");
-	else
-	    in= fopen(tmpname, "r");
-#endif
-    }
+    status = Success;
+
     if (!in)
-    {
-        if (buf != NULL)
-	    xfree (buf);
-#ifdef WIN32
-	unlink(tmpname);
-#endif
 	return BadImplementation;
-    }
-    list->nFound[what]= 0;
-    if (buf) {
-        xfree(buf);
-        buf = NULL;
-    }
+
+    list->nFound[what] = 0;
+
     buf = xalloc(PATH_MAX * sizeof(char));
-    if (!buf)
-        return BadAlloc;
+    if (buf == NULL) {
+	fclose(in);
+	return BadAlloc;
+    }
+
+    status = Success;
     while ((status==Success)&&((tmp=fgets(buf,PATH_MAX,in))!=NULL)) {
 	unsigned flags;
 	register unsigned int i;
@@ -257,19 +233,10 @@ char	tmpname[PATH_MAX];
 	}
 	status= _AddListComponent(list,what,flags,tmp,client);
     }
-#ifndef WIN32
-    if (haveDir)
-	fclose(in);
-    else if ((rval=Pclose(in))!=0) {
-	if (xkbDebugFlags)
-	    ErrorF("[xkb] xkbcomp returned exit code %d\n",rval);
-    }
-#else
+
     fclose(in);
-    unlink(tmpname);
-#endif
-    if (buf != NULL)
-        xfree (buf);
+    xfree(buf);
+
     return status;
 }
 
diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c
index 4d5dfb6..4796425 100644
--- a/xkb/ddxLoad.c
+++ b/xkb/ddxLoad.c
@@ -34,6 +34,13 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #include <stdio.h>
 #include <ctype.h>
+
+#ifdef HAVE_SHA1_IN_LIBMD
+# include <sha1.h>
+#else
+# include <openssl/sha.h>
+#endif
+
 #define	NEED_EVENTS 1
 #include <X11/X.h>
 #include <X11/Xos.h>
@@ -48,58 +55,27 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #include <X11/extensions/XI.h>
 #include "xkb.h"
 
+#include <stdarg.h>
+#include <stdio.h>
+
 #if defined(CSRG_BASED) || defined(linux) || defined(__GNU__)
 #include <paths.h>
 #endif
 
-	/*
-	 * If XKM_OUTPUT_DIR specifies a path without a leading slash, it is
-	 * relative to the top-level XKB configuration directory.
-	 * Making the server write to a subdirectory of that directory
-	 * requires some work in the general case (install procedure
-	 * has to create links to /var or somesuch on many machines),
-	 * so we just compile into /usr/tmp for now.
-	 */
-#ifndef XKM_OUTPUT_DIR
-#define	XKM_OUTPUT_DIR	"compiled/"
-#endif
-
 #define	PRE_ERROR_MSG "\"The XKEYBOARD keymap compiler (xkbcomp) reports:\""
 #define	ERROR_PREFIX	"\"> \""
 #define	POST_ERROR_MSG1 "\"Errors from xkbcomp are not fatal to the X server\""
 #define	POST_ERROR_MSG2 "\"End of messages from xkbcomp\""
 
-#if defined(WIN32)
-#define PATHSEPARATOR "\\"
-#else
-#define PATHSEPARATOR "/"
-#endif
+static struct {
+    SHA_CTX	 sha;
+    char	*buffer;
+    int		 offset;
+    int		 space;
+} cookie;
 
 #ifdef WIN32
-
 #include <X11/Xwindows.h>
-const char* 
-Win32TempDir()
-{
-    static char buffer[PATH_MAX];
-    if (GetTempPath(sizeof(buffer), buffer))
-    {
-        int len;
-        buffer[sizeof(buffer)-1] = 0;
-        len = strlen(buffer);
-        if (len > 0)
-            if (buffer[len-1] == '\\')
-                buffer[len-1] = 0;
-        return buffer;
-    }
-    if (getenv("TEMP") != NULL)
-        return getenv("TEMP");
-    else if (getenv("TMP") != NULL)
-        return getenv("TEMP");
-    else
-        return "/tmp";
-}
-
 int 
 Win32System(const char *cmdline)
 {
@@ -153,180 +129,148 @@ Win32System(const char *cmdline)
 #define System(x) Win32System(x)
 #endif
 
-static void
-OutputDirectory(
-    char* outdir,
-    size_t size)
+int
+Xkb_printf(void *context, const char *format, ...)
 {
-#ifndef WIN32
-    if (getuid() == 0 && (strlen(XKM_OUTPUT_DIR) < size))
-    {
-	/* if server running as root it *may* be able to write */
-	/* FIXME: check whether directory is writable at all */
-	(void) strcpy (outdir, XKM_OUTPUT_DIR);
-    } else
-#else
-    if (strlen(Win32TempDir()) + 1 < size)
-    {
-	(void) strcpy(outdir, Win32TempDir());
-	(void) strcat(outdir, "\\");
-    } else 
-#endif
-    if (strlen("/tmp/") < size)
-    {
-	(void) strcpy (outdir, "/tmp/");
+    va_list	ap;
+    int		length = -1;
+
+    if (context == &cookie) {
+	for (;;) {
+	    va_start(ap, format);
+	    length = vsnprintf(cookie.buffer + cookie.offset,
+			       cookie.space - cookie.offset,
+			       format, ap);
+	    if (cookie.offset + length >= cookie.space)
+		cookie.buffer = xnfrealloc(cookie.buffer, cookie.space += 4096);
+	    else {
+		SHA1_Update(&cookie.sha, cookie.buffer + cookie.offset, length);
+		cookie.offset += length;
+		break;
+	    }
+	}
+	va_end(ap);
     }
+
+    return (length);
 }
 
-static Bool    	
-XkbDDXCompileKeymapByNames(	XkbDescPtr		xkb,
-				XkbComponentNamesPtr	names,
-				unsigned		want,
-				unsigned		need,
-				char *			nameRtrn,
-				int			nameRtrnLen)
+void *
+Xkb_xkbcomp_init(void)
 {
-    FILE *	out;
-    char	*buf = NULL, keymap[PATH_MAX], xkm_output_dir[PATH_MAX];
-
-    const char	*emptystring = "";
-    const char	*xkbbasedirflag = emptystring;
-    const char	*xkbbindir = emptystring;
-    const char	*xkbbindirsep = emptystring;
-
-#ifdef WIN32
-    /* WIN32 has no popen. The input must be stored in a file which is
-       used as input for xkbcomp. xkbcomp does not read from stdin. */
-    char tmpname[PATH_MAX];
-    const char *xkmfile = tmpname;
-#else
-    const char *xkmfile = "-";
-#endif
+    SHA1_Init(&cookie.sha);
+    if (cookie.buffer == NULL)
+	cookie.buffer = xnfalloc(cookie.space = 4096);
+    cookie.offset = 0;
 
-    snprintf(keymap, sizeof(keymap), "server-%s", display);
+    return (&cookie);
+}
 
-    XkbEnsureSafeMapName(keymap);
-    OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir));
+void
+Xkb_xkbcomp_final(char name[PATH_MAX], unsigned char sha1[42], char *ext)
+{
+    int			 i;
+    static char		 hex[] = "0123456789abcdef";
 
-#ifdef WIN32
-    strcpy(tmpname, Win32TempDir());
-    strcat(tmpname, "\\xkb_XXXXXX");
-    (void) mktemp(tmpname);
-#endif
+    SHA1_Final(sha1, &cookie.sha);
 
-    if (XkbBaseDirectory != NULL) {
-	xkbbasedirflag = Xprintf("\"-R%s\"", XkbBaseDirectory);
+    for (i = 19; i >= 0; i--) {
+	sha1[i * 2 + 1] = hex[(sha1[i] >> 4) & 0xf];
+	sha1[i * 2]     = hex[sha1[i] & 0xf];
     }
+    sha1[40] = '\0';
 
-    if (XkbBinDirectory != NULL) {
-	int ld = strlen(XkbBinDirectory);
-	int lps = strlen(PATHSEPARATOR);
-
-	xkbbindir = XkbBinDirectory;
-
-	if ((ld >= lps) &&
-	    (strcmp(xkbbindir + ld - lps, PATHSEPARATOR) != 0)) {
-	    xkbbindirsep = PATHSEPARATOR;
-	}
-    }
+    snprintf(name, PATH_MAX, "%s%s%s", XkmOutputDirectory, sha1, ext);
+}
 
-    buf = Xprintf("\"%s%sxkbcomp\" -w %d %s -xkm \"%s\" "
-		  "-em1 %s -emp %s -eml %s \"%s%s.xkm\"",
-		  xkbbindir, xkbbindirsep,
-		  ( (xkbDebugFlags < 2) ? 1 :
-		    ((xkbDebugFlags > 10) ? 10 : (int)xkbDebugFlags) ),
-		  xkbbasedirflag, xkmfile,
-		  PRE_ERROR_MSG, ERROR_PREFIX, POST_ERROR_MSG1,
-		  xkm_output_dir, keymap);
-
-    if (xkbbasedirflag != emptystring) {
-	xfree(xkbbasedirflag);
+static Bool
+XkbDDXCompileKeymapByNames(XkbDescPtr xkb, XkbComponentNamesPtr names,
+			   unsigned want, unsigned need,
+			   unsigned char *name, int length)
+{
+    FILE	*fp;
+    struct stat	 st;
+    Bool	 result;
+    char	*cmd, *tmpfile;
+    char	 xkmfile[PATH_MAX];
+
+    if (name == NULL || length < 42)
+	return (False);
+
+    XkbWriteKeymapForNames(Xkb_xkbcomp_init(), names, xkb, want, need);
+    Xkb_xkbcomp_final(xkmfile, name, ".xkm");
+    if ((result = access(xkmfile, R_OK) == 0)) {
+	if (stat(xkmfile, &st) != 0 || !S_ISREG(st.st_mode))
+	    result = False;
     }
-    
-#ifndef WIN32
-    out= Popen(buf,"w");
+    else {
+#ifdef WIN32
+	tmpfile = Xprintf("%s\\xkb_XXXXXX.tmp", XkbOutputDirectory);
+	(void)mktemp(tmpfile);
+	if ((fp = fopen(tmpfile, "wb")) != NULL) {
+	    fwrite(cookie.buffer, cookie.offset, 1, fp);
+	    fclose(fp);
+	}
 #else
-    out= fopen(tmpname, "w");
+	tmpfile = "-";
 #endif
-    
-    if (out!=NULL) {
-#ifdef DEBUG
-    if (xkbDebugFlags) {
-       ErrorF("[xkb] XkbDDXCompileKeymapByNames compiling keymap:\n");
-       XkbWriteXKBKeymapForNames(stderr,names,xkb,want,need);
-    }
-#endif
-	XkbWriteXKBKeymapForNames(out,names,xkb,want,need);
-#ifndef WIN32
-	if (Pclose(out)==0)
+	cmd = Xprintf("\"%sxkbcomp\" "
+		      "-w %d "
+		      "\"-R%s\" -xkm \"%s\" "
+		      "-em1 %s -emp %s -eml %s "
+		      "\"%s\"",
+		      XkbBinDirectory,
+		      xkbDebugFlags < 2 ? 1 : xkbDebugFlags > 10 ? 10 : xkbDebugFlags,
+		      XkbBaseDirectory, tmpfile,
+		      PRE_ERROR_MSG, ERROR_PREFIX, POST_ERROR_MSG1,
+		      xkmfile);
+#ifdef WIN32
+	if (System(cmd) >= 0)
+	    result = True;
+	unlink(tmpfile);
 #else
-	if (fclose(out)==0 && System(buf) >= 0)
-#endif
-	{
-            if (xkbDebugFlags)
-                DebugF("[xkb] xkb executes: %s\n",buf);
-	    if (nameRtrn) {
-		strncpy(nameRtrn,keymap,nameRtrnLen);
-		nameRtrn[nameRtrnLen-1]= '\0';
+	if ((fp = Popen(cmd, "w")) != NULL) {
+	    int	offset, bytes;
+
+	    for (offset = 0; offset < cookie.offset; ) {
+		bytes = fwrite(cookie.buffer + offset, 1,
+			       cookie.offset - offset, fp);
+		if (bytes <= 0)
+		    break;
+		offset += bytes;
 	    }
-            if (buf != NULL)
-                xfree (buf);
-	    return True;
+	    result = Pclose(fp) == 0;
 	}
-	else
-	    LogMessage(X_ERROR, "Error compiling keymap (%s)\n", keymap);
-#ifdef WIN32
-        /* remove the temporary file */
-        unlink(tmpname);
-#endif
-    }
-    else {
-#ifndef WIN32
-	LogMessage(X_ERROR, "XKB: Could not invoke xkbcomp\n");
-#else
-	LogMessage(X_ERROR, "Could not open file %s\n", tmpname);
 #endif
+	xfree(cmd);
     }
-    if (nameRtrn)
-	nameRtrn[0]= '\0';
-    if (buf != NULL)
-        xfree (buf);
-    return False;
+
+    if (result == False)
+	name[0] = '\0';
+
+    return (result);
 }
 
 static FILE *
 XkbDDXOpenConfigFile(char *mapName,char *fileNameRtrn,int fileNameRtrnLen)
 {
-char	buf[PATH_MAX],xkm_output_dir[PATH_MAX];
-FILE *	file;
-
-    buf[0]= '\0';
-    if (mapName!=NULL) {
-	OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir));
-	if ((XkbBaseDirectory!=NULL)&&(xkm_output_dir[0]!='/')
-#ifdef WIN32
-                &&(!isalpha(xkm_output_dir[0]) || xkm_output_dir[1]!=':')
-#endif
-                ) {
-	    if (strlen(XkbBaseDirectory)+strlen(xkm_output_dir)
-		     +strlen(mapName)+6 <= PATH_MAX)
-	    {
-	        sprintf(buf,"%s/%s%s.xkm",XkbBaseDirectory,
-					xkm_output_dir,mapName);
+    char	*buf;
+    FILE	*file;
+
+    file = NULL;
+    if (mapName != NULL) {
+	buf = Xprintf("%s%s.xkm", XkmOutputDirectory, mapName);
+	if (buf != NULL) {
+	    file = fopen(buf, "rb");
+	    if (fileNameRtrn != NULL && fileNameRtrnLen > 0) {
+		strncpy(fileNameRtrn, buf, fileNameRtrnLen);
+		fileNameRtrn[fileNameRtrnLen - 1] = '\0';
 	    }
+	    xfree(buf);
 	}
-	else if (strlen(xkm_output_dir)+strlen(mapName)+5 <= PATH_MAX)
-	    sprintf(buf,"%s%s.xkm",xkm_output_dir,mapName);
-	if (buf[0] != '\0')
-	    file= fopen(buf,"rb");
-	else file= NULL;
     }
-    else file= NULL;
-    if ((fileNameRtrn!=NULL)&&(fileNameRtrnLen>0)) {
-	strncpy(fileNameRtrn,buf,fileNameRtrnLen);
-	buf[fileNameRtrnLen-1]= '\0';
-    }
-    return file;
+
+    return (file);
 }
 
 unsigned
@@ -375,7 +319,6 @@ unsigned	missing;
 	DebugF("Loaded XKB keymap %s, defined=0x%x\n",fileName,(*xkbRtrn)->defined);
     }
     fclose(file);
-    (void) unlink (fileName);
     return (need|want)&(~missing);
 }
 
@@ -397,7 +340,7 @@ XkbRF_RulesPtr	rules;
         LogMessage(X_ERROR, "XKB: Rules name is too long\n");
         return False;
     }
-    sprintf(buf,"%s/rules/%s", XkbBaseDirectory, rules_name);
+    sprintf(buf,"%srules/%s", XkbBaseDirectory, rules_name);
 
     file = fopen(buf, "r");
     if (!file) {
diff --git a/xkb/maprules.c b/xkb/maprules.c
index b25d929..15d5b15 100644
--- a/xkb/maprules.c
+++ b/xkb/maprules.c
@@ -865,7 +865,7 @@ XkbRF_GetComponents(	XkbRF_RulesPtr		rules,
 
     FreeMultiDefs(&mdefs);
     return (names->keycodes && names->symbols && names->types &&
-		names->compat && names->geometry ) || names->keymap;
+		names->compat && names->geometry) || names->keymap;
 }
 
 XkbRF_RulePtr
diff --git a/xkb/xkb.h b/xkb/xkb.h
index bc6c6c9..72f7b11 100644
--- a/xkb/xkb.h
+++ b/xkb/xkb.h
@@ -37,4 +37,90 @@ extern Bool XkbCopyKeymap(
     XkbDescPtr              dst,
     Bool                    sendNotifies);
 
+extern Bool XkbWriteKeymapForNames(
+    void *		/* cookie */,
+    XkbComponentNamesPtr/* names */,
+    XkbDescPtr		/* xkb */,
+    unsigned		/* want */,
+    unsigned		/* need */
+);
+
+#ifdef __GNUC__
+#define PRINTF_FORMAT	__attribute__ ((format (printf, 2, 3)))
+#else
+#define PRINTF_FORMAT	/**/
+#endif
+extern int Xkb_printf(
+    void *		/* cookie */,
+    const char *	/* format */,
+    ...
+)  PRINTF_FORMAT;
+#undef PRINTF_FORMAT
+#define xkb_printf	Xkb_printf
+
+extern void *Xkb_xkbcomp_init(
+    void
+);
+
+extern void Xkb_xkbcomp_final(
+    char [PATH_MAX]	/* name */,
+    unsigned char [42]	/* sha1 */,
+    char *		/* ext */
+);
+
+typedef void (*XkbCookieAddOnFunc)(
+    void *		/* cookie */,
+    XkbDescPtr		/* result */,
+    Bool		/* topLevel */,
+    Bool		/* showImplicit */,
+    int			/* fileSection */,
+    void *		/* priv */
+);
+
+extern Bool XkbWrite_Keycodes(
+    void *		/* file */,
+    XkbDescPtr		/* result */,
+    Bool		/* topLevel */,
+    Bool		/* showImplicit */,
+    XkbCookieAddOnFunc	/* addOn */,
+    void *		/* priv */
+);
+
+extern Bool XkbWrite_KeyTypes(
+    void *		/* cookie */,
+    XkbDescPtr		/* result */,
+    Bool		/* topLevel */,
+    Bool		/* showImplicit */,
+    XkbCookieAddOnFunc	/* addOn */,
+    void *		/* priv */
+);
+
+extern Bool XkbWrite_CompatMap(
+    void *		/* cookie */,
+    XkbDescPtr		/* result */,
+    Bool		/* topLevel */,
+    Bool		/* showImplicit */,
+    XkbCookieAddOnFunc	/* addOn */,
+    void *		/* priv */
+);
+
+extern Bool XkbWrite_Symbols(
+    void *		/* cookie */,
+    XkbDescPtr		/* result */,
+    Bool		/* topLevel */,
+    Bool		/* showImplicit */,
+    XkbCookieAddOnFunc	/* addOn */,
+    void *		/* priv */
+);
+
+Bool
+XkbWrite_Geometry(
+    void *		/* cookie */,
+    XkbDescPtr		/* result */,
+    Bool		/* topLevel */,
+    Bool		/* showImplicit */,
+    XkbCookieAddOnFunc	/* addOn */,
+    void *		/* priv */
+);
+
 #endif
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index aea479c..4b42775 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -1021,9 +1021,6 @@ _XkbFilterDeviceBtn(	XkbSrvInfoPtr	xkbi,
 DeviceIntPtr	dev;
 int		button;
 
-    if (xkbi->device == inputInfo.keyboard)
-        return 0;
-
     if (filter->keycode==0) {		/* initial press */
 	_XkbLookupButtonDevice(&dev, pAction->devbtn.device, serverClient,
 			       DixUnknownAccess, &button);
@@ -1272,6 +1269,7 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
 
     if (sendEvent) {
         DeviceIntPtr tmpdev;
+        realMods = 0;
 	if (keyEvent) {
 	    realMods = keyc->modifierMap[key];
 	    keyc->modifierMap[key] = 0;
diff --git a/xkb/xkbInit.c b/xkb/xkbInit.c
index 3a0e375..5d0a02b 100644
--- a/xkb/xkbInit.c
+++ b/xkb/xkbInit.c
@@ -39,6 +39,7 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #include <math.h>
 #define NEED_EVENTS 1
 #include <X11/X.h>
+#include <X11/Xos.h>
 #include <X11/Xproto.h>
 #include <X11/keysym.h>
 #include <X11/Xatom.h>
@@ -86,11 +87,14 @@ typedef struct	_SrvXkmInfo {
 
 /***====================================================================***/
 
+#ifndef XKM_OUTPUT_DIRECTORY
+#define XKM_OUTPUT_DIRECTORY	"/usr/share/X11/xkb/compiled/"
+#endif
 #ifndef XKB_BASE_DIRECTORY
-#define	XKB_BASE_DIRECTORY	"/usr/lib/X11/xkb"
+#define	XKB_BASE_DIRECTORY	"/usr/share/X11/xkb/"
 #endif
 #ifndef XKB_BIN_DIRECTORY
-#define	XKB_BIN_DIRECTORY	XKB_BASE_DIRECTORY
+#define	XKB_BIN_DIRECTORY	"/usr/bin/"
 #endif
 #ifndef XKB_DFLT_RULES_FILE
 #define	XKB_DFLT_RULES_FILE	"base"
@@ -114,8 +118,9 @@ typedef struct	_SrvXkmInfo {
 #define	XKB_DFLT_RULES_PROP	True
 #endif
 
-char	*		XkbBaseDirectory=	XKB_BASE_DIRECTORY;
-char	*		XkbBinDirectory=	XKB_BIN_DIRECTORY;
+char	*		XkmOutputDirectory=	NULL;
+char	*		XkbBaseDirectory=	NULL;
+char	*		XkbBinDirectory=	NULL;
 static int	 	XkbWantAccessX=		0;	
 
 static Bool		rulesDefined=		False;
@@ -137,6 +142,50 @@ static Bool		XkbWantRulesProp=	XKB_DFLT_RULES_PROP;
 
 /***====================================================================***/
 
+#if defined(WIN32)
+#define PATHSEPARATOR '\\'
+#else
+#define PATHSEPARATOR '/'
+#endif
+
+static void
+CheckDirectory(char **path, char *def)
+{
+    int	length;
+
+    if (*path == NULL)
+	*path = xnfstrdup(def);
+
+    length = strlen(*path);
+    if (length && (*path)[length - 1] != PATHSEPARATOR) {
+	*path = xnfrealloc(*path, length + 2);
+	(*path)[length++] = PATHSEPARATOR;
+	(*path)[length++] = '\0';
+    }
+}
+
+void
+XkbInitGlobals(void)
+{
+#ifdef WIN32
+    char	*compiled;
+    static char	 buffer[PATH_MAX];
+
+    if (GetTempPath(sizeof(buffer), buffer) != NULL) {
+	buffer[sizeof(buffer) - 1] = 0;
+	compiled = buffer;
+    }
+    else if ((compiled = getenv("TEMP")) == NULL)
+	if ((compiled = getenv("TMP")) == NULL)
+	    compiled = "\\tmp\\";
+    CheckDirectory(&XkmOutputDirectory, compiled);
+#else
+    CheckDirectory(&XkmOutputDirectory, XKM_OUTPUT_DIRECTORY);
+#endif
+    CheckDirectory(&XkbBinDirectory, XKB_BIN_DIRECTORY);
+    CheckDirectory(&XkbBaseDirectory, XKB_BASE_DIRECTORY);
+}
+
 static char *
 XkbGetRulesDflts(XkbRF_VarDefsPtr defs)
 {
@@ -857,7 +906,10 @@ XkbProcessArguments(int argc,char *argv[],int i)
 #endif
 	    {
 		if (strlen(argv[i]) < PATH_MAX) {
-		    XkbBaseDirectory= argv[i];
+		    /* XkbInitGlobals() must have been already called */
+		    xfree(XkbBaseDirectory);
+		    XkbBaseDirectory = NULL;
+		    CheckDirectory(&XkbBaseDirectory, argv[i]);
 		    return 2;
 	        } else {
 		    LogMessage(X_ERROR, "-xkbdir pathname too long\n");
diff --git a/xkb/xkbfmisc.c b/xkb/xkbfmisc.c
index ae752e9..a4b42c0 100644
--- a/xkb/xkbfmisc.c
+++ b/xkb/xkbfmisc.c
@@ -134,9 +134,9 @@ unsigned	set,rtrn;
 /***===================================================================***/
 
 static Bool
-XkbWriteSectionFromName(FILE *file,char *sectionName,char *name)
+XkbWrite_SectionFromName(void *cookie,char *sectionName,char *name)
 {
-    fprintf(file,"    xkb_%-20s { include \"%s\" };\n",sectionName,name);
+    xkb_printf(cookie,"    xkb_%-20s { include \"%s\" };\n",sectionName,name);
     return True;
 }
 
@@ -145,7 +145,7 @@ XkbWriteSectionFromName(FILE *file,char *sectionName,char *name)
 
 /* ARGSUSED */
 static void
-_AddIncl(	FILE *		file,
+_AddIncl(	void *		cookie,
 		XkbDescPtr 	xkb,
 		Bool 		topLevel,
 		Bool 		showImplicit,
@@ -153,12 +153,11 @@ _AddIncl(	FILE *		file,
 		void *		priv)
 {
     if ((priv)&&(strcmp((char *)priv,"%")!=0))
-	fprintf(file,"    include \"%s\"\n",(char *)priv);
-    return;
+       xkb_printf(cookie,"    include \"%s\"\n",(char *)priv);
 }
 
 Bool
-XkbWriteXKBKeymapForNames(	FILE *			file,
+XkbWriteKeymapForNames(		void *			cookie,
 				XkbComponentNamesPtr	names,
 				XkbDescPtr		xkb,
 				unsigned		want,
@@ -293,15 +292,15 @@ unsigned	wantNames,wantConfig,wantDflts;
     multi_section= 1;
     if (((complete&XkmKeymapRequired)==XkmKeymapRequired)&&
 	((complete&(~XkmKeymapLegal))==0)) {
-	fprintf(file,"xkb_keymap \"%s\" {\n",name);
+	xkb_printf(cookie,"xkb_keymap \"%s\" {\n",name);
     }
     else if (((complete&XkmSemanticsRequired)==XkmSemanticsRequired)&&
 	((complete&(~XkmSemanticsLegal))==0)) {
-	fprintf(file,"xkb_semantics \"%s\" {\n",name);
+	xkb_printf(cookie,"xkb_semantics \"%s\" {\n",name);
     }
     else if (((complete&XkmLayoutRequired)==XkmLayoutRequired)&&
 	((complete&(~XkmLayoutLegal))==0)) {
-	fprintf(file,"xkb_layout \"%s\" {\n",name);
+	xkb_printf(cookie,"xkb_layout \"%s\" {\n",name);
     }
     else if (XkmSingleSection(complete&(~XkmVirtualModsMask))) {
 	multi_section= 0;
@@ -313,42 +312,42 @@ unsigned	wantNames,wantConfig,wantDflts;
     wantNames= complete&(~(wantConfig|wantDflts));
     name= names->keycodes;
     if (wantConfig&XkmKeyNamesMask)
-	XkbWriteXKBKeycodes(file,xkb,False,False,_AddIncl,name);
+	XkbWrite_Keycodes(cookie,xkb,False,False,_AddIncl,name);
     else if (wantDflts&XkmKeyNamesMask)
 	fprintf(stderr,"Default symbols not implemented yet!\n");
     else if (wantNames&XkmKeyNamesMask)
-	XkbWriteSectionFromName(file,"keycodes",name);
+	XkbWrite_SectionFromName(cookie,"keycodes",name);
 
     name= names->types;
     if (wantConfig&XkmTypesMask)
-	XkbWriteXKBKeyTypes(file,xkb,False,False,_AddIncl,name);
+	XkbWrite_KeyTypes(cookie,xkb,False,False,_AddIncl,name);
     else if (wantDflts&XkmTypesMask)
 	fprintf(stderr,"Default types not implemented yet!\n");
     else if (wantNames&XkmTypesMask)
-	XkbWriteSectionFromName(file,"types",name);
+	XkbWrite_SectionFromName(cookie,"types",name);
 
     name= names->compat;
     if (wantConfig&XkmCompatMapMask)
-	XkbWriteXKBCompatMap(file,xkb,False,False,_AddIncl,name);
+	XkbWrite_CompatMap(cookie,xkb,False,False,_AddIncl,name);
     else if (wantDflts&XkmCompatMapMask)
 	fprintf(stderr,"Default interps not implemented yet!\n");
     else if (wantNames&XkmCompatMapMask)
-	XkbWriteSectionFromName(file,"compatibility",name);
+	XkbWrite_SectionFromName(cookie,"compatibility",name);
 
     name= names->symbols;
     if (wantConfig&XkmSymbolsMask)
-	XkbWriteXKBSymbols(file,xkb,False,False,_AddIncl,name);
+	XkbWrite_Symbols(cookie,xkb,False,False,_AddIncl,name);
     else if (wantNames&XkmSymbolsMask)
-	XkbWriteSectionFromName(file,"symbols",name);
+	XkbWrite_SectionFromName(cookie,"symbols",name);
 
     name= names->geometry;
     if (wantConfig&XkmGeometryMask)
-	XkbWriteXKBGeometry(file,xkb,False,False,_AddIncl,name);
+	XkbWrite_Geometry(cookie,xkb,False,False,_AddIncl,name);
     else if (wantNames&XkmGeometryMask)
-	XkbWriteSectionFromName(file,"geometry",name);
+	XkbWrite_SectionFromName(cookie,"geometry",name);
 
     if (multi_section)
-	fprintf(file,"};\n");
+	xkb_printf(cookie,"};\n");
     return True;
 }
 
@@ -412,59 +411,3 @@ unsigned	rtrn;
     }
     return rtrn;
 }
-
-/* all latin-1 alphanumerics, plus parens, slash, minus, underscore and */
-/* wildcards */
-
-static unsigned char componentSpecLegal[] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x83,
-	0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
-};
-
-void
-XkbEnsureSafeMapName(char *name)
-{
-   if (name==NULL)
-        return;
-    while (*name!='\0') {
-	if ((componentSpecLegal[(*name)/8]&(1<<((*name)%8)))==0)
-	    *name= '_';
-        name++;
-    }
-    return;
-}
-
-/***====================================================================***/
-
-#define	UNMATCHABLE(c)	(((c)=='(')||((c)==')')||((c)=='/'))
-
-Bool
-XkbNameMatchesPattern(char *name,char *ptrn)
-{
-    while (ptrn[0]!='\0') {
-	if (name[0]=='\0') {
-	    if (ptrn[0]=='*') {
-		ptrn++;
-		continue;
-	    }
-	    return False;
-	}
-	if (ptrn[0]=='?') {
-	    if (UNMATCHABLE(name[0]))
-		return False;
-	}
-	else if (ptrn[0]=='*') {
-	    if ((!UNMATCHABLE(name[0]))&&XkbNameMatchesPattern(name+1,ptrn))
-		return True;
-	    return XkbNameMatchesPattern(name,ptrn+1);
-	}
-	else if (ptrn[0]!=name[0])
-	    return False;
-	name++;
-	ptrn++;
-    }
-    /* if we get here, the pattern is exhausted (-:just like me:-) */
-    return (name[0]=='\0');
-}
diff --git a/xkb/xkbout.c b/xkb/xkbout.c
index 229cc92..4ab461b 100644
--- a/xkb/xkbout.c
+++ b/xkb/xkbout.c
@@ -47,12 +47,14 @@
 #include "xkbgeom.h"
 #include "xkbfile.h"
 
+#include "xkb.h"
+
 #define	VMOD_HIDE_VALUE	0
 #define	VMOD_SHOW_VALUE	1
 #define	VMOD_COMMENT_VALUE 2
 
 static Bool
-WriteXKBVModDecl(FILE *file,XkbDescPtr xkb,int showValue)
+WriteXKBVModDecl(void *cookie,XkbDescPtr xkb,int showValue)
 {
 register int 	i,nMods;
 Atom *		vmodNames;
@@ -65,17 +67,17 @@ Atom *		vmodNames;
 
     for (i=nMods=0;i<XkbNumVirtualMods;i++) {
 	if ((vmodNames!=NULL)&&(vmodNames[i]!=None)) {
-	    if (nMods==0)	fprintf(file,"    virtual_modifiers ");
-	    else		fprintf(file,",");
-	    fprintf(file,"%s",XkbAtomText(vmodNames[i],XkbXKBFile));
+	    if (nMods==0)	xkb_printf(cookie,"    virtual_modifiers ");
+	    else		xkb_printf(cookie,",");
+	    xkb_printf(cookie,"%s",XkbAtomText(vmodNames[i],XkbXKBFile));
 	    if ((showValue!=VMOD_HIDE_VALUE)&&
 		(xkb->server)&&(xkb->server->vmods[i]!=XkbNoModifierMask)) {
 		if (showValue==VMOD_COMMENT_VALUE) {
-		    fprintf(file,"/* = %s */",
+		    xkb_printf(cookie,"/* = %s */",
 			XkbModMaskText(xkb->server->vmods[i],XkbXKBFile));
 		}
 		else  {
-		    fprintf(file,"= %s",
+		    xkb_printf(cookie,"= %s",
 			XkbModMaskText(xkb->server->vmods[i],XkbXKBFile));
 		}
 	    }
@@ -83,27 +85,27 @@ Atom *		vmodNames;
 	}
     }
     if (nMods>0)
-	fprintf(file,";\n\n");
+	xkb_printf(cookie,";\n\n");
     return True;
 }
 
 /***====================================================================***/
 
 static Bool
-WriteXKBAction(FILE *file,XkbDescPtr xkb,XkbAnyAction *action)
+WriteXKBAction(void *cookie,XkbDescPtr xkb,XkbAnyAction *action)
 {
-    fprintf(file,"%s",XkbActionText(xkb,(XkbAction *)action,XkbXKBFile));
+    xkb_printf(cookie,"%s",XkbActionText(xkb,(XkbAction *)action,XkbXKBFile));
     return True;
 }
 
 /***====================================================================***/
 
 Bool
-XkbWriteXKBKeycodes(	FILE *			file,
+XkbWrite_Keycodes(	void *			cookie,
 			XkbDescPtr		xkb,
 			Bool			topLevel,
 			Bool			showImplicit,
-			XkbFileAddOnFunc	addOn,
+			XkbCookieAddOnFunc	addOn,
 			void *			priv)
 {
 Atom			kcName;
@@ -111,22 +113,22 @@ register unsigned 	i;
 char *			alternate;
 
     if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) {
-	_XkbLibError(_XkbErrMissingNames,"XkbWriteXKBKeycodes",0);
+	_XkbLibError(_XkbErrMissingNames,"XkbWrite_Keycodes",0);
 	return False;
     }
     kcName= xkb->names->keycodes;
     if (kcName!=None)
-	 fprintf(file,"xkb_keycodes \"%s\" {\n",
+	 xkb_printf(cookie,"xkb_keycodes \"%s\" {\n",
 					XkbAtomText(kcName,XkbXKBFile));
-    else fprintf(file,"xkb_keycodes {\n");
-    fprintf(file,"    minimum = %d;\n",xkb->min_key_code);
-    fprintf(file,"    maximum = %d;\n",xkb->max_key_code);
+    else xkb_printf(cookie,"xkb_keycodes {\n");
+    xkb_printf(cookie,"    minimum = %d;\n",xkb->min_key_code);
+    xkb_printf(cookie,"    maximum = %d;\n",xkb->max_key_code);
     for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
 	if (xkb->names->keys[i].name[0]!='\0') {
 	    if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,True)!=i)
 		 alternate= "alternate ";
 	    else alternate= "";
-	    fprintf(file,"    %s%6s = %d;\n",alternate,
+	    xkb_printf(cookie,"    %s%6s = %d;\n",alternate,
 			XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile),
 			i);
 	}
@@ -138,7 +140,7 @@ char *			alternate;
 			type= "    ";
 	    else	type= "    virtual ";
 	    if (xkb->names->indicators[i]!=None) {
-		fprintf(file,"%sindicator %d = \"%s\";\n",type,i+1,
+		xkb_printf(cookie,"%sindicator %d = \"%s\";\n",type,i+1,
 			XkbAtomText(xkb->names->indicators[i],XkbXKBFile));
 	    }
 	}
@@ -147,23 +149,23 @@ char *			alternate;
 	XkbKeyAliasPtr	pAl;
 	pAl= xkb->names->key_aliases;
 	for (i=0;i<xkb->names->num_key_aliases;i++,pAl++) {
-	    fprintf(file,"    alias %6s = %6s;\n",
+	    xkb_printf(cookie,"    alias %6s = %6s;\n",
 			XkbKeyNameText(pAl->alias,XkbXKBFile),
 			XkbKeyNameText(pAl->real,XkbXKBFile));
 	}
     }
     if (addOn)
-	(*addOn)(file,xkb,topLevel,showImplicit,XkmKeyNamesIndex,priv);
-    fprintf(file,"};\n\n");
+	(*addOn)(cookie,xkb,topLevel,showImplicit,XkmKeyNamesIndex,priv);
+    xkb_printf(cookie,"};\n\n");
     return True;
 }
 
 Bool
-XkbWriteXKBKeyTypes(	FILE *			file,
+XkbWrite_KeyTypes(	void *			cookie,
 			XkbDescPtr              xkb,
 			Bool			topLevel,
 			Bool			showImplicit,
-			XkbFileAddOnFunc	addOn,
+			XkbCookieAddOnFunc	addOn,
 			void *			priv)
 {
 register unsigned	i,n;
@@ -171,25 +173,25 @@ XkbKeyTypePtr		type;
 XkbKTMapEntryPtr	entry;
 
     if ((!xkb)||(!xkb->map)||(!xkb->map->types)) {
-	_XkbLibError(_XkbErrMissingTypes,"XkbWriteXKBKeyTypes",0);
+	_XkbLibError(_XkbErrMissingTypes,"XkbWrite_KeyTypes",0);
 	return False;
     }
     if (xkb->map->num_types<XkbNumRequiredTypes) {
-	_XkbLibError(_XkbErrMissingReqTypes,"XkbWriteXKBKeyTypes",0);
+	_XkbLibError(_XkbErrMissingReqTypes,"XkbWrite_KeyTypes",0);
 	return 0;
     }
     if ((xkb->names==NULL)||(xkb->names->types==None))
-	 fprintf(file,"xkb_types {\n\n");
-    else fprintf(file,"xkb_types \"%s\" {\n\n",
+	 xkb_printf(cookie,"xkb_types {\n\n");
+    else xkb_printf(cookie,"xkb_types \"%s\" {\n\n",
 			XkbAtomText(xkb->names->types,XkbXKBFile));
-    WriteXKBVModDecl(file,xkb,
+    WriteXKBVModDecl(cookie,xkb,
 			(showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE));
 
     type= xkb->map->types;
     for (i=0;i<xkb->map->num_types;i++,type++) {
-	fprintf(file,"    type \"%s\" {\n",
+	xkb_printf(cookie,"    type \"%s\" {\n",
 		XkbAtomText(type->name,XkbXKBFile));
-	fprintf(file,"        modifiers= %s;\n",
+	xkb_printf(cookie,"        modifiers= %s;\n",
 	       XkbVModMaskText(xkb,type->mods.real_mods,type->mods.vmods,
 								XkbXKBFile));
 	entry= type->map;
@@ -197,11 +199,11 @@ XkbKTMapEntryPtr	entry;
 	    char *str;	
 	    str=XkbVModMaskText(xkb,entry->mods.real_mods,entry->mods.vmods,
 								XkbXKBFile);
-	    fprintf(file,"        map[%s]= Level%d;\n",str,entry->level+1);
+	    xkb_printf(cookie,"        map[%s]= Level%d;\n",str,entry->level+1);
 	    if ((type->preserve)&&((type->preserve[n].real_mods)||
 				   (type->preserve[n].vmods))) {
-		fprintf(file,"        preserve[%s]= ",str);
-		fprintf(file,"%s;\n",XkbVModMaskText(xkb,
+		xkb_printf(cookie,"        preserve[%s]= ",str);
+		xkb_printf(cookie,"%s;\n",XkbVModMaskText(xkb,
 					type->preserve[n].real_mods,
 					type->preserve[n].vmods,
 					XkbXKBFile));
@@ -212,105 +214,105 @@ XkbKTMapEntryPtr	entry;
 	    for (n=0;n<type->num_levels;n++,name++) {
 		if ((*name)==None)
 		    continue;
-		fprintf(file,"        level_name[Level%d]= \"%s\";\n",n+1,
+		xkb_printf(cookie,"        level_name[Level%d]= \"%s\";\n",n+1,
 					XkbAtomText(*name,XkbXKBFile));
 	    }
 	}
-	fprintf(file,"    };\n");
+	xkb_printf(cookie,"    };\n");
     }
     if (addOn)
-	(*addOn)(file,xkb,topLevel,showImplicit,XkmTypesIndex,priv);
-    fprintf(file,"};\n\n");
+	(*addOn)(cookie,xkb,topLevel,showImplicit,XkmTypesIndex,priv);
+    xkb_printf(cookie,"};\n\n");
     return True;
 }
 
 static Bool
-WriteXKBIndicatorMap(	FILE *			file,
+WriteXKBIndicatorMap(	void *			cookie,
 			XkbDescPtr              xkb,
 			Atom			name,
 			XkbIndicatorMapPtr	led,
-			XkbFileAddOnFunc	addOn,
+			XkbCookieAddOnFunc	addOn,
 			void *			priv)
 {
 
-    fprintf(file,"    indicator \"%s\" {\n",XkbAtomGetString(name));
+    xkb_printf(cookie,"    indicator \"%s\" {\n",XkbAtomGetString(name));
     if (led->flags&XkbIM_NoExplicit)
-	fprintf(file,"        !allowExplicit;\n");
+	xkb_printf(cookie,"        !allowExplicit;\n");
     if (led->flags&XkbIM_LEDDrivesKB)
-	fprintf(file,"        indicatorDrivesKeyboard;\n");
+	xkb_printf(cookie,"        indicatorDrivesKeyboard;\n");
     if (led->which_groups!=0) {
 	if (led->which_groups!=XkbIM_UseEffective) {
-	    fprintf(file,"        whichGroupState= %s;\n",
+	    xkb_printf(cookie,"        whichGroupState= %s;\n",
 			XkbIMWhichStateMaskText(led->which_groups,XkbXKBFile));
 	}
-	fprintf(file,"        groups= 0x%02x;\n",led->groups);
+	xkb_printf(cookie,"        groups= 0x%02x;\n",led->groups);
     }
     if (led->which_mods!=0) {
 	if (led->which_mods!=XkbIM_UseEffective) {
-	    fprintf(file,"        whichModState= %s;\n",
+	    xkb_printf(cookie,"        whichModState= %s;\n",
 			XkbIMWhichStateMaskText(led->which_mods,XkbXKBFile));
 	}
-	fprintf(file,"        modifiers= %s;\n",
+	xkb_printf(cookie,"        modifiers= %s;\n",
 			XkbVModMaskText(xkb,
 					led->mods.real_mods,led->mods.vmods,
 					XkbXKBFile));
     }
     if (led->ctrls!=0) {
-	fprintf(file,"        controls= %s;\n",
+	xkb_printf(cookie,"        controls= %s;\n",
 			XkbControlsMaskText(led->ctrls,XkbXKBFile));
     }
     if (addOn)
-	(*addOn)(file,xkb,False,True,XkmIndicatorsIndex,priv);
-    fprintf(file,"    };\n");
+	(*addOn)(cookie,xkb,False,True,XkmIndicatorsIndex,priv);
+    xkb_printf(cookie,"    };\n");
     return True;
 }
 
 Bool
-XkbWriteXKBCompatMap(	FILE *			file,
+XkbWrite_CompatMap(	void *			cookie,
 			XkbDescPtr              xkb,
 			Bool			topLevel,
 			Bool			showImplicit,
-			XkbFileAddOnFunc	addOn,
+			XkbCookieAddOnFunc	addOn,
 			void *			priv)
 {
 register unsigned	i;
 XkbSymInterpretPtr	interp;
 
     if ((!xkb)||(!xkb->compat)||(!xkb->compat->sym_interpret)) {
-	_XkbLibError(_XkbErrMissingCompatMap,"XkbWriteXKBCompatMap",0);
+	_XkbLibError(_XkbErrMissingCompatMap,"XkbWrite_CompatMap",0);
 	return False;
     }
     if ((xkb->names==NULL)||(xkb->names->compat==None))
-	 fprintf(file,"xkb_compatibility {\n\n");
-    else fprintf(file,"xkb_compatibility \"%s\" {\n\n",
+	 xkb_printf(cookie,"xkb_compatibility {\n\n");
+    else xkb_printf(cookie,"xkb_compatibility \"%s\" {\n\n",
 			XkbAtomText(xkb->names->compat,XkbXKBFile));
-    WriteXKBVModDecl(file,xkb,
+    WriteXKBVModDecl(cookie,xkb,
 			(showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE));
 
-    fprintf(file,"    interpret.useModMapMods= AnyLevel;\n");
-    fprintf(file,"    interpret.repeat= False;\n");
-    fprintf(file,"    interpret.locking= False;\n");
+    xkb_printf(cookie,"    interpret.useModMapMods= AnyLevel;\n");
+    xkb_printf(cookie,"    interpret.repeat= False;\n");
+    xkb_printf(cookie,"    interpret.locking= False;\n");
     interp= xkb->compat->sym_interpret;
     for (i=0;i<xkb->compat->num_si;i++,interp++) {
-	fprintf(file,"    interpret %s+%s(%s) {\n",	
+	xkb_printf(cookie,"    interpret %s+%s(%s) {\n",	
 				((interp->sym==NoSymbol)?"Any":
 					XkbKeysymText(interp->sym,XkbXKBFile)),
 				XkbSIMatchText(interp->match,XkbXKBFile),
 				XkbModMaskText(interp->mods,XkbXKBFile));
 	if (interp->virtual_mod!=XkbNoModifier) {
-	    fprintf(file,"        virtualModifier= %s;\n",
+	    xkb_printf(cookie,"        virtualModifier= %s;\n",
 		XkbVModIndexText(xkb,interp->virtual_mod,XkbXKBFile));
 	}
 	if (interp->match&XkbSI_LevelOneOnly)
-	    fprintf(file,"        useModMapMods=level1;\n");
+	    xkb_printf(cookie,"        useModMapMods=level1;\n");
 	if (interp->flags&XkbSI_LockingKey)
-	    fprintf(file,"        locking= True;\n");
+	    xkb_printf(cookie,"        locking= True;\n");
 	if (interp->flags&XkbSI_AutoRepeat)
-	    fprintf(file,"        repeat= True;\n");
-	fprintf(file,"        action= ");
-	WriteXKBAction(file,xkb,&interp->act);
-	fprintf(file,";\n");
-	fprintf(file,"    };\n");
+	    xkb_printf(cookie,"        repeat= True;\n");
+	xkb_printf(cookie,"        action= ");
+	WriteXKBAction(cookie,xkb,&interp->act);
+	xkb_printf(cookie,";\n");
+	xkb_printf(cookie,"    };\n");
     }
     for (i=0;i<XkbNumKbdGroups;i++) {
 	XkbModsPtr	gc;
@@ -318,7 +320,7 @@ XkbSymInterpretPtr	interp;
 	gc= &xkb->compat->groups[i];
 	if ((gc->real_mods==0)&&(gc->vmods==0))
 	    continue;
-	fprintf(file,"    group %d = %s;\n",i+1,XkbVModMaskText(xkb,
+	xkb_printf(cookie,"    group %d = %s;\n",i+1,XkbVModMaskText(xkb,
 							gc->real_mods,gc->vmods,
 							XkbXKBFile));
     }
@@ -329,23 +331,23 @@ XkbSymInterpretPtr	interp;
 		(map->which_mods!=0)||
 		(map->mods.real_mods!=0)||(map->mods.vmods!=0)||
 		(map->ctrls!=0)) {
-		WriteXKBIndicatorMap(file,xkb,xkb->names->indicators[i],map,
+		WriteXKBIndicatorMap(cookie,xkb,xkb->names->indicators[i],map,
 								addOn,priv);
 	    }
 	}
     }
     if (addOn)
-	(*addOn)(file,xkb,topLevel,showImplicit,XkmCompatMapIndex,priv);
-    fprintf(file,"};\n\n");
+	(*addOn)(cookie,xkb,topLevel,showImplicit,XkmCompatMapIndex,priv);
+    xkb_printf(cookie,"};\n\n");
     return True;
 }
 
 Bool
-XkbWriteXKBSymbols(	FILE *			file,
+XkbWrite_Symbols(	void *			cookie,
 			XkbDescPtr              xkb,
 			Bool			topLevel,
 			Bool			showImplicit,
-			XkbFileAddOnFunc	addOn,
+			XkbCookieAddOnFunc	addOn,
 			void *			priv)
 {
 register unsigned	i,tmp;
@@ -364,18 +366,18 @@ Bool			showActions;
 	return False;
     }
     if ((xkb->names==NULL)||(xkb->names->symbols==None))
-	 fprintf(file,"xkb_symbols {\n\n");
-    else fprintf(file,"xkb_symbols \"%s\" {\n\n",
+	 xkb_printf(cookie,"xkb_symbols {\n\n");
+    else xkb_printf(cookie,"xkb_symbols \"%s\" {\n\n",
 			XkbAtomText(xkb->names->symbols,XkbXKBFile));
     for (tmp=i=0;i<XkbNumKbdGroups;i++) {
 	if (xkb->names->groups[i]!=None) {
-	    fprintf(file,"    name[group%d]=\"%s\";\n",i+1,
+	    xkb_printf(cookie,"    name[group%d]=\"%s\";\n",i+1,
 			XkbAtomText(xkb->names->groups[i],XkbXKBFile));
 	    tmp++;
 	}
     }
     if (tmp>0)
-	fprintf(file,"\n");
+	xkb_printf(cookie,"\n");
     for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
 	Bool	simple;
 	if ((int)XkbKeyNumSyms(xkb,i)<1)
@@ -383,12 +385,12 @@ Bool			showActions;
 	if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,True)!=i)
 	    continue;
 	simple= True;
-	fprintf(file,"    key %6s {",
-			XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile));
+	xkb_printf(cookie,"    key %6s {",
+		   XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile));
 	if (srv->explicit) {
 	    if (((srv->explicit[i]&XkbExplicitKeyTypesMask)!=0)||
-	   						(showImplicit)) {
-		int 	typeNdx,g;
+		(showImplicit)) {
+		int	typeNdx,g;
 		Bool	multi;
 		char *	comment="  ";
 
@@ -404,20 +406,20 @@ Bool			showActions;
 		    for (g=0;g<XkbKeyNumGroups(xkb,i);g++) {
 			typeNdx= XkbKeyKeyTypeIndex(xkb,i,g);
 			if (srv->explicit[i]&(1<<g)) {
-			    fprintf(file,"\n%s      type[group%d]= \"%s\",",
+			    xkb_printf(cookie,"\n%s      type[group%d]= \"%s\",",
 			    	comment,g+1,
 				XkbAtomText(map->types[typeNdx].name,
 			    	XkbXKBFile));
 			}
 			else if (showImplicit) {
-			    fprintf(file,"\n//      type[group%d]= \"%s\",",g+1,
+			    xkb_printf(cookie,"\n//      type[group%d]= \"%s\",",g+1,
 				XkbAtomText(map->types[typeNdx].name,
 			    	XkbXKBFile));
 			}
 		    }
 		}
 		else {
-		    fprintf(file,"\n%s      type= \"%s\",",comment,
+		    xkb_printf(cookie,"\n%s      type= \"%s\",",comment,
 				XkbAtomText(map->types[typeNdx].name,
 			    	XkbXKBFile));
 		}
@@ -426,20 +428,20 @@ Bool			showActions;
 	    if (((srv->explicit[i]&XkbExplicitAutoRepeatMask)!=0)&&
 		    					  (xkb->ctrls!=NULL)) {
 		if (xkb->ctrls->per_key_repeat[i/8]&(1<<(i%8)))
-		     fprintf(file,"\n        repeat= Yes,");
-		else fprintf(file,"\n        repeat= No,");
+		     xkb_printf(cookie,"\n        repeat= Yes,");
+		else xkb_printf(cookie,"\n        repeat= No,");
 		simple= False;
 	    }
 	    if ((xkb->server!=NULL)&&(xkb->server->vmodmap!=NULL)&&
 					(xkb->server->vmodmap[i]!=0)) {
 		if ((srv->explicit[i]&XkbExplicitVModMapMask)!=0) {
-		    fprintf(file,"\n        virtualMods= %s,",
+		    xkb_printf(cookie,"\n        virtualMods= %s,",
 				XkbVModMaskText(xkb,0,
 						xkb->server->vmodmap[i],
 						XkbXKBFile));
 		}
 		else if (showImplicit) {
-		    fprintf(file,"\n//      virtualMods= %s,",
+		    xkb_printf(cookie,"\n//      virtualMods= %s,",
 				XkbVModMaskText(xkb,0,
 						xkb->server->vmodmap[i],
 						XkbXKBFile));
@@ -448,10 +450,10 @@ Bool			showActions;
 	}
 	switch (XkbOutOfRangeGroupAction(XkbKeyGroupInfo(xkb,i))) {
 	    case XkbClampIntoRange:
-		fprintf(file,"\n        groupsClamp,");
+		xkb_printf(cookie,"\n        groupsClamp,");
 		break;
 	    case XkbRedirectIntoRange:
-		fprintf(file,"\n        groupsRedirect= Group%d,",
+		xkb_printf(cookie,"\n        groupsRedirect= Group%d,",
 			XkbOutOfRangeGroupNumber(XkbKeyGroupInfo(xkb,i))+1);
 		break;
 	}
@@ -461,8 +463,8 @@ Bool			showActions;
 
 	    if (type!=XkbKB_Default) {
 		simple= False;
-		fprintf(file,"\n        %s,",
-			XkbBehaviorText(xkb,&srv->behaviors[i],XkbXKBFile));
+		xkb_printf(cookie,"\n        %s,",
+			   XkbBehaviorText(xkb,&srv->behaviors[i],XkbXKBFile));
 	    }
 	}
 	if ((srv->explicit==NULL) || showImplicit ||
@@ -477,13 +479,13 @@ Bool			showActions;
 	    unsigned s;
 
 	    syms= XkbKeySymsPtr(xkb,i);
-	    fprintf(file,"         [ ");
+	    xkb_printf(cookie,"         [ ");
 	    for (s=0;s<XkbKeyGroupWidth(xkb,i,XkbGroup1Index);s++) {
 		if (s!=0)
-		    fprintf(file,", ");
-		fprintf(file,"%15s",XkbKeysymText(*syms++,XkbXKBFile));
+		    xkb_printf(cookie,", ");
+		xkb_printf(cookie,"%15s",XkbKeysymText(*syms++,XkbXKBFile));
 	    }
-	    fprintf(file," ] };\n");
+	    xkb_printf(cookie," ] };\n");
 	}
 	else {
 	    unsigned g,s;
@@ -493,27 +495,27 @@ Bool			showActions;
 	    acts= XkbKeyActionsPtr(xkb,i);
 	    for (g=0;g<XkbKeyNumGroups(xkb,i);g++) {
 		if (g!=0)
-		    fprintf(file,",");
-		fprintf(file,"\n        symbols[Group%d]= [ ",g+1);
+		    xkb_printf(cookie,",");
+		xkb_printf(cookie,"\n        symbols[Group%d]= [ ",g+1);
 		for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) {
 		    if (s!=0)
-			fprintf(file,", ");
-		    fprintf(file,"%15s",XkbKeysymText(syms[s],XkbXKBFile));
+			xkb_printf(cookie,", ");
+		    xkb_printf(cookie,"%15s",XkbKeysymText(syms[s],XkbXKBFile));
 		}
-		fprintf(file," ]");
+		xkb_printf(cookie," ]");
 		syms+= XkbKeyGroupsWidth(xkb,i);
 		if (showActions) {
-		    fprintf(file,",\n        actions[Group%d]= [ ",g+1);
+		    xkb_printf(cookie,",\n        actions[Group%d]= [ ",g+1);
 		    for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) {
 			if (s!=0)
-			    fprintf(file,", ");
-			WriteXKBAction(file,xkb,(XkbAnyAction *)&acts[s]);
+			    xkb_printf(cookie,", ");
+			WriteXKBAction(cookie,xkb,(XkbAnyAction *)&acts[s]);
 		    }
-		    fprintf(file," ]");
+		    xkb_printf(cookie," ]");
 		    acts+= XkbKeyGroupsWidth(xkb,i);
 		}
 	    }
-	    fprintf(file,"\n    };\n");
+	    xkb_printf(cookie,"\n    };\n");
 	}
     }
     if (map && map->modmap) {
@@ -525,7 +527,7 @@ Bool			showActions;
 			char buf[5];
 			memcpy(buf,xkb->names->keys[i].name,4);
 			buf[4]= '\0';
-			fprintf(file,"    modifier_map %s { <%s> };\n",
+			xkb_printf(cookie,"    modifier_map %s { <%s> };\n",
 					XkbModIndexText(n,XkbXKBFile),buf);
 		    }
 		}
@@ -533,13 +535,13 @@ Bool			showActions;
 	}
     }
     if (addOn)
-	(*addOn)(file,xkb,topLevel,showImplicit,XkmSymbolsIndex,priv);
-    fprintf(file,"};\n\n");
+	(*addOn)(cookie,xkb,topLevel,showImplicit,XkmSymbolsIndex,priv);
+    xkb_printf(cookie,"};\n\n");
     return True;
 }
 
 static Bool
-WriteXKBOutline(	FILE *		file,
+WriteXKBOutline(	void *		cookie,
 			XkbShapePtr	shape,
 			XkbOutlinePtr	outline,
 			int		lastRadius,
@@ -550,36 +552,36 @@ register int	i;
 XkbPointPtr	pt;
 char *		iStr;
 
-    fprintf(file,"%s",iStr= XkbIndentText(first));
+    xkb_printf(cookie,"%s",iStr= XkbIndentText(first));
     if (first!=indent)
 	iStr= XkbIndentText(indent);
     if (outline->corner_radius!=lastRadius) {
-	fprintf(file,"corner= %s,",
+	xkb_printf(cookie,"corner= %s,",
 			XkbGeomFPText(outline->corner_radius,XkbMessage));
 	if (shape!=NULL) {
-	    fprintf(file,"\n%s",iStr);
+	    xkb_printf(cookie,"\n%s",iStr);
 	}
     }
     if (shape) {
 	if (outline==shape->approx)
-	    fprintf(file,"approx= ");
+	    xkb_printf(cookie,"approx= ");
 	else if (outline==shape->primary)
-	    fprintf(file,"primary= ");
+	    xkb_printf(cookie,"primary= ");
     }
-    fprintf(file,"{");
+    xkb_printf(cookie,"{");
     for (pt=outline->points,i=0;i<outline->num_points;i++,pt++) {
-	if (i==0)		fprintf(file," ");
-	else if ((i%4)==0)	fprintf(file,",\n%s  ",iStr);
-	else			fprintf(file,", ");
-	fprintf(file,"[ %3s, %3s ]",XkbGeomFPText(pt->x,XkbXKBFile),
+	if (i==0)		xkb_printf(cookie," ");
+	else if ((i%4)==0)	xkb_printf(cookie,",\n%s  ",iStr);
+	else			xkb_printf(cookie,", ");
+	xkb_printf(cookie,"[ %3s, %3s ]",XkbGeomFPText(pt->x,XkbXKBFile),
 				  XkbGeomFPText(pt->y,XkbXKBFile));
     }
-    fprintf(file," }");
+    xkb_printf(cookie," }");
     return True;
 }
 
 static Bool
-WriteXKBDoodad(	FILE *		file,
+WriteXKBDoodad(	void *		cookie,
 		unsigned	indent,
 		XkbGeometryPtr	geom,
 		XkbDoodadPtr	doodad)
@@ -589,88 +591,88 @@ XkbShapePtr	shape;
 XkbColorPtr	color;
 
     i_str= XkbIndentText(indent);
-    fprintf(file,"%s%s \"%s\" {\n",i_str,
+    xkb_printf(cookie,"%s%s \"%s\" {\n",i_str,
 				XkbDoodadTypeText(doodad->any.type,XkbMessage),
 				XkbAtomText(doodad->any.name,XkbMessage));
-    fprintf(file,"%s    top=      %s;\n",i_str,
+    xkb_printf(cookie,"%s    top=      %s;\n",i_str,
 				 XkbGeomFPText(doodad->any.top,XkbXKBFile));
-    fprintf(file,"%s    left=     %s;\n",i_str,
+    xkb_printf(cookie,"%s    left=     %s;\n",i_str,
 				XkbGeomFPText(doodad->any.left,XkbXKBFile));
-    fprintf(file,"%s    priority= %d;\n",i_str,doodad->any.priority);
+    xkb_printf(cookie,"%s    priority= %d;\n",i_str,doodad->any.priority);
     switch (doodad->any.type) {
 	case XkbOutlineDoodad:
 	case XkbSolidDoodad:
 	    if (doodad->shape.angle!=0) {
-		fprintf(file,"%s    angle=  %s;\n",i_str,
+		xkb_printf(cookie,"%s    angle=  %s;\n",i_str,
 			     XkbGeomFPText(doodad->shape.angle,XkbXKBFile));
 	    }
 	    if (doodad->shape.color_ndx!=0) {
-		fprintf(file,"%s    color= \"%s\";\n",i_str,
+		xkb_printf(cookie,"%s    color= \"%s\";\n",i_str,
 			     XkbShapeDoodadColor(geom,&doodad->shape)->spec);
 	    }
 	    shape= XkbShapeDoodadShape(geom,&doodad->shape);
-	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
+	    xkb_printf(cookie,"%s    shape= \"%s\";\n",i_str,
 			    XkbAtomText(shape->name,XkbXKBFile));
 	    break;
 	case XkbTextDoodad:
 	    if (doodad->text.angle!=0) {
-		fprintf(file,"%s    angle=  %s;\n",i_str,
+		xkb_printf(cookie,"%s    angle=  %s;\n",i_str,
 			     XkbGeomFPText(doodad->text.angle,XkbXKBFile));
 	    }
 	    if (doodad->text.width!=0) {
-		fprintf(file,"%s    width=  %s;\n",i_str,
+		xkb_printf(cookie,"%s    width=  %s;\n",i_str,
 			     XkbGeomFPText(doodad->text.width,XkbXKBFile));
 
 	    }
 	    if (doodad->text.height!=0) {
-		fprintf(file,"%s    height=  %s;\n",i_str,
+		xkb_printf(cookie,"%s    height=  %s;\n",i_str,
 			     XkbGeomFPText(doodad->text.height,XkbXKBFile));
 
 	    }
 	    if (doodad->text.color_ndx!=0) {
 		color= XkbTextDoodadColor(geom,&doodad->text);
-		fprintf(file,"%s    color= \"%s\";\n",i_str,
+		xkb_printf(cookie,"%s    color= \"%s\";\n",i_str,
 			     XkbStringText(color->spec,XkbXKBFile));
 	    }
-	    fprintf(file,"%s    XFont= \"%s\";\n",i_str,
+	    xkb_printf(cookie,"%s    XFont= \"%s\";\n",i_str,
 	    		     XkbStringText(doodad->text.font,XkbXKBFile));
-	    fprintf(file,"%s    text=  \"%s\";\n",i_str,
+	    xkb_printf(cookie,"%s    text=  \"%s\";\n",i_str,
 	    		    XkbStringText(doodad->text.text,XkbXKBFile));
 	    break;
 	case XkbIndicatorDoodad:
 	    shape= XkbIndicatorDoodadShape(geom,&doodad->indicator);
 	    color= XkbIndicatorDoodadOnColor(geom,&doodad->indicator);
-	    fprintf(file,"%s    onColor= \"%s\";\n",i_str,
+	    xkb_printf(cookie,"%s    onColor= \"%s\";\n",i_str,
 	    		    XkbStringText(color->spec,XkbXKBFile));
 	    color= XkbIndicatorDoodadOffColor(geom,&doodad->indicator);
-	    fprintf(file,"%s    offColor= \"%s\";\n",i_str,
+	    xkb_printf(cookie,"%s    offColor= \"%s\";\n",i_str,
 	    		    XkbStringText(color->spec,XkbXKBFile));
-	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
+	    xkb_printf(cookie,"%s    shape= \"%s\";\n",i_str,
 			     XkbAtomText(shape->name,XkbXKBFile));
 	    break;
 	case XkbLogoDoodad:
-	    fprintf(file,"%s    logoName= \"%s\";\n",i_str,
+	    xkb_printf(cookie,"%s    logoName= \"%s\";\n",i_str,
 			     XkbStringText(doodad->logo.logo_name,XkbXKBFile));
 	    if (doodad->shape.angle!=0) {
-		fprintf(file,"%s    angle=  %s;\n",i_str,
+		xkb_printf(cookie,"%s    angle=  %s;\n",i_str,
 			     XkbGeomFPText(doodad->logo.angle,XkbXKBFile));
 	    }
 	    if (doodad->shape.color_ndx!=0) {
-		fprintf(file,"%s    color= \"%s\";\n",i_str,
+		xkb_printf(cookie,"%s    color= \"%s\";\n",i_str,
 			     XkbLogoDoodadColor(geom,&doodad->logo)->spec);
 	    }
 	    shape= XkbLogoDoodadShape(geom,&doodad->logo);
-	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
+	    xkb_printf(cookie,"%s    shape= \"%s\";\n",i_str,
 			    XkbAtomText(shape->name,XkbXKBFile));
 	    break;
     }
-    fprintf(file,"%s};\n",i_str);
+    xkb_printf(cookie,"%s};\n",i_str);
     return True;
 }
 
 /*ARGSUSED*/
 static Bool
-WriteXKBOverlay(	FILE *		file,
+WriteXKBOverlay(	void *		cookie,
 			unsigned	indent,
 			XkbGeometryPtr	geom,
 			XkbOverlayPtr	ol)
@@ -682,29 +684,29 @@ XkbOverlayKeyPtr	key;
 
     i_str= XkbIndentText(indent);
     if (ol->name!=None) {
-	 fprintf(file,"%soverlay \"%s\" {\n",i_str,
+	 xkb_printf(cookie,"%soverlay \"%s\" {\n",i_str,
     					XkbAtomText(ol->name,XkbMessage));
     }
-    else fprintf(file,"%soverlay {\n",i_str);
+    else xkb_printf(cookie,"%soverlay {\n",i_str);
     for (nOut=r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
 	for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
 	    char *over,*under;
 	    over= XkbKeyNameText(key->over.name,XkbXKBFile);
 	    under= XkbKeyNameText(key->under.name,XkbXKBFile);
 	    if (nOut==0)
-		 fprintf(file,"%s    %6s=%6s",i_str,under,over);
+		 xkb_printf(cookie,"%s    %6s=%6s",i_str,under,over);
 	    else if ((nOut%4)==0)
-		 fprintf(file,",\n%s    %6s=%6s",i_str,under,over);
-	    else fprintf(file,", %6s=%6s",under,over);
+		 xkb_printf(cookie,",\n%s    %6s=%6s",i_str,under,over);
+	    else xkb_printf(cookie,", %6s=%6s",under,over);
 	    nOut++;
 	}
     }
-    fprintf(file,"\n%s};\n",i_str);
+    xkb_printf(cookie,"\n%s};\n",i_str);
     return True;
 }
 
 static Bool
-WriteXKBSection(	FILE *		file,
+WriteXKBSection(	void *		cookie,
 			XkbSectionPtr 	s,
 			XkbGeometryPtr	geom)
 {
@@ -712,145 +714,145 @@ register int	i;
 XkbRowPtr	row;
 int		dfltKeyColor = 0;
 
-    fprintf(file,"    section \"%s\" {\n",
+    xkb_printf(cookie,"    section \"%s\" {\n",
 				XkbAtomText(s->name,XkbXKBFile));
     if (s->rows&&(s->rows->num_keys>0)) {
 	dfltKeyColor= s->rows->keys[0].color_ndx;
-	fprintf(file,"        key.color= \"%s\";\n",
+	xkb_printf(cookie,"        key.color= \"%s\";\n",
 		XkbStringText(geom->colors[dfltKeyColor].spec,XkbXKBFile));
     }
-    fprintf(file,"        priority=  %d;\n",s->priority);
-    fprintf(file,"        top=       %s;\n",XkbGeomFPText(s->top,XkbXKBFile));
-    fprintf(file,"        left=      %s;\n",XkbGeomFPText(s->left,XkbXKBFile));
-    fprintf(file,"        width=     %s;\n",XkbGeomFPText(s->width,XkbXKBFile));
-    fprintf(file,"        height=    %s;\n",
+    xkb_printf(cookie,"        priority=  %d;\n",s->priority);
+    xkb_printf(cookie,"        top=       %s;\n",XkbGeomFPText(s->top,XkbXKBFile));
+    xkb_printf(cookie,"        left=      %s;\n",XkbGeomFPText(s->left,XkbXKBFile));
+    xkb_printf(cookie,"        width=     %s;\n",XkbGeomFPText(s->width,XkbXKBFile));
+    xkb_printf(cookie,"        height=    %s;\n",
 					XkbGeomFPText(s->height,XkbXKBFile));
     if (s->angle!=0) {
-	fprintf(file,"        angle=  %s;\n",
+	xkb_printf(cookie,"        angle=  %s;\n",
 					XkbGeomFPText(s->angle,XkbXKBFile));
     }
     for (i=0,row=s->rows;i<s->num_rows;i++,row++) {
-	fprintf(file,"        row {\n");
-	fprintf(file,"            top=  %s;\n",
+	xkb_printf(cookie,"        row {\n");
+	xkb_printf(cookie,"            top=  %s;\n",
 					XkbGeomFPText(row->top,XkbXKBFile));
-	fprintf(file,"            left= %s;\n",
+	xkb_printf(cookie,"            left= %s;\n",
 					XkbGeomFPText(row->left,XkbXKBFile));
 	if (row->vertical)
-	    fprintf(file,"            vertical;\n");
+	    xkb_printf(cookie,"            vertical;\n");
 	if (row->num_keys>0) {
 	    register int 	k;
 	    register XkbKeyPtr	key;
 	    int			forceNL=0;
 	    int			nThisLine= 0;
-	    fprintf(file,"            keys {\n");
+	    xkb_printf(cookie,"            keys {\n");
 	    for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
 		XkbShapePtr	shape;
 		if (key->color_ndx!=dfltKeyColor)
 		    forceNL= 1;
 		if (k==0) {
-		     fprintf(file,"                ");
+		     xkb_printf(cookie,"                ");
 		     nThisLine= 0;
 		}
 		else if (((nThisLine%2)==1)||(forceNL)) {
-		     fprintf(file,",\n                ");
+		     xkb_printf(cookie,",\n                ");
 		     forceNL= nThisLine= 0;
 		}
 		else {
-		     fprintf(file,", ");
+		     xkb_printf(cookie,", ");
 		     nThisLine++;
 		}
 		shape= XkbKeyShape(geom,key);
-		fprintf(file,"{ %6s, \"%s\", %3s",
+		xkb_printf(cookie,"{ %6s, \"%s\", %3s",
 		      XkbKeyNameText(key->name.name,XkbXKBFile),
 		      XkbAtomText(shape->name,XkbXKBFile),
 		      XkbGeomFPText(key->gap,XkbXKBFile));
 		if (key->color_ndx!=dfltKeyColor) {
-		    fprintf(file,", color=\"%s\"",XkbKeyColor(geom,key)->spec);
+		    xkb_printf(cookie,", color=\"%s\"",XkbKeyColor(geom,key)->spec);
 		    forceNL= 1;
 		}
-		fprintf(file," }");
+		xkb_printf(cookie," }");
 	    }
-	    fprintf(file,"\n            };\n");
+	    xkb_printf(cookie,"\n            };\n");
 	}
-	fprintf(file,"        };\n");
+	xkb_printf(cookie,"        };\n");
     }
     if (s->doodads!=NULL) {
 	XkbDoodadPtr	doodad;
 	for (i=0,doodad=s->doodads;i<s->num_doodads;i++,doodad++) {
-	    WriteXKBDoodad(file,8,geom,doodad);
+	    WriteXKBDoodad(cookie,8,geom,doodad);
 	}
     }
     if (s->overlays!=NULL) {
 	XkbOverlayPtr	ol;
 	for (i=0,ol=s->overlays;i<s->num_overlays;i++,ol++) {
-	    WriteXKBOverlay(file,8,geom,ol);
+	    WriteXKBOverlay(cookie,8,geom,ol);
 	}
     }
-    fprintf(file,"    }; // End of \"%s\" section\n\n",
+    xkb_printf(cookie,"    }; // End of \"%s\" section\n\n",
 				XkbAtomText(s->name,XkbXKBFile));
     return True;
 }
 
 Bool
-XkbWriteXKBGeometry(	FILE *			file,
+XkbWrite_Geometry(	void *			cookie,
 			XkbDescPtr              xkb,
 			Bool			topLevel,
 			Bool			showImplicit,
-			XkbFileAddOnFunc	addOn,
+			XkbCookieAddOnFunc	addOn,
 			void *			priv)
 {
 register unsigned	i,n;
 XkbGeometryPtr		geom;
 
     if ((!xkb)||(!xkb->geom)) {
-	_XkbLibError(_XkbErrMissingGeometry,"XkbWriteXKBGeometry",0);
+	_XkbLibError(_XkbErrMissingGeometry,"XkbWrite_Geometry",0);
  	return False;
     }
     geom= xkb->geom;
     if (geom->name==None)
-	 fprintf(file,"xkb_geometry {\n\n");
-    else fprintf(file,"xkb_geometry \"%s\" {\n\n",
+	 xkb_printf(cookie,"xkb_geometry {\n\n");
+    else xkb_printf(cookie,"xkb_geometry \"%s\" {\n\n",
 				XkbAtomText(geom->name,XkbXKBFile));
-    fprintf(file,"    width=       %s;\n",
+    xkb_printf(cookie,"    width=       %s;\n",
 				XkbGeomFPText(geom->width_mm,XkbXKBFile));
-    fprintf(file,"    height=      %s;\n\n",
+    xkb_printf(cookie,"    height=      %s;\n\n",
 				XkbGeomFPText(geom->height_mm,XkbXKBFile));
 
     if (geom->key_aliases!=NULL) {
 	XkbKeyAliasPtr	pAl;
 	pAl= geom->key_aliases;
 	for (i=0;i<geom->num_key_aliases;i++,pAl++) {
-	    fprintf(file,"    alias %6s = %6s;\n",
+	    xkb_printf(cookie,"    alias %6s = %6s;\n",
 				XkbKeyNameText(pAl->alias,XkbXKBFile),
 				XkbKeyNameText(pAl->real,XkbXKBFile));
 	}
-	fprintf(file,"\n");
+	xkb_printf(cookie,"\n");
     }
 
     if (geom->base_color!=NULL)
-	fprintf(file,"    baseColor=   \"%s\";\n",
+	xkb_printf(cookie,"    baseColor=   \"%s\";\n",
 			XkbStringText(geom->base_color->spec,XkbXKBFile));
     if (geom->label_color!=NULL)
-	fprintf(file,"    labelColor=  \"%s\";\n",
+	xkb_printf(cookie,"    labelColor=  \"%s\";\n",
 			XkbStringText(geom->label_color->spec,XkbXKBFile));
     if (geom->label_font!=NULL)
-	fprintf(file,"    xfont=       \"%s\";\n",
+	xkb_printf(cookie,"    xfont=       \"%s\";\n",
 			XkbStringText(geom->label_font,XkbXKBFile));
     if ((geom->num_colors>0)&&(showImplicit)) {
 	XkbColorPtr	color;
 	for (color=geom->colors,i=0;i<geom->num_colors;i++,color++) {
-		fprintf(file,"//     color[%d]= \"%s\"\n",i,
+		xkb_printf(cookie,"//     color[%d]= \"%s\"\n",i,
 				XkbStringText(color->spec,XkbXKBFile));
 	}
-	fprintf(file,"\n");
+	xkb_printf(cookie,"\n");
     }
     if (geom->num_properties>0) {
 	XkbPropertyPtr	prop;
 	for (prop=geom->properties,i=0;i<geom->num_properties;i++,prop++) {
-	    fprintf(file,"    %s= \"%s\";\n",prop->name,
+	    xkb_printf(cookie,"    %s= \"%s\";\n",prop->name,
     				XkbStringText(prop->value,XkbXKBFile));
 	}
-	fprintf(file,"\n");
+	xkb_printf(cookie,"\n");
     }
     if (geom->num_shapes>0) {
 	XkbShapePtr	shape;
@@ -858,38 +860,38 @@ XkbGeometryPtr		geom;
 	int		lastR;
 	for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) {
 	    lastR=0;
-	    fprintf(file,"    shape \"%s\" {",
+	    xkb_printf(cookie,"    shape \"%s\" {",
 				   XkbAtomText(shape->name,XkbXKBFile));
 	    outline= shape->outlines;
 	    if (shape->num_outlines>1) {
 		for (n=0;n<shape->num_outlines;n++,outline++) {
-		    if (n==0)	fprintf(file,"\n");
-		    else	fprintf(file,",\n");
-		    WriteXKBOutline(file,shape,outline,lastR,8,8);
+		    if (n==0)	xkb_printf(cookie,"\n");
+		    else	xkb_printf(cookie,",\n");
+		    WriteXKBOutline(cookie,shape,outline,lastR,8,8);
 		    lastR= outline->corner_radius;
 		}
-		fprintf(file,"\n    };\n");
+		xkb_printf(cookie,"\n    };\n");
 	    }
 	    else {
-		WriteXKBOutline(file,NULL,outline,lastR,1,8);
-		fprintf(file," };\n");
+		WriteXKBOutline(cookie,NULL,outline,lastR,1,8);
+		xkb_printf(cookie," };\n");
 	    }
 	}
     }
     if (geom->num_sections>0) {
 	XkbSectionPtr	section;
 	for (section=geom->sections,i=0;i<geom->num_sections;i++,section++){
-	    WriteXKBSection(file,section,geom);
+	    WriteXKBSection(cookie,section,geom);
 	}
     }
     if (geom->num_doodads>0) {
 	XkbDoodadPtr	doodad;
 	for (i=0,doodad=geom->doodads;i<geom->num_doodads;i++,doodad++) {
-	    WriteXKBDoodad(file,4,geom,doodad);
+	    WriteXKBDoodad(cookie,4,geom,doodad);
 	}
     }
     if (addOn)
-	(*addOn)(file,xkb,topLevel,showImplicit,XkmGeometryIndex,priv);
-    fprintf(file,"};\n\n");
+	(*addOn)(cookie,xkb,topLevel,showImplicit,XkmGeometryIndex,priv);
+    xkb_printf(cookie,"};\n\n");
     return True;
 }
-- 
1.6.2.1